• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 
27 #include "unity/examples/unity_config.h"
28 #include "unity/src/unity.h"
29 #include "common.h"
30 
cjson_array_foreach_should_loop_over_arrays(void)31 static void cjson_array_foreach_should_loop_over_arrays(void)
32 {
33     cJSON array[1];
34     cJSON elements[10];
35     cJSON *element_pointer = NULL;
36     size_t i = 0;
37 
38     memset(array, 0, sizeof(array));
39     memset(elements, 0, sizeof(elements));
40 
41     /* create array */
42     array[0].child = &elements[0];
43     elements[0].prev = NULL;
44     elements[9].next = NULL;
45     for (i = 0; i < 9; i++)
46     {
47         elements[i].next = &elements[i + 1];
48         elements[i + 1].prev = &elements[i];
49     }
50 
51     i = 0;
52     cJSON_ArrayForEach(element_pointer, array)
53     {
54         TEST_ASSERT_TRUE_MESSAGE(element_pointer == &elements[i], "Not iterating over array properly");
55         i++;
56     }
57 }
58 
cjson_array_foreach_should_not_dereference_null_pointer(void)59 static void cjson_array_foreach_should_not_dereference_null_pointer(void)
60 {
61     cJSON *array = NULL;
62     cJSON *element = NULL;
63     cJSON_ArrayForEach(element, array);
64 }
65 
cjson_get_object_item_should_get_object_items(void)66 static void cjson_get_object_item_should_get_object_items(void)
67 {
68     cJSON *item = NULL;
69     cJSON *found = NULL;
70 
71     item = cJSON_Parse("{\"one\":1, \"Two\":2, \"tHree\":3}");
72 
73     found = cJSON_GetObjectItem(NULL, "test");
74     TEST_ASSERT_NULL_MESSAGE(found, "Failed to fail on NULL pointer.");
75 
76     found = cJSON_GetObjectItem(item, NULL);
77     TEST_ASSERT_NULL_MESSAGE(found, "Failed to fail on NULL string.");
78 
79     found = cJSON_GetObjectItem(item, "one");
80     TEST_ASSERT_NOT_NULL_MESSAGE(found, "Failed to find first item.");
81     TEST_ASSERT_EQUAL_DOUBLE(found->valuedouble, 1);
82 
83     found = cJSON_GetObjectItem(item, "tWo");
84     TEST_ASSERT_NOT_NULL_MESSAGE(found, "Failed to find first item.");
85     TEST_ASSERT_EQUAL_DOUBLE(found->valuedouble, 2);
86 
87     found = cJSON_GetObjectItem(item, "three");
88     TEST_ASSERT_NOT_NULL_MESSAGE(found, "Failed to find item.");
89     TEST_ASSERT_EQUAL_DOUBLE(found->valuedouble, 3);
90 
91     found = cJSON_GetObjectItem(item, "four");
92     TEST_ASSERT_NULL_MESSAGE(found, "Should not find something that isn't there.");
93 
94     cJSON_Delete(item);
95 }
96 
cjson_get_object_item_case_sensitive_should_get_object_items(void)97 static void cjson_get_object_item_case_sensitive_should_get_object_items(void)
98 {
99     cJSON *item = NULL;
100     cJSON *found = NULL;
101 
102     item = cJSON_Parse("{\"one\":1, \"Two\":2, \"tHree\":3}");
103 
104     found = cJSON_GetObjectItemCaseSensitive(NULL, "test");
105     TEST_ASSERT_NULL_MESSAGE(found, "Failed to fail on NULL pointer.");
106 
107     found = cJSON_GetObjectItemCaseSensitive(item, NULL);
108     TEST_ASSERT_NULL_MESSAGE(found, "Failed to fail on NULL string.");
109 
110     found = cJSON_GetObjectItemCaseSensitive(item, "one");
111     TEST_ASSERT_NOT_NULL_MESSAGE(found, "Failed to find first item.");
112     TEST_ASSERT_EQUAL_DOUBLE(found->valuedouble, 1);
113 
114     found = cJSON_GetObjectItemCaseSensitive(item, "Two");
115     TEST_ASSERT_NOT_NULL_MESSAGE(found, "Failed to find first item.");
116     TEST_ASSERT_EQUAL_DOUBLE(found->valuedouble, 2);
117 
118     found = cJSON_GetObjectItemCaseSensitive(item, "tHree");
119     TEST_ASSERT_NOT_NULL_MESSAGE(found, "Failed to find item.");
120     TEST_ASSERT_EQUAL_DOUBLE(found->valuedouble, 3);
121 
122     found = cJSON_GetObjectItemCaseSensitive(item, "One");
123     TEST_ASSERT_NULL_MESSAGE(found, "Should not find something that isn't there.");
124 
125     cJSON_Delete(item);
126 }
127 
cjson_get_object_item_should_not_crash_with_array(void)128 static void cjson_get_object_item_should_not_crash_with_array(void)
129 {
130     cJSON *array = NULL;
131     cJSON *found = NULL;
132     array = cJSON_Parse("[1]");
133 
134     found = cJSON_GetObjectItem(array, "name");
135     TEST_ASSERT_NULL(found);
136 
137     cJSON_Delete(array);
138 }
139 
cjson_get_object_item_case_sensitive_should_not_crash_with_array(void)140 static void cjson_get_object_item_case_sensitive_should_not_crash_with_array(void)
141 {
142     cJSON *array = NULL;
143     cJSON *found = NULL;
144     array = cJSON_Parse("[1]");
145 
146     found = cJSON_GetObjectItemCaseSensitive(array, "name");
147     TEST_ASSERT_NULL(found);
148 
149     cJSON_Delete(array);
150 }
151 
typecheck_functions_should_check_type(void)152 static void typecheck_functions_should_check_type(void)
153 {
154     cJSON invalid[1];
155     cJSON item[1];
156     invalid->type = cJSON_Invalid;
157     invalid->type |= cJSON_StringIsConst;
158     item->type = cJSON_False;
159     item->type |= cJSON_StringIsConst;
160 
161     TEST_ASSERT_FALSE(cJSON_IsInvalid(NULL));
162     TEST_ASSERT_FALSE(cJSON_IsInvalid(item));
163     TEST_ASSERT_TRUE(cJSON_IsInvalid(invalid));
164 
165     item->type = cJSON_False | cJSON_StringIsConst;
166     TEST_ASSERT_FALSE(cJSON_IsFalse(NULL));
167     TEST_ASSERT_FALSE(cJSON_IsFalse(invalid));
168     TEST_ASSERT_TRUE(cJSON_IsFalse(item));
169     TEST_ASSERT_TRUE(cJSON_IsBool(item));
170 
171     item->type = cJSON_True | cJSON_StringIsConst;
172     TEST_ASSERT_FALSE(cJSON_IsTrue(NULL));
173     TEST_ASSERT_FALSE(cJSON_IsTrue(invalid));
174     TEST_ASSERT_TRUE(cJSON_IsTrue(item));
175     TEST_ASSERT_TRUE(cJSON_IsBool(item));
176 
177     item->type = cJSON_NULL | cJSON_StringIsConst;
178     TEST_ASSERT_FALSE(cJSON_IsNull(NULL));
179     TEST_ASSERT_FALSE(cJSON_IsNull(invalid));
180     TEST_ASSERT_TRUE(cJSON_IsNull(item));
181 
182     item->type = cJSON_Number | cJSON_StringIsConst;
183     TEST_ASSERT_FALSE(cJSON_IsNumber(NULL));
184     TEST_ASSERT_FALSE(cJSON_IsNumber(invalid));
185     TEST_ASSERT_TRUE(cJSON_IsNumber(item));
186 
187     item->type = cJSON_String | cJSON_StringIsConst;
188     TEST_ASSERT_FALSE(cJSON_IsString(NULL));
189     TEST_ASSERT_FALSE(cJSON_IsString(invalid));
190     TEST_ASSERT_TRUE(cJSON_IsString(item));
191 
192     item->type = cJSON_Array | cJSON_StringIsConst;
193     TEST_ASSERT_FALSE(cJSON_IsArray(NULL));
194     TEST_ASSERT_FALSE(cJSON_IsArray(invalid));
195     TEST_ASSERT_TRUE(cJSON_IsArray(item));
196 
197     item->type = cJSON_Object | cJSON_StringIsConst;
198     TEST_ASSERT_FALSE(cJSON_IsObject(NULL));
199     TEST_ASSERT_FALSE(cJSON_IsObject(invalid));
200     TEST_ASSERT_TRUE(cJSON_IsObject(item));
201 
202     item->type = cJSON_Raw | cJSON_StringIsConst;
203     TEST_ASSERT_FALSE(cJSON_IsRaw(NULL));
204     TEST_ASSERT_FALSE(cJSON_IsRaw(invalid));
205     TEST_ASSERT_TRUE(cJSON_IsRaw(item));
206 }
207 
cjson_should_not_parse_to_deeply_nested_jsons(void)208 static void cjson_should_not_parse_to_deeply_nested_jsons(void)
209 {
210     char deep_json[CJSON_NESTING_LIMIT + 1];
211     size_t position = 0;
212 
213     for (position = 0; position < sizeof(deep_json); position++)
214     {
215         deep_json[position] = '[';
216     }
217     deep_json[sizeof(deep_json) - 1] = '\0';
218 
219     TEST_ASSERT_NULL_MESSAGE(cJSON_Parse(deep_json), "To deep JSONs should not be parsed.");
220 }
221 
cjson_set_number_value_should_set_numbers(void)222 static void cjson_set_number_value_should_set_numbers(void)
223 {
224     cJSON number[1] = {{NULL, NULL, NULL, cJSON_Number, NULL, 0, 0, NULL}};
225 
226     cJSON_SetNumberValue(number, 1.5);
227     TEST_ASSERT_EQUAL(1, number->valueint);
228     TEST_ASSERT_EQUAL_DOUBLE(1.5, number->valuedouble);
229 
230     cJSON_SetNumberValue(number, -1.5);
231     TEST_ASSERT_EQUAL(-1, number->valueint);
232     TEST_ASSERT_EQUAL_DOUBLE(-1.5, number->valuedouble);
233 
234 #ifdef __CJSON_USE_INT64
235     cJSON_SetNumberValue(number, 1 + (double)LLONG_MAX);
236     TEST_ASSERT_EQUAL(LLONG_MAX, number->valueint);
237     TEST_ASSERT_EQUAL_DOUBLE(1 + (double)LLONG_MAX, number->valuedouble);
238 
239     cJSON_SetNumberValue(number, -1 + (double)LLONG_MIN);
240     TEST_ASSERT_EQUAL(LLONG_MIN, number->valueint);
241     TEST_ASSERT_EQUAL_DOUBLE(-1 + (double)LLONG_MIN, number->valuedouble);
242 #else
243     cJSON_SetNumberValue(number, 1 + (double)INT_MAX);
244     TEST_ASSERT_EQUAL(INT_MAX, number->valueint);
245     TEST_ASSERT_EQUAL_DOUBLE(1 + (double)INT_MAX, number->valuedouble);
246 
247     cJSON_SetNumberValue(number, -1 + (double)INT_MIN);
248     TEST_ASSERT_EQUAL(INT_MIN, number->valueint);
249     TEST_ASSERT_EQUAL_DOUBLE(-1 + (double)INT_MIN, number->valuedouble);
250 #endif /* __CJSON_USE_INT64 */
251 }
252 
cjson_detach_item_via_pointer_should_detach_items(void)253 static void cjson_detach_item_via_pointer_should_detach_items(void)
254 {
255     cJSON list[4];
256     cJSON parent[1];
257 
258     memset(list, '\0', sizeof(list));
259 
260     /* link the list */
261     list[0].next = &(list[1]);
262     list[1].next = &(list[2]);
263     list[2].next = &(list[3]);
264 
265     list[3].prev = &(list[2]);
266     list[2].prev = &(list[1]);
267     list[1].prev = &(list[0]);
268     list[0].prev = &(list[3]);
269 
270     parent->child = &list[0];
271 
272     /* detach in the middle (list[1]) */
273     TEST_ASSERT_TRUE_MESSAGE(cJSON_DetachItemViaPointer(parent, &(list[1])) == &(list[1]), "Failed to detach in the middle.");
274     TEST_ASSERT_TRUE_MESSAGE((list[1].prev == NULL) && (list[1].next == NULL), "Didn't set pointers of detached item to NULL.");
275     TEST_ASSERT_TRUE((list[0].next == &(list[2])) && (list[2].prev == &(list[0])));
276 
277     /* detach beginning (list[0]) */
278     TEST_ASSERT_TRUE_MESSAGE(cJSON_DetachItemViaPointer(parent, &(list[0])) == &(list[0]), "Failed to detach beginning.");
279     TEST_ASSERT_TRUE_MESSAGE((list[0].prev == NULL) && (list[0].next == NULL), "Didn't set pointers of detached item to NULL.");
280     TEST_ASSERT_TRUE_MESSAGE((list[2].prev == &(list[3])) && (parent->child == &(list[2])), "Didn't set the new beginning.");
281 
282     /* detach end (list[3])*/
283     TEST_ASSERT_TRUE_MESSAGE(cJSON_DetachItemViaPointer(parent, &(list[3])) == &(list[3]), "Failed to detach end.");
284     TEST_ASSERT_TRUE_MESSAGE((list[3].prev == NULL) && (list[3].next == NULL), "Didn't set pointers of detached item to NULL.");
285     TEST_ASSERT_TRUE_MESSAGE((list[2].next == NULL) && (parent->child == &(list[2])), "Didn't set the new end");
286 
287     /* detach single item (list[2]) */
288     TEST_ASSERT_TRUE_MESSAGE(cJSON_DetachItemViaPointer(parent, &list[2]) == &list[2], "Failed to detach single item.");
289     TEST_ASSERT_TRUE_MESSAGE((list[2].prev == NULL) && (list[2].next == NULL), "Didn't set pointers of detached item to NULL.");
290     TEST_ASSERT_NULL_MESSAGE(parent->child, "Child of the parent wasn't set to NULL.");
291 }
292 
cjson_replace_item_via_pointer_should_replace_items(void)293 static void cjson_replace_item_via_pointer_should_replace_items(void)
294 {
295     cJSON replacements[3];
296     cJSON *beginning = NULL;
297     cJSON *middle = NULL;
298     cJSON *end = NULL;
299     cJSON *array = NULL;
300 
301     beginning = cJSON_CreateNull();
302     TEST_ASSERT_NOT_NULL(beginning);
303     middle = cJSON_CreateNull();
304     TEST_ASSERT_NOT_NULL(middle);
305     end = cJSON_CreateNull();
306     TEST_ASSERT_NOT_NULL(end);
307 
308     array = cJSON_CreateArray();
309     TEST_ASSERT_NOT_NULL(array);
310 
311     cJSON_AddItemToArray(array, beginning);
312     cJSON_AddItemToArray(array, middle);
313     cJSON_AddItemToArray(array, end);
314 
315     memset(replacements, '\0', sizeof(replacements));
316 
317     /* replace beginning */
318     TEST_ASSERT_TRUE(cJSON_ReplaceItemViaPointer(array, beginning, &(replacements[0])));
319     TEST_ASSERT_TRUE(replacements[0].prev == end);
320     TEST_ASSERT_TRUE(replacements[0].next == middle);
321     TEST_ASSERT_TRUE(middle->prev == &(replacements[0]));
322     TEST_ASSERT_TRUE(array->child == &(replacements[0]));
323 
324     /* replace middle */
325     TEST_ASSERT_TRUE(cJSON_ReplaceItemViaPointer(array, middle, &(replacements[1])));
326     TEST_ASSERT_TRUE(replacements[1].prev == &(replacements[0]));
327     TEST_ASSERT_TRUE(replacements[1].next == end);
328     TEST_ASSERT_TRUE(end->prev == &(replacements[1]));
329 
330     /* replace end */
331     TEST_ASSERT_TRUE(cJSON_ReplaceItemViaPointer(array, end, &(replacements[2])));
332     TEST_ASSERT_TRUE(replacements[2].prev == &(replacements[1]));
333     TEST_ASSERT_NULL(replacements[2].next);
334     TEST_ASSERT_TRUE(replacements[1].next == &(replacements[2]));
335 
336     cJSON_free(array);
337 }
338 
cjson_replace_item_in_object_should_preserve_name(void)339 static void cjson_replace_item_in_object_should_preserve_name(void)
340 {
341     cJSON root[1] = {{NULL, NULL, NULL, 0, NULL, 0, 0, NULL}};
342     cJSON *child = NULL;
343     cJSON *replacement = NULL;
344     cJSON_bool flag = false;
345 
346     child = cJSON_CreateNumber(1);
347     TEST_ASSERT_NOT_NULL(child);
348     replacement = cJSON_CreateNumber(2);
349     TEST_ASSERT_NOT_NULL(replacement);
350 
351     flag = cJSON_AddItemToObject(root, "child", child);
352     TEST_ASSERT_TRUE_MESSAGE(flag, "add item to object failed");
353     cJSON_ReplaceItemInObject(root, "child", replacement);
354 
355     TEST_ASSERT_TRUE(root->child == replacement);
356     TEST_ASSERT_EQUAL_STRING("child", replacement->string);
357 
358     cJSON_Delete(replacement);
359 }
360 
cjson_functions_should_not_crash_with_null_pointers(void)361 static void cjson_functions_should_not_crash_with_null_pointers(void)
362 {
363     char buffer[10];
364     cJSON *item = cJSON_CreateString("item");
365     cJSON *array = cJSON_CreateArray();
366     cJSON *item1 = cJSON_CreateString("item1");
367     cJSON *item2 = cJSON_CreateString("corrupted array item3");
368     cJSON *corruptedString = cJSON_CreateString("corrupted");
369     struct cJSON *originalPrev;
370 
371     add_item_to_array(array, item1);
372     add_item_to_array(array, item2);
373 
374     originalPrev = item2->prev;
375     item2->prev = NULL;
376     free(corruptedString->valuestring);
377     corruptedString->valuestring = NULL;
378 
379     cJSON_InitHooks(NULL);
380     TEST_ASSERT_NULL(cJSON_Parse(NULL));
381     TEST_ASSERT_NULL(cJSON_ParseWithOpts(NULL, NULL, true));
382     TEST_ASSERT_NULL(cJSON_Print(NULL));
383     TEST_ASSERT_NULL(cJSON_PrintUnformatted(NULL));
384     TEST_ASSERT_NULL(cJSON_PrintBuffered(NULL, 10, true));
385     TEST_ASSERT_FALSE(cJSON_PrintPreallocated(NULL, buffer, sizeof(buffer), true));
386     TEST_ASSERT_FALSE(cJSON_PrintPreallocated(item, NULL, 1, true));
387     cJSON_Delete(NULL);
388     cJSON_GetArraySize(NULL);
389     TEST_ASSERT_NULL(cJSON_GetArrayItem(NULL, 0));
390     TEST_ASSERT_NULL(cJSON_GetObjectItem(NULL, "item"));
391     TEST_ASSERT_NULL(cJSON_GetObjectItem(item, NULL));
392     TEST_ASSERT_NULL(cJSON_GetObjectItemCaseSensitive(NULL, "item"));
393     TEST_ASSERT_NULL(cJSON_GetObjectItemCaseSensitive(item, NULL));
394     TEST_ASSERT_FALSE(cJSON_HasObjectItem(NULL, "item"));
395     TEST_ASSERT_FALSE(cJSON_HasObjectItem(item, NULL));
396     TEST_ASSERT_FALSE(cJSON_IsInvalid(NULL));
397     TEST_ASSERT_FALSE(cJSON_IsFalse(NULL));
398     TEST_ASSERT_FALSE(cJSON_IsTrue(NULL));
399     TEST_ASSERT_FALSE(cJSON_IsBool(NULL));
400     TEST_ASSERT_FALSE(cJSON_IsNull(NULL));
401     TEST_ASSERT_FALSE(cJSON_IsNumber(NULL));
402     TEST_ASSERT_FALSE(cJSON_IsString(NULL));
403     TEST_ASSERT_FALSE(cJSON_IsArray(NULL));
404     TEST_ASSERT_FALSE(cJSON_IsObject(NULL));
405     TEST_ASSERT_FALSE(cJSON_IsRaw(NULL));
406     TEST_ASSERT_NULL(cJSON_CreateString(NULL));
407     TEST_ASSERT_NULL(cJSON_CreateRaw(NULL));
408     TEST_ASSERT_NULL(cJSON_CreateIntArray(NULL, 10));
409     TEST_ASSERT_NULL(cJSON_CreateFloatArray(NULL, 10));
410     TEST_ASSERT_NULL(cJSON_CreateDoubleArray(NULL, 10));
411     TEST_ASSERT_NULL(cJSON_CreateStringArray(NULL, 10));
412     cJSON_AddItemToArray(NULL, item);
413     cJSON_AddItemToArray(item, NULL);
414     cJSON_AddItemToObject(item, "item", NULL);
415     cJSON_AddItemToObject(item, NULL, item);
416     cJSON_AddItemToObject(NULL, "item", item);
417     cJSON_AddItemToObjectCS(item, "item", NULL);
418     cJSON_AddItemToObjectCS(item, NULL, item);
419     cJSON_AddItemToObjectCS(NULL, "item", item);
420     cJSON_AddItemReferenceToArray(NULL, item);
421     cJSON_AddItemReferenceToArray(item, NULL);
422     cJSON_AddItemReferenceToObject(item, "item", NULL);
423     cJSON_AddItemReferenceToObject(item, NULL, item);
424     cJSON_AddItemReferenceToObject(NULL, "item", item);
425     TEST_ASSERT_NULL(cJSON_DetachItemViaPointer(NULL, item));
426     TEST_ASSERT_NULL(cJSON_DetachItemViaPointer(item, NULL));
427     TEST_ASSERT_NULL(cJSON_DetachItemFromArray(NULL, 0));
428     cJSON_DeleteItemFromArray(NULL, 0);
429     TEST_ASSERT_NULL(cJSON_DetachItemFromObject(NULL, "item"));
430     TEST_ASSERT_NULL(cJSON_DetachItemFromObject(item, NULL));
431     TEST_ASSERT_NULL(cJSON_DetachItemFromObjectCaseSensitive(NULL, "item"));
432     TEST_ASSERT_NULL(cJSON_DetachItemFromObjectCaseSensitive(item, NULL));
433     cJSON_DeleteItemFromObject(NULL, "item");
434     cJSON_DeleteItemFromObject(item, NULL);
435     cJSON_DeleteItemFromObjectCaseSensitive(NULL, "item");
436     cJSON_DeleteItemFromObjectCaseSensitive(item, NULL);
437     TEST_ASSERT_FALSE(cJSON_InsertItemInArray(array, 0, NULL));
438     TEST_ASSERT_FALSE(cJSON_InsertItemInArray(array, 1, item));
439     TEST_ASSERT_FALSE(cJSON_InsertItemInArray(NULL, 0, item));
440     TEST_ASSERT_FALSE(cJSON_InsertItemInArray(item, 0, NULL));
441     TEST_ASSERT_FALSE(cJSON_ReplaceItemViaPointer(NULL, item, item));
442     TEST_ASSERT_FALSE(cJSON_ReplaceItemViaPointer(item, NULL, item));
443     TEST_ASSERT_FALSE(cJSON_ReplaceItemViaPointer(item, item, NULL));
444     TEST_ASSERT_FALSE(cJSON_ReplaceItemInArray(item, 0, NULL));
445     TEST_ASSERT_FALSE(cJSON_ReplaceItemInArray(NULL, 0, item));
446     TEST_ASSERT_FALSE(cJSON_ReplaceItemInObject(NULL, "item", item));
447     TEST_ASSERT_FALSE(cJSON_ReplaceItemInObject(item, NULL, item));
448     TEST_ASSERT_FALSE(cJSON_ReplaceItemInObject(item, "item", NULL));
449     TEST_ASSERT_FALSE(cJSON_ReplaceItemInObjectCaseSensitive(NULL, "item", item));
450     TEST_ASSERT_FALSE(cJSON_ReplaceItemInObjectCaseSensitive(item, NULL, item));
451     TEST_ASSERT_FALSE(cJSON_ReplaceItemInObjectCaseSensitive(item, "item", NULL));
452     TEST_ASSERT_NULL(cJSON_Duplicate(NULL, true));
453     TEST_ASSERT_FALSE(cJSON_Compare(item, NULL, false));
454     TEST_ASSERT_FALSE(cJSON_Compare(NULL, item, false));
455     TEST_ASSERT_NULL(cJSON_SetValuestring(NULL, "test"));
456     TEST_ASSERT_NULL(cJSON_SetValuestring(corruptedString, "test"));
457     cJSON_Minify(NULL);
458     /* skipped because it is only used via a macro that checks for NULL */
459     /* cJSON_SetNumberHelper(NULL, 0); */
460 
461     /* restore corrupted item2 to delete it */
462     item2->prev = originalPrev;
463     cJSON_Delete(corruptedString);
464     cJSON_Delete(array);
465     cJSON_Delete(item);
466 }
467 
failing_realloc(void * pointer,size_t size)468 static void *CJSON_CDECL failing_realloc(void *pointer, size_t size)
469 {
470     (void)size;
471     (void)pointer;
472     return NULL;
473 }
474 
ensure_should_fail_on_failed_realloc(void)475 static void ensure_should_fail_on_failed_realloc(void)
476 {
477     printbuffer buffer = {NULL, 10, 0, 0, false, false, {&malloc, &free, &failing_realloc}};
478     buffer.buffer = (unsigned char *)malloc(100);
479     TEST_ASSERT_NOT_NULL(buffer.buffer);
480 
481     TEST_ASSERT_NULL_MESSAGE(ensure(&buffer, 200), "Ensure didn't fail with failing realloc.");
482 }
483 
skip_utf8_bom_should_skip_bom(void)484 static void skip_utf8_bom_should_skip_bom(void)
485 {
486     const unsigned char string[] = "\xEF\xBB\xBF{}";
487     parse_buffer buffer = {0, 0, 0, 0, {0, 0, 0}};
488     buffer.content = string;
489     buffer.length = sizeof(string);
490     buffer.hooks = global_hooks;
491 
492     TEST_ASSERT_TRUE(skip_utf8_bom(&buffer) == &buffer);
493     TEST_ASSERT_EQUAL_UINT(3U, (unsigned int)buffer.offset);
494 }
495 
skip_utf8_bom_should_not_skip_bom_if_not_at_beginning(void)496 static void skip_utf8_bom_should_not_skip_bom_if_not_at_beginning(void)
497 {
498     const unsigned char string[] = " \xEF\xBB\xBF{}";
499     parse_buffer buffer = {0, 0, 0, 0, {0, 0, 0}};
500     buffer.content = string;
501     buffer.length = sizeof(string);
502     buffer.hooks = global_hooks;
503     buffer.offset = 1;
504 
505     TEST_ASSERT_NULL(skip_utf8_bom(&buffer));
506 }
507 
cjson_get_string_value_should_get_a_string(void)508 static void cjson_get_string_value_should_get_a_string(void)
509 {
510     cJSON *string = cJSON_CreateString("test");
511     cJSON *number = cJSON_CreateNumber(1);
512 
513     TEST_ASSERT_TRUE(cJSON_GetStringValue(string) == string->valuestring);
514     TEST_ASSERT_NULL(cJSON_GetStringValue(number));
515     TEST_ASSERT_NULL(cJSON_GetStringValue(NULL));
516 
517     cJSON_Delete(number);
518     cJSON_Delete(string);
519 }
520 
cjson_get_number_value_should_get_a_number(void)521 static void cjson_get_number_value_should_get_a_number(void)
522 {
523     cJSON *string = cJSON_CreateString("test");
524     cJSON *number = cJSON_CreateNumber(1);
525 
526     TEST_ASSERT_EQUAL_DOUBLE(cJSON_GetNumberValue(number), number->valuedouble);
527     TEST_ASSERT_DOUBLE_IS_NAN(cJSON_GetNumberValue(string));
528     TEST_ASSERT_DOUBLE_IS_NAN(cJSON_GetNumberValue(NULL));
529 
530     cJSON_Delete(number);
531     cJSON_Delete(string);
532 }
533 
cjson_create_string_reference_should_create_a_string_reference(void)534 static void cjson_create_string_reference_should_create_a_string_reference(void)
535 {
536     const char *string = "I am a string!";
537 
538     cJSON *string_reference = cJSON_CreateStringReference(string);
539     TEST_ASSERT_TRUE(string_reference->valuestring == string);
540     TEST_ASSERT_EQUAL_INT(cJSON_IsReference | cJSON_String, string_reference->type);
541 
542     cJSON_Delete(string_reference);
543 }
544 
cjson_create_object_reference_should_create_an_object_reference(void)545 static void cjson_create_object_reference_should_create_an_object_reference(void)
546 {
547     cJSON *number_reference = NULL;
548     cJSON *number_object = cJSON_CreateObject();
549     cJSON *number = cJSON_CreateNumber(42);
550     const char key[] = "number";
551 
552     TEST_ASSERT_TRUE(cJSON_IsNumber(number));
553     TEST_ASSERT_TRUE(cJSON_IsObject(number_object));
554     cJSON_AddItemToObjectCS(number_object, key, number);
555 
556     number_reference = cJSON_CreateObjectReference(number);
557     TEST_ASSERT_TRUE(number_reference->child == number);
558     TEST_ASSERT_EQUAL_INT(cJSON_Object | cJSON_IsReference, number_reference->type);
559 
560     cJSON_Delete(number_object);
561     cJSON_Delete(number_reference);
562 }
563 
cjson_create_array_reference_should_create_an_array_reference(void)564 static void cjson_create_array_reference_should_create_an_array_reference(void)
565 {
566     cJSON *number_reference = NULL;
567     cJSON *number_array = cJSON_CreateArray();
568     cJSON *number = cJSON_CreateNumber(42);
569 
570     TEST_ASSERT_TRUE(cJSON_IsNumber(number));
571     TEST_ASSERT_TRUE(cJSON_IsArray(number_array));
572     cJSON_AddItemToArray(number_array, number);
573 
574     number_reference = cJSON_CreateArrayReference(number);
575     TEST_ASSERT_TRUE(number_reference->child == number);
576     TEST_ASSERT_EQUAL_INT(cJSON_Array | cJSON_IsReference, number_reference->type);
577 
578     cJSON_Delete(number_array);
579     cJSON_Delete(number_reference);
580 }
581 
cjson_add_item_to_object_or_array_should_not_add_itself(void)582 static void cjson_add_item_to_object_or_array_should_not_add_itself(void)
583 {
584     cJSON *object = cJSON_CreateObject();
585     cJSON *array = cJSON_CreateArray();
586     cJSON_bool flag = false;
587 
588     flag = cJSON_AddItemToObject(object, "key", object);
589     TEST_ASSERT_FALSE_MESSAGE(flag, "add an object to itself should fail");
590 
591     flag = cJSON_AddItemToArray(array, array);
592     TEST_ASSERT_FALSE_MESSAGE(flag, "add an array to itself should fail");
593 
594     cJSON_Delete(object);
595     cJSON_Delete(array);
596 }
597 
cjson_add_item_to_object_should_not_use_after_free_when_string_is_aliased(void)598 static void cjson_add_item_to_object_should_not_use_after_free_when_string_is_aliased(void)
599 {
600     cJSON *object = cJSON_CreateObject();
601     cJSON *number = cJSON_CreateNumber(42);
602     char *name = (char *)cJSON_strdup((const unsigned char *)"number", &global_hooks);
603 
604     TEST_ASSERT_NOT_NULL(object);
605     TEST_ASSERT_NOT_NULL(number);
606     TEST_ASSERT_NOT_NULL(name);
607 
608     number->string = name;
609 
610     /* The following should not have a use after free
611      * that would show up in valgrind or with AddressSanitizer */
612     cJSON_AddItemToObject(object, number->string, number);
613 
614     cJSON_Delete(object);
615 }
616 
cjson_delete_item_from_array_should_not_broken_list_structure(void)617 static void cjson_delete_item_from_array_should_not_broken_list_structure(void)
618 {
619     const char expected_json1[] = "{\"rd\":[{\"a\":\"123\"}]}";
620     const char expected_json2[] = "{\"rd\":[{\"a\":\"123\"},{\"b\":\"456\"}]}";
621     const char expected_json3[] = "{\"rd\":[{\"b\":\"456\"}]}";
622     char *str1 = NULL;
623     char *str2 = NULL;
624     char *str3 = NULL;
625 
626     cJSON *root = cJSON_Parse("{}");
627 
628     cJSON *array = cJSON_AddArrayToObject(root, "rd");
629     cJSON *item1 = cJSON_Parse("{\"a\":\"123\"}");
630     cJSON *item2 = cJSON_Parse("{\"b\":\"456\"}");
631 
632     cJSON_AddItemToArray(array, item1);
633     str1 = cJSON_PrintUnformatted(root);
634     TEST_ASSERT_EQUAL_STRING(expected_json1, str1);
635     free(str1);
636 
637     cJSON_AddItemToArray(array, item2);
638     str2 = cJSON_PrintUnformatted(root);
639     TEST_ASSERT_EQUAL_STRING(expected_json2, str2);
640     free(str2);
641 
642     /* this should not broken list structure */
643     cJSON_DeleteItemFromArray(array, 0);
644     str3 = cJSON_PrintUnformatted(root);
645     TEST_ASSERT_EQUAL_STRING(expected_json3, str3);
646     free(str3);
647 
648     cJSON_Delete(root);
649 }
650 
cjson_set_valuestring_to_object_should_not_leak_memory(void)651 static void cjson_set_valuestring_to_object_should_not_leak_memory(void)
652 {
653     cJSON *root = cJSON_Parse("{}");
654     const char *stringvalue = "valuestring could be changed safely";
655     const char *reference_valuestring = "reference item should be freed by yourself";
656     const char *short_valuestring = "shorter valuestring";
657     const char *long_valuestring = "new valuestring which much longer than previous should be changed safely";
658     cJSON *item1 = cJSON_CreateString(stringvalue);
659     cJSON *item2 = cJSON_CreateStringReference(reference_valuestring);
660     char *ptr1 = NULL;
661     char *return_value = NULL;
662 
663     cJSON_AddItemToObject(root, "one", item1);
664     cJSON_AddItemToObject(root, "two", item2);
665 
666     ptr1 = item1->valuestring;
667     return_value = cJSON_SetValuestring(cJSON_GetObjectItem(root, "one"), short_valuestring);
668     TEST_ASSERT_NOT_NULL(return_value);
669     TEST_ASSERT_EQUAL_PTR_MESSAGE(ptr1, return_value, "new valuestring shorter than old should not reallocate memory");
670     TEST_ASSERT_EQUAL_STRING(short_valuestring, cJSON_GetObjectItem(root, "one")->valuestring);
671 
672     /* we needn't to free the original valuestring manually */
673     ptr1 = item1->valuestring;
674     return_value = cJSON_SetValuestring(cJSON_GetObjectItem(root, "one"), long_valuestring);
675     TEST_ASSERT_NOT_NULL(return_value);
676     TEST_ASSERT_NOT_EQUAL_MESSAGE(ptr1, return_value, "new valuestring longer than old should reallocate memory")
677     TEST_ASSERT_EQUAL_STRING(long_valuestring, cJSON_GetObjectItem(root, "one")->valuestring);
678 
679     return_value = cJSON_SetValuestring(cJSON_GetObjectItem(root, "two"), long_valuestring);
680     TEST_ASSERT_NULL_MESSAGE(return_value, "valuestring of reference object should not be changed");
681     TEST_ASSERT_EQUAL_STRING(reference_valuestring, cJSON_GetObjectItem(root, "two")->valuestring);
682 
683     cJSON_Delete(root);
684 }
685 
cjson_set_bool_value_must_not_break_objects(void)686 static void cjson_set_bool_value_must_not_break_objects(void)
687 {
688     cJSON *bobj, *sobj, *oobj, *refobj = NULL;
689 
690     TEST_ASSERT_TRUE((cJSON_SetBoolValue(refobj, 1) == cJSON_Invalid));
691 
692     bobj = cJSON_CreateFalse();
693     TEST_ASSERT_TRUE(cJSON_IsFalse(bobj));
694     TEST_ASSERT_TRUE((cJSON_SetBoolValue(bobj, 1) == cJSON_True));
695     TEST_ASSERT_TRUE(cJSON_IsTrue(bobj));
696     cJSON_SetBoolValue(bobj, 1);
697     TEST_ASSERT_TRUE(cJSON_IsTrue(bobj));
698     TEST_ASSERT_TRUE((cJSON_SetBoolValue(bobj, 0) == cJSON_False));
699     TEST_ASSERT_TRUE(cJSON_IsFalse(bobj));
700     cJSON_SetBoolValue(bobj, 0);
701     TEST_ASSERT_TRUE(cJSON_IsFalse(bobj));
702 
703     sobj = cJSON_CreateString("test");
704     TEST_ASSERT_TRUE(cJSON_IsString(sobj));
705     cJSON_SetBoolValue(sobj, 1);
706     TEST_ASSERT_TRUE(cJSON_IsString(sobj));
707     cJSON_SetBoolValue(sobj, 0);
708     TEST_ASSERT_TRUE(cJSON_IsString(sobj));
709 
710     oobj = cJSON_CreateObject();
711     TEST_ASSERT_TRUE(cJSON_IsObject(oobj));
712     cJSON_SetBoolValue(oobj, 1);
713     TEST_ASSERT_TRUE(cJSON_IsObject(oobj));
714     cJSON_SetBoolValue(oobj, 0);
715     TEST_ASSERT_TRUE(cJSON_IsObject(oobj));
716 
717     refobj = cJSON_CreateStringReference("conststring");
718     TEST_ASSERT_TRUE(cJSON_IsString(refobj));
719     TEST_ASSERT_TRUE(refobj->type & cJSON_IsReference);
720     cJSON_SetBoolValue(refobj, 1);
721     TEST_ASSERT_TRUE(cJSON_IsString(refobj));
722     TEST_ASSERT_TRUE(refobj->type & cJSON_IsReference);
723     cJSON_SetBoolValue(refobj, 0);
724     TEST_ASSERT_TRUE(cJSON_IsString(refobj));
725     TEST_ASSERT_TRUE(refobj->type & cJSON_IsReference);
726     cJSON_Delete(refobj);
727 
728     refobj = cJSON_CreateObjectReference(oobj);
729     TEST_ASSERT_TRUE(cJSON_IsObject(refobj));
730     TEST_ASSERT_TRUE(refobj->type & cJSON_IsReference);
731     cJSON_SetBoolValue(refobj, 1);
732     TEST_ASSERT_TRUE(cJSON_IsObject(refobj));
733     TEST_ASSERT_TRUE(refobj->type & cJSON_IsReference);
734     cJSON_SetBoolValue(refobj, 0);
735     TEST_ASSERT_TRUE(cJSON_IsObject(refobj));
736     TEST_ASSERT_TRUE(refobj->type & cJSON_IsReference);
737     cJSON_Delete(refobj);
738 
739     cJSON_Delete(oobj);
740     cJSON_Delete(bobj);
741     cJSON_Delete(sobj);
742 }
743 
main(void)744 int CJSON_CDECL main(void)
745 {
746     UNITY_BEGIN();
747 
748     RUN_TEST(cjson_array_foreach_should_loop_over_arrays);
749     RUN_TEST(cjson_array_foreach_should_not_dereference_null_pointer);
750     RUN_TEST(cjson_get_object_item_should_get_object_items);
751     RUN_TEST(cjson_get_object_item_case_sensitive_should_get_object_items);
752     RUN_TEST(cjson_get_object_item_should_not_crash_with_array);
753     RUN_TEST(cjson_get_object_item_case_sensitive_should_not_crash_with_array);
754     RUN_TEST(typecheck_functions_should_check_type);
755     RUN_TEST(cjson_should_not_parse_to_deeply_nested_jsons);
756     RUN_TEST(cjson_set_number_value_should_set_numbers);
757     RUN_TEST(cjson_detach_item_via_pointer_should_detach_items);
758     RUN_TEST(cjson_replace_item_via_pointer_should_replace_items);
759     RUN_TEST(cjson_replace_item_in_object_should_preserve_name);
760     RUN_TEST(cjson_functions_should_not_crash_with_null_pointers);
761     RUN_TEST(ensure_should_fail_on_failed_realloc);
762     RUN_TEST(skip_utf8_bom_should_skip_bom);
763     RUN_TEST(skip_utf8_bom_should_not_skip_bom_if_not_at_beginning);
764     RUN_TEST(cjson_get_string_value_should_get_a_string);
765     RUN_TEST(cjson_get_number_value_should_get_a_number);
766     RUN_TEST(cjson_create_string_reference_should_create_a_string_reference);
767     RUN_TEST(cjson_create_object_reference_should_create_an_object_reference);
768     RUN_TEST(cjson_create_array_reference_should_create_an_array_reference);
769     RUN_TEST(cjson_add_item_to_object_or_array_should_not_add_itself);
770     RUN_TEST(cjson_add_item_to_object_should_not_use_after_free_when_string_is_aliased);
771     RUN_TEST(cjson_delete_item_from_array_should_not_broken_list_structure);
772     RUN_TEST(cjson_set_valuestring_to_object_should_not_leak_memory);
773     RUN_TEST(cjson_set_bool_value_must_not_break_objects);
774 
775     return UNITY_END();
776 }
777