From e709651a20f3b32c5cca9e3ca29c6b0b43bbb4d8 Mon Sep 17 00:00:00 2001 From: goriy Date: Sat, 24 Oct 2015 23:32:51 +0300 Subject: [PATCH 1/2] small fix of jsondump example for cases of realloc failures When realloc() function fails it returns NULL pointer. But old data pointer remains valid in such a case. It's a mistake to use old data pointer to store new pointer returned by realloc. In case of realloc failure, pointer is overwritten with NULL value, but old used memory remains unreferenced and could not be even freed anymore. Such mistakes could lead to memory leaks. --- example/jsondump.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/example/jsondump.c b/example/jsondump.c index 3490bbf..a5b5972 100644 --- a/example/jsondump.c +++ b/example/jsondump.c @@ -48,7 +48,7 @@ static int dump(const char *js, jsmntok_t *t, size_t count, int indent) { int main() { int r; int eof_expected = 0; - char *js = NULL; + char *tmp, *js = NULL; size_t jslen = 0; char buf[BUFSIZ]; @@ -82,11 +82,13 @@ int main() { } } - js = realloc(js, jslen + r + 1); - if (js == NULL) { + tmp = realloc(js, jslen + r + 1); + if (tmp == NULL) { + free (js); fprintf(stderr, "realloc(): errno=%d\n", errno); return 3; } + js = tmp; strncpy(js + jslen, buf, r); jslen = jslen + r; @@ -94,12 +96,16 @@ again: r = jsmn_parse(&p, js, jslen, tok, tokcount); if (r < 0) { if (r == JSMN_ERROR_NOMEM) { + jsmntok_t *tmptok; + tokcount = tokcount * 2; - tok = realloc(tok, sizeof(*tok) * tokcount); - if (tok == NULL) { + tmptok = realloc(tok, sizeof(*tok) * tokcount); + if (tmptok == NULL) { + free (tok); fprintf(stderr, "realloc(): errno=%d\n", errno); return 3; } + tok = tmptok; goto again; } } else { From 2d185aa465782ba30bfaea5ccd39cea4917e69a8 Mon Sep 17 00:00:00 2001 From: goriy Date: Sun, 25 Oct 2015 23:28:19 +0300 Subject: [PATCH 2/2] tiny realloc function wrapper which handles cases of realloc failures Memory reallocation with old data pointer handling is done by means of realloc_it() function. Tiny inline function realloc_it() is a wrapper function for standart realloc() which frees old memory pointer and prints errno to stderr if realloc fails. --- example/jsondump.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/example/jsondump.c b/example/jsondump.c index a5b5972..7be6287 100644 --- a/example/jsondump.c +++ b/example/jsondump.c @@ -4,6 +4,21 @@ #include #include "../jsmn.h" +/* Function realloc_it() is a wrapper function for standart realloc() + * with one difference - it frees old memory pointer in case of realloc + * failure. Thus, DO NOT use old data pointer in anyway after call to + * realloc_it(). If your code has some kind of fallback algorithm if + * memory can't be re-allocated - use standart realloc() instead. + */ +static inline void *realloc_it(void *ptrmem, size_t size) { + void *p = realloc(ptrmem, size); + if (!p) { + free (ptrmem); + fprintf(stderr, "realloc(): errno=%d\n", errno); + } + return p; +} + /* * An example of reading JSON from stdin and printing its content to stdout. * The output looks like YAML, but I'm not sure if it's really compatible. @@ -48,7 +63,7 @@ static int dump(const char *js, jsmntok_t *t, size_t count, int indent) { int main() { int r; int eof_expected = 0; - char *tmp, *js = NULL; + char *js = NULL; size_t jslen = 0; char buf[BUFSIZ]; @@ -82,13 +97,10 @@ int main() { } } - tmp = realloc(js, jslen + r + 1); - if (tmp == NULL) { - free (js); - fprintf(stderr, "realloc(): errno=%d\n", errno); + js = realloc_it(js, jslen + r + 1); + if (js == NULL) { return 3; } - js = tmp; strncpy(js + jslen, buf, r); jslen = jslen + r; @@ -96,16 +108,11 @@ again: r = jsmn_parse(&p, js, jslen, tok, tokcount); if (r < 0) { if (r == JSMN_ERROR_NOMEM) { - jsmntok_t *tmptok; - tokcount = tokcount * 2; - tmptok = realloc(tok, sizeof(*tok) * tokcount); - if (tmptok == NULL) { - free (tok); - fprintf(stderr, "realloc(): errno=%d\n", errno); + tok = realloc_it(tok, sizeof(*tok) * tokcount); + if (tok == NULL) { return 3; } - tok = tmptok; goto again; } } else {