mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-01-20 04:30:46 +00:00
f9476a5a30
chunk_dup() was affected by two bugs at once related to dst->size :
- first, it didn't check dst->size to know if it could free(dst->str),
so using it on a statically allocated chunk would cause a free(constant)
and crash the process ;
- second, it didn't properly set dst->size, possibly causing smaller
strings not to be properly reported in a chunk that was previously
used for something else.
Fortunately, neither of these situations ever happened since the function
is rarely used.
In the process of doing this, we even allocate one more byte for a
trailing zero if the input chunk was not full, so that the copied
string can safely be reused by standard string functions.
The bug was introduced in 1.3.4 nine years ago with this commit :
0f77253
("[MINOR] store HTTP error messages into a chunk array")
It's better to backport this fix in case a future fix relies on it.
153 lines
3.6 KiB
C
153 lines
3.6 KiB
C
/*
|
|
* include/common/chunk.h
|
|
* Chunk management definitions, macros and inline functions.
|
|
*
|
|
* Copyright (C) 2000-2012 Willy Tarreau - w@1wt.eu
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation, version 2.1
|
|
* exclusively.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
#ifndef _TYPES_CHUNK_H
|
|
#define _TYPES_CHUNK_H
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include <common/config.h>
|
|
|
|
|
|
/* describes a chunk of string */
|
|
struct chunk {
|
|
char *str; /* beginning of the string itself. Might not be 0-terminated */
|
|
int size; /* total size of the buffer, 0 if the *str is read-only */
|
|
int len; /* current size of the string from first to last char. <0 = uninit. */
|
|
};
|
|
|
|
/* function prototypes */
|
|
|
|
int chunk_printf(struct chunk *chk, const char *fmt, ...)
|
|
__attribute__ ((format(printf, 2, 3)));
|
|
|
|
int chunk_appendf(struct chunk *chk, const char *fmt, ...)
|
|
__attribute__ ((format(printf, 2, 3)));
|
|
|
|
int chunk_htmlencode(struct chunk *dst, struct chunk *src);
|
|
int chunk_asciiencode(struct chunk *dst, struct chunk *src, char qc);
|
|
int chunk_strcmp(const struct chunk *chk, const char *str);
|
|
int chunk_strcasecmp(const struct chunk *chk, const char *str);
|
|
int alloc_trash_buffers(int bufsize);
|
|
void free_trash_buffers(void);
|
|
struct chunk *get_trash_chunk(void);
|
|
|
|
static inline void chunk_reset(struct chunk *chk)
|
|
{
|
|
chk->len = 0;
|
|
}
|
|
|
|
static inline void chunk_init(struct chunk *chk, char *str, size_t size)
|
|
{
|
|
chk->str = str;
|
|
chk->len = 0;
|
|
chk->size = size;
|
|
}
|
|
|
|
/* report 0 in case of error, 1 if OK. */
|
|
static inline int chunk_initlen(struct chunk *chk, char *str, size_t size, int len)
|
|
{
|
|
|
|
if (size && len > size)
|
|
return 0;
|
|
|
|
chk->str = str;
|
|
chk->len = len;
|
|
chk->size = size;
|
|
|
|
return 1;
|
|
}
|
|
|
|
static inline void chunk_initstr(struct chunk *chk, char *str)
|
|
{
|
|
chk->str = str;
|
|
chk->len = strlen(str);
|
|
chk->size = 0; /* mark it read-only */
|
|
}
|
|
|
|
static inline int chunk_strcpy(struct chunk *chk, const char *str)
|
|
{
|
|
size_t len;
|
|
|
|
len = strlen(str);
|
|
|
|
if (unlikely(len > chk->size))
|
|
return 0;
|
|
|
|
chk->len = len;
|
|
memcpy(chk->str, str, len);
|
|
|
|
return 1;
|
|
}
|
|
|
|
static inline void chunk_drop(struct chunk *chk)
|
|
{
|
|
chk->str = NULL;
|
|
chk->len = -1;
|
|
chk->size = 0;
|
|
}
|
|
|
|
static inline void chunk_destroy(struct chunk *chk)
|
|
{
|
|
if (!chk->size)
|
|
return;
|
|
|
|
free(chk->str);
|
|
chunk_drop(chk);
|
|
}
|
|
|
|
/*
|
|
* frees the destination chunk if already allocated, allocates a new string,
|
|
* and copies the source into it. The new chunk will have extra room for a
|
|
* trailing zero unless the source chunk was actually full. The pointer to
|
|
* the destination string is returned, or NULL if the allocation fails or if
|
|
* any pointer is NULL.
|
|
*/
|
|
static inline char *chunk_dup(struct chunk *dst, const struct chunk *src)
|
|
{
|
|
if (!dst || !src || !src->str)
|
|
return NULL;
|
|
|
|
if (dst->size)
|
|
free(dst->str);
|
|
dst->len = src->len;
|
|
dst->size = src->len;
|
|
if (dst->size < src->size || !src->size)
|
|
dst->size++;
|
|
|
|
dst->str = (char *)malloc(dst->size);
|
|
memcpy(dst->str, src->str, dst->len);
|
|
if (dst->len < dst->size)
|
|
dst->str[dst->len] = 0;
|
|
|
|
return dst->str;
|
|
}
|
|
|
|
#endif /* _TYPES_CHUNK_H */
|
|
|
|
/*
|
|
* Local variables:
|
|
* c-indent-level: 8
|
|
* c-basic-offset: 8
|
|
* End:
|
|
*/
|