summaryrefslogtreecommitdiff
path: root/src/cJSON.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cJSON.c')
-rw-r--r--src/cJSON.c89
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. */