cJSON

mirror of Dave's cJSON
git clone git://git.thc420.xyz/cJSON
Log | Files | Refs | README | LICENSE

commit 4d9563900172ef828cf08923c7a41011b3e5e519
parent 981f59b1638ee7f23c382c3cd94643f06609289c
Author: Max Bruckner <max@maxbruckner.de>
Date:   Fri,  3 Feb 2017 19:43:11 +0100

Merge pull request #98 from DaveGamble/compiler-options

More compiler flags + correctness improvements
Diffstat:
MCMakeLists.txt | 2+-
MMakefile | 2+-
McJSON.c | 485++++++++++++++++++++++++++++++++++++++++++++++++-------------------------------
McJSON_Utils.c | 146+++++++++++++++++++++++++++++++++++++++++--------------------------------------
Mtest.c | 8++++----
5 files changed, 378 insertions(+), 265 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt @@ -15,7 +15,7 @@ set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT option(ENABLE_CUSTOM_COMPILER_FLAGS "Enables custom compiler flags for Clang and GCC" ON) if (ENABLE_CUSTOM_COMPILER_FLAGS) if(("${CMAKE_C_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_C_COMPILER_ID}" MATCHES "Clang")) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c89 -pedantic -Wall -Wextra -Werror -Wstrict-prototypes -Wwrite-strings -Wshadow -Winit-self -Wcast-align -Wformat=2 -Wmissing-prototypes -Wstrict-overflow=2 -Wcast-qual -Wc++-compat") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c89 -pedantic -Wall -Wextra -Werror -Wstrict-prototypes -Wwrite-strings -Wshadow -Winit-self -Wcast-align -Wformat=2 -Wmissing-prototypes -Wstrict-overflow=2 -Wcast-qual -Wc++-compat -Wundef -Wswitch-default -Wconversion") endif() endif() diff --git a/Makefile b/Makefile @@ -23,7 +23,7 @@ INSTALL_LIBRARY_PATH = $(DESTDIR)$(PREFIX)/$(LIBRARY_PATH) INSTALL ?= cp -a -R_CFLAGS = -fPIC -std=c89 -pedantic -Wall -Werror -Wstrict-prototypes -Wwrite-strings -Wshadow -Winit-self -Wcast-align -Wformat=2 -Wmissing-prototypes -Wstrict-overflow=2 -Wcast-qual -Wc++-compat $(CFLAGS) +R_CFLAGS = -fPIC -std=c89 -pedantic -Wall -Werror -Wstrict-prototypes -Wwrite-strings -Wshadow -Winit-self -Wcast-align -Wformat=2 -Wmissing-prototypes -Wstrict-overflow=2 -Wcast-qual -Wc++-compat -Wundef -Wswitch-default -Wconversion $(CFLAGS) uname := $(shell sh -c 'uname -s 2>/dev/null || echo false') diff --git a/cJSON.c b/cJSON.c @@ -51,11 +51,11 @@ typedef int cjbool; #define true ((cjbool)1) #define false ((cjbool)0) -static const char *global_ep = NULL; +static const unsigned char *global_ep = NULL; const char *cJSON_GetErrorPtr(void) { - return global_ep; + return (const char*) global_ep; } extern const char* cJSON_Version(void) @@ -67,7 +67,7 @@ extern const char* cJSON_Version(void) } /* case insensitive strcmp */ -static int cJSON_strcasecmp(const char *s1, const char *s2) +static int cJSON_strcasecmp(const unsigned char *s1, const unsigned char *s2) { if (!s1) { @@ -77,7 +77,7 @@ static int cJSON_strcasecmp(const char *s1, const char *s2) { return 1; } - for(; tolower(*(const unsigned char *)s1) == tolower(*(const unsigned char *)s2); ++s1, ++s2) + for(; tolower(*s1) == tolower(*s2); ++s1, ++s2) { if (*s1 == '\0') { @@ -85,24 +85,24 @@ static int cJSON_strcasecmp(const char *s1, const char *s2) } } - return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2); + return tolower(*s1) - tolower(*s2); } static void *(*cJSON_malloc)(size_t sz) = malloc; static void (*cJSON_free)(void *ptr) = free; -static char* cJSON_strdup(const char* str) +static unsigned char* cJSON_strdup(const unsigned char* str) { size_t len = 0; - char *copy = NULL; + unsigned char *copy = NULL; if (str == NULL) { return NULL; } - len = strlen(str) + 1; - if (!(copy = (char*)cJSON_malloc(len))) + len = strlen((const char*)str) + 1; + if (!(copy = (unsigned char*)cJSON_malloc(len))) { return NULL; } @@ -162,7 +162,7 @@ void cJSON_Delete(cJSON *c) } /* Parse the input text to generate a number, and populate the result into item. */ -static const char *parse_number(cJSON *item, const char *num) +static const unsigned char *parse_number(cJSON *item, const unsigned char *num) { double n = 0; double sign = 1; @@ -225,7 +225,19 @@ static const char *parse_number(cJSON *item, const char *num) n = sign * n * pow(10.0, (scale + subscale * signsubscale)); item->valuedouble = n; - item->valueint = (int)n; + /* use saturation in case of overflow */ + if (n >= INT_MAX) + { + item->valueint = INT_MAX; + } + else if (n <= INT_MIN) + { + item->valueint = INT_MIN; + } + else + { + item->valueint = (int)n; + } item->type = cJSON_Number; return num; @@ -245,7 +257,7 @@ static int pow2gt (int x) #if INTEGER_SIZE & 0x1100 /* at least 32 bit */ x |= x >> 16; #endif -#if INT_SIZE & 0x1000 /* 64 bit */ +#if INTEGER_SIZE & 0x1000 /* 64 bit */ x |= x >> 32; #endif @@ -254,17 +266,24 @@ static int pow2gt (int x) typedef struct { - char *buffer; - int length; - int offset; + unsigned char *buffer; + size_t length; + size_t offset; cjbool noalloc; } printbuffer; /* realloc printbuffer if necessary to have at least "needed" bytes more */ -static char* ensure(printbuffer *p, int needed) +static unsigned char* ensure(printbuffer *p, size_t needed) { - char *newbuffer = NULL; - int newsize = 0; + unsigned char *newbuffer = NULL; + size_t newsize = 0; + + if (needed > INT_MAX) + { + /* sizes bigger than INT_MAX are currently not supported */ + return NULL; + } + if (!p || !p->buffer) { return NULL; @@ -279,8 +298,8 @@ static char* ensure(printbuffer *p, int needed) return NULL; } - newsize = pow2gt(needed); - newbuffer = (char*)cJSON_malloc(newsize); + newsize = (size_t) pow2gt((int)needed); + newbuffer = (unsigned char*)cJSON_malloc(newsize); if (!newbuffer) { cJSON_free(p->buffer); @@ -301,22 +320,22 @@ static char* ensure(printbuffer *p, int needed) } /* calculate the new length of the string in a printbuffer */ -static int update(const printbuffer *p) +static size_t update(const printbuffer *p) { - char *str = NULL; + unsigned char *str = NULL; if (!p || !p->buffer) { return 0; } str = p->buffer + p->offset; - return p->offset + strlen(str); + return p->offset + strlen((char*)str); } /* Render the number nicely from the given item into a string. */ -static char *print_number(const cJSON *item, printbuffer *p) +static unsigned char *print_number(const cJSON *item, printbuffer *p) { - char *str = NULL; + unsigned char *str = NULL; double d = item->valuedouble; /* special case for 0. */ if (d == 0) @@ -327,11 +346,11 @@ static char *print_number(const cJSON *item, printbuffer *p) } else { - str = (char*)cJSON_malloc(2); + str = (unsigned char*)cJSON_malloc(2); } if (str) { - strcpy(str,"0"); + strcpy((char*)str,"0"); } } /* value is an int */ @@ -344,11 +363,11 @@ static char *print_number(const cJSON *item, printbuffer *p) else { /* 2^64+1 can be represented in 21 chars. */ - str = (char*)cJSON_malloc(21); + str = (unsigned char*)cJSON_malloc(21); } if (str) { - sprintf(str, "%d", item->valueint); + sprintf((char*)str, "%d", item->valueint); } } /* value is a floating point number */ @@ -362,26 +381,26 @@ static char *print_number(const cJSON *item, printbuffer *p) else { /* This is a nice tradeoff. */ - str=(char*)cJSON_malloc(64); + str = (unsigned char*)cJSON_malloc(64); } if (str) { /* This checks for NaN and Infinity */ if ((d * 0) != 0) { - sprintf(str, "null"); + sprintf((char*)str, "null"); } else if ((fabs(floor(d) - d) <= DBL_EPSILON) && (fabs(d) < 1.0e60)) { - sprintf(str, "%.0f", d); + sprintf((char*)str, "%.0f", d); } else if ((fabs(d) < 1.0e-6) || (fabs(d) > 1.0e9)) { - sprintf(str, "%e", d); + sprintf((char*)str, "%e", d); } else { - sprintf(str, "%f", d); + sprintf((char*)str, "%f", d); } } } @@ -389,21 +408,22 @@ static char *print_number(const cJSON *item, printbuffer *p) } /* parse 4 digit hexadecimal number */ -static unsigned parse_hex4(const char *str) +static unsigned parse_hex4(const unsigned char *str) { - unsigned h = 0; + unsigned int h = 0; + /* first digit */ if ((*str >= '0') && (*str <= '9')) { - h += (*str) - '0'; + h += (unsigned int) (*str) - '0'; } else if ((*str >= 'A') && (*str <= 'F')) { - h += 10 + (*str) - 'A'; + h += (unsigned int) 10 + (*str) - 'A'; } else if ((*str >= 'a') && (*str <= 'f')) { - h += 10 + (*str) - 'a'; + h += (unsigned int) 10 + (*str) - 'a'; } else /* invalid */ { @@ -416,15 +436,15 @@ static unsigned parse_hex4(const char *str) str++; if ((*str >= '0') && (*str <= '9')) { - h += (*str) - '0'; + h += (unsigned int) (*str) - '0'; } else if ((*str >= 'A') && (*str <= 'F')) { - h += 10 + (*str) - 'A'; + h += (unsigned int) 10 + (*str) - 'A'; } else if ((*str >= 'a') && (*str <= 'f')) { - h += 10 + (*str) - 'a'; + h += (unsigned int) 10 + (*str) - 'a'; } else /* invalid */ { @@ -436,15 +456,15 @@ static unsigned parse_hex4(const char *str) str++; if ((*str >= '0') && (*str <= '9')) { - h += (*str) - '0'; + h += (unsigned int) (*str) - '0'; } else if ((*str >= 'A') && (*str <= 'F')) { - h += 10 + (*str) - 'A'; + h += (unsigned int) 10 + (*str) - 'A'; } else if ((*str >= 'a') && (*str <= 'f')) { - h += 10 + (*str) - 'a'; + h += (unsigned int) 10 + (*str) - 'a'; } else /* invalid */ { @@ -456,15 +476,15 @@ static unsigned parse_hex4(const char *str) str++; if ((*str >= '0') && (*str <= '9')) { - h += (*str) - '0'; + h += (unsigned int) (*str) - '0'; } else if ((*str >= 'A') && (*str <= 'F')) { - h += 10 + (*str) - 'A'; + h += (unsigned int) 10 + (*str) - 'A'; } else if ((*str >= 'a') && (*str <= 'f')) { - h += 10 + (*str) - 'a'; + h += (unsigned int) 10 + (*str) - 'a'; } else /* invalid */ { @@ -487,13 +507,13 @@ static const unsigned char firstByteMark[7] = }; /* Parse the input text into an unescaped cstring, and populate item. */ -static const char *parse_string(cJSON *item, const char *str, const char **ep) +static const unsigned char *parse_string(cJSON *item, const unsigned char *str, const unsigned char **ep) { - const char *ptr = str + 1; - const char *end_ptr =str + 1; - char *ptr2 = NULL; - char *out = NULL; - int len = 0; + const unsigned char *ptr = str + 1; + const unsigned char *end_ptr =str + 1; + unsigned char *ptr2 = NULL; + unsigned char *out = NULL; + size_t len = 0; unsigned uc = 0; unsigned uc2 = 0; @@ -520,12 +540,12 @@ static const char *parse_string(cJSON *item, const char *str, const char **ep) } /* This is at most how long we need for the string, roughly. */ - out = (char*)cJSON_malloc(len + 1); + out = (unsigned char*)cJSON_malloc(len + 1); if (!out) { return NULL; } - item->valuestring = out; /* assign here so out will be deleted during cJSON_Delete() later */ + item->valuestring = (char*)out; /* assign here so out will be deleted during cJSON_Delete() later */ item->type = cJSON_String; ptr = str + 1; @@ -631,20 +651,23 @@ static const char *parse_string(cJSON *item, const char *str, const char **ep) switch (len) { case 4: /* 10xxxxxx */ - *--ptr2 = ((uc | 0x80) & 0xBF); + *--ptr2 = (unsigned char)((uc | 0x80) & 0xBF); uc >>= 6; case 3: /* 10xxxxxx */ - *--ptr2 = ((uc | 0x80) & 0xBF); + *--ptr2 = (unsigned char)((uc | 0x80) & 0xBF); uc >>= 6; case 2: /* 10xxxxxx */ - *--ptr2 = ((uc | 0x80) & 0xBF); + *--ptr2 = (unsigned char)((uc | 0x80) & 0xBF); uc >>= 6; case 1: /* depending on the length in bytes this determines the * encoding ofthe first UTF8 byte */ - *--ptr2 = (uc | firstByteMark[len]); + *--ptr2 = (unsigned char)((uc | firstByteMark[len]) & 0xFF); + default: + *ep = str; + return NULL; } ptr2 += len; break; @@ -665,12 +688,12 @@ static const char *parse_string(cJSON *item, const char *str, const char **ep) } /* Render the cstring provided to an escaped version that can be printed. */ -static char *print_string_ptr(const char *str, printbuffer *p) +static unsigned char *print_string_ptr(const unsigned char *str, printbuffer *p) { - const char *ptr = NULL; - char *ptr2 = NULL; - char *out = NULL; - int len = 0; + const unsigned char *ptr = NULL; + unsigned char *ptr2 = NULL; + unsigned char *out = NULL; + size_t len = 0; cjbool flag = false; unsigned char token = '\0'; @@ -683,13 +706,13 @@ static char *print_string_ptr(const char *str, printbuffer *p) } else { - out = (char*)cJSON_malloc(3); + out = (unsigned char*)cJSON_malloc(3); } if (!out) { return NULL; } - strcpy(out, "\"\""); + strcpy((char*)out, "\"\""); return out; } @@ -706,14 +729,14 @@ static char *print_string_ptr(const char *str, printbuffer *p) /* no characters have to be escaped */ if (!flag) { - len = ptr - str; + len = (size_t)(ptr - str); if (p) { out = ensure(p, len + 3); } else { - out = (char*)cJSON_malloc(len + 3); + out = (unsigned char*)cJSON_malloc(len + 3); } if (!out) { @@ -722,7 +745,7 @@ static char *print_string_ptr(const char *str, printbuffer *p) ptr2 = out; *ptr2++ = '\"'; - strcpy(ptr2, str); + strcpy((char*)ptr2, (const char*)str); ptr2[len] = '\"'; ptr2[len + 1] = '\0'; @@ -751,7 +774,7 @@ static char *print_string_ptr(const char *str, printbuffer *p) } else { - out = (char*)cJSON_malloc(len + 3); + out = (unsigned char*)cJSON_malloc(len + 3); } if (!out) { @@ -764,7 +787,7 @@ static char *print_string_ptr(const char *str, printbuffer *p) /* copy the string */ while (*ptr) { - if (((unsigned char)*ptr > 31) && (*ptr != '\"') && (*ptr != '\\')) + if ((*ptr > 31) && (*ptr != '\"') && (*ptr != '\\')) { /* normal character, copy */ *ptr2++ = *ptr++; @@ -798,7 +821,7 @@ static char *print_string_ptr(const char *str, printbuffer *p) break; default: /* escape and print as unicode codepoint */ - sprintf(ptr2, "u%04x", token); + sprintf((char*)ptr2, "u%04x", token); ptr2 += 5; break; } @@ -811,23 +834,23 @@ static char *print_string_ptr(const char *str, printbuffer *p) } /* Invoke print_string_ptr (which is useful) on an item. */ -static char *print_string(const cJSON *item, printbuffer *p) +static unsigned char *print_string(const cJSON *item, printbuffer *p) { - return print_string_ptr(item->valuestring, p); + return print_string_ptr((unsigned char*)item->valuestring, p); } /* Predeclare these prototypes. */ -static const char *parse_value(cJSON *item, const char *value, const char **ep); -static char *print_value(const cJSON *item, int depth, cjbool fmt, printbuffer *p); -static const char *parse_array(cJSON *item, const char *value, const char **ep); -static char *print_array(const cJSON *item, int depth, cjbool fmt, printbuffer *p); -static const char *parse_object(cJSON *item, const char *value, const char **ep); -static char *print_object(const cJSON *item, int depth, cjbool fmt, printbuffer *p); +static const unsigned char *parse_value(cJSON *item, const unsigned char *value, const unsigned char **ep); +static unsigned char *print_value(const cJSON *item, size_t depth, cjbool fmt, printbuffer *p); +static const unsigned char *parse_array(cJSON *item, const unsigned char *value, const unsigned char **ep); +static unsigned char *print_array(const cJSON *item, size_t depth, cjbool fmt, printbuffer *p); +static const unsigned char *parse_object(cJSON *item, const unsigned char *value, const unsigned char **ep); +static unsigned char *print_object(const cJSON *item, size_t depth, cjbool fmt, printbuffer *p); /* Utility to jump whitespace and cr/lf */ -static const char *skip(const char *in) +static const unsigned char *skip(const unsigned char *in) { - while (in && *in && ((unsigned char)*in<=32)) + while (in && *in && (*in <= 32)) { in++; } @@ -838,9 +861,9 @@ static const char *skip(const char *in) /* Parse an object - create a new root, and populate. */ cJSON *cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cjbool require_null_terminated) { - const char *end = NULL; + const unsigned char *end = NULL; /* use global error pointer if no specific one was given */ - const char **ep = return_parse_end ? return_parse_end : &global_ep; + const unsigned char **ep = return_parse_end ? (const unsigned char**)return_parse_end : &global_ep; cJSON *c = cJSON_New_Item(); *ep = NULL; if (!c) /* memory fail */ @@ -848,7 +871,7 @@ cJSON *cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cjb return NULL; } - end = parse_value(c, skip(value), ep); + end = parse_value(c, skip((const unsigned char*)value), ep); if (!end) { /* parse failure. ep is set. */ @@ -869,7 +892,7 @@ cJSON *cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cjb } if (return_parse_end) { - *return_parse_end = end; + *return_parse_end = (const char*)end; } return c; @@ -884,41 +907,54 @@ cJSON *cJSON_Parse(const char *value) /* Render a cJSON item/entity/structure to text. */ char *cJSON_Print(const cJSON *item) { - return print_value(item, 0, 1, 0); + return (char*)print_value(item, 0, 1, 0); } char *cJSON_PrintUnformatted(const cJSON *item) { - return print_value(item, 0, 0, 0); + return (char*)print_value(item, 0, 0, 0); } char *cJSON_PrintBuffered(const cJSON *item, int prebuffer, cjbool fmt) { printbuffer p; - p.buffer = (char*)cJSON_malloc(prebuffer); + + if (prebuffer < 0) + { + return false; + } + + p.buffer = (unsigned char*)cJSON_malloc((size_t)prebuffer); if (!p.buffer) { return NULL; } - p.length = prebuffer; + + p.length = (size_t)prebuffer; p.offset = 0; p.noalloc = false; - return print_value(item, 0, fmt, &p); + return (char*)print_value(item, 0, fmt, &p); } -int cJSON_PrintPreallocated(cJSON *item,char *buf, const int len, const cjbool fmt) +int cJSON_PrintPreallocated(cJSON *item, char *buf, const int len, const cjbool fmt) { printbuffer p; - p.buffer = buf; - p.length = len; + + if (len < 0) + { + return false; + } + + p.buffer = (unsigned char*)buf; + p.length = (size_t)len; p.offset = 0; p.noalloc = true; - return print_value(item,0,fmt,&p) != NULL; + return print_value(item, 0, fmt, &p) != NULL; } /* Parser core - when encountering text, process appropriately. */ -static const char *parse_value(cJSON *item, const char *value, const char **ep) +static const unsigned char *parse_value(cJSON *item, const unsigned char *value, const unsigned char **ep) { if (!value) { @@ -927,17 +963,17 @@ static const char *parse_value(cJSON *item, const char *value, const char **ep) } /* parse the different types of values */ - if (!strncmp(value, "null", 4)) + if (!strncmp((const char*)value, "null", 4)) { item->type = cJSON_NULL; return value + 4; } - if (!strncmp(value, "false", 5)) + if (!strncmp((const char*)value, "false", 5)) { item->type = cJSON_False; return value + 5; } - if (!strncmp(value, "true", 4)) + if (!strncmp((const char*)value, "true", 4)) { item->type = cJSON_True; item->valueint = 1; @@ -966,9 +1002,9 @@ static const char *parse_value(cJSON *item, const char *value, const char **ep) } /* Render a value to text. */ -static char *print_value(const cJSON *item, int depth, cjbool fmt, printbuffer *p) +static unsigned char *print_value(const cJSON *item, size_t depth, cjbool fmt, printbuffer *p) { - char *out = NULL; + unsigned char *out = NULL; if (!item) { @@ -982,21 +1018,21 @@ static char *print_value(const cJSON *item, int depth, cjbool fmt, printbuffer * out = ensure(p, 5); if (out) { - strcpy(out, "null"); + strcpy((char*)out, "null"); } break; case cJSON_False: out = ensure(p, 6); if (out) { - strcpy(out, "false"); + strcpy((char*)out, "false"); } break; case cJSON_True: out = ensure(p, 5); if (out) { - strcpy(out, "true"); + strcpy((char*)out, "true"); } break; case cJSON_Number: @@ -1032,6 +1068,9 @@ static char *print_value(const cJSON *item, int depth, cjbool fmt, printbuffer * case cJSON_Object: out = print_object(item, depth, fmt, p); break; + default: + out = NULL; + break; } } else @@ -1039,19 +1078,19 @@ static char *print_value(const cJSON *item, int depth, cjbool fmt, printbuffer * switch ((item->type) & 0xFF) { case cJSON_NULL: - out = cJSON_strdup("null"); + out = cJSON_strdup((const unsigned char*)"null"); break; case cJSON_False: - out = cJSON_strdup("false"); + out = cJSON_strdup((const unsigned char*)"false"); break; case cJSON_True: - out = cJSON_strdup("true"); + out = cJSON_strdup((const unsigned char*)"true"); break; case cJSON_Number: out = print_number(item, 0); break; case cJSON_Raw: - out = cJSON_strdup(item->valuestring); + out = cJSON_strdup((unsigned char*)item->valuestring); break; case cJSON_String: out = print_string(item, 0); @@ -1062,6 +1101,9 @@ static char *print_value(const cJSON *item, int depth, cjbool fmt, printbuffer * case cJSON_Object: out = print_object(item, depth, fmt, 0); break; + default: + out = NULL; + break; } } @@ -1069,7 +1111,7 @@ static char *print_value(const cJSON *item, int depth, cjbool fmt, printbuffer * } /* Build an array from input text. */ -static const char *parse_array(cJSON *item,const char *value,const char **ep) +static const unsigned char *parse_array(cJSON *item, const unsigned char *value, const unsigned char **ep) { cJSON *child = NULL; if (*value != '[') @@ -1136,16 +1178,16 @@ static const char *parse_array(cJSON *item,const char *value,const char **ep) } /* Render an array to text */ -static char *print_array(const cJSON *item, int depth, cjbool fmt, printbuffer *p) +static unsigned char *print_array(const cJSON *item, size_t depth, cjbool fmt, printbuffer *p) { - char **entries; - char *out = NULL; - char *ptr = NULL; - char *ret = NULL; - int len = 5; + unsigned char **entries; + unsigned char *out = NULL; + unsigned char *ptr = NULL; + unsigned char *ret = NULL; + size_t len = 5; cJSON *child = item->child; - int numentries = 0; - int i = 0; + size_t numentries = 0; + size_t i = 0; cjbool fail = false; size_t tmplen = 0; @@ -1165,11 +1207,11 @@ static char *print_array(const cJSON *item, int depth, cjbool fmt, printbuffer * } else { - out = (char*)cJSON_malloc(3); + out = (unsigned char*)cJSON_malloc(3); } if (out) { - strcpy(out,"[]"); + strcpy((char*)out, "[]"); } return out; @@ -1226,12 +1268,12 @@ static char *print_array(const cJSON *item, int depth, cjbool fmt, printbuffer * else { /* Allocate an array to hold the pointers to all printed values */ - entries = (char**)cJSON_malloc(numentries * sizeof(char*)); + entries = (unsigned char**)cJSON_malloc(numentries * sizeof(unsigned char*)); if (!entries) { return NULL; } - memset(entries, '\0', numentries * sizeof(char*)); + memset(entries, '\0', numentries * sizeof(unsigned char*)); /* Retrieve all the results: */ child = item->child; @@ -1241,7 +1283,7 @@ static char *print_array(const cJSON *item, int depth, cjbool fmt, printbuffer * entries[i++] = ret; if (ret) { - len += strlen(ret) + 2 + (fmt ? 1 : 0); + len += strlen((char*)ret) + 2 + (fmt ? 1 : 0); } else { @@ -1253,7 +1295,7 @@ static char *print_array(const cJSON *item, int depth, cjbool fmt, printbuffer * /* If we didn't fail, try to malloc the output string */ if (!fail) { - out = (char*)cJSON_malloc(len); + out = (unsigned char*)cJSON_malloc(len); } /* If that fails, we fail. */ if (!out) @@ -1282,7 +1324,7 @@ static char *print_array(const cJSON *item, int depth, cjbool fmt, printbuffer * *ptr = '\0'; for (i = 0; i < numentries; i++) { - tmplen = strlen(entries[i]); + tmplen = strlen((char*)entries[i]); memcpy(ptr, entries[i], tmplen); ptr += tmplen; if (i != (numentries - 1)) @@ -1305,7 +1347,7 @@ static char *print_array(const cJSON *item, int depth, cjbool fmt, printbuffer * } /* Build an object from the text. */ -static const char *parse_object(cJSON *item, const char *value, const char **ep) +static const unsigned char *parse_object(cJSON *item, const unsigned char *value, const unsigned char **ep) { cJSON *child = NULL; if (*value != '{') @@ -1400,19 +1442,19 @@ static const char *parse_object(cJSON *item, const char *value, const char **ep) } /* Render an object to text. */ -static char *print_object(const cJSON *item, int depth, cjbool fmt, printbuffer *p) -{ - char **entries = NULL; - char **names = NULL; - char *out = NULL; - char *ptr = NULL; - char *ret = NULL; - char *str = NULL; - int len = 7; - int i = 0; - int j = 0; +static unsigned char *print_object(const cJSON *item, size_t depth, cjbool fmt, printbuffer *p) +{ + unsigned char **entries = NULL; + unsigned char **names = NULL; + unsigned char *out = NULL; + unsigned char *ptr = NULL; + unsigned char *ret = NULL; + unsigned char *str = NULL; + size_t len = 7; + size_t i = 0; + size_t j = 0; cJSON *child = item->child; - int numentries = 0; + size_t numentries = 0; cjbool fail = false; size_t tmplen = 0; @@ -1432,7 +1474,7 @@ static char *print_object(const cJSON *item, int depth, cjbool fmt, printbuffer } else { - out = (char*)cJSON_malloc(fmt ? depth + 4 : 3); + out = (unsigned char*)cJSON_malloc(fmt ? depth + 4 : 3); } if (!out) { @@ -1491,7 +1533,7 @@ static char *print_object(const cJSON *item, int depth, cjbool fmt, printbuffer } /* print key */ - if (!print_string_ptr(child->string, p)) + if (!print_string_ptr((unsigned char*)child->string, p)) { return NULL; } @@ -1518,7 +1560,7 @@ static char *print_object(const cJSON *item, int depth, cjbool fmt, printbuffer p->offset = update(p); /* print comma if not last */ - len = (fmt ? 1 : 0) + (child->next ? 1 : 0); + len = (size_t) (fmt ? 1 : 0) + (child->next ? 1 : 0); ptr = ensure(p, len + 1); if (!ptr) { @@ -1558,19 +1600,19 @@ static char *print_object(const cJSON *item, int depth, cjbool fmt, printbuffer else { /* Allocate space for the names and the objects */ - entries = (char**)cJSON_malloc(numentries * sizeof(char*)); + entries = (unsigned char**)cJSON_malloc(numentries * sizeof(unsigned char*)); if (!entries) { return NULL; } - names = (char**)cJSON_malloc(numentries * sizeof(char*)); + names = (unsigned char**)cJSON_malloc(numentries * sizeof(unsigned char*)); if (!names) { cJSON_free(entries); return NULL; } - memset(entries, '\0', sizeof(char*) * numentries); - memset(names, '\0', sizeof(char*) * numentries); + memset(entries, '\0', sizeof(unsigned char*) * numentries); + memset(names, '\0', sizeof(unsigned char*) * numentries); /* Collect all the results into our arrays: */ child = item->child; @@ -1581,11 +1623,11 @@ static char *print_object(const cJSON *item, int depth, cjbool fmt, printbuffer } while (child && !fail) { - names[i] = str = print_string_ptr(child->string, 0); /* print key */ + names[i] = str = print_string_ptr((unsigned char*)child->string, 0); /* print key */ entries[i++] = ret = print_value(child, depth, fmt, 0); if (str && ret) { - len += strlen(ret) + strlen(str) + 2 + (fmt ? 2 + depth : 0); + len += strlen((char*)ret) + strlen((char*)str) + 2 + (fmt ? 2 + depth : 0); } else { @@ -1597,7 +1639,7 @@ static char *print_object(const cJSON *item, int depth, cjbool fmt, printbuffer /* Try to allocate the output string */ if (!fail) { - out = (char*)cJSON_malloc(len); + out = (unsigned char*)cJSON_malloc(len); } if (!out) { @@ -1641,7 +1683,7 @@ static char *print_object(const cJSON *item, int depth, cjbool fmt, printbuffer *ptr++='\t'; } } - tmplen = strlen(names[i]); + tmplen = strlen((char*)names[i]); memcpy(ptr, names[i], tmplen); ptr += tmplen; *ptr++ = ':'; @@ -1649,8 +1691,8 @@ static char *print_object(const cJSON *item, int depth, cjbool fmt, printbuffer { *ptr++ = '\t'; } - strcpy(ptr, entries[i]); - ptr += strlen(entries[i]); + strcpy((char*)ptr, (char*)entries[i]); + ptr += strlen((char*)entries[i]); if (i != (numentries - 1)) { *ptr++ = ','; @@ -1681,16 +1723,19 @@ static char *print_object(const cJSON *item, int depth, cjbool fmt, printbuffer } /* Get Array size/item / object item. */ -int cJSON_GetArraySize(const cJSON *array) +int cJSON_GetArraySize(const cJSON *array) { cJSON *c = array->child; - int i = 0; + size_t i = 0; while(c) { i++; c = c->next; } - return i; + + /* FIXME: Can overflow here. Cannot be fixed without breaking the API */ + + return (int)i; } cJSON *cJSON_GetArrayItem(const cJSON *array, int item) @@ -1708,14 +1753,14 @@ cJSON *cJSON_GetArrayItem(const cJSON *array, int item) cJSON *cJSON_GetObjectItem(const cJSON *object, const char *string) { cJSON *c = object ? object->child : NULL; - while (c && cJSON_strcasecmp(c->string, string)) + while (c && cJSON_strcasecmp((unsigned char*)c->string, (const unsigned char*)string)) { c = c->next; } return c; } -cjbool cJSON_HasObjectItem(const cJSON *object,const char *string) +cjbool cJSON_HasObjectItem(const cJSON *object, const char *string) { return cJSON_GetObjectItem(object, string) ? 1 : 0; } @@ -1778,7 +1823,7 @@ void cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item) { cJSON_free(item->string); } - item->string = cJSON_strdup(string); + item->string = (char*)cJSON_strdup((const unsigned char*)string); cJSON_AddItemToArray(object,item); } @@ -1812,7 +1857,7 @@ void cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *it cJSON_AddItemToObject(object, string, create_reference(item)); } -cJSON *cJSON_DetachItemFromArray(cJSON *array, int which) +static cJSON *DetachItemFromArray(cJSON *array, size_t which) { cJSON *c = array->child; while (c && (which > 0)) @@ -1843,6 +1888,15 @@ cJSON *cJSON_DetachItemFromArray(cJSON *array, int which) return c; } +cJSON *cJSON_DetachItemFromArray(cJSON *array, int which) +{ + if (which < 0) + { + return NULL; + } + + return DetachItemFromArray(array, (size_t)which); +} void cJSON_DeleteItemFromArray(cJSON *array, int which) { @@ -1851,16 +1905,16 @@ void cJSON_DeleteItemFromArray(cJSON *array, int which) cJSON *cJSON_DetachItemFromObject(cJSON *object, const char *string) { - int i = 0; + size_t i = 0; cJSON *c = object->child; - while (c && cJSON_strcasecmp(c->string,string)) + while (c && cJSON_strcasecmp((unsigned char*)c->string, (const unsigned char*)string)) { i++; c = c->next; } if (c) { - return cJSON_DetachItemFromArray(object, i); + return DetachItemFromArray(object, i); } return NULL; @@ -1898,7 +1952,7 @@ void cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem) } } -void cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem) +static void ReplaceItemInArray(cJSON *array, size_t which, cJSON *newitem) { cJSON *c = array->child; while (c && (which > 0)) @@ -1927,12 +1981,21 @@ void cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem) c->next = c->prev = NULL; cJSON_Delete(c); } +void cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem) +{ + if (which < 0) + { + return; + } + + ReplaceItemInArray(array, (size_t)which, newitem); +} void cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem) { - int i = 0; + size_t i = 0; cJSON *c = object->child; - while(c && cJSON_strcasecmp(c->string, string)) + while(c && cJSON_strcasecmp((unsigned char*)c->string, (const unsigned char*)string)) { i++; c = c->next; @@ -1945,8 +2008,8 @@ void cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem cJSON_free(newitem->string); } - newitem->string = cJSON_strdup(string); - cJSON_ReplaceItemInArray(object, i, newitem); + newitem->string = (char*)cJSON_strdup((const unsigned char*)string); + ReplaceItemInArray(object, i, newitem); } } @@ -2002,7 +2065,20 @@ cJSON *cJSON_CreateNumber(double num) { item->type = cJSON_Number; item->valuedouble = num; - item->valueint = (int)num; + + /* use saturation in case of overflow */ + if (num >= INT_MAX) + { + item->valueint = INT_MAX; + } + else if (num <= INT_MIN) + { + item->valueint = INT_MIN; + } + else + { + item->valueint = (int)num; + } } return item; @@ -2014,7 +2090,7 @@ cJSON *cJSON_CreateString(const char *string) if(item) { item->type = cJSON_String; - item->valuestring = cJSON_strdup(string); + item->valuestring = (char*)cJSON_strdup((const unsigned char*)string); if(!item->valuestring) { cJSON_Delete(item); @@ -2031,7 +2107,7 @@ extern cJSON *cJSON_CreateRaw(const char *raw) if(item) { item->type = cJSON_Raw; - item->valuestring = cJSON_strdup(raw); + item->valuestring = (char*)cJSON_strdup((const unsigned char*)raw); if(!item->valuestring) { cJSON_Delete(item); @@ -2067,11 +2143,18 @@ cJSON *cJSON_CreateObject(void) /* Create Arrays: */ cJSON *cJSON_CreateIntArray(const int *numbers, int count) { - int i = 0; + size_t i = 0; cJSON *n = NULL; cJSON *p = NULL; - cJSON *a = cJSON_CreateArray(); - for(i = 0; a && (i < count); i++) + cJSON *a = NULL; + + if (count < 0) + { + return NULL; + } + + a = cJSON_CreateArray(); + for(i = 0; a && (i < (size_t)count); i++) { n = cJSON_CreateNumber(numbers[i]); if (!n) @@ -2095,11 +2178,19 @@ cJSON *cJSON_CreateIntArray(const int *numbers, int count) cJSON *cJSON_CreateFloatArray(const float *numbers, int count) { - int i = 0; + size_t i = 0; cJSON *n = NULL; cJSON *p = NULL; - cJSON *a = cJSON_CreateArray(); - for(i = 0; a && (i < count); i++) + cJSON *a = NULL; + + if (count < 0) + { + return NULL; + } + + a = cJSON_CreateArray(); + + for(i = 0; a && (i < (size_t)count); i++) { n = cJSON_CreateNumber(numbers[i]); if(!n) @@ -2123,11 +2214,19 @@ cJSON *cJSON_CreateFloatArray(const float *numbers, int count) cJSON *cJSON_CreateDoubleArray(const double *numbers, int count) { - int i = 0; + size_t i = 0; cJSON *n = NULL; cJSON *p = NULL; - cJSON *a = cJSON_CreateArray(); - for(i = 0;a && (i < count); i++) + cJSON *a = NULL; + + if (count < 0) + { + return NULL; + } + + a = cJSON_CreateArray(); + + for(i = 0;a && (i < (size_t)count); i++) { n = cJSON_CreateNumber(numbers[i]); if(!n) @@ -2151,11 +2250,19 @@ cJSON *cJSON_CreateDoubleArray(const double *numbers, int count) cJSON *cJSON_CreateStringArray(const char **strings, int count) { - int i = 0; + size_t i = 0; cJSON *n = NULL; cJSON *p = NULL; - cJSON *a = cJSON_CreateArray(); - for (i = 0; a && (i < count); i++) + cJSON *a = NULL; + + if (count < 0) + { + return NULL; + } + + a = cJSON_CreateArray(); + + for (i = 0; a && (i < (size_t)count); i++) { n = cJSON_CreateString(strings[i]); if(!n) @@ -2202,7 +2309,7 @@ cJSON *cJSON_Duplicate(const cJSON *item, cjbool recurse) newitem->valuedouble = item->valuedouble; if (item->valuestring) { - newitem->valuestring = cJSON_strdup(item->valuestring); + newitem->valuestring = (char*)cJSON_strdup((unsigned char*)item->valuestring); if (!newitem->valuestring) { cJSON_Delete(newitem); @@ -2211,7 +2318,7 @@ cJSON *cJSON_Duplicate(const cJSON *item, cjbool recurse) } if (item->string) { - newitem->string = (item->type&cJSON_StringIsConst) ? item->string : cJSON_strdup(item->string); + newitem->string = (item->type&cJSON_StringIsConst) ? item->string : (char*)cJSON_strdup((unsigned char*)item->string); if (!newitem->string) { cJSON_Delete(newitem); @@ -2253,7 +2360,7 @@ cJSON *cJSON_Duplicate(const cJSON *item, cjbool recurse) void cJSON_Minify(char *json) { - char *into = json; + unsigned char *into = (unsigned char*)json; while (*json) { if (*json == ' ') @@ -2293,21 +2400,21 @@ void cJSON_Minify(char *json) else if (*json == '\"') { /* string literals, which are \" sensitive. */ - *into++ = *json++; + *into++ = (unsigned char)*json++; while (*json && (*json != '\"')) { if (*json == '\\') { - *into++=*json++; + *into++ = (unsigned char)*json++; } - *into++ = *json++; + *into++ = (unsigned char)*json++; } - *into++ = *json++; + *into++ = (unsigned char)*json++; } else { /* All other characters. */ - *into++ = *json++; + *into++ = (unsigned char)*json++; } } diff --git a/cJSON_Utils.c b/cJSON_Utils.c @@ -2,15 +2,17 @@ #include <string.h> #include <stdlib.h> #include <stdio.h> +#include <limits.h> + #include "cJSON_Utils.h" -static char* cJSONUtils_strdup(const char* str) +static unsigned char* cJSONUtils_strdup(const unsigned char* str) { size_t len = 0; - char *copy = NULL; + unsigned char *copy = NULL; - len = strlen(str) + 1; - if (!(copy = (char*)malloc(len))) + len = strlen((const char*)str) + 1; + if (!(copy = (unsigned char*)malloc(len))) { return NULL; } @@ -19,7 +21,7 @@ static char* cJSONUtils_strdup(const char* str) return copy; } -static int cJSONUtils_strcasecmp(const char *s1, const char *s2) +static int cJSONUtils_strcasecmp(const unsigned char *s1, const unsigned char *s2) { if (!s1) { @@ -37,11 +39,11 @@ static int cJSONUtils_strcasecmp(const char *s1, const char *s2) } } - return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2); + return tolower(*s1) - tolower(*s2); } /* JSON Pointer implementation: */ -static int cJSONUtils_Pstrcasecmp(const char *a, const char *e) +static int cJSONUtils_Pstrcasecmp(const unsigned char *a, const unsigned char *e) { if (!a || !e) { @@ -76,9 +78,9 @@ static int cJSONUtils_Pstrcasecmp(const char *a, const char *e) return 0; } -static int cJSONUtils_PointerEncodedstrlen(const char *s) +static size_t cJSONUtils_PointerEncodedstrlen(const unsigned char *s) { - int l = 0; + size_t l = 0; for (; *s; s++, l++) { if ((*s == '~') || (*s == '/')) @@ -90,7 +92,7 @@ static int cJSONUtils_PointerEncodedstrlen(const char *s) return l; } -static void cJSONUtils_PointerEncodedstrcpy(char *d, const char *s) +static void cJSONUtils_PointerEncodedstrcpy(unsigned char *d, const unsigned char *s) { for (; *s; s++) { @@ -116,39 +118,39 @@ static void cJSONUtils_PointerEncodedstrcpy(char *d, const char *s) char *cJSONUtils_FindPointerFromObjectTo(cJSON *object, cJSON *target) { int type = object->type; - int c = 0; + size_t c = 0; cJSON *obj = 0; if (object == target) { /* found */ - return cJSONUtils_strdup(""); + return (char*)cJSONUtils_strdup((const unsigned char*)""); } /* recursively search all children of the object */ for (obj = object->child; obj; obj = obj->next, c++) { - char *found = cJSONUtils_FindPointerFromObjectTo(obj, target); + unsigned char *found = (unsigned char*)cJSONUtils_FindPointerFromObjectTo(obj, target); if (found) { if ((type & 0xFF) == cJSON_Array) { /* reserve enough memory for a 64 bit integer + '/' and '\0' */ - char *ret = (char*)malloc(strlen(found) + 23); - sprintf(ret, "/%d%s", c, found); /* /<array_index><path> */ + unsigned char *ret = (unsigned char*)malloc(strlen((char*)found) + 23); + sprintf((char*)ret, "/%lu%s", c, found); /* /<array_index><path> */ free(found); - return ret; + return (char*)ret; } else if ((type & 0xFF) == cJSON_Object) { - char *ret = (char*)malloc(strlen(found) + cJSONUtils_PointerEncodedstrlen(obj->string) + 2); + unsigned char *ret = (unsigned char*)malloc(strlen((char*)found) + cJSONUtils_PointerEncodedstrlen((unsigned char*)obj->string) + 2); *ret = '/'; - cJSONUtils_PointerEncodedstrcpy(ret + 1, obj->string); - strcat(ret, found); + cJSONUtils_PointerEncodedstrcpy(ret + 1, (unsigned char*)obj->string); + strcat((char*)ret, (char*)found); free(found); - return ret; + return (char*)ret; } /* reached leaf of the tree, found nothing */ @@ -168,24 +170,28 @@ cJSON *cJSONUtils_GetPointer(cJSON *object, const char *pointer) { if ((object->type & 0xFF) == cJSON_Array) { - int which = 0; + size_t which = 0; /* parse array index */ while ((*pointer >= '0') && (*pointer <= '9')) { - which = (10 * which) + (*pointer++ - '0'); + which = (10 * which) + (size_t)(*pointer++ - '0'); } if (*pointer && (*pointer != '/')) { /* not end of string or new path token */ return NULL; } - object = cJSON_GetArrayItem(object, which); + if (which > INT_MAX) + { + return NULL; + } + object = cJSON_GetArrayItem(object, (int)which); } else if ((object->type & 0xFF) == cJSON_Object) { object = object->child; /* GetObjectItem. */ - while (object && cJSONUtils_Pstrcasecmp(object->string, pointer)) + while (object && cJSONUtils_Pstrcasecmp((unsigned char*)object->string, (const unsigned char*)pointer)) { object = object->next; } @@ -205,9 +211,9 @@ cJSON *cJSONUtils_GetPointer(cJSON *object, const char *pointer) } /* JSON Patch implementation. */ -static void cJSONUtils_InplaceDecodePointerString(char *string) +static void cJSONUtils_InplaceDecodePointerString(unsigned char *string) { - char *s2 = string; + unsigned char *s2 = string; if (string == NULL) { return; @@ -225,10 +231,10 @@ static void cJSONUtils_InplaceDecodePointerString(char *string) *s2 = '\0'; } -static cJSON *cJSONUtils_PatchDetach(cJSON *object, const char *path) +static cJSON *cJSONUtils_PatchDetach(cJSON *object, const unsigned char *path) { - char *parentptr = NULL; - char *childptr = NULL; + unsigned char *parentptr = NULL; + unsigned char *childptr = NULL; cJSON *parent = NULL; cJSON *ret = NULL; @@ -238,7 +244,7 @@ static cJSON *cJSONUtils_PatchDetach(cJSON *object, const char *path) return NULL; } - childptr = strrchr(parentptr, '/'); /* last '/' */ + childptr = (unsigned char*)strrchr((char*)parentptr, '/'); /* last '/' */ if (childptr == NULL) { free(parentptr); @@ -247,7 +253,7 @@ static cJSON *cJSONUtils_PatchDetach(cJSON *object, const char *path) /* split strings */ *childptr++ = '\0'; - parent = cJSONUtils_GetPointer(object, parentptr); + parent = cJSONUtils_GetPointer(object, (char*)parentptr); cJSONUtils_InplaceDecodePointerString(childptr); if (!parent) @@ -257,11 +263,11 @@ static cJSON *cJSONUtils_PatchDetach(cJSON *object, const char *path) } else if ((parent->type & 0xFF) == cJSON_Array) { - ret = cJSON_DetachItemFromArray(parent, atoi(childptr)); + ret = cJSON_DetachItemFromArray(parent, atoi((char*)childptr)); } else if ((parent->type & 0xFF) == cJSON_Object) { - ret = cJSON_DetachItemFromObject(parent, childptr); + ret = cJSON_DetachItemFromObject(parent, (char*)childptr); } free(parentptr); @@ -304,7 +310,7 @@ static int cJSONUtils_Compare(cJSON *a, cJSON *b) { int err = 0; /* compare object keys */ - if (cJSONUtils_strcasecmp(a->string, b->string)) + if (cJSONUtils_strcasecmp((unsigned char*)a->string, (unsigned char*)b->string)) { /* missing member */ return -6; @@ -334,8 +340,8 @@ static int cJSONUtils_ApplyPatch(cJSON *object, cJSON *patch) cJSON *value = NULL; cJSON *parent = NULL; int opcode = 0; - char *parentptr = NULL; - char *childptr = NULL; + unsigned char *parentptr = NULL; + unsigned char *childptr = NULL; op = cJSON_GetObjectItem(patch, "op"); path = cJSON_GetObjectItem(patch, "path"); @@ -381,7 +387,7 @@ static int cJSONUtils_ApplyPatch(cJSON *object, cJSON *patch) if ((opcode == 1) || (opcode == 2)) { /* Get rid of old. */ - cJSON_Delete(cJSONUtils_PatchDetach(object, path->valuestring)); + cJSON_Delete(cJSONUtils_PatchDetach(object, (unsigned char*)path->valuestring)); if (opcode == 1) { /* For Remove, this is job done. */ @@ -402,7 +408,7 @@ static int cJSONUtils_ApplyPatch(cJSON *object, cJSON *patch) if (opcode == 3) { /* move */ - value = cJSONUtils_PatchDetach(object, from->valuestring); + value = cJSONUtils_PatchDetach(object, (unsigned char*)from->valuestring); } if (opcode == 4) { @@ -443,13 +449,13 @@ static int cJSONUtils_ApplyPatch(cJSON *object, cJSON *patch) /* Now, just add "value" to "path". */ /* split pointer in parent and child */ - parentptr = cJSONUtils_strdup(path->valuestring); - childptr = strrchr(parentptr, '/'); + parentptr = cJSONUtils_strdup((unsigned char*)path->valuestring); + childptr = (unsigned char*)strrchr((char*)parentptr, '/'); if (childptr) { *childptr++ = '\0'; } - parent = cJSONUtils_GetPointer(object, parentptr); + parent = cJSONUtils_GetPointer(object, (char*)parentptr); cJSONUtils_InplaceDecodePointerString(childptr); /* add, remove, replace, move, copy, test. */ @@ -462,19 +468,19 @@ static int cJSONUtils_ApplyPatch(cJSON *object, cJSON *patch) } else if ((parent->type & 0xFF) == cJSON_Array) { - if (!strcmp(childptr, "-")) + if (!strcmp((char*)childptr, "-")) { cJSON_AddItemToArray(parent, value); } else { - cJSON_InsertItemInArray(parent, atoi(childptr), value); + cJSON_InsertItemInArray(parent, atoi((char*)childptr), value); } } else if ((parent->type & 0xFF) == cJSON_Object) { - cJSON_DeleteItemFromObject(parent, childptr); - cJSON_AddItemToObject(parent, childptr, value); + cJSON_DeleteItemFromObject(parent, (char*)childptr); + cJSON_AddItemToObject(parent, (char*)childptr, value); } else { @@ -509,20 +515,20 @@ int cJSONUtils_ApplyPatches(cJSON *object, cJSON *patches) return 0; } -static void cJSONUtils_GeneratePatch(cJSON *patches, const char *op, const char *path, const char *suffix, cJSON *val) +static void cJSONUtils_GeneratePatch(cJSON *patches, const unsigned char *op, const unsigned char *path, const unsigned char *suffix, cJSON *val) { cJSON *patch = cJSON_CreateObject(); - cJSON_AddItemToObject(patch, "op", cJSON_CreateString(op)); + cJSON_AddItemToObject(patch, "op", cJSON_CreateString((const char*)op)); if (suffix) { - char *newpath = (char*)malloc(strlen(path) + cJSONUtils_PointerEncodedstrlen(suffix) + 2); - cJSONUtils_PointerEncodedstrcpy(newpath + sprintf(newpath, "%s/", path), suffix); - cJSON_AddItemToObject(patch, "path", cJSON_CreateString(newpath)); + unsigned char *newpath = (unsigned char*)malloc(strlen((const char*)path) + cJSONUtils_PointerEncodedstrlen(suffix) + 2); + cJSONUtils_PointerEncodedstrcpy(newpath + sprintf((char*)newpath, "%s/", (const char*)path), suffix); + cJSON_AddItemToObject(patch, "path", cJSON_CreateString((const char*)newpath)); free(newpath); } else { - cJSON_AddItemToObject(patch, "path", cJSON_CreateString(path)); + cJSON_AddItemToObject(patch, "path", cJSON_CreateString((const char*)path)); } if (val) { @@ -533,14 +539,14 @@ static void cJSONUtils_GeneratePatch(cJSON *patches, const char *op, const char void cJSONUtils_AddPatchToArray(cJSON *array, const char *op, const char *path, cJSON *val) { - cJSONUtils_GeneratePatch(array, op, path, 0, val); + cJSONUtils_GeneratePatch(array, (const unsigned char*)op, (const unsigned char*)path, 0, val); } -static void cJSONUtils_CompareToPatch(cJSON *patches, const char *path, cJSON *from, cJSON *to) +static void cJSONUtils_CompareToPatch(cJSON *patches, const unsigned char *path, cJSON *from, cJSON *to) { if ((from->type & 0xFF) != (to->type & 0xFF)) { - cJSONUtils_GeneratePatch(patches, "replace", path, 0, to); + cJSONUtils_GeneratePatch(patches, (const unsigned char*)"replace", path, 0, to); return; } @@ -549,37 +555,37 @@ static void cJSONUtils_CompareToPatch(cJSON *patches, const char *path, cJSON *f case cJSON_Number: if ((from->valueint != to->valueint) || (from->valuedouble != to->valuedouble)) { - cJSONUtils_GeneratePatch(patches, "replace", path, 0, to); + cJSONUtils_GeneratePatch(patches, (const unsigned char*)"replace", path, 0, to); } return; case cJSON_String: if (strcmp(from->valuestring, to->valuestring) != 0) { - cJSONUtils_GeneratePatch(patches, "replace", path, 0, to); + cJSONUtils_GeneratePatch(patches, (const unsigned char*)"replace", path, 0, to); } return; case cJSON_Array: { - int c = 0; - char *newpath = (char*)malloc(strlen(path) + 23); /* Allow space for 64bit int. */ + size_t c = 0; + unsigned char *newpath = (unsigned char*)malloc(strlen((const char*)path) + 23); /* Allow space for 64bit int. */ /* generate patches for all array elements that exist in "from" and "to" */ for (c = 0, from = from->child, to = to->child; from && to; from = from->next, to = to->next, c++) { - sprintf(newpath, "%s/%d", path, c); /* path of the current array element */ + sprintf((char*)newpath, "%s/%lu", path, c); /* path of the current array element */ cJSONUtils_CompareToPatch(patches, newpath, from, to); } /* remove leftover elements from 'from' that are not in 'to' */ for (; from; from = from->next, c++) { - sprintf(newpath, "%d", c); - cJSONUtils_GeneratePatch(patches, "remove", path, newpath, 0); + sprintf((char*)newpath, "%lu", c); + cJSONUtils_GeneratePatch(patches, (const unsigned char*)"remove", path, newpath, 0); } /* add new elements in 'to' that were not in 'from' */ for (; to; to = to->next, c++) { - cJSONUtils_GeneratePatch(patches, "add", path, "-", to); + cJSONUtils_GeneratePatch(patches, (const unsigned char*)"add", path, (const unsigned char*)"-", to); } free(newpath); return; @@ -597,12 +603,12 @@ static void cJSONUtils_CompareToPatch(cJSON *patches, const char *path, cJSON *f /* for all object values in the object with more of them */ while (a || b) { - int diff = (!a) ? 1 : ((!b) ? -1 : cJSONUtils_strcasecmp(a->string, b->string)); + int diff = (!a) ? 1 : ((!b) ? -1 : cJSONUtils_strcasecmp((unsigned char*)a->string, (unsigned char*)b->string)); if (!diff) { /* both object keys are the same */ - char *newpath = (char*)malloc(strlen(path) + cJSONUtils_PointerEncodedstrlen(a->string) + 2); - cJSONUtils_PointerEncodedstrcpy(newpath + sprintf(newpath, "%s/", path), a->string); + unsigned char *newpath = (unsigned char*)malloc(strlen((const char*)path) + cJSONUtils_PointerEncodedstrlen((unsigned char*)a->string) + 2); + cJSONUtils_PointerEncodedstrcpy(newpath + sprintf((char*)newpath, "%s/", path), (unsigned char*)a->string); /* create a patch for the element */ cJSONUtils_CompareToPatch(patches, newpath, a, b); free(newpath); @@ -612,13 +618,13 @@ static void cJSONUtils_CompareToPatch(cJSON *patches, const char *path, cJSON *f else if (diff < 0) { /* object element doesn't exist in 'to' --> remove it */ - cJSONUtils_GeneratePatch(patches, "remove", path, a->string, 0); + cJSONUtils_GeneratePatch(patches, (const unsigned char*)"remove", path, (unsigned char*)a->string, 0); a = a->next; } else { /* object element doesn't exist in 'from' --> add it */ - cJSONUtils_GeneratePatch(patches, "add", path, b->string, b); + cJSONUtils_GeneratePatch(patches, (const unsigned char*)"add", path, (unsigned char*)b->string, b); b = b->next; } } @@ -633,7 +639,7 @@ static void cJSONUtils_CompareToPatch(cJSON *patches, const char *path, cJSON *f cJSON* cJSONUtils_GeneratePatches(cJSON *from, cJSON *to) { cJSON *patches = cJSON_CreateArray(); - cJSONUtils_CompareToPatch(patches, "", from, to); + cJSONUtils_CompareToPatch(patches, (const unsigned char*)"", from, to); return patches; } @@ -651,7 +657,7 @@ static cJSON *cJSONUtils_SortList(cJSON *list) return list; } - while (ptr && ptr->next && (cJSONUtils_strcasecmp(ptr->string, ptr->next->string) < 0)) + while (ptr && ptr->next && (cJSONUtils_strcasecmp((unsigned char*)ptr->string, (unsigned char*)ptr->next->string) < 0)) { /* Test for list sorted. */ ptr = ptr->next; @@ -688,7 +694,7 @@ static cJSON *cJSONUtils_SortList(cJSON *list) while (first && second) /* Merge the sub-lists */ { - if (cJSONUtils_strcasecmp(first->string, second->string) < 0) + if (cJSONUtils_strcasecmp((unsigned char*)first->string, (unsigned char*)second->string) < 0) { if (!list) { diff --git a/test.c b/test.c @@ -97,8 +97,8 @@ static int print_preallocated(cJSON *root) char *out = NULL; char *buf = NULL; char *buf_fail = NULL; - int len = 0; - int len_fail = 0; + size_t len = 0; + size_t len_fail = 0; /* formatted print */ out = cJSON_Print(root); @@ -123,7 +123,7 @@ static int print_preallocated(cJSON *root) } /* Print to buffer */ - if (!cJSON_PrintPreallocated(root, buf, len, 1)) { + if (!cJSON_PrintPreallocated(root, buf, (int)len, 1)) { printf("cJSON_PrintPreallocated failed!\n"); if (strcmp(out, buf) != 0) { printf("cJSON_PrintPreallocated not the same as cJSON_Print!\n"); @@ -140,7 +140,7 @@ static int print_preallocated(cJSON *root) printf("%s\n", buf); /* force it to fail */ - if (cJSON_PrintPreallocated(root, buf_fail, len_fail, 1)) { + if (cJSON_PrintPreallocated(root, buf_fail, (int)len_fail, 1)) { printf("cJSON_PrintPreallocated failed to show error with insufficient memory!\n"); printf("cJSON_Print result:\n%s\n", out); printf("cJSON_PrintPreallocated result:\n%s\n", buf_fail);