From 80a7f62ad9c3fabb929e94ebb0745dcb4e42b93a Mon Sep 17 00:00:00 2001 From: Guillaume Nault Date: Wed, 10 Jul 2013 12:54:28 +0200 Subject: memdbg: Handle memory allocation failures Report memory allocation failures in md_alloc() by returning a NULL pointer. Signed-off-by: Guillaume Nault --- accel-pppd/memdebug.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'accel-pppd/memdebug.c') diff --git a/accel-pppd/memdebug.c b/accel-pppd/memdebug.c index 8e9dd4b..5ca7727 100644 --- a/accel-pppd/memdebug.c +++ b/accel-pppd/memdebug.c @@ -25,7 +25,7 @@ (type *)( (char *)__mptr - offsetof(type,member) );}) -#define MAGIC1 0x1122334455667788llu +#define MAGIC1 UINT64_C(0x1122334455667788) struct mem_t { @@ -41,10 +41,13 @@ struct mem_t static LIST_HEAD(mem_list); static spinlock_t mem_list_lock = SPINLOCK_INITIALIZER; -struct mem_t *_md_malloc(size_t size, const char *fname, int line) +static struct mem_t *_md_malloc(size_t size, const char *fname, int line) { struct mem_t *mem = malloc(sizeof(*mem) + size + 8); + if (mem == NULL) + return NULL; + if (size > 4096) line = 0; @@ -66,7 +69,7 @@ void __export *md_malloc(size_t size, const char *fname, int line) { struct mem_t *mem = _md_malloc(size, fname, line); - return mem->data; + return mem ? mem->data : NULL; } void __export md_free(void *ptr, const char *fname, int line) -- cgit v1.2.3 From 6ce3556e0b1e39fe5474114137fde0d29ab093af Mon Sep 17 00:00:00 2001 From: Guillaume Nault Date: Wed, 10 Jul 2013 12:54:35 +0200 Subject: memdbg: Allow NULL pointer as argument to free free(NULL) is a no-op, but beside that it's a valid call which should be supported. Signed-off-by: Guillaume Nault --- accel-pppd/memdebug.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'accel-pppd/memdebug.c') diff --git a/accel-pppd/memdebug.c b/accel-pppd/memdebug.c index 5ca7727..286ddd8 100644 --- a/accel-pppd/memdebug.c +++ b/accel-pppd/memdebug.c @@ -74,20 +74,21 @@ void __export *md_malloc(size_t size, const char *fname, int line) void __export md_free(void *ptr, const char *fname, int line) { - struct mem_t *mem = container_of(ptr, typeof(*mem), data); + struct mem_t *mem; + + if (!ptr) + return; + + mem = container_of(ptr, typeof(*mem), data); - if (!ptr) { - printf("free null pointer at %s:%i\n", fname, line); - abort(); - } - if (mem->magic1 != MAGIC1) { printf("memory corruption:\nfree at %s:%i\n", fname, line); abort(); } if (mem->magic2 != *(uint64_t*)(mem->data + mem->size)) { - printf("memory corruption:\nmalloc(%lu) at %s:%i\nfree at %s:%i\n", (long unsigned)mem->size, mem->fname, mem->line, fname, line); + printf("memory corruption:\nmalloc(%zu) at %s:%i\nfree at %s:%i\n", + mem->size, mem->fname, mem->line, fname, line); abort(); } -- cgit v1.2.3 From 16b4d40a0f52eed4fd7def096a443670eab96b66 Mon Sep 17 00:00:00 2001 From: Guillaume Nault Date: Wed, 10 Jul 2013 12:54:41 +0200 Subject: memdbg: improve md_realloc() compliance with plain realloc() -Allow reallocation of NULL pointers (equivalent to a malloc() call) -Allow 'size' to be 0 (equivalent to a free() call) -Handle case where 'size' is smaller than the original buffer length Signed-off-by: Guillaume Nault --- accel-pppd/memdebug.c | 38 ++++++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 12 deletions(-) (limited to 'accel-pppd/memdebug.c') diff --git a/accel-pppd/memdebug.c b/accel-pppd/memdebug.c index 286ddd8..67c8498 100644 --- a/accel-pppd/memdebug.c +++ b/accel-pppd/memdebug.c @@ -105,23 +105,37 @@ void __export md_free(void *ptr, const char *fname, int line) void __export *md_realloc(void *ptr, size_t size, const char *fname, int line) { - struct mem_t *mem = container_of(ptr, typeof(*mem), data); + struct mem_t *mem = ptr ? container_of(ptr, typeof(*mem), data) : NULL; struct mem_t *mem2; - - if (mem->magic1 != MAGIC1) { - printf("memory corruption:\nfree at %s:%i\n", fname, line); - abort(); - } - if (mem->magic2 != *(uint64_t*)(mem->data + mem->size)) { - printf("memory corruption:\nmalloc(%lu) at %s:%i\nfree at %s:%i\n", (long unsigned)mem->size, mem->fname, mem->line, fname, line); - abort(); + if (mem) { + if (mem->magic1 != MAGIC1) { + printf("memory corruption:\nfree at %s:%i\n", + fname, line); + abort(); + } + + if (mem->magic2 != *(uint64_t*)(mem->data + mem->size)) { + printf("memory corruption:\nmalloc(%zu) at %s:%i\nfree at %s:%i\n", + mem->size, mem->fname, mem->line, fname, line); + abort(); + } + + if (size == 0) { + md_free(mem->data, fname, line); + return NULL; + } } mem2 = _md_malloc(size, fname, line); - memcpy(mem2->data, mem->data, mem->size); - - md_free(mem->data, fname, line); + if (mem2 == NULL) + return NULL; + + if (mem) { + memcpy(mem2->data, mem->data, + (size < mem->size) ? size : mem->size); + md_free(mem->data, fname, line); + } return mem2->data; } -- cgit v1.2.3 From 4925a61bf843462f987def1820a4ad676100d421 Mon Sep 17 00:00:00 2001 From: Guillaume Nault Date: Wed, 10 Jul 2013 12:54:46 +0200 Subject: memdbg: Handle memory allocation failures in strdup() Don't fail if _md_malloc() returns NULL. Signed-off-by: Guillaume Nault --- accel-pppd/memdebug.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'accel-pppd/memdebug.c') diff --git a/accel-pppd/memdebug.c b/accel-pppd/memdebug.c index 67c8498..8c3c494 100644 --- a/accel-pppd/memdebug.c +++ b/accel-pppd/memdebug.c @@ -142,9 +142,13 @@ void __export *md_realloc(void *ptr, size_t size, const char *fname, int line) char __export *md_strdup(const char *ptr, const char *fname, int line) { - struct mem_t *mem = _md_malloc(strlen(ptr) + 1, fname, line); - memcpy(mem->data, ptr, strlen(ptr) + 1); - return mem->data; + size_t len = strlen(ptr); + char *str = md_malloc(len + 1, fname, line); + + if (str) + memcpy(str, ptr, len + 1); + + return str; } char __export *md_strndup(const char *ptr, size_t n, const char *fname, int line) -- cgit v1.2.3 From 09de0ff06ef5ebb3b594a42ca8996f92a854078a Mon Sep 17 00:00:00 2001 From: Guillaume Nault Date: Wed, 10 Jul 2013 12:54:52 +0200 Subject: memdbg: Accept short strings in md_strndup() Don't fail if string to duplicate is shorter than the size parameter and handle memory allocation failure. Signed-off-by: Guillaume Nault --- accel-pppd/memdebug.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'accel-pppd/memdebug.c') diff --git a/accel-pppd/memdebug.c b/accel-pppd/memdebug.c index 8c3c494..5629146 100644 --- a/accel-pppd/memdebug.c +++ b/accel-pppd/memdebug.c @@ -153,10 +153,15 @@ char __export *md_strdup(const char *ptr, const char *fname, int line) char __export *md_strndup(const char *ptr, size_t n, const char *fname, int line) { - struct mem_t *mem = _md_malloc(n + 1, fname, line); - memcpy(mem->data, ptr, n); - mem->data[n] = 0; - return mem->data; + size_t len = strnlen(ptr, n); + char *str = md_malloc(len + 1, fname, line); + + if (str) { + memcpy(str, ptr, len); + str[len] = '\0'; + } + + return str; } static void siginfo(int num) -- cgit v1.2.3 From 36070c83907db169f2e6cd443b216dbbea2e7637 Mon Sep 17 00:00:00 2001 From: Guillaume Nault Date: Wed, 10 Jul 2013 12:54:57 +0200 Subject: memdbg: Implement asprintf() Define md_asprintf() as an equivalent of the GNU libc's asprintf() (with buffer allocated by md_malloc). Signed-off-by: Guillaume Nault --- accel-pppd/memdebug.c | 36 ++++++++++++++++++++++++++++++++++++ accel-pppd/memdebug.h | 4 +++- 2 files changed, 39 insertions(+), 1 deletion(-) (limited to 'accel-pppd/memdebug.c') diff --git a/accel-pppd/memdebug.c b/accel-pppd/memdebug.c index 5629146..1f4af36 100644 --- a/accel-pppd/memdebug.c +++ b/accel-pppd/memdebug.c @@ -1,5 +1,6 @@ #undef MEMDEBUG +#include #include #include #include @@ -164,6 +165,41 @@ char __export *md_strndup(const char *ptr, size_t n, const char *fname, int line return str; } +int __export md_asprintf(const char *fname, int line, + char **strp, const char *fmt, ...) +{ + va_list ap; + va_list aq; + int len; + + va_start(ap, fmt); + va_copy(aq, ap); + + len = vsnprintf(NULL, 0, fmt, ap); + if (len < 0) + goto err; + + *strp = md_malloc(len + 1, fname, line); + if (*strp == NULL) + goto err; + + len = vsnprintf(*strp, len + 1, fmt, aq); + if (len < 0) + goto err_strp; + + va_end(aq); + va_end(ap); + + return len; + +err_strp: + md_free(*strp, fname, line); +err: + va_end(aq); + va_end(ap); + return -1; +} + static void siginfo(int num) { struct mem_t *mem; diff --git a/accel-pppd/memdebug.h b/accel-pppd/memdebug.h index 98e87d0..09978f4 100644 --- a/accel-pppd/memdebug.h +++ b/accel-pppd/memdebug.h @@ -10,12 +10,14 @@ #define _free(ptr) md_free(ptr, __FILE__, __LINE__) #define _strdup(str) md_strdup(str, __FILE__, __LINE__) #define _strndup(str, size) md_strndup(str, size, __FILE__, __LINE__) +#define _asprintf(strp, fmt, ...) md_asprintf(__FILE__, __LINE__, strp, fmt, ##__VA_ARGS__) void *md_malloc(size_t size, const char *fname, int line); void *md_realloc(void *ptr, size_t size, const char *fname, int line); void md_free(void *ptr, const char *fname, int line); char* md_strdup(const char *ptr, const char *fname, int line); char* md_strndup(const char *ptr, size_t size, const char *fname, int line); +int md_asprintf(const char *fname, int line, char **strp, const char *fmt, ...) __attribute__((format(gnu_printf, 4, 5))); void md_check(void *ptr); #else @@ -24,7 +26,7 @@ void md_check(void *ptr); #define _free(ptr) free(ptr) #define _strdup(str) strdup(str) #define _strndup(str, size) strndup(str, size) +#define _asprintf(strp, fmt, ...) asprintf(strp, fmt, ##__VA_ARGS__) #endif #endif - -- cgit v1.2.3