diff --git a/cJSON.c b/cJSON.c index d658588..a5cd84b 100644 --- a/cJSON.c +++ b/cJSON.c @@ -328,6 +328,12 @@ static unsigned char *print_number(const cJSON *item, printbuffer *p) { unsigned char *str = NULL; double d = item->valuedouble; + + if (p == NULL) + { + return NULL; + } + /* special case for 0. */ if (d == 0) { @@ -678,6 +684,11 @@ static unsigned char *print_string_ptr(const unsigned char *str, printbuffer *p) cjbool flag = false; unsigned char token = '\0'; + if (p == NULL) + { + return NULL; + } + /* empty string */ if (!str) { @@ -1028,101 +1039,71 @@ static unsigned char *print_value(const cJSON *item, size_t depth, cjbool fmt, p { return NULL; } - if (p) - { - switch ((item->type) & 0xFF) - { - case cJSON_NULL: - out = ensure(p, 5); - if (out != NULL) - { - strcpy((char*)out, "null"); - } - break; - case cJSON_False: - out = ensure(p, 6); - if (out != NULL) - { - strcpy((char*)out, "false"); - } - break; - case cJSON_True: - out = ensure(p, 5); - if (out != NULL) - { - strcpy((char*)out, "true"); - } - break; - case cJSON_Number: - out = print_number(item, p); - break; - case cJSON_Raw: - { - size_t raw_length = 0; - if (item->valuestring == NULL) - { - if (!p->noalloc) - { - cJSON_free(p->buffer); - } - out = NULL; - break; - } - raw_length = strlen(item->valuestring) + sizeof('\0'); - out = ensure(p, raw_length); - if (out != NULL) + if (p == NULL) + { + return NULL; + } + + switch ((item->type) & 0xFF) + { + case cJSON_NULL: + out = ensure(p, 5); + if (out != NULL) + { + strcpy((char*)out, "null"); + } + break; + case cJSON_False: + out = ensure(p, 6); + if (out != NULL) + { + strcpy((char*)out, "false"); + } + break; + case cJSON_True: + out = ensure(p, 5); + if (out != NULL) + { + strcpy((char*)out, "true"); + } + break; + case cJSON_Number: + out = print_number(item, p); + break; + case cJSON_Raw: + { + size_t raw_length = 0; + if (item->valuestring == NULL) + { + if (!p->noalloc) { - memcpy(out, item->valuestring, raw_length); + cJSON_free(p->buffer); } + out = NULL; break; } - case cJSON_String: - out = print_string(item, p); - break; - case cJSON_Array: - out = print_array(item, depth, fmt, p); - break; - case cJSON_Object: - out = print_object(item, depth, fmt, p); - break; - default: - out = NULL; - break; - } - } - else - { - switch ((item->type) & 0xFF) - { - case cJSON_NULL: - out = cJSON_strdup((const unsigned char*)"null"); - break; - case cJSON_False: - out = cJSON_strdup((const unsigned char*)"false"); - break; - case cJSON_True: - out = cJSON_strdup((const unsigned char*)"true"); - break; - case cJSON_Number: - out = print_number(item, 0); - break; - case cJSON_Raw: - out = cJSON_strdup((unsigned char*)item->valuestring); - break; - case cJSON_String: - out = print_string(item, 0); - break; - case cJSON_Array: - out = print_array(item, depth, fmt, 0); - break; - case cJSON_Object: - out = print_object(item, depth, fmt, 0); - break; - default: - out = NULL; - break; + + raw_length = strlen(item->valuestring) + sizeof('\0'); + out = ensure(p, raw_length); + if (out != NULL) + { + memcpy(out, item->valuestring, raw_length); + } + break; } + case cJSON_String: + out = print_string(item, p); + break; + case cJSON_Array: + out = print_array(item, depth, fmt, p); + break; + case cJSON_Object: + out = print_object(item, depth, fmt, p); + break; + default: + out = NULL; + break; } return out; @@ -1209,16 +1190,18 @@ fail: /* Render an array to text */ static unsigned char *print_array(const cJSON *item, size_t depth, cjbool fmt, printbuffer *p) { - unsigned char **entries; unsigned char *out = NULL; unsigned char *ptr = NULL; - unsigned char *ret = NULL; size_t len = 5; cJSON *child = item->child; size_t numentries = 0; size_t i = 0; cjbool fail = false; - size_t tmplen = 0; + + if (p == NULL) + { + return NULL; + } /* How many entries in the array? */ while (child) @@ -1239,131 +1222,51 @@ static unsigned char *print_array(const cJSON *item, size_t depth, cjbool fmt, p return out; } - if (p) + /* Compose the output array. */ + /* opening square bracket */ + i = p->offset; + ptr = ensure(p, 1); + if (ptr == NULL) { - /* Compose the output array. */ - /* opening square bracket */ - i = p->offset; - ptr = ensure(p, 1); - if (ptr == NULL) + return NULL; + } + *ptr = '['; + p->offset++; + + child = item->child; + while (child && !fail) + { + if (!print_value(child, depth + 1, fmt, p)) { return NULL; } - *ptr = '['; - p->offset++; - - child = item->child; - while (child && !fail) + p->offset = update(p); + if (child->next) { - if (!print_value(child, depth + 1, fmt, p)) + len = fmt ? 2 : 1; + ptr = ensure(p, len + 1); + if (ptr == NULL) { return NULL; } - p->offset = update(p); - if (child->next) + *ptr++ = ','; + if(fmt) { - len = fmt ? 2 : 1; - ptr = ensure(p, len + 1); - if (ptr == NULL) - { - return NULL; - } - *ptr++ = ','; - if(fmt) - { - *ptr++ = ' '; - } - *ptr = '\0'; - p->offset += len; + *ptr++ = ' '; } - child = child->next; + *ptr = '\0'; + p->offset += len; } - ptr = ensure(p, 2); - if (ptr == NULL) - { - return NULL; - } - *ptr++ = ']'; - *ptr = '\0'; - out = (p->buffer) + i; + child = child->next; } - else + ptr = ensure(p, 2); + if (ptr == NULL) { - /* Allocate an array to hold the pointers to all printed values */ - entries = (unsigned char**)cJSON_malloc(numentries * sizeof(unsigned char*)); - if (!entries) - { - return NULL; - } - memset(entries, '\0', numentries * sizeof(unsigned char*)); - - /* Retrieve all the results: */ - child = item->child; - while (child && !fail) - { - ret = print_value(child, depth + 1, fmt, 0); - entries[i++] = ret; - if (ret) - { - len += strlen((char*)ret) + 2 + (fmt ? 1 : 0); - } - else - { - fail = true; - } - child = child->next; - } - - /* If we didn't fail, try to malloc the output string */ - if (!fail) - { - out = (unsigned char*)cJSON_malloc(len); - } - /* If that fails, we fail. */ - if (!out) - { - fail = true; - } - - /* Handle failure. */ - if (fail) - { - /* free all the entries in the array */ - for (i = 0; i < numentries; i++) - { - if (entries[i]) - { - cJSON_free(entries[i]); - } - } - cJSON_free(entries); - return NULL; - } - - /* Compose the output array. */ - *out='['; - ptr = out + 1; - *ptr = '\0'; - for (i = 0; i < numentries; i++) - { - tmplen = strlen((char*)entries[i]); - memcpy(ptr, entries[i], tmplen); - ptr += tmplen; - if (i != (numentries - 1)) - { - *ptr++ = ','; - if(fmt) - { - *ptr++ = ' '; - } - *ptr = '\0'; - } - cJSON_free(entries[i]); - } - cJSON_free(entries); - *ptr++ = ']'; - *ptr++ = '\0'; + return NULL; } + *ptr++ = ']'; + *ptr = '\0'; + out = (p->buffer) + i; return out; } @@ -1466,19 +1369,18 @@ fail: /* Render an object to text. */ 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; size_t numentries = 0; - cjbool fail = false; - size_t tmplen = 0; + + if (p == NULL) + { + return NULL; + } /* Count the number of entries. */ while (child) @@ -1510,18 +1412,80 @@ static unsigned char *print_object(const cJSON *item, size_t depth, cjbool fmt, return out; } - if (p) + /* Compose the output: */ + i = p->offset; + len = fmt ? 2 : 1; /* fmt: {\n */ + ptr = ensure(p, len + 1); + if (ptr == NULL) { - /* Compose the output: */ - i = p->offset; - len = fmt ? 2 : 1; /* fmt: {\n */ + return NULL; + } + + *ptr++ = '{'; + if (fmt) + { + *ptr++ = '\n'; + } + *ptr = '\0'; + p->offset += len; + + child = item->child; + depth++; + while (child) + { + if (fmt) + { + ptr = ensure(p, depth); + if (ptr == NULL) + { + return NULL; + } + for (j = 0; j < depth; j++) + { + *ptr++ = '\t'; + } + p->offset += depth; + } + + /* print key */ + if (!print_string_ptr((unsigned char*)child->string, p)) + { + return NULL; + } + p->offset = update(p); + + len = fmt ? 2 : 1; + ptr = ensure(p, len); + if (ptr == NULL) + { + return NULL; + } + *ptr++ = ':'; + if (fmt) + { + *ptr++ = '\t'; + } + p->offset+=len; + + /* print value */ + if (!print_value(child, depth, fmt, p)) + { + return NULL; + } + p->offset = update(p); + + /* print comma if not last */ + len = (size_t) (fmt ? 1 : 0) + (child->next ? 1 : 0); ptr = ensure(p, len + 1); if (ptr == NULL) { return NULL; } + if (child->next) + { + *ptr++ = ','; + } - *ptr++ = '{'; if (fmt) { *ptr++ = '\n'; @@ -1529,210 +1493,24 @@ static unsigned char *print_object(const cJSON *item, size_t depth, cjbool fmt, *ptr = '\0'; p->offset += len; - child = item->child; - depth++; - while (child) - { - if (fmt) - { - ptr = ensure(p, depth); - if (ptr == NULL) - { - return NULL; - } - for (j = 0; j < depth; j++) - { - *ptr++ = '\t'; - } - p->offset += depth; - } - - /* print key */ - if (!print_string_ptr((unsigned char*)child->string, p)) - { - return NULL; - } - p->offset = update(p); - - len = fmt ? 2 : 1; - ptr = ensure(p, len); - if (ptr == NULL) - { - return NULL; - } - *ptr++ = ':'; - if (fmt) - { - *ptr++ = '\t'; - } - p->offset+=len; - - /* print value */ - if (!print_value(child, depth, fmt, p)) - { - return NULL; - }; - p->offset = update(p); - - /* print comma if not last */ - len = (size_t) (fmt ? 1 : 0) + (child->next ? 1 : 0); - ptr = ensure(p, len + 1); - if (ptr == NULL) - { - return NULL; - } - if (child->next) - { - *ptr++ = ','; - } - - if (fmt) - { - *ptr++ = '\n'; - } - *ptr = '\0'; - p->offset += len; - - child = child->next; - } - - ptr = ensure(p, fmt ? (depth + 1) : 2); - if (ptr == NULL) - { - return NULL; - } - if (fmt) - { - for (i = 0; i < (depth - 1); i++) - { - *ptr++ = '\t'; - } - } - *ptr++ = '}'; - *ptr = '\0'; - out = (p->buffer) + i; + child = child->next; } - else + + ptr = ensure(p, fmt ? (depth + 1) : 2); + if (ptr == NULL) { - /* Allocate space for the names and the objects */ - entries = (unsigned char**)cJSON_malloc(numentries * sizeof(unsigned char*)); - if (!entries) - { - return NULL; - } - names = (unsigned char**)cJSON_malloc(numentries * sizeof(unsigned char*)); - if (!names) - { - cJSON_free(entries); - return NULL; - } - memset(entries, '\0', sizeof(unsigned char*) * numentries); - memset(names, '\0', sizeof(unsigned char*) * numentries); - - /* Collect all the results into our arrays: */ - child = item->child; - depth++; - if (fmt) - { - len += depth; - } - while (child && !fail) - { - 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((char*)ret) + strlen((char*)str) + 2 + (fmt ? 2 + depth : 0); - } - else - { - fail = true; - } - child = child->next; - } - - /* Try to allocate the output string */ - if (!fail) - { - out = (unsigned char*)cJSON_malloc(len); - } - if (!out) - { - fail = true; - } - - /* Handle failure */ - if (fail) - { - /* free all the printed keys and values */ - for (i = 0; i < numentries; i++) - { - if (names[i]) - { - cJSON_free(names[i]); - } - if (entries[i]) - { - cJSON_free(entries[i]); - } - } - cJSON_free(names); - cJSON_free(entries); - return NULL; - } - - /* Compose the output: */ - *out = '{'; - ptr = out + 1; - if (fmt) - { - *ptr++ = '\n'; - } - *ptr = '\0'; - for (i = 0; i < numentries; i++) - { - if (fmt) - { - for (j = 0; j < depth; j++) - { - *ptr++='\t'; - } - } - tmplen = strlen((char*)names[i]); - memcpy(ptr, names[i], tmplen); - ptr += tmplen; - *ptr++ = ':'; - if (fmt) - { - *ptr++ = '\t'; - } - strcpy((char*)ptr, (char*)entries[i]); - ptr += strlen((char*)entries[i]); - if (i != (numentries - 1)) - { - *ptr++ = ','; - } - if (fmt) - { - *ptr++ = '\n'; - } - *ptr = '\0'; - cJSON_free(names[i]); - cJSON_free(entries[i]); - } - - cJSON_free(names); - cJSON_free(entries); - if (fmt) - { - for (i = 0; i < (depth - 1); i++) - { - *ptr++ = '\t'; - } - } - *ptr++ = '}'; - *ptr++ = '\0'; + return NULL; } + if (fmt) + { + for (i = 0; i < (depth - 1); i++) + { + *ptr++ = '\t'; + } + } + *ptr++ = '}'; + *ptr = '\0'; + out = (p->buffer) + i; return out; }