1 /*
2   Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
3 
4   Permission is hereby granted, free of charge, to any person obtaining a copy
5   of this software and associated documentation files (the "Software"), to deal
6   in the Software without restriction, including without limitation the rights
7   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8   copies of the Software, and to permit persons to whom the Software is
9   furnished to do so, subject to the following conditions:
10 
11   The above copyright notice and this permission notice shall be included in
12   all copies or substantial portions of the Software.
13 
14   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20   THE SOFTWARE.
21 
22 */
23 
24 /*
25 This file has been modified from its original version by Amazon:
26  *   (1) Include path
27  *   (2) header order via clang-format
28  *   (3) Clang-tidy error removal: Added parens around macro params in a number of macro bodies
29  *   (4) NOLINT annotations to disable clang-tidy errors around raw/unsafe function use
30  *   (5) strcpy() replaced with memcpy()
31 */
32 
33 /* clang-format off */
34 
35 /* cJSON */
36 /* JSON parser in C. */
37 
38 /* disable warnings about old C89 functions in MSVC */
39 #if !defined(_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER)
40 #define _CRT_SECURE_NO_DEPRECATE
41 #endif
42 
43 #ifdef __GNUC__
44 #pragma GCC visibility push(default)
45 #endif
46 #if defined(_MSC_VER)
47 #pragma warning (push)
48 /* disable warning about single line comments in system headers */
49 #pragma warning (disable : 4001)
50 #endif
51 
52 #include <ctype.h>
53 #include <limits.h>
54 #include <math.h>
55 #include <stdio.h>
56 #include <stdlib.h>
57 #include <string.h>
58 
59 #ifdef ENABLE_LOCALES
60 #include <locale.h>
61 #endif
62 
63 #if defined(_MSC_VER)
64 #pragma warning (pop)
65 #endif
66 #ifdef __GNUC__
67 #pragma GCC visibility pop
68 #endif
69 
70 #include <aws/auth/external/cJSON.h>
71 
72 /* define our own boolean type */
73 #ifdef true
74 #undef true
75 #endif
76 #define true ((cJSON_bool)1)
77 
78 #ifdef false
79 #undef false
80 #endif
81 #define false ((cJSON_bool)0)
82 
83 typedef struct {
84     const unsigned char *json;
85     size_t position;
86 } error;
87 static error global_error = { NULL, 0 };
88 
cJSON_GetErrorPtr(void)89 CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void)
90 {
91     return (const char*) (global_error.json + global_error.position);
92 }
93 
cJSON_GetStringValue(cJSON * item)94 CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item) {
95     if (!cJSON_IsString(item)) {
96         return NULL;
97     }
98 
99     return item->valuestring;
100 }
101 
102 /* This is a safeguard to prevent copy-pasters from using incompatible C and header files */
103 #if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 12)
104     #error cJSON.h and cJSON.c have different versions. Make sure that both have the same.
105 #endif
106 
cJSON_Version(void)107 CJSON_PUBLIC(const char*) cJSON_Version(void)
108 {
109     static char version[15];
110     snprintf(version, sizeof(version) / sizeof(char), "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, CJSON_VERSION_PATCH);
111 
112     return version;
113 }
114 
115 /* Case insensitive string comparison, doesn't consider two NULL pointers equal though */
case_insensitive_strcmp(const unsigned char * string1,const unsigned char * string2)116 static int case_insensitive_strcmp(const unsigned char *string1, const unsigned char *string2)
117 {
118     if ((string1 == NULL) || (string2 == NULL))
119     {
120         return 1;
121     }
122 
123     if (string1 == string2)
124     {
125         return 0;
126     }
127 
128     for(; tolower(*string1) == tolower(*string2); (void)string1++, string2++)
129     {
130         if (*string1 == '\0')
131         {
132             return 0;
133         }
134     }
135 
136     return tolower(*string1) - tolower(*string2);
137 }
138 
139 typedef struct internal_hooks
140 {
141     void *(CJSON_CDECL *allocate)(size_t size);
142     void (CJSON_CDECL *deallocate)(void *pointer);
143     void *(CJSON_CDECL *reallocate)(void *pointer, size_t size);
144 } internal_hooks;
145 
146 #if defined(_MSC_VER)
147 /* work around MSVC error C2322: '...' address of dillimport '...' is not static */
internal_malloc(size_t size)148 static void * CJSON_CDECL internal_malloc(size_t size)
149 {
150     return malloc(size);
151 }
internal_free(void * pointer)152 static void CJSON_CDECL internal_free(void *pointer)
153 {
154     free(pointer);
155 }
internal_realloc(void * pointer,size_t size)156 static void * CJSON_CDECL internal_realloc(void *pointer, size_t size)
157 {
158     return realloc(pointer, size);
159 }
160 #else
161 #define internal_malloc malloc
162 #define internal_free free
163 #define internal_realloc realloc
164 #endif
165 
166 /* strlen of character literals resolved at compile time */
167 #define static_strlen(string_literal) (sizeof(string_literal) - sizeof(""))
168 
169 static internal_hooks global_hooks = { internal_malloc, internal_free, internal_realloc };
170 
cJSON_strdup(const unsigned char * string,const internal_hooks * const hooks)171 static unsigned char* cJSON_strdup(const unsigned char* string, const internal_hooks * const hooks)
172 {
173     size_t length = 0;
174     unsigned char *copy = NULL;
175 
176     if (string == NULL)
177     {
178         return NULL;
179     }
180 
181     length = strlen((const char*)string) + sizeof("");
182     copy = (unsigned char*)hooks->allocate(length);
183     if (copy == NULL)
184     {
185         return NULL;
186     }
187     memcpy(copy, string, length);
188 
189     return copy;
190 }
191 
cJSON_InitHooks(cJSON_Hooks * hooks)192 CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks)
193 {
194     if (hooks == NULL)
195     {
196         /* Reset hooks */
197         global_hooks.allocate = malloc;
198         global_hooks.deallocate = free;
199         global_hooks.reallocate = realloc;
200         return;
201     }
202 
203     global_hooks.allocate = malloc;
204     if (hooks->malloc_fn != NULL)
205     {
206         global_hooks.allocate = hooks->malloc_fn;
207     }
208 
209     global_hooks.deallocate = free;
210     if (hooks->free_fn != NULL)
211     {
212         global_hooks.deallocate = hooks->free_fn;
213     }
214 
215     /* use realloc only if both free and malloc are used */
216     global_hooks.reallocate = NULL;
217     if ((global_hooks.allocate == malloc) && (global_hooks.deallocate == free))
218     {
219         global_hooks.reallocate = realloc;
220     }
221 }
222 
223 /* Internal constructor. */
cJSON_New_Item(const internal_hooks * const hooks)224 static cJSON *cJSON_New_Item(const internal_hooks * const hooks)
225 {
226     cJSON* node = (cJSON*)hooks->allocate(sizeof(cJSON));
227     if (node)
228     {
229         memset(node, '\0', sizeof(cJSON));
230     }
231 
232     return node;
233 }
234 
235 /* Delete a cJSON structure. */
cJSON_Delete(cJSON * item)236 CJSON_PUBLIC(void) cJSON_Delete(cJSON *item)
237 {
238     cJSON *next = NULL;
239     while (item != NULL)
240     {
241         next = item->next;
242         if (!(item->type & cJSON_IsReference) && (item->child != NULL))
243         {
244             cJSON_Delete(item->child);
245         }
246         if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL))
247         {
248             global_hooks.deallocate(item->valuestring);
249         }
250         if (!(item->type & cJSON_StringIsConst) && (item->string != NULL))
251         {
252             global_hooks.deallocate(item->string);
253         }
254         global_hooks.deallocate(item);
255         item = next;
256     }
257 }
258 
259 /* get the decimal point character of the current locale */
get_decimal_point(void)260 static unsigned char get_decimal_point(void)
261 {
262 #ifdef ENABLE_LOCALES
263     struct lconv *lconv = localeconv();
264     return (unsigned char) lconv->decimal_point[0];
265 #else
266     return '.';
267 #endif
268 }
269 
270 typedef struct
271 {
272     const unsigned char *content;
273     size_t length;
274     size_t offset;
275     size_t depth; /* How deeply nested (in arrays/objects) is the input at the current offset. */
276     internal_hooks hooks;
277 } parse_buffer;
278 
279 /* check if the given size is left to read in a given parse buffer (starting with 1) */
280 #define can_read(buffer, size) (((buffer) != NULL) && (((buffer)->offset + (size)) <= (buffer)->length))
281 /* check if the buffer can be accessed at the given index (starting with 0) */
282 #define can_access_at_index(buffer, index) (((buffer) != NULL) && (((buffer)->offset + (index)) < (buffer)->length))
283 #define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
284 /* get a pointer to the buffer at the position */
285 #define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
286 
287 /* Parse the input text to generate a number, and populate the result into item. */
parse_number(cJSON * const item,parse_buffer * const input_buffer)288 static cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_buffer)
289 {
290     double number = 0;
291     unsigned char *after_end = NULL;
292     unsigned char number_c_string[64];
293     unsigned char decimal_point = get_decimal_point();
294     size_t i = 0;
295 
296     if ((input_buffer == NULL) || (input_buffer->content == NULL))
297     {
298         return false;
299     }
300 
301     /* copy the number into a temporary buffer and replace '.' with the decimal point
302      * of the current locale (for strtod)
303      * This also takes care of '\0' not necessarily being available for marking the end of the input */
304     for (i = 0; (i < (sizeof(number_c_string) - 1)) && can_access_at_index(input_buffer, i); i++)
305     {
306         switch (buffer_at_offset(input_buffer)[i])
307         {
308             case '0':
309             case '1':
310             case '2':
311             case '3':
312             case '4':
313             case '5':
314             case '6':
315             case '7':
316             case '8':
317             case '9':
318             case '+':
319             case '-':
320             case 'e':
321             case 'E':
322                 number_c_string[i] = buffer_at_offset(input_buffer)[i];
323                 break;
324 
325             case '.':
326                 number_c_string[i] = decimal_point;
327                 break;
328 
329             default:
330                 goto loop_end;
331         }
332     }
333 loop_end:
334     number_c_string[i] = '\0';
335 
336     number = strtod((const char*)number_c_string, (char**)&after_end);
337     if (number_c_string == after_end)
338     {
339         return false; /* parse_error */
340     }
341 
342     item->valuedouble = number;
343 
344     /* use saturation in case of overflow */
345     if (number >= INT_MAX)
346     {
347         item->valueint = INT_MAX;
348     }
349     else if (number <= (double)INT_MIN)
350     {
351         item->valueint = INT_MIN;
352     }
353     else
354     {
355         item->valueint = (int)number;
356     }
357 
358     item->type = cJSON_Number;
359 
360     input_buffer->offset += (size_t)(after_end - number_c_string);
361     return true;
362 }
363 
364 /* don't ask me, but the original cJSON_SetNumberValue returns an integer or double */
cJSON_SetNumberHelper(cJSON * object,double number)365 CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number)
366 {
367     if (number >= INT_MAX)
368     {
369         object->valueint = INT_MAX;
370     }
371     else if (number <= (double)INT_MIN)
372     {
373         object->valueint = INT_MIN;
374     }
375     else
376     {
377         object->valueint = (int)number;
378     }
379 
380     return object->valuedouble = number;
381 }
382 
383 typedef struct
384 {
385     unsigned char *buffer;
386     size_t length;
387     size_t offset;
388     size_t depth; /* current nesting depth (for formatted printing) */
389     cJSON_bool noalloc;
390     cJSON_bool format; /* is this print a formatted print */
391     internal_hooks hooks;
392 } printbuffer;
393 
394 /* realloc printbuffer if necessary to have at least "needed" bytes more */
ensure(printbuffer * const p,size_t needed)395 static unsigned char* ensure(printbuffer * const p, size_t needed)
396 {
397     unsigned char *newbuffer = NULL;
398     size_t newsize = 0;
399 
400     if ((p == NULL) || (p->buffer == NULL))
401     {
402         return NULL;
403     }
404 
405     if ((p->length > 0) && (p->offset >= p->length))
406     {
407         /* make sure that offset is valid */
408         return NULL;
409     }
410 
411     if (needed > INT_MAX)
412     {
413         /* sizes bigger than INT_MAX are currently not supported */
414         return NULL;
415     }
416 
417     needed += p->offset + 1;
418     if (needed <= p->length)
419     {
420         return p->buffer + p->offset;
421     }
422 
423     if (p->noalloc) {
424         return NULL;
425     }
426 
427     /* calculate new buffer size */
428     if (needed > (INT_MAX / 2))
429     {
430         /* overflow of int, use INT_MAX if possible */
431         if (needed <= INT_MAX)
432         {
433             newsize = INT_MAX;
434         }
435         else
436         {
437             return NULL;
438         }
439     }
440     else
441     {
442         newsize = needed * 2;
443     }
444 
445     if (p->hooks.reallocate != NULL)
446     {
447         /* reallocate with realloc if available */
448         newbuffer = (unsigned char*)p->hooks.reallocate(p->buffer, newsize);
449         if (newbuffer == NULL)
450         {
451             p->hooks.deallocate(p->buffer);
452             p->length = 0;
453             p->buffer = NULL;
454 
455             return NULL;
456         }
457     }
458     else
459     {
460         /* otherwise reallocate manually */
461         newbuffer = (unsigned char*)p->hooks.allocate(newsize);
462         if (!newbuffer)
463         {
464             p->hooks.deallocate(p->buffer);
465             p->length = 0;
466             p->buffer = NULL;
467 
468             return NULL;
469         }
470         if (newbuffer)
471         {
472             memcpy(newbuffer, p->buffer, p->offset + 1);
473         }
474         p->hooks.deallocate(p->buffer);
475     }
476     p->length = newsize;
477     p->buffer = newbuffer;
478 
479     return newbuffer + p->offset;
480 }
481 
482 /* calculate the new length of the string in a printbuffer and update the offset */
update_offset(printbuffer * const buffer)483 static void update_offset(printbuffer * const buffer)
484 {
485     const unsigned char *buffer_pointer = NULL;
486     if ((buffer == NULL) || (buffer->buffer == NULL))
487     {
488         return;
489     }
490     buffer_pointer = buffer->buffer + buffer->offset;
491 
492     buffer->offset += strlen((const char*)buffer_pointer);
493 }
494 
495 /* Render the number nicely from the given item into a string. */
print_number(const cJSON * const item,printbuffer * const output_buffer)496 static cJSON_bool print_number(const cJSON * const item, printbuffer * const output_buffer)
497 {
498     unsigned char *output_pointer = NULL;
499     double d = item->valuedouble;
500     int length = 0;
501     size_t i = 0;
502     unsigned char number_buffer[26]; /* temporary buffer to print the number into */
503     unsigned char decimal_point = get_decimal_point();
504     double test;
505 
506     if (output_buffer == NULL)
507     {
508         return false;
509     }
510 
511     /* This checks for NaN and Infinity */
512     if ((d * 0) != 0)
513     {
514         length = snprintf((char*)number_buffer, sizeof(number_buffer) / sizeof(char), "null");
515     }
516     else
517     {
518         /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */
519         length = snprintf((char*)number_buffer, sizeof(number_buffer) / sizeof(char), "%1.15g", d);
520 
521         /* Check whether the original double can be recovered */
522         if ((sscanf((char*)number_buffer, "%lg", &test) != 1) || ((double)test != d))
523         {
524             /* If not, print with 17 decimal places of precision */
525             length = snprintf((char*)number_buffer, sizeof(number_buffer) / sizeof(char), "%1.17g", d);
526         }
527     }
528 
529     /* sprintf failed or buffer overrun occurred */
530     if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1)))
531     {
532         return false;
533     }
534 
535     /* reserve appropriate space in the output */
536     output_pointer = ensure(output_buffer, (size_t)length + sizeof(""));
537     if (output_pointer == NULL)
538     {
539         return false;
540     }
541 
542     /* copy the printed number to the output and replace locale
543      * dependent decimal point with '.' */
544     for (i = 0; i < ((size_t)length); i++)
545     {
546         if (number_buffer[i] == decimal_point)
547         {
548             output_pointer[i] = '.';
549             continue;
550         }
551 
552         output_pointer[i] = number_buffer[i];
553     }
554     output_pointer[i] = '\0';
555 
556     output_buffer->offset += (size_t)length;
557 
558     return true;
559 }
560 
561 /* parse 4 digit hexadecimal number */
parse_hex4(const unsigned char * const input)562 static unsigned parse_hex4(const unsigned char * const input)
563 {
564     unsigned int h = 0;
565     size_t i = 0;
566 
567     for (i = 0; i < 4; i++)
568     {
569         /* parse digit */
570         if ((input[i] >= '0') && (input[i] <= '9'))
571         {
572             h += (unsigned int) input[i] - '0';
573         }
574         else if ((input[i] >= 'A') && (input[i] <= 'F'))
575         {
576             h += (unsigned int) 10 + input[i] - 'A';
577         }
578         else if ((input[i] >= 'a') && (input[i] <= 'f'))
579         {
580             h += (unsigned int) 10 + input[i] - 'a';
581         }
582         else /* invalid */
583         {
584             return 0;
585         }
586 
587         if (i < 3)
588         {
589             /* shift left to make place for the next nibble */
590             h = h << 4;
591         }
592     }
593 
594     return h;
595 }
596 
597 /* converts a UTF-16 literal to UTF-8
598  * A literal can be one or two sequences of the form \uXXXX */
utf16_literal_to_utf8(const unsigned char * const input_pointer,const unsigned char * const input_end,unsigned char ** output_pointer)599 static unsigned char utf16_literal_to_utf8(const unsigned char * const input_pointer, const unsigned char * const input_end, unsigned char **output_pointer)
600 {
601     long unsigned int codepoint = 0;
602     unsigned int first_code = 0;
603     const unsigned char *first_sequence = input_pointer;
604     unsigned char utf8_length = 0;
605     unsigned char utf8_position = 0;
606     unsigned char sequence_length = 0;
607     unsigned char first_byte_mark = 0;
608 
609     if ((input_end - first_sequence) < 6)
610     {
611         /* input ends unexpectedly */
612         goto fail;
613     }
614 
615     /* get the first utf16 sequence */
616     first_code = parse_hex4(first_sequence + 2);
617 
618     /* check that the code is valid */
619     if (((first_code >= 0xDC00) && (first_code <= 0xDFFF)))
620     {
621         goto fail;
622     }
623 
624     /* UTF16 surrogate pair */
625     if ((first_code >= 0xD800) && (first_code <= 0xDBFF))
626     {
627         const unsigned char *second_sequence = first_sequence + 6;
628         unsigned int second_code = 0;
629         sequence_length = 12; /* \uXXXX\uXXXX */
630 
631         if ((input_end - second_sequence) < 6)
632         {
633             /* input ends unexpectedly */
634             goto fail;
635         }
636 
637         if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u'))
638         {
639             /* missing second half of the surrogate pair */
640             goto fail;
641         }
642 
643         /* get the second utf16 sequence */
644         second_code = parse_hex4(second_sequence + 2);
645         /* check that the code is valid */
646         if ((second_code < 0xDC00) || (second_code > 0xDFFF))
647         {
648             /* invalid second half of the surrogate pair */
649             goto fail;
650         }
651 
652 
653         /* calculate the unicode codepoint from the surrogate pair */
654         codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF));
655     }
656     else
657     {
658         sequence_length = 6; /* \uXXXX */
659         codepoint = first_code;
660     }
661 
662     /* encode as UTF-8
663      * takes at maximum 4 bytes to encode:
664      * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
665     if (codepoint < 0x80)
666     {
667         /* normal ascii, encoding 0xxxxxxx */
668         utf8_length = 1;
669     }
670     else if (codepoint < 0x800)
671     {
672         /* two bytes, encoding 110xxxxx 10xxxxxx */
673         utf8_length = 2;
674         first_byte_mark = 0xC0; /* 11000000 */
675     }
676     else if (codepoint < 0x10000)
677     {
678         /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */
679         utf8_length = 3;
680         first_byte_mark = 0xE0; /* 11100000 */
681     }
682     else if (codepoint <= 0x10FFFF)
683     {
684         /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */
685         utf8_length = 4;
686         first_byte_mark = 0xF0; /* 11110000 */
687     }
688     else
689     {
690         /* invalid unicode codepoint */
691         goto fail;
692     }
693 
694     /* encode as utf8 */
695     for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; utf8_position--)
696     {
697         /* 10xxxxxx */
698         (*output_pointer)[utf8_position] = (unsigned char)((codepoint | 0x80) & 0xBF);
699         codepoint >>= 6;
700     }
701     /* encode first byte */
702     if (utf8_length > 1)
703     {
704         (*output_pointer)[0] = (unsigned char)((codepoint | first_byte_mark) & 0xFF);
705     }
706     else
707     {
708         (*output_pointer)[0] = (unsigned char)(codepoint & 0x7F);
709     }
710 
711     *output_pointer += utf8_length;
712 
713     return sequence_length;
714 
715 fail:
716     return 0;
717 }
718 
719 /* Parse the input text into an unescaped cinput, and populate item. */
parse_string(cJSON * const item,parse_buffer * const input_buffer)720 static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_buffer)
721 {
722     const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1;
723     const unsigned char *input_end = buffer_at_offset(input_buffer) + 1;
724     unsigned char *output_pointer = NULL;
725     unsigned char *output = NULL;
726 
727     /* not a string */
728     if (buffer_at_offset(input_buffer)[0] != '\"')
729     {
730         goto fail;
731     }
732 
733     {
734         /* calculate approximate size of the output (overestimate) */
735         size_t allocation_length = 0;
736         size_t skipped_bytes = 0;
737         while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"'))
738         {
739             /* is escape sequence */
740             if (input_end[0] == '\\')
741             {
742                 if ((size_t)(input_end + 1 - input_buffer->content) >= input_buffer->length)
743                 {
744                     /* prevent buffer overflow when last input character is a backslash */
745                     goto fail;
746                 }
747                 skipped_bytes++;
748                 input_end++;
749             }
750             input_end++;
751         }
752         if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"'))
753         {
754             goto fail; /* string ended unexpectedly */
755         }
756 
757         /* This is at most how much we need for the output */
758         allocation_length = (size_t) (input_end - buffer_at_offset(input_buffer)) - skipped_bytes;
759         output = (unsigned char*)input_buffer->hooks.allocate(allocation_length + sizeof(""));
760         if (output == NULL)
761         {
762             goto fail; /* allocation failure */
763         }
764     }
765 
766     output_pointer = output;
767     /* loop through the string literal */
768     while (input_pointer < input_end)
769     {
770         if (*input_pointer != '\\')
771         {
772             *output_pointer++ = *input_pointer++;
773         }
774         /* escape sequence */
775         else
776         {
777             unsigned char sequence_length = 2;
778             if ((input_end - input_pointer) < 1)
779             {
780                 goto fail;
781             }
782 
783             switch (input_pointer[1])
784             {
785                 case 'b':
786                     *output_pointer++ = '\b';
787                     break;
788                 case 'f':
789                     *output_pointer++ = '\f';
790                     break;
791                 case 'n':
792                     *output_pointer++ = '\n';
793                     break;
794                 case 'r':
795                     *output_pointer++ = '\r';
796                     break;
797                 case 't':
798                     *output_pointer++ = '\t';
799                     break;
800                 case '\"':
801                 case '\\':
802                 case '/':
803                     *output_pointer++ = input_pointer[1];
804                     break;
805 
806                 /* UTF-16 literal */
807                 case 'u':
808                     sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer);
809                     if (sequence_length == 0)
810                     {
811                         /* failed to convert UTF16-literal to UTF-8 */
812                         goto fail;
813                     }
814                     break;
815 
816                 default:
817                     goto fail;
818             }
819             input_pointer += sequence_length;
820         }
821     }
822 
823     /* zero terminate the output */
824     *output_pointer = '\0';
825 
826     item->type = cJSON_String;
827     item->valuestring = (char*)output;
828 
829     input_buffer->offset = (size_t) (input_end - input_buffer->content);
830     input_buffer->offset++;
831 
832     return true;
833 
834 fail:
835     if (output != NULL)
836     {
837         input_buffer->hooks.deallocate(output);
838     }
839 
840     if (input_pointer != NULL)
841     {
842         input_buffer->offset = (size_t)(input_pointer - input_buffer->content);
843     }
844 
845     return false;
846 }
847 
848 /* Render the cstring provided to an escaped version that can be printed. */
print_string_ptr(const unsigned char * const input,printbuffer * const output_buffer)849 static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffer * const output_buffer)
850 {
851     const unsigned char *input_pointer = NULL;
852     unsigned char *output = NULL;
853     unsigned char *output_pointer = NULL;
854     size_t output_length = 0;
855     /* numbers of additional characters needed for escaping */
856     size_t escape_characters = 0;
857 
858     if (output_buffer == NULL)
859     {
860         return false;
861     }
862 
863     /* empty string */
864     if (input == NULL)
865     {
866         output = ensure(output_buffer, sizeof("\"\""));
867         if (output == NULL)
868         {
869             return false;
870         }
871         memcpy(output, "\"\"", 3); /* NOLINT */
872 
873         return true;
874     }
875 
876     /* set "flag" to 1 if something needs to be escaped */
877     for (input_pointer = input; *input_pointer; input_pointer++)
878     {
879         switch (*input_pointer)
880         {
881             case '\"':
882             case '\\':
883             case '\b':
884             case '\f':
885             case '\n':
886             case '\r':
887             case '\t':
888                 /* one character escape sequence */
889                 escape_characters++;
890                 break;
891             default:
892                 if (*input_pointer < 32)
893                 {
894                     /* UTF-16 escape sequence uXXXX */
895                     escape_characters += 5;
896                 }
897                 break;
898         }
899     }
900     output_length = (size_t)(input_pointer - input) + escape_characters;
901 
902     output = ensure(output_buffer, output_length + sizeof("\"\""));
903     if (output == NULL)
904     {
905         return false;
906     }
907 
908     /* no characters have to be escaped */
909     if (escape_characters == 0)
910     {
911         output[0] = '\"';
912         memcpy(output + 1, input, output_length);
913         output[output_length + 1] = '\"';
914         output[output_length + 2] = '\0';
915 
916         return true;
917     }
918 
919     output[0] = '\"';
920     output_pointer = output + 1;
921     /* copy the string */
922     for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++)
923     {
924         if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\'))
925         {
926             /* normal character, copy */
927             *output_pointer = *input_pointer;
928         }
929         else
930         {
931             /* character needs to be escaped */
932             *output_pointer++ = '\\';
933             switch (*input_pointer)
934             {
935                 case '\\':
936                     *output_pointer = '\\';
937                     break;
938                 case '\"':
939                     *output_pointer = '\"';
940                     break;
941                 case '\b':
942                     *output_pointer = 'b';
943                     break;
944                 case '\f':
945                     *output_pointer = 'f';
946                     break;
947                 case '\n':
948                     *output_pointer = 'n';
949                     break;
950                 case '\r':
951                     *output_pointer = 'r';
952                     break;
953                 case '\t':
954                     *output_pointer = 't';
955                     break;
956                 default:
957                     /* escape and print as unicode codepoint */
958                     snprintf((char*)output_pointer, 6 * sizeof(char), "u%04x", *input_pointer);
959                     output_pointer += 4;
960                     break;
961             }
962         }
963     }
964     output[output_length + 1] = '\"';
965     output[output_length + 2] = '\0';
966 
967     return true;
968 }
969 
970 /* Invoke print_string_ptr (which is useful) on an item. */
print_string(const cJSON * const item,printbuffer * const p)971 static cJSON_bool print_string(const cJSON * const item, printbuffer * const p)
972 {
973     return print_string_ptr((unsigned char*)item->valuestring, p);
974 }
975 
976 /* Predeclare these prototypes. */
977 static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer); /* NOLINT */
978 static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer); /* NOLINT */
979 static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer); /* NOLINT */
980 static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer); /* NOLINT */
981 static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer); /* NOLINT */
982 static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer); /* NOLINT */
983 
984 /* Utility to jump whitespace and cr/lf */
buffer_skip_whitespace(parse_buffer * const buffer)985 static parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer)
986 {
987     if ((buffer == NULL) || (buffer->content == NULL))
988     {
989         return NULL;
990     }
991 
992     while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32))
993     {
994        buffer->offset++;
995     }
996 
997     if (buffer->offset == buffer->length)
998     {
999         buffer->offset--;
1000     }
1001 
1002     return buffer;
1003 }
1004 
1005 /* skip the UTF-8 BOM (byte order mark) if it is at the beginning of a buffer */
skip_utf8_bom(parse_buffer * const buffer)1006 static parse_buffer *skip_utf8_bom(parse_buffer * const buffer)
1007 {
1008     if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0))
1009     {
1010         return NULL;
1011     }
1012 
1013     if (can_access_at_index(buffer, 4) && (strncmp((const char*)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0))
1014     {
1015         buffer->offset += 3;
1016     }
1017 
1018     return buffer;
1019 }
1020 
1021 /* Parse an object - create a new root, and populate. */
cJSON_ParseWithOpts(const char * value,const char ** return_parse_end,cJSON_bool require_null_terminated)1022 CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated)
1023 {
1024     parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } };
1025     cJSON *item = NULL;
1026 
1027     /* reset error position */
1028     global_error.json = NULL;
1029     global_error.position = 0;
1030 
1031     if (value == NULL)
1032     {
1033         goto fail;
1034     }
1035 
1036     buffer.content = (const unsigned char*)value;
1037     buffer.length = strlen((const char*)value) + sizeof("");
1038     buffer.offset = 0;
1039     buffer.hooks = global_hooks;
1040 
1041     item = cJSON_New_Item(&global_hooks);
1042     if (item == NULL) /* memory fail */
1043     {
1044         goto fail;
1045     }
1046 
1047     if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer))))
1048     {
1049         /* parse failure. ep is set. */
1050         goto fail;
1051     }
1052 
1053     /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
1054     if (require_null_terminated)
1055     {
1056         buffer_skip_whitespace(&buffer);
1057         if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0')
1058         {
1059             goto fail;
1060         }
1061     }
1062     if (return_parse_end)
1063     {
1064         *return_parse_end = (const char*)buffer_at_offset(&buffer);
1065     }
1066 
1067     return item;
1068 
1069 fail:
1070     if (item != NULL)
1071     {
1072         cJSON_Delete(item);
1073     }
1074 
1075     if (value != NULL)
1076     {
1077         error local_error;
1078         local_error.json = (const unsigned char*)value;
1079         local_error.position = 0;
1080 
1081         if (buffer.offset < buffer.length)
1082         {
1083             local_error.position = buffer.offset;
1084         }
1085         else if (buffer.length > 0)
1086         {
1087             local_error.position = buffer.length - 1;
1088         }
1089 
1090         if (return_parse_end != NULL)
1091         {
1092             *return_parse_end = (const char*)local_error.json + local_error.position;
1093         }
1094 
1095         global_error = local_error;
1096     }
1097 
1098     return NULL;
1099 }
1100 
1101 /* Default options for cJSON_Parse */
cJSON_Parse(const char * value)1102 CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value)
1103 {
1104     return cJSON_ParseWithOpts(value, 0, 0);
1105 }
1106 
1107 #define cjson_min(a, b) (((a) < (b)) ? (a) : (b))
1108 
print(const cJSON * const item,cJSON_bool format,const internal_hooks * const hooks)1109 static unsigned char *print(const cJSON * const item, cJSON_bool format, const internal_hooks * const hooks)
1110 {
1111     static const size_t default_buffer_size = 256;
1112     printbuffer buffer[1];
1113     unsigned char *printed = NULL;
1114 
1115     memset(buffer, 0, sizeof(buffer));
1116 
1117     /* create buffer */
1118     buffer->buffer = (unsigned char*) hooks->allocate(default_buffer_size);
1119     buffer->length = default_buffer_size;
1120     buffer->format = format;
1121     buffer->hooks = *hooks;
1122     if (buffer->buffer == NULL)
1123     {
1124         goto fail;
1125     }
1126 
1127     /* print the value */
1128     if (!print_value(item, buffer))
1129     {
1130         goto fail;
1131     }
1132     update_offset(buffer);
1133 
1134     /* check if reallocate is available */
1135     if (hooks->reallocate != NULL)
1136     {
1137         printed = (unsigned char*) hooks->reallocate(buffer->buffer, buffer->offset + 1);
1138         if (printed == NULL) {
1139             goto fail;
1140         }
1141         buffer->buffer = NULL;
1142     }
1143     else /* otherwise copy the JSON over to a new buffer */
1144     {
1145         printed = (unsigned char*) hooks->allocate(buffer->offset + 1);
1146         if (printed == NULL)
1147         {
1148             goto fail;
1149         }
1150         memcpy(printed, buffer->buffer, cjson_min(buffer->length, buffer->offset + 1));
1151         printed[buffer->offset] = '\0'; /* just to be sure */
1152 
1153         /* free the buffer */
1154         hooks->deallocate(buffer->buffer);
1155     }
1156 
1157     return printed;
1158 
1159 fail:
1160     if (buffer->buffer != NULL)
1161     {
1162         hooks->deallocate(buffer->buffer);
1163     }
1164 
1165     if (printed != NULL)
1166     {
1167         hooks->deallocate(printed);
1168     }
1169 
1170     return NULL;
1171 }
1172 
1173 /* Render a cJSON item/entity/structure to text. */
cJSON_Print(const cJSON * item)1174 CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item)
1175 {
1176     return (char*)print(item, true, &global_hooks);
1177 }
1178 
cJSON_PrintUnformatted(const cJSON * item)1179 CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item)
1180 {
1181     return (char*)print(item, false, &global_hooks);
1182 }
1183 
cJSON_PrintBuffered(const cJSON * item,int prebuffer,cJSON_bool fmt)1184 CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt)
1185 {
1186     printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };
1187 
1188     if (prebuffer < 0)
1189     {
1190         return NULL;
1191     }
1192 
1193     p.buffer = (unsigned char*)global_hooks.allocate((size_t)prebuffer);
1194     if (!p.buffer)
1195     {
1196         return NULL;
1197     }
1198 
1199     p.length = (size_t)prebuffer;
1200     p.offset = 0;
1201     p.noalloc = false;
1202     p.format = fmt;
1203     p.hooks = global_hooks;
1204 
1205     if (!print_value(item, &p))
1206     {
1207         global_hooks.deallocate(p.buffer);
1208         return NULL;
1209     }
1210 
1211     return (char*)p.buffer;
1212 }
1213 
cJSON_PrintPreallocated(cJSON * item,char * buf,const int len,const cJSON_bool fmt)1214 CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buf, const int len, const cJSON_bool fmt)
1215 {
1216     printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };
1217 
1218     if ((len < 0) || (buf == NULL))
1219     {
1220         return false;
1221     }
1222 
1223     p.buffer = (unsigned char*)buf;
1224     p.length = (size_t)len;
1225     p.offset = 0;
1226     p.noalloc = true;
1227     p.format = fmt;
1228     p.hooks = global_hooks;
1229 
1230     return print_value(item, &p);
1231 }
1232 
1233 /* Parser core - when encountering text, process appropriately. */
parse_value(cJSON * const item,parse_buffer * const input_buffer)1234 static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer)
1235 {
1236     if ((input_buffer == NULL) || (input_buffer->content == NULL))
1237     {
1238         return false; /* no input */
1239     }
1240 
1241     /* parse the different types of values */
1242     /* null */
1243     if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "null", 4) == 0))
1244     {
1245         item->type = cJSON_NULL;
1246         input_buffer->offset += 4;
1247         return true;
1248     }
1249     /* false */
1250     if (can_read(input_buffer, 5) && (strncmp((const char*)buffer_at_offset(input_buffer), "false", 5) == 0))
1251     {
1252         item->type = cJSON_False;
1253         input_buffer->offset += 5;
1254         return true;
1255     }
1256     /* true */
1257     if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "true", 4) == 0))
1258     {
1259         item->type = cJSON_True;
1260         item->valueint = 1;
1261         input_buffer->offset += 4;
1262         return true;
1263     }
1264     /* string */
1265     if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"'))
1266     {
1267         return parse_string(item, input_buffer);
1268     }
1269     /* number */
1270     if (can_access_at_index(input_buffer, 0) && ((buffer_at_offset(input_buffer)[0] == '-') || ((buffer_at_offset(input_buffer)[0] >= '0') && (buffer_at_offset(input_buffer)[0] <= '9'))))
1271     {
1272         return parse_number(item, input_buffer);
1273     }
1274     /* array */
1275     if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '['))
1276     {
1277         return parse_array(item, input_buffer);
1278     }
1279     /* object */
1280     if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{'))
1281     {
1282         return parse_object(item, input_buffer);
1283     }
1284 
1285     return false;
1286 }
1287 
1288 /* Render a value to text. */
print_value(const cJSON * const item,printbuffer * const output_buffer)1289 static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer)
1290 {
1291     unsigned char *output = NULL;
1292 
1293     if ((item == NULL) || (output_buffer == NULL))
1294     {
1295         return false;
1296     }
1297 
1298     switch ((item->type) & 0xFF)
1299     {
1300         case cJSON_NULL:
1301             output = ensure(output_buffer, 5);
1302             if (output == NULL)
1303             {
1304                 return false;
1305             }
1306             memcpy(output, "null", 5); /* NOLINT */
1307             return true;
1308 
1309         case cJSON_False:
1310             output = ensure(output_buffer, 6);
1311             if (output == NULL)
1312             {
1313                 return false;
1314             }
1315             memcpy(output, "false", 6); /* NOLINT */
1316             return true;
1317 
1318         case cJSON_True:
1319             output = ensure(output_buffer, 5);
1320             if (output == NULL)
1321             {
1322                 return false;
1323             }
1324             memcpy(output, "true", 5); /* NOLINT */
1325             return true;
1326 
1327         case cJSON_Number:
1328             return print_number(item, output_buffer);
1329 
1330         case cJSON_Raw:
1331         {
1332             size_t raw_length = 0;
1333             if (item->valuestring == NULL)
1334             {
1335                 return false;
1336             }
1337 
1338             raw_length = strlen(item->valuestring) + sizeof("");
1339             output = ensure(output_buffer, raw_length);
1340             if (output == NULL)
1341             {
1342                 return false;
1343             }
1344             memcpy(output, item->valuestring, raw_length);
1345             return true;
1346         }
1347 
1348         case cJSON_String:
1349             return print_string(item, output_buffer);
1350 
1351         case cJSON_Array:
1352             return print_array(item, output_buffer);
1353 
1354         case cJSON_Object:
1355             return print_object(item, output_buffer);
1356 
1357         default:
1358             return false;
1359     }
1360 }
1361 
1362 /* Build an array from input text. */
parse_array(cJSON * const item,parse_buffer * const input_buffer)1363 static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer)
1364 {
1365     cJSON *head = NULL; /* head of the linked list */
1366     cJSON *current_item = NULL;
1367 
1368     if (input_buffer->depth >= CJSON_NESTING_LIMIT)
1369     {
1370         return false; /* to deeply nested */
1371     }
1372     input_buffer->depth++;
1373 
1374     if (buffer_at_offset(input_buffer)[0] != '[')
1375     {
1376         /* not an array */
1377         goto fail;
1378     }
1379 
1380     input_buffer->offset++;
1381     buffer_skip_whitespace(input_buffer);
1382     if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']'))
1383     {
1384         /* empty array */
1385         goto success;
1386     }
1387 
1388     /* check if we skipped to the end of the buffer */
1389     if (cannot_access_at_index(input_buffer, 0))
1390     {
1391         input_buffer->offset--;
1392         goto fail;
1393     }
1394 
1395     /* step back to character in front of the first element */
1396     input_buffer->offset--;
1397     /* loop through the comma separated array elements */
1398     do
1399     {
1400         /* allocate next item */
1401         cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));
1402         if (new_item == NULL)
1403         {
1404             goto fail; /* allocation failure */
1405         }
1406 
1407         /* attach next item to list */
1408         if (head == NULL)
1409         {
1410             /* start the linked list */
1411             current_item = head = new_item;
1412         }
1413         else
1414         {
1415             /* add to the end and advance */
1416             current_item->next = new_item;
1417             new_item->prev = current_item;
1418             current_item = new_item;
1419         }
1420 
1421         /* parse next value */
1422         input_buffer->offset++;
1423         buffer_skip_whitespace(input_buffer);
1424         if (!parse_value(current_item, input_buffer))
1425         {
1426             goto fail; /* failed to parse value */
1427         }
1428         buffer_skip_whitespace(input_buffer);
1429     }
1430     while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
1431 
1432     if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']')
1433     {
1434         goto fail; /* expected end of array */
1435     }
1436 
1437 success:
1438     input_buffer->depth--;
1439 
1440     item->type = cJSON_Array;
1441     item->child = head;
1442 
1443     input_buffer->offset++;
1444 
1445     return true;
1446 
1447 fail:
1448     if (head != NULL)
1449     {
1450         cJSON_Delete(head);
1451     }
1452 
1453     return false;
1454 }
1455 
1456 /* Render an array to text */
print_array(const cJSON * const item,printbuffer * const output_buffer)1457 static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer)
1458 {
1459     unsigned char *output_pointer = NULL;
1460     size_t length = 0;
1461     cJSON *current_element = item->child;
1462 
1463     if (output_buffer == NULL)
1464     {
1465         return false;
1466     }
1467 
1468     /* Compose the output array. */
1469     /* opening square bracket */
1470     output_pointer = ensure(output_buffer, 1);
1471     if (output_pointer == NULL)
1472     {
1473         return false;
1474     }
1475 
1476     *output_pointer = '[';
1477     output_buffer->offset++;
1478     output_buffer->depth++;
1479 
1480     while (current_element != NULL)
1481     {
1482         if (!print_value(current_element, output_buffer))
1483         {
1484             return false;
1485         }
1486         update_offset(output_buffer);
1487         if (current_element->next)
1488         {
1489             length = (size_t) (output_buffer->format ? 2 : 1);
1490             output_pointer = ensure(output_buffer, length + 1);
1491             if (output_pointer == NULL)
1492             {
1493                 return false;
1494             }
1495             *output_pointer++ = ',';
1496             if(output_buffer->format)
1497             {
1498                 *output_pointer++ = ' ';
1499             }
1500             *output_pointer = '\0';
1501             output_buffer->offset += length;
1502         }
1503         current_element = current_element->next;
1504     }
1505 
1506     output_pointer = ensure(output_buffer, 2);
1507     if (output_pointer == NULL)
1508     {
1509         return false;
1510     }
1511     *output_pointer++ = ']';
1512     *output_pointer = '\0';
1513     output_buffer->depth--;
1514 
1515     return true;
1516 }
1517 
1518 /* Build an object from the text. */
parse_object(cJSON * const item,parse_buffer * const input_buffer)1519 static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer)
1520 {
1521     cJSON *head = NULL; /* linked list head */
1522     cJSON *current_item = NULL;
1523 
1524     if (input_buffer->depth >= CJSON_NESTING_LIMIT)
1525     {
1526         return false; /* to deeply nested */
1527     }
1528     input_buffer->depth++;
1529 
1530     if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{'))
1531     {
1532         goto fail; /* not an object */
1533     }
1534 
1535     input_buffer->offset++;
1536     buffer_skip_whitespace(input_buffer);
1537     if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}'))
1538     {
1539         goto success; /* empty object */
1540     }
1541 
1542     /* check if we skipped to the end of the buffer */
1543     if (cannot_access_at_index(input_buffer, 0))
1544     {
1545         input_buffer->offset--;
1546         goto fail;
1547     }
1548 
1549     /* step back to character in front of the first element */
1550     input_buffer->offset--;
1551     /* loop through the comma separated array elements */
1552     do
1553     {
1554         /* allocate next item */
1555         cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));
1556         if (new_item == NULL)
1557         {
1558             goto fail; /* allocation failure */
1559         }
1560 
1561         /* attach next item to list */
1562         if (head == NULL)
1563         {
1564             /* start the linked list */
1565             current_item = head = new_item;
1566         }
1567         else
1568         {
1569             /* add to the end and advance */
1570             current_item->next = new_item;
1571             new_item->prev = current_item;
1572             current_item = new_item;
1573         }
1574 
1575         /* parse the name of the child */
1576         input_buffer->offset++;
1577         buffer_skip_whitespace(input_buffer);
1578         if (!parse_string(current_item, input_buffer))
1579         {
1580             goto fail; /* failed to parse name */
1581         }
1582         buffer_skip_whitespace(input_buffer);
1583 
1584         /* swap valuestring and string, because we parsed the name */
1585         current_item->string = current_item->valuestring;
1586         current_item->valuestring = NULL;
1587 
1588         if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':'))
1589         {
1590             goto fail; /* invalid object */
1591         }
1592 
1593         /* parse the value */
1594         input_buffer->offset++;
1595         buffer_skip_whitespace(input_buffer);
1596         if (!parse_value(current_item, input_buffer))
1597         {
1598             goto fail; /* failed to parse value */
1599         }
1600         buffer_skip_whitespace(input_buffer);
1601     }
1602     while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
1603 
1604     if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}'))
1605     {
1606         goto fail; /* expected end of object */
1607     }
1608 
1609 success:
1610     input_buffer->depth--;
1611 
1612     item->type = cJSON_Object;
1613     item->child = head;
1614 
1615     input_buffer->offset++;
1616     return true;
1617 
1618 fail:
1619     if (head != NULL)
1620     {
1621         cJSON_Delete(head);
1622     }
1623 
1624     return false;
1625 }
1626 
1627 /* Render an object to text. */
print_object(const cJSON * const item,printbuffer * const output_buffer)1628 static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer)
1629 {
1630     unsigned char *output_pointer = NULL;
1631     size_t length = 0;
1632     cJSON *current_item = item->child;
1633 
1634     if (output_buffer == NULL)
1635     {
1636         return false;
1637     }
1638 
1639     /* Compose the output: */
1640     length = (size_t) (output_buffer->format ? 2 : 1); /* fmt: {\n */
1641     output_pointer = ensure(output_buffer, length + 1);
1642     if (output_pointer == NULL)
1643     {
1644         return false;
1645     }
1646 
1647     *output_pointer++ = '{';
1648     output_buffer->depth++;
1649     if (output_buffer->format)
1650     {
1651         *output_pointer++ = '\n';
1652     }
1653     output_buffer->offset += length;
1654 
1655     while (current_item)
1656     {
1657         if (output_buffer->format)
1658         {
1659             size_t i;
1660             output_pointer = ensure(output_buffer, output_buffer->depth);
1661             if (output_pointer == NULL)
1662             {
1663                 return false;
1664             }
1665             for (i = 0; i < output_buffer->depth; i++)
1666             {
1667                 *output_pointer++ = '\t';
1668             }
1669             output_buffer->offset += output_buffer->depth;
1670         }
1671 
1672         /* print key */
1673         if (!print_string_ptr((unsigned char*)current_item->string, output_buffer))
1674         {
1675             return false;
1676         }
1677         update_offset(output_buffer);
1678 
1679         length = (size_t) (output_buffer->format ? 2 : 1);
1680         output_pointer = ensure(output_buffer, length);
1681         if (output_pointer == NULL)
1682         {
1683             return false;
1684         }
1685         *output_pointer++ = ':';
1686         if (output_buffer->format)
1687         {
1688             *output_pointer++ = '\t';
1689         }
1690         output_buffer->offset += length;
1691 
1692         /* print value */
1693         if (!print_value(current_item, output_buffer))
1694         {
1695             return false;
1696         }
1697         update_offset(output_buffer);
1698 
1699         /* print comma if not last */
1700         length = ((size_t)(output_buffer->format ? 1 : 0) + (size_t)(current_item->next ? 1 : 0));
1701         output_pointer = ensure(output_buffer, length + 1);
1702         if (output_pointer == NULL)
1703         {
1704             return false;
1705         }
1706         if (current_item->next)
1707         {
1708             *output_pointer++ = ',';
1709         }
1710 
1711         if (output_buffer->format)
1712         {
1713             *output_pointer++ = '\n';
1714         }
1715         *output_pointer = '\0';
1716         output_buffer->offset += length;
1717 
1718         current_item = current_item->next;
1719     }
1720 
1721     output_pointer = ensure(output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2);
1722     if (output_pointer == NULL)
1723     {
1724         return false;
1725     }
1726     if (output_buffer->format)
1727     {
1728         size_t i;
1729         for (i = 0; i < (output_buffer->depth - 1); i++)
1730         {
1731             *output_pointer++ = '\t';
1732         }
1733     }
1734     *output_pointer++ = '}';
1735     *output_pointer = '\0';
1736     output_buffer->depth--;
1737 
1738     return true;
1739 }
1740 
1741 /* Get Array size/item / object item. */
cJSON_GetArraySize(const cJSON * array)1742 CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array)
1743 {
1744     cJSON *child = NULL;
1745     size_t size = 0;
1746 
1747     if (array == NULL)
1748     {
1749         return 0;
1750     }
1751 
1752     child = array->child;
1753 
1754     while(child != NULL)
1755     {
1756         size++;
1757         child = child->next;
1758     }
1759 
1760     /* FIXME: Can overflow here. Cannot be fixed without breaking the API */
1761 
1762     return (int)size;
1763 }
1764 
get_array_item(const cJSON * array,size_t index)1765 static cJSON* get_array_item(const cJSON *array, size_t index)
1766 {
1767     cJSON *current_child = NULL;
1768 
1769     if (array == NULL)
1770     {
1771         return NULL;
1772     }
1773 
1774     current_child = array->child;
1775     while ((current_child != NULL) && (index > 0))
1776     {
1777         index--;
1778         current_child = current_child->next;
1779     }
1780 
1781     return current_child;
1782 }
1783 
cJSON_GetArrayItem(const cJSON * array,int index)1784 CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index)
1785 {
1786     if (index < 0)
1787     {
1788         return NULL;
1789     }
1790 
1791     return get_array_item(array, (size_t)index);
1792 }
1793 
get_object_item(const cJSON * const object,const char * const name,const cJSON_bool case_sensitive)1794 static cJSON *get_object_item(const cJSON * const object, const char * const name, const cJSON_bool case_sensitive)
1795 {
1796     cJSON *current_element = NULL;
1797 
1798     if ((object == NULL) || (name == NULL))
1799     {
1800         return NULL;
1801     }
1802 
1803     current_element = object->child;
1804     if (case_sensitive)
1805     {
1806         while ((current_element != NULL) && (current_element->string != NULL) && (strcmp(name, current_element->string) != 0))
1807         {
1808             current_element = current_element->next;
1809         }
1810     }
1811     else
1812     {
1813         while ((current_element != NULL) && (case_insensitive_strcmp((const unsigned char*)name, (const unsigned char*)(current_element->string)) != 0))
1814         {
1815             current_element = current_element->next;
1816         }
1817     }
1818 
1819     if ((current_element == NULL) || (current_element->string == NULL)) {
1820         return NULL;
1821     }
1822 
1823     return current_element;
1824 }
1825 
cJSON_GetObjectItem(const cJSON * const object,const char * const string)1826 CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string)
1827 {
1828     return get_object_item(object, string, false);
1829 }
1830 
cJSON_GetObjectItemCaseSensitive(const cJSON * const object,const char * const string)1831 CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string)
1832 {
1833     return get_object_item(object, string, true);
1834 }
1835 
cJSON_HasObjectItem(const cJSON * object,const char * string)1836 CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string)
1837 {
1838     return cJSON_GetObjectItem(object, string) ? 1 : 0;
1839 }
1840 
1841 /* Utility for array list handling. */
suffix_object(cJSON * prev,cJSON * item)1842 static void suffix_object(cJSON *prev, cJSON *item)
1843 {
1844     prev->next = item;
1845     item->prev = prev;
1846 }
1847 
1848 /* Utility for handling references. */
create_reference(const cJSON * item,const internal_hooks * const hooks)1849 static cJSON *create_reference(const cJSON *item, const internal_hooks * const hooks)
1850 {
1851     cJSON *reference = NULL;
1852     if (item == NULL)
1853     {
1854         return NULL;
1855     }
1856 
1857     reference = cJSON_New_Item(hooks);
1858     if (reference == NULL)
1859     {
1860         return NULL;
1861     }
1862 
1863     memcpy(reference, item, sizeof(cJSON));
1864     reference->string = NULL;
1865     reference->type |= cJSON_IsReference;
1866     reference->next = reference->prev = NULL;
1867     return reference;
1868 }
1869 
add_item_to_array(cJSON * array,cJSON * item)1870 static cJSON_bool add_item_to_array(cJSON *array, cJSON *item)
1871 {
1872     cJSON *child = NULL;
1873 
1874     if ((item == NULL) || (array == NULL))
1875     {
1876         return false;
1877     }
1878 
1879     child = array->child;
1880 
1881     if (child == NULL)
1882     {
1883         /* list is empty, start new one */
1884         array->child = item;
1885     }
1886     else
1887     {
1888         /* append to the end */
1889         while (child->next)
1890         {
1891             child = child->next;
1892         }
1893         suffix_object(child, item);
1894     }
1895 
1896     return true;
1897 }
1898 
1899 /* Add item to array/object. */
cJSON_AddItemToArray(cJSON * array,cJSON * item)1900 CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON *array, cJSON *item)
1901 {
1902     add_item_to_array(array, item);
1903 }
1904 
1905 #if defined(__clang__) || (defined(__GNUC__)  && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
1906     #pragma GCC diagnostic push
1907 #endif
1908 #ifdef __GNUC__
1909     #if ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 1)))
1910         #pragma GCC diagnostic ignored "-Wcast-qual"
1911     #endif
1912 #endif
1913 /* helper function to cast away const */
cast_away_const(const void * string)1914 static void* cast_away_const(const void* string)
1915 {
1916     return (void*)string;
1917 }
1918 #if defined(__clang__) || (defined(__GNUC__)  && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
1919     #pragma GCC diagnostic pop
1920 #endif
1921 
1922 
add_item_to_object(cJSON * const object,const char * const string,cJSON * const item,const internal_hooks * const hooks,const cJSON_bool constant_key)1923 static cJSON_bool add_item_to_object(cJSON * const object, const char * const string, cJSON * const item, const internal_hooks * const hooks, const cJSON_bool constant_key)
1924 {
1925     char *new_key = NULL;
1926     int new_type = cJSON_Invalid;
1927 
1928     if ((object == NULL) || (string == NULL) || (item == NULL))
1929     {
1930         return false;
1931     }
1932 
1933     if (constant_key)
1934     {
1935         new_key = (char*)cast_away_const(string);
1936         new_type = item->type | cJSON_StringIsConst;
1937     }
1938     else
1939     {
1940         new_key = (char*)cJSON_strdup((const unsigned char*)string, hooks);
1941         if (new_key == NULL)
1942         {
1943             return false;
1944         }
1945 
1946         new_type = item->type & ~cJSON_StringIsConst;
1947     }
1948 
1949     if (!(item->type & cJSON_StringIsConst) && (item->string != NULL))
1950     {
1951         hooks->deallocate(item->string);
1952     }
1953 
1954     item->string = new_key;
1955     item->type = new_type;
1956 
1957     return add_item_to_array(object, item);
1958 }
1959 
cJSON_AddItemToObject(cJSON * object,const char * string,cJSON * item)1960 CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item)
1961 {
1962     add_item_to_object(object, string, item, &global_hooks, false);
1963 }
1964 
1965 /* Add an item to an object with constant string as key */
cJSON_AddItemToObjectCS(cJSON * object,const char * string,cJSON * item)1966 CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item)
1967 {
1968     add_item_to_object(object, string, item, &global_hooks, true);
1969 }
1970 
cJSON_AddItemReferenceToArray(cJSON * array,cJSON * item)1971 CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)
1972 {
1973     if (array == NULL)
1974     {
1975         return;
1976     }
1977 
1978     add_item_to_array(array, create_reference(item, &global_hooks));
1979 }
1980 
cJSON_AddItemReferenceToObject(cJSON * object,const char * string,cJSON * item)1981 CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item)
1982 {
1983     if ((object == NULL) || (string == NULL))
1984     {
1985         return;
1986     }
1987 
1988     add_item_to_object(object, string, create_reference(item, &global_hooks), &global_hooks, false);
1989 }
1990 
cJSON_AddNullToObject(cJSON * const object,const char * const name)1991 CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name)
1992 {
1993     cJSON *null = cJSON_CreateNull();
1994     if (add_item_to_object(object, name, null, &global_hooks, false))
1995     {
1996         return null;
1997     }
1998 
1999     cJSON_Delete(null);
2000     return NULL;
2001 }
2002 
cJSON_AddTrueToObject(cJSON * const object,const char * const name)2003 CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name)
2004 {
2005     cJSON *true_item = cJSON_CreateTrue();
2006     if (add_item_to_object(object, name, true_item, &global_hooks, false))
2007     {
2008         return true_item;
2009     }
2010 
2011     cJSON_Delete(true_item);
2012     return NULL;
2013 }
2014 
cJSON_AddFalseToObject(cJSON * const object,const char * const name)2015 CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name)
2016 {
2017     cJSON *false_item = cJSON_CreateFalse();
2018     if (add_item_to_object(object, name, false_item, &global_hooks, false))
2019     {
2020         return false_item;
2021     }
2022 
2023     cJSON_Delete(false_item);
2024     return NULL;
2025 }
2026 
cJSON_AddBoolToObject(cJSON * const object,const char * const name,const cJSON_bool boolean)2027 CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean)
2028 {
2029     cJSON *bool_item = cJSON_CreateBool(boolean);
2030     if (add_item_to_object(object, name, bool_item, &global_hooks, false))
2031     {
2032         return bool_item;
2033     }
2034 
2035     cJSON_Delete(bool_item);
2036     return NULL;
2037 }
2038 
cJSON_AddNumberToObject(cJSON * const object,const char * const name,const double number)2039 CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number)
2040 {
2041     cJSON *number_item = cJSON_CreateNumber(number);
2042     if (add_item_to_object(object, name, number_item, &global_hooks, false))
2043     {
2044         return number_item;
2045     }
2046 
2047     cJSON_Delete(number_item);
2048     return NULL;
2049 }
2050 
cJSON_AddStringToObject(cJSON * const object,const char * const name,const char * const string)2051 CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string)
2052 {
2053     cJSON *string_item = cJSON_CreateString(string);
2054     if (add_item_to_object(object, name, string_item, &global_hooks, false))
2055     {
2056         return string_item;
2057     }
2058 
2059     cJSON_Delete(string_item);
2060     return NULL;
2061 }
2062 
cJSON_AddRawToObject(cJSON * const object,const char * const name,const char * const raw)2063 CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw)
2064 {
2065     cJSON *raw_item = cJSON_CreateRaw(raw);
2066     if (add_item_to_object(object, name, raw_item, &global_hooks, false))
2067     {
2068         return raw_item;
2069     }
2070 
2071     cJSON_Delete(raw_item);
2072     return NULL;
2073 }
2074 
cJSON_AddObjectToObject(cJSON * const object,const char * const name)2075 CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name)
2076 {
2077     cJSON *object_item = cJSON_CreateObject();
2078     if (add_item_to_object(object, name, object_item, &global_hooks, false))
2079     {
2080         return object_item;
2081     }
2082 
2083     cJSON_Delete(object_item);
2084     return NULL;
2085 }
2086 
cJSON_AddArrayToObject(cJSON * const object,const char * const name)2087 CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name)
2088 {
2089     cJSON *array = cJSON_CreateArray();
2090     if (add_item_to_object(object, name, array, &global_hooks, false))
2091     {
2092         return array;
2093     }
2094 
2095     cJSON_Delete(array);
2096     return NULL;
2097 }
2098 
cJSON_DetachItemViaPointer(cJSON * parent,cJSON * const item)2099 CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item)
2100 {
2101     if ((parent == NULL) || (item == NULL))
2102     {
2103         return NULL;
2104     }
2105 
2106     if (item->prev != NULL)
2107     {
2108         /* not the first element */
2109         item->prev->next = item->next;
2110     }
2111     if (item->next != NULL)
2112     {
2113         /* not the last element */
2114         item->next->prev = item->prev;
2115     }
2116 
2117     if (item == parent->child)
2118     {
2119         /* first element */
2120         parent->child = item->next;
2121     }
2122     /* make sure the detached item doesn't point anywhere anymore */
2123     item->prev = NULL;
2124     item->next = NULL;
2125 
2126     return item;
2127 }
2128 
cJSON_DetachItemFromArray(cJSON * array,int which)2129 CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which)
2130 {
2131     if (which < 0)
2132     {
2133         return NULL;
2134     }
2135 
2136     return cJSON_DetachItemViaPointer(array, get_array_item(array, (size_t)which));
2137 }
2138 
cJSON_DeleteItemFromArray(cJSON * array,int which)2139 CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which)
2140 {
2141     cJSON_Delete(cJSON_DetachItemFromArray(array, which));
2142 }
2143 
cJSON_DetachItemFromObject(cJSON * object,const char * string)2144 CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string)
2145 {
2146     cJSON *to_detach = cJSON_GetObjectItem(object, string);
2147 
2148     return cJSON_DetachItemViaPointer(object, to_detach);
2149 }
2150 
cJSON_DetachItemFromObjectCaseSensitive(cJSON * object,const char * string)2151 CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string)
2152 {
2153     cJSON *to_detach = cJSON_GetObjectItemCaseSensitive(object, string);
2154 
2155     return cJSON_DetachItemViaPointer(object, to_detach);
2156 }
2157 
cJSON_DeleteItemFromObject(cJSON * object,const char * string)2158 CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string)
2159 {
2160     cJSON_Delete(cJSON_DetachItemFromObject(object, string));
2161 }
2162 
cJSON_DeleteItemFromObjectCaseSensitive(cJSON * object,const char * string)2163 CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string)
2164 {
2165     cJSON_Delete(cJSON_DetachItemFromObjectCaseSensitive(object, string));
2166 }
2167 
2168 /* Replace array/object items with new ones. */
cJSON_InsertItemInArray(cJSON * array,int which,cJSON * newitem)2169 CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem)
2170 {
2171     cJSON *after_inserted = NULL;
2172 
2173     if (which < 0)
2174     {
2175         return;
2176     }
2177 
2178     after_inserted = get_array_item(array, (size_t)which);
2179     if (after_inserted == NULL)
2180     {
2181         add_item_to_array(array, newitem);
2182         return;
2183     }
2184 
2185     newitem->next = after_inserted;
2186     newitem->prev = after_inserted->prev;
2187     after_inserted->prev = newitem;
2188     if (after_inserted == array->child)
2189     {
2190         array->child = newitem;
2191     }
2192     else
2193     {
2194         newitem->prev->next = newitem;
2195     }
2196 }
2197 
cJSON_ReplaceItemViaPointer(cJSON * const parent,cJSON * const item,cJSON * replacement)2198 CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement)
2199 {
2200     if ((parent == NULL) || (replacement == NULL) || (item == NULL))
2201     {
2202         return false;
2203     }
2204 
2205     if (replacement == item)
2206     {
2207         return true;
2208     }
2209 
2210     replacement->next = item->next;
2211     replacement->prev = item->prev;
2212 
2213     if (replacement->next != NULL)
2214     {
2215         replacement->next->prev = replacement;
2216     }
2217     if (replacement->prev != NULL)
2218     {
2219         replacement->prev->next = replacement;
2220     }
2221     if (parent->child == item)
2222     {
2223         parent->child = replacement;
2224     }
2225 
2226     item->next = NULL;
2227     item->prev = NULL;
2228     cJSON_Delete(item);
2229 
2230     return true;
2231 }
2232 
cJSON_ReplaceItemInArray(cJSON * array,int which,cJSON * newitem)2233 CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem)
2234 {
2235     if (which < 0)
2236     {
2237         return;
2238     }
2239 
2240     cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), newitem);
2241 }
2242 
replace_item_in_object(cJSON * object,const char * string,cJSON * replacement,cJSON_bool case_sensitive)2243 static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSON *replacement, cJSON_bool case_sensitive)
2244 {
2245     if ((replacement == NULL) || (string == NULL))
2246     {
2247         return false;
2248     }
2249 
2250     /* replace the name in the replacement */
2251     if (!(replacement->type & cJSON_StringIsConst) && (replacement->string != NULL))
2252     {
2253         cJSON_free(replacement->string);
2254     }
2255     replacement->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
2256     replacement->type &= ~cJSON_StringIsConst;
2257 
2258     cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement);
2259 
2260     return true;
2261 }
2262 
cJSON_ReplaceItemInObject(cJSON * object,const char * string,cJSON * newitem)2263 CJSON_PUBLIC(void) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem)
2264 {
2265     replace_item_in_object(object, string, newitem, false);
2266 }
2267 
cJSON_ReplaceItemInObjectCaseSensitive(cJSON * object,const char * string,cJSON * newitem)2268 CJSON_PUBLIC(void) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem)
2269 {
2270     replace_item_in_object(object, string, newitem, true);
2271 }
2272 
2273 /* Create basic types: */
cJSON_CreateNull(void)2274 CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void)
2275 {
2276     cJSON *item = cJSON_New_Item(&global_hooks);
2277     if(item)
2278     {
2279         item->type = cJSON_NULL;
2280     }
2281 
2282     return item;
2283 }
2284 
cJSON_CreateTrue(void)2285 CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void)
2286 {
2287     cJSON *item = cJSON_New_Item(&global_hooks);
2288     if(item)
2289     {
2290         item->type = cJSON_True;
2291     }
2292 
2293     return item;
2294 }
2295 
cJSON_CreateFalse(void)2296 CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void)
2297 {
2298     cJSON *item = cJSON_New_Item(&global_hooks);
2299     if(item)
2300     {
2301         item->type = cJSON_False;
2302     }
2303 
2304     return item;
2305 }
2306 
cJSON_CreateBool(cJSON_bool b)2307 CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool b)
2308 {
2309     cJSON *item = cJSON_New_Item(&global_hooks);
2310     if(item)
2311     {
2312         item->type = b ? cJSON_True : cJSON_False;
2313     }
2314 
2315     return item;
2316 }
2317 
cJSON_CreateNumber(double num)2318 CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num)
2319 {
2320     cJSON *item = cJSON_New_Item(&global_hooks);
2321     if(item)
2322     {
2323         item->type = cJSON_Number;
2324         item->valuedouble = num;
2325 
2326         /* use saturation in case of overflow */
2327         if (num >= INT_MAX)
2328         {
2329             item->valueint = INT_MAX;
2330         }
2331         else if (num <= (double)INT_MIN)
2332         {
2333             item->valueint = INT_MIN;
2334         }
2335         else
2336         {
2337             item->valueint = (int)num;
2338         }
2339     }
2340 
2341     return item;
2342 }
2343 
cJSON_CreateString(const char * string)2344 CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string)
2345 {
2346     cJSON *item = cJSON_New_Item(&global_hooks);
2347     if(item)
2348     {
2349         item->type = cJSON_String;
2350         item->valuestring = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
2351         if(!item->valuestring)
2352         {
2353             cJSON_Delete(item);
2354             return NULL;
2355         }
2356     }
2357 
2358     return item;
2359 }
2360 
cJSON_CreateStringReference(const char * string)2361 CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string)
2362 {
2363     cJSON *item = cJSON_New_Item(&global_hooks);
2364     if (item != NULL)
2365     {
2366         item->type = cJSON_String | cJSON_IsReference;
2367         item->valuestring = (char*)cast_away_const(string);
2368     }
2369 
2370     return item;
2371 }
2372 
cJSON_CreateObjectReference(const cJSON * child)2373 CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child)
2374 {
2375     cJSON *item = cJSON_New_Item(&global_hooks);
2376     if (item != NULL) {
2377         item->type = cJSON_Object | cJSON_IsReference;
2378         item->child = (cJSON*)cast_away_const(child);
2379     }
2380 
2381     return item;
2382 }
2383 
cJSON_CreateArrayReference(const cJSON * child)2384 CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child) {
2385     cJSON *item = cJSON_New_Item(&global_hooks);
2386     if (item != NULL) {
2387         item->type = cJSON_Array | cJSON_IsReference;
2388         item->child = (cJSON*)cast_away_const(child);
2389     }
2390 
2391     return item;
2392 }
2393 
cJSON_CreateRaw(const char * raw)2394 CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw)
2395 {
2396     cJSON *item = cJSON_New_Item(&global_hooks);
2397     if(item)
2398     {
2399         item->type = cJSON_Raw;
2400         item->valuestring = (char*)cJSON_strdup((const unsigned char*)raw, &global_hooks);
2401         if(!item->valuestring)
2402         {
2403             cJSON_Delete(item);
2404             return NULL;
2405         }
2406     }
2407 
2408     return item;
2409 }
2410 
cJSON_CreateArray(void)2411 CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void)
2412 {
2413     cJSON *item = cJSON_New_Item(&global_hooks);
2414     if(item)
2415     {
2416         item->type=cJSON_Array;
2417     }
2418 
2419     return item;
2420 }
2421 
cJSON_CreateObject(void)2422 CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void)
2423 {
2424     cJSON *item = cJSON_New_Item(&global_hooks);
2425     if (item)
2426     {
2427         item->type = cJSON_Object;
2428     }
2429 
2430     return item;
2431 }
2432 
2433 /* Create Arrays: */
cJSON_CreateIntArray(const int * numbers,int count)2434 CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count)
2435 {
2436     size_t i = 0;
2437     cJSON *n = NULL;
2438     cJSON *p = NULL;
2439     cJSON *a = NULL;
2440 
2441     if ((count < 0) || (numbers == NULL))
2442     {
2443         return NULL;
2444     }
2445 
2446     a = cJSON_CreateArray();
2447     for(i = 0; a && (i < (size_t)count); i++)
2448     {
2449         n = cJSON_CreateNumber(numbers[i]);
2450         if (!n)
2451         {
2452             cJSON_Delete(a);
2453             return NULL;
2454         }
2455         if(!i)
2456         {
2457             a->child = n;
2458         }
2459         else
2460         {
2461             suffix_object(p, n);
2462         }
2463         p = n;
2464     }
2465 
2466     return a;
2467 }
2468 
cJSON_CreateFloatArray(const float * numbers,int count)2469 CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count)
2470 {
2471     size_t i = 0;
2472     cJSON *n = NULL;
2473     cJSON *p = NULL;
2474     cJSON *a = NULL;
2475 
2476     if ((count < 0) || (numbers == NULL))
2477     {
2478         return NULL;
2479     }
2480 
2481     a = cJSON_CreateArray();
2482 
2483     for(i = 0; a && (i < (size_t)count); i++)
2484     {
2485         n = cJSON_CreateNumber((double)numbers[i]);
2486         if(!n)
2487         {
2488             cJSON_Delete(a);
2489             return NULL;
2490         }
2491         if(!i)
2492         {
2493             a->child = n;
2494         }
2495         else
2496         {
2497             suffix_object(p, n);
2498         }
2499         p = n;
2500     }
2501 
2502     return a;
2503 }
2504 
cJSON_CreateDoubleArray(const double * numbers,int count)2505 CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count)
2506 {
2507     size_t i = 0;
2508     cJSON *n = NULL;
2509     cJSON *p = NULL;
2510     cJSON *a = NULL;
2511 
2512     if ((count < 0) || (numbers == NULL))
2513     {
2514         return NULL;
2515     }
2516 
2517     a = cJSON_CreateArray();
2518 
2519     for(i = 0;a && (i < (size_t)count); i++)
2520     {
2521         n = cJSON_CreateNumber(numbers[i]);
2522         if(!n)
2523         {
2524             cJSON_Delete(a);
2525             return NULL;
2526         }
2527         if(!i)
2528         {
2529             a->child = n;
2530         }
2531         else
2532         {
2533             suffix_object(p, n);
2534         }
2535         p = n;
2536     }
2537 
2538     return a;
2539 }
2540 
cJSON_CreateStringArray(const char ** strings,int count)2541 CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count)
2542 {
2543     size_t i = 0;
2544     cJSON *n = NULL;
2545     cJSON *p = NULL;
2546     cJSON *a = NULL;
2547 
2548     if ((count < 0) || (strings == NULL))
2549     {
2550         return NULL;
2551     }
2552 
2553     a = cJSON_CreateArray();
2554 
2555     for (i = 0; a && (i < (size_t)count); i++)
2556     {
2557         n = cJSON_CreateString(strings[i]);
2558         if(!n)
2559         {
2560             cJSON_Delete(a);
2561             return NULL;
2562         }
2563         if(!i)
2564         {
2565             a->child = n;
2566         }
2567         else
2568         {
2569             suffix_object(p,n);
2570         }
2571         p = n;
2572     }
2573 
2574     return a;
2575 }
2576 
2577 /* Duplication */
cJSON_Duplicate(const cJSON * item,cJSON_bool recurse)2578 CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse)
2579 {
2580     cJSON *newitem = NULL;
2581     cJSON *child = NULL;
2582     cJSON *next = NULL;
2583     cJSON *newchild = NULL;
2584 
2585     /* Bail on bad ptr */
2586     if (!item)
2587     {
2588         goto fail;
2589     }
2590     /* Create new item */
2591     newitem = cJSON_New_Item(&global_hooks);
2592     if (!newitem)
2593     {
2594         goto fail;
2595     }
2596     /* Copy over all vars */
2597     newitem->type = item->type & (~cJSON_IsReference);
2598     newitem->valueint = item->valueint;
2599     newitem->valuedouble = item->valuedouble;
2600     if (item->valuestring)
2601     {
2602         newitem->valuestring = (char*)cJSON_strdup((unsigned char*)item->valuestring, &global_hooks);
2603         if (!newitem->valuestring)
2604         {
2605             goto fail;
2606         }
2607     }
2608     if (item->string)
2609     {
2610         newitem->string = (item->type&cJSON_StringIsConst) ? item->string : (char*)cJSON_strdup((unsigned char*)item->string, &global_hooks);
2611         if (!newitem->string)
2612         {
2613             goto fail;
2614         }
2615     }
2616     /* If non-recursive, then we're done! */
2617     if (!recurse)
2618     {
2619         return newitem;
2620     }
2621     /* Walk the ->next chain for the child. */
2622     child = item->child;
2623     while (child != NULL)
2624     {
2625         newchild = cJSON_Duplicate(child, true); /* Duplicate (with recurse) each item in the ->next chain */
2626         if (!newchild)
2627         {
2628             goto fail;
2629         }
2630         if (next != NULL)
2631         {
2632             /* If newitem->child already set, then crosswire ->prev and ->next and move on */
2633             next->next = newchild;
2634             newchild->prev = next;
2635             next = newchild;
2636         }
2637         else
2638         {
2639             /* Set newitem->child and move to it */
2640             newitem->child = newchild;
2641             next = newchild;
2642         }
2643         child = child->next;
2644     }
2645 
2646     return newitem;
2647 
2648 fail:
2649     if (newitem != NULL)
2650     {
2651         cJSON_Delete(newitem);
2652     }
2653 
2654     return NULL;
2655 }
2656 
skip_oneline_comment(char ** input)2657 static void skip_oneline_comment(char **input)
2658 {
2659     *input += static_strlen("//");
2660 
2661     for (; (*input)[0] != '\0'; ++(*input))
2662     {
2663         if ((*input)[0] == '\n') {
2664             *input += static_strlen("\n");
2665             return;
2666         }
2667     }
2668 }
2669 
skip_multiline_comment(char ** input)2670 static void skip_multiline_comment(char **input)
2671 {
2672     *input += static_strlen("/*");
2673 
2674     for (; (*input)[0] != '\0'; ++(*input))
2675     {
2676         if (((*input)[0] == '*') && ((*input)[1] == '/'))
2677         {
2678             *input += static_strlen("*/");
2679             return;
2680         }
2681     }
2682 }
2683 
minify_string(char ** input,char ** output)2684 static void minify_string(char **input, char **output) {
2685     (*output)[0] = (*input)[0];
2686     *input += static_strlen("\"");
2687     *output += static_strlen("\"");
2688 
2689 
2690     for (; (*input)[0] != '\0'; (void)++(*input), ++(*output)) {
2691         (*output)[0] = (*input)[0];
2692 
2693         if ((*input)[0] == '\"') {
2694             (*output)[0] = '\"';
2695             *input += static_strlen("\"");
2696             *output += static_strlen("\"");
2697             return;
2698         } else if (((*input)[0] == '\\') && ((*input)[1] == '\"')) { /* NOLINT */
2699             (*output)[1] = (*input)[1];
2700             *input += static_strlen("\"");
2701             *output += static_strlen("\"");
2702         }
2703     }
2704 }
2705 
cJSON_Minify(char * json)2706 CJSON_PUBLIC(void) cJSON_Minify(char *json)
2707 {
2708     char *into = json;
2709 
2710     if (json == NULL)
2711     {
2712         return;
2713     }
2714 
2715     while (json[0] != '\0')
2716     {
2717         switch (json[0])
2718         {
2719             case ' ':
2720             case '\t':
2721             case '\r':
2722             case '\n':
2723                 json++;
2724                 break;
2725 
2726             case '/':
2727                 if (json[1] == '/')
2728                 {
2729                     skip_oneline_comment(&json);
2730                 }
2731                 else if (json[1] == '*')
2732                 {
2733                     skip_multiline_comment(&json);
2734                 } else {
2735                     json++;
2736                 }
2737                 break;
2738 
2739             case '\"':
2740                 minify_string(&json, (char**)&into);
2741                 break;
2742 
2743             default:
2744                 into[0] = json[0];
2745                 json++;
2746                 into++;
2747         }
2748     }
2749 
2750     /* and null-terminate. */
2751     *into = '\0';
2752 }
2753 
cJSON_IsInvalid(const cJSON * const item)2754 CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item)
2755 {
2756     if (item == NULL)
2757     {
2758         return false;
2759     }
2760 
2761     return (item->type & 0xFF) == cJSON_Invalid;
2762 }
2763 
cJSON_IsFalse(const cJSON * const item)2764 CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item)
2765 {
2766     if (item == NULL)
2767     {
2768         return false;
2769     }
2770 
2771     return (item->type & 0xFF) == cJSON_False;
2772 }
2773 
cJSON_IsTrue(const cJSON * const item)2774 CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item)
2775 {
2776     if (item == NULL)
2777     {
2778         return false;
2779     }
2780 
2781     return (item->type & 0xff) == cJSON_True;
2782 }
2783 
2784 
cJSON_IsBool(const cJSON * const item)2785 CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item)
2786 {
2787     if (item == NULL)
2788     {
2789         return false;
2790     }
2791 
2792     return (item->type & (cJSON_True | cJSON_False)) != 0;
2793 }
cJSON_IsNull(const cJSON * const item)2794 CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item)
2795 {
2796     if (item == NULL)
2797     {
2798         return false;
2799     }
2800 
2801     return (item->type & 0xFF) == cJSON_NULL;
2802 }
2803 
cJSON_IsNumber(const cJSON * const item)2804 CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item)
2805 {
2806     if (item == NULL)
2807     {
2808         return false;
2809     }
2810 
2811     return (item->type & 0xFF) == cJSON_Number;
2812 }
2813 
cJSON_IsString(const cJSON * const item)2814 CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item)
2815 {
2816     if (item == NULL)
2817     {
2818         return false;
2819     }
2820 
2821     return (item->type & 0xFF) == cJSON_String;
2822 }
2823 
cJSON_IsArray(const cJSON * const item)2824 CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item)
2825 {
2826     if (item == NULL)
2827     {
2828         return false;
2829     }
2830 
2831     return (item->type & 0xFF) == cJSON_Array;
2832 }
2833 
cJSON_IsObject(const cJSON * const item)2834 CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item)
2835 {
2836     if (item == NULL)
2837     {
2838         return false;
2839     }
2840 
2841     return (item->type & 0xFF) == cJSON_Object;
2842 }
2843 
cJSON_IsRaw(const cJSON * const item)2844 CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item)
2845 {
2846     if (item == NULL)
2847     {
2848         return false;
2849     }
2850 
2851     return (item->type & 0xFF) == cJSON_Raw;
2852 }
2853 
cJSON_Compare(const cJSON * const a,const cJSON * const b,const cJSON_bool case_sensitive)2854 CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive)
2855 {
2856     if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF)) || cJSON_IsInvalid(a))
2857     {
2858         return false;
2859     }
2860 
2861     /* check if type is valid */
2862     switch (a->type & 0xFF)
2863     {
2864         case cJSON_False:
2865         case cJSON_True:
2866         case cJSON_NULL:
2867         case cJSON_Number:
2868         case cJSON_String:
2869         case cJSON_Raw:
2870         case cJSON_Array:
2871         case cJSON_Object:
2872             break;
2873 
2874         default:
2875             return false;
2876     }
2877 
2878     /* identical objects are equal */
2879     if (a == b)
2880     {
2881         return true;
2882     }
2883 
2884     switch (a->type & 0xFF)
2885     {
2886         /* in these cases and equal type is enough */
2887         case cJSON_False:
2888         case cJSON_True:
2889         case cJSON_NULL:
2890             return true;
2891 
2892         case cJSON_Number:
2893             if (a->valuedouble == b->valuedouble)
2894             {
2895                 return true;
2896             }
2897             return false;
2898 
2899         case cJSON_String:
2900         case cJSON_Raw:
2901             if ((a->valuestring == NULL) || (b->valuestring == NULL))
2902             {
2903                 return false;
2904             }
2905             if (strcmp(a->valuestring, b->valuestring) == 0)
2906             {
2907                 return true;
2908             }
2909 
2910             return false;
2911 
2912         case cJSON_Array:
2913         {
2914             cJSON *a_element = a->child;
2915             cJSON *b_element = b->child;
2916 
2917             for (; (a_element != NULL) && (b_element != NULL);)
2918             {
2919                 if (!cJSON_Compare(a_element, b_element, case_sensitive))
2920                 {
2921                     return false;
2922                 }
2923 
2924                 a_element = a_element->next;
2925                 b_element = b_element->next;
2926             }
2927 
2928             /* one of the arrays is longer than the other */
2929             if (a_element != b_element) {
2930                 return false;
2931             }
2932 
2933             return true;
2934         }
2935 
2936         case cJSON_Object:
2937         {
2938             cJSON *a_element = NULL;
2939             cJSON *b_element = NULL;
2940             cJSON_ArrayForEach(a_element, a)
2941             {
2942                 /* TODO This has O(n^2) runtime, which is horrible! */
2943                 b_element = get_object_item(b, a_element->string, case_sensitive);
2944                 if (b_element == NULL)
2945                 {
2946                     return false;
2947                 }
2948 
2949                 if (!cJSON_Compare(a_element, b_element, case_sensitive))
2950                 {
2951                     return false;
2952                 }
2953             }
2954 
2955             /* doing this twice, once on a and b to prevent true comparison if a subset of b
2956              * TODO: Do this the proper way, this is just a fix for now */
2957             cJSON_ArrayForEach(b_element, b)
2958             {
2959                 a_element = get_object_item(a, b_element->string, case_sensitive);
2960                 if (a_element == NULL)
2961                 {
2962                     return false;
2963                 }
2964 
2965                 if (!cJSON_Compare(b_element, a_element, case_sensitive))
2966                 {
2967                     return false;
2968                 }
2969             }
2970 
2971             return true;
2972         }
2973 
2974         default:
2975             return false;
2976     }
2977 }
2978 
cJSON_malloc(size_t size)2979 CJSON_PUBLIC(void *) cJSON_malloc(size_t size)
2980 {
2981     return global_hooks.allocate(size);
2982 }
2983 
cJSON_free(void * object)2984 CJSON_PUBLIC(void) cJSON_free(void *object)
2985 {
2986     global_hooks.deallocate(object);
2987 }
2988