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 
31 
cjson_array_foreach_should_loop_over_arrays(void)32 static void cjson_array_foreach_should_loop_over_arrays(void)
33 {
34     cJSON array[1];
35     cJSON elements[10];
36     cJSON *element_pointer = NULL;
37     size_t i = 0;
38 
39     memset(array, 0, sizeof(array));
40     memset(elements, 0, sizeof(elements));
41 
42     /* create array */
43     array[0].child = &elements[0];
44     elements[0].prev = NULL;
45     elements[9].next = NULL;
46     for (i = 0; i < 9; i++)
47     {
48         elements[i].next = &elements[i + 1];
49         elements[i + 1].prev = &elements[i];
50     }
51 
52     i = 0;
53     cJSON_ArrayForEach(element_pointer, array)
54     {
55         TEST_ASSERT_TRUE_MESSAGE(element_pointer == &elements[i], "Not iterating over array properly");
56         i++;
57     }
58 }
59 
cjson_array_foreach_should_not_dereference_null_pointer(void)60 static void cjson_array_foreach_should_not_dereference_null_pointer(void)
61 {
62     cJSON *array = NULL;
63     cJSON *element = NULL;
64     cJSON_ArrayForEach(element, array);
65 }
66 
cjson_get_object_item_should_get_object_items(void)67 static void cjson_get_object_item_should_get_object_items(void)
68 {
69     cJSON *item = NULL;
70     cJSON *found = NULL;
71 
72     item = cJSON_Parse("{\"one\":1, \"Two\":2, \"tHree\":3}");
73 
74     found = cJSON_GetObjectItem(NULL, "test");
75     TEST_ASSERT_NULL_MESSAGE(found, "Failed to fail on NULL pointer.");
76 
77     found = cJSON_GetObjectItem(item, NULL);
78     TEST_ASSERT_NULL_MESSAGE(found, "Failed to fail on NULL string.");
79 
80 
81     found = cJSON_GetObjectItem(item, "one");
82     TEST_ASSERT_NOT_NULL_MESSAGE(found, "Failed to find first item.");
83     TEST_ASSERT_EQUAL_DOUBLE(found->valuedouble, 1);
84 
85     found = cJSON_GetObjectItem(item, "tWo");
86     TEST_ASSERT_NOT_NULL_MESSAGE(found, "Failed to find first item.");
87     TEST_ASSERT_EQUAL_DOUBLE(found->valuedouble, 2);
88 
89     found = cJSON_GetObjectItem(item, "three");
90     TEST_ASSERT_NOT_NULL_MESSAGE(found, "Failed to find item.");
91     TEST_ASSERT_EQUAL_DOUBLE(found->valuedouble, 3);
92 
93     found = cJSON_GetObjectItem(item, "four");
94     TEST_ASSERT_NULL_MESSAGE(found, "Should not find something that isn't there.");
95 
96     cJSON_Delete(item);
97 }
98 
cjson_get_object_item_case_sensitive_should_get_object_items(void)99 static void cjson_get_object_item_case_sensitive_should_get_object_items(void)
100 {
101     cJSON *item = NULL;
102     cJSON *found = NULL;
103 
104     item = cJSON_Parse("{\"one\":1, \"Two\":2, \"tHree\":3}");
105 
106     found = cJSON_GetObjectItemCaseSensitive(NULL, "test");
107     TEST_ASSERT_NULL_MESSAGE(found, "Failed to fail on NULL pointer.");
108 
109     found = cJSON_GetObjectItemCaseSensitive(item, NULL);
110     TEST_ASSERT_NULL_MESSAGE(found, "Failed to fail on NULL string.");
111 
112     found = cJSON_GetObjectItemCaseSensitive(item, "one");
113     TEST_ASSERT_NOT_NULL_MESSAGE(found, "Failed to find first item.");
114     TEST_ASSERT_EQUAL_DOUBLE(found->valuedouble, 1);
115 
116     found = cJSON_GetObjectItemCaseSensitive(item, "Two");
117     TEST_ASSERT_NOT_NULL_MESSAGE(found, "Failed to find first item.");
118     TEST_ASSERT_EQUAL_DOUBLE(found->valuedouble, 2);
119 
120     found = cJSON_GetObjectItemCaseSensitive(item, "tHree");
121     TEST_ASSERT_NOT_NULL_MESSAGE(found, "Failed to find item.");
122     TEST_ASSERT_EQUAL_DOUBLE(found->valuedouble, 3);
123 
124     found = cJSON_GetObjectItemCaseSensitive(item, "One");
125     TEST_ASSERT_NULL_MESSAGE(found, "Should not find something that isn't there.");
126 
127     cJSON_Delete(item);
128 }
129 
cjson_get_object_item_should_not_crash_with_array(void)130 static void cjson_get_object_item_should_not_crash_with_array(void) {
131     cJSON *array = NULL;
132     cJSON *found = NULL;
133     array = cJSON_Parse("[1]");
134 
135     found = cJSON_GetObjectItem(array, "name");
136     TEST_ASSERT_NULL(found);
137 
138     cJSON_Delete(array);
139 }
140 
cjson_get_object_item_case_sensitive_should_not_crash_with_array(void)141 static void cjson_get_object_item_case_sensitive_should_not_crash_with_array(void) {
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     cJSON_SetNumberValue(number, 1 + (double)INT_MAX);
235     TEST_ASSERT_EQUAL(INT_MAX, number->valueint);
236     TEST_ASSERT_EQUAL_DOUBLE(1 + (double)INT_MAX, number->valuedouble);
237 
238     cJSON_SetNumberValue(number, -1 + (double)INT_MIN);
239     TEST_ASSERT_EQUAL(INT_MIN, number->valueint);
240     TEST_ASSERT_EQUAL_DOUBLE(-1 + (double)INT_MIN, number->valuedouble);
241 }
242 
cjson_detach_item_via_pointer_should_detach_items(void)243 static void cjson_detach_item_via_pointer_should_detach_items(void)
244 {
245     cJSON list[4];
246     cJSON parent[1];
247 
248     memset(list, '\0', sizeof(list));
249 
250     /* link the list */
251     list[0].next = &(list[1]);
252     list[1].next = &(list[2]);
253     list[2].next = &(list[3]);
254 
255     list[3].prev = &(list[2]);
256     list[2].prev = &(list[1]);
257     list[1].prev = &(list[0]);
258     list[0].prev = &(list[3]);
259 
260     parent->child = &list[0];
261 
262     /* detach in the middle (list[1]) */
263     TEST_ASSERT_TRUE_MESSAGE(cJSON_DetachItemViaPointer(parent, &(list[1])) == &(list[1]), "Failed to detach in the middle.");
264     TEST_ASSERT_TRUE_MESSAGE((list[1].prev == NULL) && (list[1].next == NULL), "Didn't set pointers of detached item to NULL.");
265     TEST_ASSERT_TRUE((list[0].next == &(list[2])) && (list[2].prev == &(list[0])));
266 
267     /* detach beginning (list[0]) */
268     TEST_ASSERT_TRUE_MESSAGE(cJSON_DetachItemViaPointer(parent, &(list[0])) == &(list[0]), "Failed to detach beginning.");
269     TEST_ASSERT_TRUE_MESSAGE((list[0].prev == NULL) && (list[0].next == NULL), "Didn't set pointers of detached item to NULL.");
270     TEST_ASSERT_TRUE_MESSAGE((list[2].prev == &(list[3])) && (parent->child == &(list[2])), "Didn't set the new beginning.");
271 
272     /* detach end (list[3])*/
273     TEST_ASSERT_TRUE_MESSAGE(cJSON_DetachItemViaPointer(parent, &(list[3])) == &(list[3]), "Failed to detach end.");
274     TEST_ASSERT_TRUE_MESSAGE((list[3].prev == NULL) && (list[3].next == NULL), "Didn't set pointers of detached item to NULL.");
275     TEST_ASSERT_TRUE_MESSAGE((list[2].next == NULL) && (parent->child == &(list[2])), "Didn't set the new end");
276 
277     /* detach single item (list[2]) */
278     TEST_ASSERT_TRUE_MESSAGE(cJSON_DetachItemViaPointer(parent, &list[2]) == &list[2], "Failed to detach single item.");
279     TEST_ASSERT_TRUE_MESSAGE((list[2].prev == NULL) && (list[2].next == NULL), "Didn't set pointers of detached item to NULL.");
280     TEST_ASSERT_NULL_MESSAGE(parent->child, "Child of the parent wasn't set to NULL.");
281 }
282 
cjson_replace_item_via_pointer_should_replace_items(void)283 static void cjson_replace_item_via_pointer_should_replace_items(void)
284 {
285     cJSON replacements[3];
286     cJSON *beginning = NULL;
287     cJSON *middle = NULL;
288     cJSON *end = NULL;
289     cJSON *array = NULL;
290 
291     beginning = cJSON_CreateNull();
292     TEST_ASSERT_NOT_NULL(beginning);
293     middle = cJSON_CreateNull();
294     TEST_ASSERT_NOT_NULL(middle);
295     end = cJSON_CreateNull();
296     TEST_ASSERT_NOT_NULL(end);
297 
298     array = cJSON_CreateArray();
299     TEST_ASSERT_NOT_NULL(array);
300 
301     cJSON_AddItemToArray(array, beginning);
302     cJSON_AddItemToArray(array, middle);
303     cJSON_AddItemToArray(array, end);
304 
305 
306     memset(replacements, '\0', sizeof(replacements));
307 
308     /* replace beginning */
309     TEST_ASSERT_TRUE(cJSON_ReplaceItemViaPointer(array, beginning, &(replacements[0])));
310     TEST_ASSERT_TRUE(replacements[0].prev == end);
311     TEST_ASSERT_TRUE(replacements[0].next == middle);
312     TEST_ASSERT_TRUE(middle->prev == &(replacements[0]));
313     TEST_ASSERT_TRUE(array->child == &(replacements[0]));
314 
315     /* replace middle */
316     TEST_ASSERT_TRUE(cJSON_ReplaceItemViaPointer(array, middle, &(replacements[1])));
317     TEST_ASSERT_TRUE(replacements[1].prev == &(replacements[0]));
318     TEST_ASSERT_TRUE(replacements[1].next == end);
319     TEST_ASSERT_TRUE(end->prev == &(replacements[1]));
320 
321     /* replace end */
322     TEST_ASSERT_TRUE(cJSON_ReplaceItemViaPointer(array, end, &(replacements[2])));
323     TEST_ASSERT_TRUE(replacements[2].prev == &(replacements[1]));
324     TEST_ASSERT_NULL(replacements[2].next);
325     TEST_ASSERT_TRUE(replacements[1].next == &(replacements[2]));
326 
327     cJSON_free(array);
328 }
329 
cjson_replace_item_in_object_should_preserve_name(void)330 static void cjson_replace_item_in_object_should_preserve_name(void)
331 {
332     cJSON root[1] = {{ NULL, NULL, NULL, 0, NULL, 0, 0, NULL }};
333     cJSON *child = NULL;
334     cJSON *replacement = NULL;
335     cJSON_bool flag = false;
336 
337     child = cJSON_CreateNumber(1);
338     TEST_ASSERT_NOT_NULL(child);
339     replacement = cJSON_CreateNumber(2);
340     TEST_ASSERT_NOT_NULL(replacement);
341 
342     flag  = cJSON_AddItemToObject(root, "child", child);
343     TEST_ASSERT_TRUE_MESSAGE(flag, "add item to object failed");
344     cJSON_ReplaceItemInObject(root, "child", replacement);
345 
346     TEST_ASSERT_TRUE(root->child == replacement);
347     TEST_ASSERT_EQUAL_STRING("child", replacement->string);
348 
349     cJSON_Delete(replacement);
350 }
351 
cjson_functions_should_not_crash_with_null_pointers(void)352 static void cjson_functions_should_not_crash_with_null_pointers(void)
353 {
354     char buffer[10];
355     cJSON *item = cJSON_CreateString("item");
356 
357     cJSON_InitHooks(NULL);
358     TEST_ASSERT_NULL(cJSON_Parse(NULL));
359     TEST_ASSERT_NULL(cJSON_ParseWithOpts(NULL, NULL, true));
360     TEST_ASSERT_NULL(cJSON_Print(NULL));
361     TEST_ASSERT_NULL(cJSON_PrintUnformatted(NULL));
362     TEST_ASSERT_NULL(cJSON_PrintBuffered(NULL, 10, true));
363     TEST_ASSERT_FALSE(cJSON_PrintPreallocated(NULL, buffer, sizeof(buffer), true));
364     TEST_ASSERT_FALSE(cJSON_PrintPreallocated(item, NULL, 1, true));
365     cJSON_Delete(NULL);
366     cJSON_GetArraySize(NULL);
367     TEST_ASSERT_NULL(cJSON_GetArrayItem(NULL, 0));
368     TEST_ASSERT_NULL(cJSON_GetObjectItem(NULL, "item"));
369     TEST_ASSERT_NULL(cJSON_GetObjectItem(item, NULL));
370     TEST_ASSERT_NULL(cJSON_GetObjectItemCaseSensitive(NULL, "item"));
371     TEST_ASSERT_NULL(cJSON_GetObjectItemCaseSensitive(item, NULL));
372     TEST_ASSERT_FALSE(cJSON_HasObjectItem(NULL, "item"));
373     TEST_ASSERT_FALSE(cJSON_HasObjectItem(item, NULL));
374     TEST_ASSERT_FALSE(cJSON_IsInvalid(NULL));
375     TEST_ASSERT_FALSE(cJSON_IsFalse(NULL));
376     TEST_ASSERT_FALSE(cJSON_IsTrue(NULL));
377     TEST_ASSERT_FALSE(cJSON_IsBool(NULL));
378     TEST_ASSERT_FALSE(cJSON_IsNull(NULL));
379     TEST_ASSERT_FALSE(cJSON_IsNumber(NULL));
380     TEST_ASSERT_FALSE(cJSON_IsString(NULL));
381     TEST_ASSERT_FALSE(cJSON_IsArray(NULL));
382     TEST_ASSERT_FALSE(cJSON_IsObject(NULL));
383     TEST_ASSERT_FALSE(cJSON_IsRaw(NULL));
384     TEST_ASSERT_NULL(cJSON_CreateString(NULL));
385     TEST_ASSERT_NULL(cJSON_CreateRaw(NULL));
386     TEST_ASSERT_NULL(cJSON_CreateIntArray(NULL, 10));
387     TEST_ASSERT_NULL(cJSON_CreateFloatArray(NULL, 10));
388     TEST_ASSERT_NULL(cJSON_CreateDoubleArray(NULL, 10));
389     TEST_ASSERT_NULL(cJSON_CreateStringArray(NULL, 10));
390     cJSON_AddItemToArray(NULL, item);
391     cJSON_AddItemToArray(item, NULL);
392     cJSON_AddItemToObject(item, "item", NULL);
393     cJSON_AddItemToObject(item, NULL, item);
394     cJSON_AddItemToObject(NULL, "item", item);
395     cJSON_AddItemToObjectCS(item, "item", NULL);
396     cJSON_AddItemToObjectCS(item, NULL, item);
397     cJSON_AddItemToObjectCS(NULL, "item", item);
398     cJSON_AddItemReferenceToArray(NULL, item);
399     cJSON_AddItemReferenceToArray(item, NULL);
400     cJSON_AddItemReferenceToObject(item, "item", NULL);
401     cJSON_AddItemReferenceToObject(item, NULL, item);
402     cJSON_AddItemReferenceToObject(NULL, "item", item);
403     TEST_ASSERT_NULL(cJSON_DetachItemViaPointer(NULL, item));
404     TEST_ASSERT_NULL(cJSON_DetachItemViaPointer(item, NULL));
405     TEST_ASSERT_NULL(cJSON_DetachItemFromArray(NULL, 0));
406     cJSON_DeleteItemFromArray(NULL, 0);
407     TEST_ASSERT_NULL(cJSON_DetachItemFromObject(NULL, "item"));
408     TEST_ASSERT_NULL(cJSON_DetachItemFromObject(item, NULL));
409     TEST_ASSERT_NULL(cJSON_DetachItemFromObjectCaseSensitive(NULL, "item"));
410     TEST_ASSERT_NULL(cJSON_DetachItemFromObjectCaseSensitive(item, NULL));
411     cJSON_DeleteItemFromObject(NULL, "item");
412     cJSON_DeleteItemFromObject(item, NULL);
413     cJSON_DeleteItemFromObjectCaseSensitive(NULL, "item");
414     cJSON_DeleteItemFromObjectCaseSensitive(item, NULL);
415     TEST_ASSERT_FALSE(cJSON_InsertItemInArray(NULL, 0, item));
416     TEST_ASSERT_FALSE(cJSON_InsertItemInArray(item, 0, NULL));
417     TEST_ASSERT_FALSE(cJSON_ReplaceItemViaPointer(NULL, item, item));
418     TEST_ASSERT_FALSE(cJSON_ReplaceItemViaPointer(item, NULL, item));
419     TEST_ASSERT_FALSE(cJSON_ReplaceItemViaPointer(item, item, NULL));
420     TEST_ASSERT_FALSE(cJSON_ReplaceItemInArray(item, 0, NULL));
421     TEST_ASSERT_FALSE(cJSON_ReplaceItemInArray(NULL, 0, item));
422     TEST_ASSERT_FALSE(cJSON_ReplaceItemInObject(NULL, "item", item));
423     TEST_ASSERT_FALSE(cJSON_ReplaceItemInObject(item, NULL, item));
424     TEST_ASSERT_FALSE(cJSON_ReplaceItemInObject(item, "item", NULL));
425     TEST_ASSERT_FALSE(cJSON_ReplaceItemInObjectCaseSensitive(NULL, "item", item));
426     TEST_ASSERT_FALSE(cJSON_ReplaceItemInObjectCaseSensitive(item, NULL, item));
427     TEST_ASSERT_FALSE(cJSON_ReplaceItemInObjectCaseSensitive(item, "item", NULL));
428     TEST_ASSERT_NULL(cJSON_Duplicate(NULL, true));
429     TEST_ASSERT_FALSE(cJSON_Compare(item, NULL, false));
430     TEST_ASSERT_FALSE(cJSON_Compare(NULL, item, false));
431     cJSON_Minify(NULL);
432     /* skipped because it is only used via a macro that checks for NULL */
433     /* cJSON_SetNumberHelper(NULL, 0); */
434 
435     cJSON_Delete(item);
436 }
437 
failing_realloc(void * pointer,size_t size)438 static void * CJSON_CDECL failing_realloc(void *pointer, size_t size)
439 {
440     (void)size;
441     (void)pointer;
442     return NULL;
443 }
444 
ensure_should_fail_on_failed_realloc(void)445 static void ensure_should_fail_on_failed_realloc(void)
446 {
447     printbuffer buffer = {NULL, 10, 0, 0, false, false, {&malloc, &free, &failing_realloc}};
448     buffer.buffer = (unsigned char*)malloc(100);
449     TEST_ASSERT_NOT_NULL(buffer.buffer);
450 
451     TEST_ASSERT_NULL_MESSAGE(ensure(&buffer, 200), "Ensure didn't fail with failing realloc.");
452 }
453 
skip_utf8_bom_should_skip_bom(void)454 static void skip_utf8_bom_should_skip_bom(void)
455 {
456     const unsigned char string[] = "\xEF\xBB\xBF{}";
457     parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } };
458     buffer.content = string;
459     buffer.length = sizeof(string);
460     buffer.hooks = global_hooks;
461 
462     TEST_ASSERT_TRUE(skip_utf8_bom(&buffer) == &buffer);
463     TEST_ASSERT_EQUAL_UINT(3U, (unsigned int)buffer.offset);
464 }
465 
skip_utf8_bom_should_not_skip_bom_if_not_at_beginning(void)466 static void skip_utf8_bom_should_not_skip_bom_if_not_at_beginning(void)
467 {
468     const unsigned char string[] = " \xEF\xBB\xBF{}";
469     parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } };
470     buffer.content = string;
471     buffer.length = sizeof(string);
472     buffer.hooks = global_hooks;
473     buffer.offset = 1;
474 
475     TEST_ASSERT_NULL(skip_utf8_bom(&buffer));
476 }
477 
cjson_get_string_value_should_get_a_string(void)478 static void cjson_get_string_value_should_get_a_string(void)
479 {
480     cJSON *string = cJSON_CreateString("test");
481     cJSON *number = cJSON_CreateNumber(1);
482 
483     TEST_ASSERT_TRUE(cJSON_GetStringValue(string) == string->valuestring);
484     TEST_ASSERT_NULL(cJSON_GetStringValue(number));
485     TEST_ASSERT_NULL(cJSON_GetStringValue(NULL));
486 
487     cJSON_Delete(number);
488     cJSON_Delete(string);
489 }
490 
cjson_get_number_value_should_get_a_number(void)491 static void cjson_get_number_value_should_get_a_number(void)
492 {
493     cJSON *string = cJSON_CreateString("test");
494     cJSON *number = cJSON_CreateNumber(1);
495 
496     TEST_ASSERT_EQUAL_DOUBLE(cJSON_GetNumberValue(number), number->valuedouble);
497     TEST_ASSERT_DOUBLE_IS_NAN(cJSON_GetNumberValue(string));
498     TEST_ASSERT_DOUBLE_IS_NAN(cJSON_GetNumberValue(NULL));
499 
500     cJSON_Delete(number);
501     cJSON_Delete(string);
502 }
503 
cjson_create_string_reference_should_create_a_string_reference(void)504 static void cjson_create_string_reference_should_create_a_string_reference(void) {
505     const char *string = "I am a string!";
506 
507     cJSON *string_reference = cJSON_CreateStringReference(string);
508     TEST_ASSERT_TRUE(string_reference->valuestring == string);
509     TEST_ASSERT_EQUAL_INT(cJSON_IsReference | cJSON_String, string_reference->type);
510 
511     cJSON_Delete(string_reference);
512 }
513 
cjson_create_object_reference_should_create_an_object_reference(void)514 static void cjson_create_object_reference_should_create_an_object_reference(void) {
515     cJSON *number_reference = NULL;
516     cJSON *number_object = cJSON_CreateObject();
517     cJSON *number = cJSON_CreateNumber(42);
518     const char key[] = "number";
519 
520     TEST_ASSERT_TRUE(cJSON_IsNumber(number));
521     TEST_ASSERT_TRUE(cJSON_IsObject(number_object));
522     cJSON_AddItemToObjectCS(number_object, key, number);
523 
524     number_reference = cJSON_CreateObjectReference(number);
525     TEST_ASSERT_TRUE(number_reference->child == number);
526     TEST_ASSERT_EQUAL_INT(cJSON_Object | cJSON_IsReference, number_reference->type);
527 
528     cJSON_Delete(number_object);
529     cJSON_Delete(number_reference);
530 }
531 
cjson_create_array_reference_should_create_an_array_reference(void)532 static void cjson_create_array_reference_should_create_an_array_reference(void) {
533     cJSON *number_reference = NULL;
534     cJSON *number_array = cJSON_CreateArray();
535     cJSON *number = cJSON_CreateNumber(42);
536 
537     TEST_ASSERT_TRUE(cJSON_IsNumber(number));
538     TEST_ASSERT_TRUE(cJSON_IsArray(number_array));
539     cJSON_AddItemToArray(number_array, number);
540 
541     number_reference = cJSON_CreateArrayReference(number);
542     TEST_ASSERT_TRUE(number_reference->child == number);
543     TEST_ASSERT_EQUAL_INT(cJSON_Array | cJSON_IsReference, number_reference->type);
544 
545     cJSON_Delete(number_array);
546     cJSON_Delete(number_reference);
547 }
548 
cjson_add_item_to_object_or_array_should_not_add_itself(void)549 static void cjson_add_item_to_object_or_array_should_not_add_itself(void)
550 {
551     cJSON *object = cJSON_CreateObject();
552     cJSON *array = cJSON_CreateArray();
553     cJSON_bool flag = false;
554 
555     flag = cJSON_AddItemToObject(object, "key", object);
556     TEST_ASSERT_FALSE_MESSAGE(flag, "add an object to itself should fail");
557 
558     flag = cJSON_AddItemToArray(array, array);
559     TEST_ASSERT_FALSE_MESSAGE(flag, "add an array to itself should fail");
560 
561     cJSON_Delete(object);
562     cJSON_Delete(array);
563 }
564 
cjson_add_item_to_object_should_not_use_after_free_when_string_is_aliased(void)565 static void cjson_add_item_to_object_should_not_use_after_free_when_string_is_aliased(void)
566 {
567     cJSON *object = cJSON_CreateObject();
568     cJSON *number = cJSON_CreateNumber(42);
569     char *name = (char*)cJSON_strdup((const unsigned char*)"number", &global_hooks);
570 
571     TEST_ASSERT_NOT_NULL(object);
572     TEST_ASSERT_NOT_NULL(number);
573     TEST_ASSERT_NOT_NULL(name);
574 
575     number->string = name;
576 
577     /* The following should not have a use after free
578      * that would show up in valgrind or with AddressSanitizer */
579     cJSON_AddItemToObject(object, number->string, number);
580 
581     cJSON_Delete(object);
582 }
583 
cjson_delete_item_from_array_should_not_broken_list_structure(void)584 static void cjson_delete_item_from_array_should_not_broken_list_structure(void)
585 {
586     const char expected_json1[] = "{\"rd\":[{\"a\":\"123\"}]}";
587     const char expected_json2[] = "{\"rd\":[{\"a\":\"123\"},{\"b\":\"456\"}]}";
588     const char expected_json3[] = "{\"rd\":[{\"b\":\"456\"}]}";
589     char *str1 = NULL;
590     char *str2 = NULL;
591     char *str3 = NULL;
592 
593     cJSON *root = cJSON_Parse("{}");
594 
595     cJSON *array = cJSON_AddArrayToObject(root, "rd");
596     cJSON *item1 = cJSON_Parse("{\"a\":\"123\"}");
597     cJSON *item2 = cJSON_Parse("{\"b\":\"456\"}");
598 
599     cJSON_AddItemToArray(array, item1);
600     str1 = cJSON_PrintUnformatted(root);
601     TEST_ASSERT_EQUAL_STRING(expected_json1, str1);
602     free(str1);
603 
604     cJSON_AddItemToArray(array, item2);
605     str2 = cJSON_PrintUnformatted(root);
606     TEST_ASSERT_EQUAL_STRING(expected_json2, str2);
607     free(str2);
608 
609     /* this should not broken list structure */
610     cJSON_DeleteItemFromArray(array, 0);
611     str3 = cJSON_PrintUnformatted(root);
612     TEST_ASSERT_EQUAL_STRING(expected_json3, str3);
613     free(str3);
614 
615     cJSON_Delete(root);
616 }
617 
cjson_set_valuestring_to_object_should_not_leak_memory(void)618 static void cjson_set_valuestring_to_object_should_not_leak_memory(void)
619 {
620     cJSON *root = cJSON_Parse("{}");
621     const char *stringvalue = "valuestring could be changed safely";
622     const char *reference_valuestring = "reference item should be freed by yourself";
623     const char *short_valuestring = "shorter valuestring";
624     const char *long_valuestring = "new valuestring which much longer than previous should be changed safely";
625     cJSON *item1 = cJSON_CreateString(stringvalue);
626     cJSON *item2 = cJSON_CreateStringReference(reference_valuestring);
627     char *ptr1 = NULL;
628     char *return_value = NULL;
629 
630     cJSON_AddItemToObject(root, "one", item1);
631     cJSON_AddItemToObject(root, "two", item2);
632 
633     ptr1 = item1->valuestring;
634     return_value = cJSON_SetValuestring(cJSON_GetObjectItem(root, "one"), short_valuestring);
635     TEST_ASSERT_NOT_NULL(return_value);
636     TEST_ASSERT_EQUAL_PTR_MESSAGE(ptr1, return_value, "new valuestring shorter than old should not reallocate memory");
637     TEST_ASSERT_EQUAL_STRING(short_valuestring, cJSON_GetObjectItem(root, "one")->valuestring);
638 
639     /* we needn't to free the original valuestring manually */
640     ptr1 = item1->valuestring;
641     return_value = cJSON_SetValuestring(cJSON_GetObjectItem(root, "one"), long_valuestring);
642     TEST_ASSERT_NOT_NULL(return_value);
643     TEST_ASSERT_NOT_EQUAL_MESSAGE(ptr1, return_value, "new valuestring longer than old should reallocate memory")
644     TEST_ASSERT_EQUAL_STRING(long_valuestring, cJSON_GetObjectItem(root, "one")->valuestring);
645 
646     return_value = cJSON_SetValuestring(cJSON_GetObjectItem(root, "two"), long_valuestring);
647     TEST_ASSERT_NULL_MESSAGE(return_value, "valuestring of reference object should not be changed");
648     TEST_ASSERT_EQUAL_STRING(reference_valuestring, cJSON_GetObjectItem(root, "two")->valuestring);
649 
650     cJSON_Delete(root);
651 }
652 
main(void)653 int CJSON_CDECL main(void)
654 {
655     UNITY_BEGIN();
656 
657     RUN_TEST(cjson_array_foreach_should_loop_over_arrays);
658     RUN_TEST(cjson_array_foreach_should_not_dereference_null_pointer);
659     RUN_TEST(cjson_get_object_item_should_get_object_items);
660     RUN_TEST(cjson_get_object_item_case_sensitive_should_get_object_items);
661     RUN_TEST(cjson_get_object_item_should_not_crash_with_array);
662     RUN_TEST(cjson_get_object_item_case_sensitive_should_not_crash_with_array);
663     RUN_TEST(typecheck_functions_should_check_type);
664     RUN_TEST(cjson_should_not_parse_to_deeply_nested_jsons);
665     RUN_TEST(cjson_set_number_value_should_set_numbers);
666     RUN_TEST(cjson_detach_item_via_pointer_should_detach_items);
667     RUN_TEST(cjson_replace_item_via_pointer_should_replace_items);
668     RUN_TEST(cjson_replace_item_in_object_should_preserve_name);
669     RUN_TEST(cjson_functions_should_not_crash_with_null_pointers);
670     RUN_TEST(ensure_should_fail_on_failed_realloc);
671     RUN_TEST(skip_utf8_bom_should_skip_bom);
672     RUN_TEST(skip_utf8_bom_should_not_skip_bom_if_not_at_beginning);
673     RUN_TEST(cjson_get_string_value_should_get_a_string);
674     RUN_TEST(cjson_get_number_value_should_get_a_number);
675     RUN_TEST(cjson_create_string_reference_should_create_a_string_reference);
676     RUN_TEST(cjson_create_object_reference_should_create_an_object_reference);
677     RUN_TEST(cjson_create_array_reference_should_create_an_array_reference);
678     RUN_TEST(cjson_add_item_to_object_or_array_should_not_add_itself);
679     RUN_TEST(cjson_add_item_to_object_should_not_use_after_free_when_string_is_aliased);
680     RUN_TEST(cjson_delete_item_from_array_should_not_broken_list_structure);
681     RUN_TEST(cjson_set_valuestring_to_object_should_not_leak_memory);
682 
683     return UNITY_END();
684 }
685