diff options
Diffstat (limited to 'src/cJSON.c')
-rw-r--r-- | src/cJSON.c | 89 |
1 files changed, 72 insertions, 17 deletions
diff --git a/src/cJSON.c b/src/cJSON.c index cf0cb13..9e53012 100644 --- a/src/cJSON.c +++ b/src/cJSON.c @@ -22,7 +22,14 @@ * SPDX-License-Identifier: MIT * * Note that this code has been modified from the original code taken - * from cjson-code-58.zip. + * from cjson-code-58.zip before 2014 (my first local commit was in + * 2014 but I may used the code even earlier). Since 2016 the project + * was revived and moved to https://github.com/DaveGamble/cJSON.git. + * It is now a lot more complex and has substantial changes so that it + * is not possible to merge them directly. In any case we only need a + * simple parser and not a complete library. I have looked through + * the commits and fixed a few things which should apply; I also added + * a few references to the upstream code. Regression test are missing! */ #ifdef HAVE_CONFIG_H @@ -38,20 +45,42 @@ #include <ctype.h> #include <errno.h> +#include <gpg-error.h> + #include "cJSON.h" +/* Only use calloc. */ +#define CALLOC_ONLY 1 + +/* To avoid that a compiler optimizes certain memset calls away, these + macros may be used instead. */ +#define wipememory2(_ptr,_set,_len) do { \ + volatile char *_vptr=(volatile char *)(_ptr); \ + size_t _vlen=(_len); \ + while(_vlen) { *_vptr=(_set); _vptr++; _vlen--; } \ + } while(0) +#define wipememory(_ptr,_len) wipememory2(_ptr,0,_len) + /* We use malloc function wrappers from gpgrt (aka libgpg-error). */ -#if 1 +#if GPGRT_VERSION_NUMBER >= 0x011c00 /* 1.28 */ # include <gpgrt.h> -# define xtrymalloc(a) gpgrt_malloc ((a)) # define xtrycalloc(a,b) gpgrt_calloc ((a), (b)) # define xtrystrdup(a) gpgrt_strdup ((a)) # define xfree(a) gpgrt_free ((a)) -#else -# define xtrymalloc(a) malloc ((a)) +# if CALLOC_ONLY +# define xtrymalloc(a) gpgrt_calloc (1, (a)) +# else +# define xtrymalloc(a) gpgrt_malloc ((a)) +# endif +#else /* Without gpgrt (aka libgpg-error). */ # define xtrycalloc(a,b) calloc ((a), (b)) # define xtrystrdup(a) strdup ((a)) # define xfree(a) free ((a)) +# if CALLOC_ONLY +# define xtrymalloc(a) calloc (1, (a)) +# else +# define xtrymalloc(a) malloc ((a)) +# endif #endif @@ -94,9 +123,15 @@ cJSON_Delete (cJSON * c) if (!(c->type & cJSON_IsReference) && c->child) cJSON_Delete (c->child); if (!(c->type & cJSON_IsReference) && c->valuestring) - xfree (c->valuestring); + { + wipememory (c->valuestring, strlen (c->valuestring)); + xfree (c->valuestring); + } if (c->string) - xfree (c->string); + { + wipememory (c->string, strlen (c->string)); + xfree (c->string); + } xfree (c); c = next; } @@ -232,6 +267,9 @@ parse_string (cJSON * item, const char *str, const char **ep) char *out; int len = 0; unsigned uc, uc2; + + /* FIXME: We should consider eary failure like it is done with + * commit 8656386c4f4a12f1cf3d6b26158407fd05e65029 in upstream. */ if (*str != '\"') { *ep = str; @@ -239,11 +277,13 @@ parse_string (cJSON * item, const char *str, const char **ep) } /* not a string! */ while (*ptr != '\"' && *ptr && ++len) - if (*ptr++ == '\\') + if (*ptr++ == '\\' && *ptr) ptr++; /* Skip escaped quotes. */ - out = xtrymalloc (len + 1); /* This is how long we need for the - string, roughly. */ + out = xtrymalloc (len + 2); /* This is how long we need for the + * string, roughly. We add one extra + * byte in case the last input + * character is a backslash. */ if (!out) return 0; @@ -256,6 +296,8 @@ parse_string (cJSON * item, const char *str, const char **ep) else { ptr++; + if (!*ptr) + break; switch (*ptr) { case 'b': @@ -275,17 +317,22 @@ parse_string (cJSON * item, const char *str, const char **ep) break; case 'u': /* transcode utf16 to utf8. */ uc = parse_hex4 (ptr + 1); + if (!uc) + break; /* Bad hex; continue right after the 'u'. */ ptr += 4; /* get the unicode char. */ - if ((uc >= 0xDC00 && uc <= 0xDFFF) || uc == 0) + if ((uc >= 0xDC00 && uc <= 0xDFFF)) break; /* check for invalid. */ if (uc >= 0xD800 && uc <= 0xDBFF) /* UTF16 surrogate pairs. */ { if (ptr[1] != '\\' || ptr[2] != 'u') break; /* missing second-half of surrogate. */ - uc2 = parse_hex4 (ptr + 3); - ptr += 6; + ptr += 2; + uc2 = parse_hex4 (ptr + 1); + if (!uc2) + break; /* Bad hex; continue right after the 'u'. */ + ptr += 4; if (uc2 < 0xDC00 || uc2 > 0xDFFF) break; /* invalid second-half of surrogate. */ uc = 0x10000 + (((uc & 0x3FF) << 10) | (uc2 & 0x3FF)); @@ -317,6 +364,8 @@ parse_string (cJSON * item, const char *str, const char **ep) ptr2 += len; break; default: + /* Fixme: Should we fail here: See + * https://github.com/DaveGamble/cJSON/issues/10 */ *ptr2++ = *ptr; break; } @@ -929,9 +978,11 @@ create_reference (cJSON * item) void cJSON_AddItemToArray (cJSON * array, cJSON * item) { - cJSON *c = array->child; - if (!item) + cJSON *c; + + if (!item || !array) return; + c = array->child; if (!c) { array->child = item; @@ -1132,6 +1183,8 @@ cJSON_ReplaceItemInObject (cJSON * object, const char *string, i++, c = c->next; if (c) { + /* FIXME: I guess we should free newitem->string here. See + * upstream commit 0d10e279c8b604f71829b5d49d092719f4ae96b6. */ newitem->string = xtrystrdup (string); cJSON_ReplaceItemInArray (object, i, newitem); } @@ -1393,9 +1446,11 @@ cJSON_Minify (char *json) { if (*json == '\\') *into++ = *json++; - *into++ = *json++; + if (*json) + *into++ = *json++; } - *into++ = *json++; + if (*json) + *into++ = *json++; } /* String literals, which are \" sensitive. */ else *into++ = *json++; /* All other characters. */ |