mirror of
https://github.com/servalproject/serval-dna.git
synced 2024-12-20 05:37:57 +00:00
Under GCC, enforce proper strbuf_local_buf() arg
Internally the strbuf_local_buf(x) macro uses sizeof(x) to determine the size of the buffer, but this will give the wrong behaviour if x is a pointer (char *x), not an array (char x[]). With this change, invoking it with a pointer will cause a compile error. The safety check makes use of the GCC extensions: __builtin_object_size() and __attribute__((alloc_size(n)). Under non-GCC compilers, the safety check will not be performed.
This commit is contained in:
parent
2ddbb86cb5
commit
fdc6156ec7
14
mem.h
14
mem.h
@ -29,8 +29,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#define malloc(X) _serval_debug_malloc(X,__WHENCE__)
|
||||
#define calloc(X,Y) _serval_debug_calloc(X,Y,__WHENCE__)
|
||||
#define free(X) _serval_debug_free(X,__WHENCE__)
|
||||
void *_serval_debug_malloc(unsigned int bytes, struct __sourceloc whence);
|
||||
void *_serval_debug_calloc(unsigned int bytes, unsigned int count, struct __sourceloc whence);
|
||||
void *_serval_debug_malloc(unsigned int bytes, struct __sourceloc whence) __attribute__ ((malloc, alloc_size(1)));
|
||||
void *_serval_debug_calloc(unsigned int bytes, unsigned int count, struct __sourceloc whence) __attribute__ ((malloc, alloc_size(1)));
|
||||
void _serval_debug_free(void *p, struct __sourceloc whence);
|
||||
#endif
|
||||
|
||||
@ -38,20 +38,20 @@ void _serval_debug_free(void *p, struct __sourceloc whence);
|
||||
*
|
||||
* @author Andrew Bettison <andrew@servalproject.com>
|
||||
*/
|
||||
void *_emalloc(struct __sourceloc, size_t bytes);
|
||||
void *_emalloc(struct __sourceloc, size_t bytes) __attribute__ ((malloc, alloc_size(2), returns_nonnull));
|
||||
|
||||
/* Equivalent to realloc(3), but logs an error before returning NULL.
|
||||
*
|
||||
* @author Andrew Bettison <andrew@servalproject.com>
|
||||
*/
|
||||
void *_erealloc(struct __sourceloc __whence, void *ptr, size_t bytes);
|
||||
void *_erealloc(struct __sourceloc __whence, void *ptr, size_t bytes) __attribute__ ((alloc_size(3), returns_nonnull));
|
||||
|
||||
/* Equivalent to malloc(3) followed by memset(3) to zerofill, but logs an error
|
||||
* before returning NULL.
|
||||
*
|
||||
* @author Andrew Bettison <andrew@servalproject.com>
|
||||
*/
|
||||
void *_emalloc_zero(struct __sourceloc, size_t bytes);
|
||||
void *_emalloc_zero(struct __sourceloc, size_t bytes) __attribute__ ((malloc, alloc_size(2), returns_nonnull));
|
||||
|
||||
/* Equivalent to strdup(3)/strndup(3), but logs an error before returning NULL.
|
||||
*
|
||||
@ -60,8 +60,8 @@ void *_emalloc_zero(struct __sourceloc, size_t bytes);
|
||||
*
|
||||
* @author Andrew Bettison <andrew@servalproject.com>
|
||||
*/
|
||||
char *_str_edup(struct __sourceloc, const char *str);
|
||||
char *_strn_edup(struct __sourceloc, const char *str, size_t len);
|
||||
char *_str_edup(struct __sourceloc, const char *str) __attribute__ ((malloc, returns_nonnull));
|
||||
char *_strn_edup(struct __sourceloc, const char *str, size_t len) __attribute__ ((malloc, returns_nonnull));
|
||||
|
||||
#define emalloc(bytes) _emalloc(__HERE__, (bytes))
|
||||
#define erealloc(ptr, bytes) _erealloc(__HERE__, (ptr), (bytes))
|
||||
|
34
strbuf.h
34
strbuf.h
@ -1,6 +1,6 @@
|
||||
/*
|
||||
Serval string buffer primitives
|
||||
Copyright (C) 2012 Serval Project Inc.
|
||||
Copyright (C) 2012-2015 Serval Project Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
@ -238,9 +238,39 @@ typedef const struct strbuf *const_strbuf;
|
||||
* printf("%s\n", temp);
|
||||
* }
|
||||
*
|
||||
* WARNING: 'buf' must name a char[] array, not a char* pointer. The following
|
||||
* code is wrong:
|
||||
*
|
||||
* char *p = malloc(50);
|
||||
* ...
|
||||
* strbuf b = strbuf_local_buf(p); // ERROR!
|
||||
*
|
||||
* In the above example, sizeof(p) will be 8 (4 on 32-bit architectures) which
|
||||
* is NOT the size of the buffer that p points to (50), and not the desired
|
||||
* effect: the string in strbuf b will be limited to 7 chars in length. If the
|
||||
* buffer pointed to by p were less than 8 in size, then appending to strbuf b
|
||||
* would cause memory corruption and a likely SIGSEGV.
|
||||
*
|
||||
* If compiled with the GNU C compiler, then the above example would result in
|
||||
* an error at compile time.
|
||||
*
|
||||
* @author Andrew Bettison <andrew@servalproject.com>
|
||||
*/
|
||||
#define strbuf_local_buf(buf) strbuf_local((char*)(buf), sizeof (buf))
|
||||
#ifdef __GNUC__
|
||||
#define strbuf_local_buf(buf) strbuf_local((char*)(buf), (sizeof(buf) == __builtin_object_size(buf, 1)) ? sizeof(buf) : __buffer_arg_is_not_array())
|
||||
#else
|
||||
#define strbuf_local_buf(buf) strbuf_local((char*)(buf), sizeof(buf))
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
// If the following error occurs at compile time or this function is not found
|
||||
// at link time, it means that the argument passed to strbuf_local_buf() was
|
||||
// not an array whose size is known at compile time. The most common cause of
|
||||
// this is passing a pointer as the argument. The solution is to use
|
||||
// strbuf_local(b, len) instead of strbuf_local_buf(b), and supply the length
|
||||
// of the buffer explicitly.
|
||||
size_t __buffer_arg_is_not_array() __attribute__ ((error("argument to strbuf_local_buf() must be an array not a pointer")));
|
||||
#endif
|
||||
|
||||
/** Initialise a strbuf with a caller-supplied backing buffer. The current
|
||||
* backing buffer and its contents are forgotten, and all strbuf operations
|
||||
|
Loading…
Reference in New Issue
Block a user