• 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 
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     cJSON *array = cJSON_CreateArray();
357     cJSON *item1 = cJSON_CreateString("item1");
358     cJSON *item2 = cJSON_CreateString("corrupted array item3");
359     cJSON *corruptedString = cJSON_CreateString("corrupted");
360     struct cJSON *originalPrev;
361 
362     add_item_to_array(array, item1);
363     add_item_to_array(array, item2);
364 
365     originalPrev = item2->prev;
366     item2->prev = NULL;
367     free(corruptedString->valuestring);
368     corruptedString->valuestring = NULL;
369 
370     cJSON_InitHooks(NULL);
371     TEST_ASSERT_NULL(cJSON_Parse(NULL));
372     TEST_ASSERT_NULL(cJSON_ParseWithOpts(NULL, NULL, true));
373     TEST_ASSERT_NULL(cJSON_Print(NULL));
374     TEST_ASSERT_NULL(cJSON_PrintUnformatted(NULL));
375     TEST_ASSERT_NULL(cJSON_PrintBuffered(NULL, 10, true));
376     TEST_ASSERT_FALSE(cJSON_PrintPreallocated(NULL, buffer, sizeof(buffer), true));
377     TEST_ASSERT_FALSE(cJSON_PrintPreallocated(item, NULL, 1, true));
378     cJSON_Delete(NULL);
379     cJSON_GetArraySize(NULL);
380     TEST_ASSERT_NULL(cJSON_GetArrayItem(NULL, 0));
381     TEST_ASSERT_NULL(cJSON_GetObjectItem(NULL, "item"));
382     TEST_ASSERT_NULL(cJSON_GetObjectItem(item, NULL));
383     TEST_ASSERT_NULL(cJSON_GetObjectItemCaseSensitive(NULL, "item"));
384     TEST_ASSERT_NULL(cJSON_GetObjectItemCaseSensitive(item, NULL));
385     TEST_ASSERT_FALSE(cJSON_HasObjectItem(NULL, "item"));
386     TEST_ASSERT_FALSE(cJSON_HasObjectItem(item, NULL));
387     TEST_ASSERT_FALSE(cJSON_IsInvalid(NULL));
388     TEST_ASSERT_FALSE(cJSON_IsFalse(NULL));
389     TEST_ASSERT_FALSE(cJSON_IsTrue(NULL));
390     TEST_ASSERT_FALSE(cJSON_IsBool(NULL));
391     TEST_ASSERT_FALSE(cJSON_IsNull(NULL));
392     TEST_ASSERT_FALSE(cJSON_IsNumber(NULL));
393     TEST_ASSERT_FALSE(cJSON_IsString(NULL));
394     TEST_ASSERT_FALSE(cJSON_IsArray(NULL));
395     TEST_ASSERT_FALSE(cJSON_IsObject(NULL));
396     TEST_ASSERT_FALSE(cJSON_IsRaw(NULL));
397     TEST_ASSERT_NULL(cJSON_CreateString(NULL));
398     TEST_ASSERT_NULL(cJSON_CreateRaw(NULL));
399     TEST_ASSERT_NULL(cJSON_CreateIntArray(NULL, 10));
400     TEST_ASSERT_NULL(cJSON_CreateFloatArray(NULL, 10));
401     TEST_ASSERT_NULL(cJSON_CreateDoubleArray(NULL, 10));
402     TEST_ASSERT_NULL(cJSON_CreateStringArray(NULL, 10));
403     cJSON_AddItemToArray(NULL, item);
404     cJSON_AddItemToArray(item, NULL);
405     cJSON_AddItemToObject(item, "item", NULL);
406     cJSON_AddItemToObject(item, NULL, item);
407     cJSON_AddItemToObject(NULL, "item", item);
408     cJSON_AddItemToObjectCS(item, "item", NULL);
409     cJSON_AddItemToObjectCS(item, NULL, item);
410     cJSON_AddItemToObjectCS(NULL, "item", item);
411     cJSON_AddItemReferenceToArray(NULL, item);
412     cJSON_AddItemReferenceToArray(item, NULL);
413     cJSON_AddItemReferenceToObject(item, "item", NULL);
414     cJSON_AddItemReferenceToObject(item, NULL, item);
415     cJSON_AddItemReferenceToObject(NULL, "item", item);
416     TEST_ASSERT_NULL(cJSON_DetachItemViaPointer(NULL, item));
417     TEST_ASSERT_NULL(cJSON_DetachItemViaPointer(item, NULL));
418     TEST_ASSERT_NULL(cJSON_DetachItemFromArray(NULL, 0));
419     cJSON_DeleteItemFromArray(NULL, 0);
420     TEST_ASSERT_NULL(cJSON_DetachItemFromObject(NULL, "item"));
421     TEST_ASSERT_NULL(cJSON_DetachItemFromObject(item, NULL));
422     TEST_ASSERT_NULL(cJSON_DetachItemFromObjectCaseSensitive(NULL, "item"));
423     TEST_ASSERT_NULL(cJSON_DetachItemFromObjectCaseSensitive(item, NULL));
424     cJSON_DeleteItemFromObject(NULL, "item");
425     cJSON_DeleteItemFromObject(item, NULL);
426     cJSON_DeleteItemFromObjectCaseSensitive(NULL, "item");
427     cJSON_DeleteItemFromObjectCaseSensitive(item, NULL);
428     TEST_ASSERT_FALSE(cJSON_InsertItemInArray(array, 0, NULL));
429     TEST_ASSERT_FALSE(cJSON_InsertItemInArray(array, 1, item));
430     TEST_ASSERT_FALSE(cJSON_InsertItemInArray(NULL, 0, item));
431     TEST_ASSERT_FALSE(cJSON_InsertItemInArray(item, 0, NULL));
432     TEST_ASSERT_FALSE(cJSON_ReplaceItemViaPointer(NULL, item, item));
433     TEST_ASSERT_FALSE(cJSON_ReplaceItemViaPointer(item, NULL, item));
434     TEST_ASSERT_FALSE(cJSON_ReplaceItemViaPointer(item, item, NULL));
435     TEST_ASSERT_FALSE(cJSON_ReplaceItemInArray(item, 0, NULL));
436     TEST_ASSERT_FALSE(cJSON_ReplaceItemInArray(NULL, 0, item));
437     TEST_ASSERT_FALSE(cJSON_ReplaceItemInObject(NULL, "item", item));
438     TEST_ASSERT_FALSE(cJSON_ReplaceItemInObject(item, NULL, item));
439     TEST_ASSERT_FALSE(cJSON_ReplaceItemInObject(item, "item", NULL));
440     TEST_ASSERT_FALSE(cJSON_ReplaceItemInObjectCaseSensitive(NULL, "item", item));
441     TEST_ASSERT_FALSE(cJSON_ReplaceItemInObjectCaseSensitive(item, NULL, item));
442     TEST_ASSERT_FALSE(cJSON_ReplaceItemInObjectCaseSensitive(item, "item", NULL));
443     TEST_ASSERT_NULL(cJSON_Duplicate(NULL, true));
444     TEST_ASSERT_FALSE(cJSON_Compare(item, NULL, false));
445     TEST_ASSERT_FALSE(cJSON_Compare(NULL, item, false));
446     TEST_ASSERT_NULL(cJSON_SetValuestring(NULL, "test"));
447     TEST_ASSERT_NULL(cJSON_SetValuestring(corruptedString, "test"));
448     cJSON_Minify(NULL);
449     /* skipped because it is only used via a macro that checks for NULL */
450     /* cJSON_SetNumberHelper(NULL, 0); */
451 
452     /* restore corrupted item2 to delete it */
453     item2->prev = originalPrev;
454     cJSON_Delete(corruptedString);
455     cJSON_Delete(array);
456     cJSON_Delete(item);
457 }
458 
failing_realloc(void * pointer,size_t size)459 static void * CJSON_CDECL failing_realloc(void *pointer, size_t size)
460 {
461     (void)size;
462     (void)pointer;
463     return NULL;
464 }
465 
ensure_should_fail_on_failed_realloc(void)466 static void ensure_should_fail_on_failed_realloc(void)
467 {
468     printbuffer buffer = {NULL, 10, 0, 0, false, false, {&malloc, &free, &failing_realloc}};
469     buffer.buffer = (unsigned char*)malloc(100);
470     TEST_ASSERT_NOT_NULL(buffer.buffer);
471 
472     TEST_ASSERT_NULL_MESSAGE(ensure(&buffer, 200), "Ensure didn't fail with failing realloc.");
473 }
474 
skip_utf8_bom_should_skip_bom(void)475 static void skip_utf8_bom_should_skip_bom(void)
476 {
477     const unsigned char string[] = "\xEF\xBB\xBF{}";
478     parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } };
479     buffer.content = string;
480     buffer.length = sizeof(string);
481     buffer.hooks = global_hooks;
482 
483     TEST_ASSERT_TRUE(skip_utf8_bom(&buffer) == &buffer);
484     TEST_ASSERT_EQUAL_UINT(3U, (unsigned int)buffer.offset);
485 }
486 
skip_utf8_bom_should_not_skip_bom_if_not_at_beginning(void)487 static void skip_utf8_bom_should_not_skip_bom_if_not_at_beginning(void)
488 {
489     const unsigned char string[] = " \xEF\xBB\xBF{}";
490     parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } };
491     buffer.content = string;
492     buffer.length = sizeof(string);
493     buffer.hooks = global_hooks;
494     buffer.offset = 1;
495 
496     TEST_ASSERT_NULL(skip_utf8_bom(&buffer));
497 }
498 
cjson_get_string_value_should_get_a_string(void)499 static void cjson_get_string_value_should_get_a_string(void)
500 {
501     cJSON *string = cJSON_CreateString("test");
502     cJSON *number = cJSON_CreateNumber(1);
503 
504     TEST_ASSERT_TRUE(cJSON_GetStringValue(string) == string->valuestring);
505     TEST_ASSERT_NULL(cJSON_GetStringValue(number));
506     TEST_ASSERT_NULL(cJSON_GetStringValue(NULL));
507 
508     cJSON_Delete(number);
509     cJSON_Delete(string);
510 }
511 
cjson_get_number_value_should_get_a_number(void)512 static void cjson_get_number_value_should_get_a_number(void)
513 {
514     cJSON *string = cJSON_CreateString("test");
515     cJSON *number = cJSON_CreateNumber(1);
516 
517     TEST_ASSERT_EQUAL_DOUBLE(cJSON_GetNumberValue(number), number->valuedouble);
518     TEST_ASSERT_DOUBLE_IS_NAN(cJSON_GetNumberValue(string));
519     TEST_ASSERT_DOUBLE_IS_NAN(cJSON_GetNumberValue(NULL));
520 
521     cJSON_Delete(number);
522     cJSON_Delete(string);
523 }
524 
cjson_create_string_reference_should_create_a_string_reference(void)525 static void cjson_create_string_reference_should_create_a_string_reference(void) {
526     const char *string = "I am a string!";
527 
528     cJSON *string_reference = cJSON_CreateStringReference(string);
529     TEST_ASSERT_TRUE(string_reference->valuestring == string);
530     TEST_ASSERT_EQUAL_INT(cJSON_IsReference | cJSON_String, string_reference->type);
531 
532     cJSON_Delete(string_reference);
533 }
534 
cjson_create_object_reference_should_create_an_object_reference(void)535 static void cjson_create_object_reference_should_create_an_object_reference(void) {
536     cJSON *number_reference = NULL;
537     cJSON *number_object = cJSON_CreateObject();
538     cJSON *number = cJSON_CreateNumber(42);
539     const char key[] = "number";
540 
541     TEST_ASSERT_TRUE(cJSON_IsNumber(number));
542     TEST_ASSERT_TRUE(cJSON_IsObject(number_object));
543     cJSON_AddItemToObjectCS(number_object, key, number);
544 
545     number_reference = cJSON_CreateObjectReference(number);
546     TEST_ASSERT_TRUE(number_reference->child == number);
547     TEST_ASSERT_EQUAL_INT(cJSON_Object | cJSON_IsReference, number_reference->type);
548 
549     cJSON_Delete(number_object);
550     cJSON_Delete(number_reference);
551 }
552 
cjson_create_array_reference_should_create_an_array_reference(void)553 static void cjson_create_array_reference_should_create_an_array_reference(void) {
554     cJSON *number_reference = NULL;
555     cJSON *number_array = cJSON_CreateArray();
556     cJSON *number = cJSON_CreateNumber(42);
557 
558     TEST_ASSERT_TRUE(cJSON_IsNumber(number));
559     TEST_ASSERT_TRUE(cJSON_IsArray(number_array));
560     cJSON_AddItemToArray(number_array, number);
561 
562     number_reference = cJSON_CreateArrayReference(number);
563     TEST_ASSERT_TRUE(number_reference->child == number);
564     TEST_ASSERT_EQUAL_INT(cJSON_Array | cJSON_IsReference, number_reference->type);
565 
566     cJSON_Delete(number_array);
567     cJSON_Delete(number_reference);
568 }
569 
cjson_add_item_to_object_or_array_should_not_add_itself(void)570 static void cjson_add_item_to_object_or_array_should_not_add_itself(void)
571 {
572     cJSON *object = cJSON_CreateObject();
573     cJSON *array = cJSON_CreateArray();
574     cJSON_bool flag = false;
575 
576     flag = cJSON_AddItemToObject(object, "key", object);
577     TEST_ASSERT_FALSE_MESSAGE(flag, "add an object to itself should fail");
578 
579     flag = cJSON_AddItemToArray(array, array);
580     TEST_ASSERT_FALSE_MESSAGE(flag, "add an array to itself should fail");
581 
582     cJSON_Delete(object);
583     cJSON_Delete(array);
584 }
585 
cjson_add_item_to_object_should_not_use_after_free_when_string_is_aliased(void)586 static void cjson_add_item_to_object_should_not_use_after_free_when_string_is_aliased(void)
587 {
588     cJSON *object = cJSON_CreateObject();
589     cJSON *number = cJSON_CreateNumber(42);
590     char *name = (char*)cJSON_strdup((const unsigned char*)"number", &global_hooks);
591 
592     TEST_ASSERT_NOT_NULL(object);
593     TEST_ASSERT_NOT_NULL(number);
594     TEST_ASSERT_NOT_NULL(name);
595 
596     number->string = name;
597 
598     /* The following should not have a use after free
599      * that would show up in valgrind or with AddressSanitizer */
600     cJSON_AddItemToObject(object, number->string, number);
601 
602     cJSON_Delete(object);
603 }
604 
cjson_delete_item_from_array_should_not_broken_list_structure(void)605 static void cjson_delete_item_from_array_should_not_broken_list_structure(void)
606 {
607     const char expected_json1[] = "{\"rd\":[{\"a\":\"123\"}]}";
608     const char expected_json2[] = "{\"rd\":[{\"a\":\"123\"},{\"b\":\"456\"}]}";
609     const char expected_json3[] = "{\"rd\":[{\"b\":\"456\"}]}";
610     char *str1 = NULL;
611     char *str2 = NULL;
612     char *str3 = NULL;
613 
614     cJSON *root = cJSON_Parse("{}");
615 
616     cJSON *array = cJSON_AddArrayToObject(root, "rd");
617     cJSON *item1 = cJSON_Parse("{\"a\":\"123\"}");
618     cJSON *item2 = cJSON_Parse("{\"b\":\"456\"}");
619 
620     cJSON_AddItemToArray(array, item1);
621     str1 = cJSON_PrintUnformatted(root);
622     TEST_ASSERT_EQUAL_STRING(expected_json1, str1);
623     free(str1);
624 
625     cJSON_AddItemToArray(array, item2);
626     str2 = cJSON_PrintUnformatted(root);
627     TEST_ASSERT_EQUAL_STRING(expected_json2, str2);
628     free(str2);
629 
630     /* this should not broken list structure */
631     cJSON_DeleteItemFromArray(array, 0);
632     str3 = cJSON_PrintUnformatted(root);
633     TEST_ASSERT_EQUAL_STRING(expected_json3, str3);
634     free(str3);
635 
636     cJSON_Delete(root);
637 }
638 
cjson_set_valuestring_to_object_should_not_leak_memory(void)639 static void cjson_set_valuestring_to_object_should_not_leak_memory(void)
640 {
641     cJSON *root = cJSON_Parse("{}");
642     const char *stringvalue = "valuestring could be changed safely";
643     const char *reference_valuestring = "reference item should be freed by yourself";
644     const char *short_valuestring = "shorter valuestring";
645     const char *long_valuestring = "new valuestring which much longer than previous should be changed safely";
646     cJSON *item1 = cJSON_CreateString(stringvalue);
647     cJSON *item2 = cJSON_CreateStringReference(reference_valuestring);
648     char *ptr1 = NULL;
649     char *return_value = NULL;
650 
651     cJSON_AddItemToObject(root, "one", item1);
652     cJSON_AddItemToObject(root, "two", item2);
653 
654     ptr1 = item1->valuestring;
655     return_value = cJSON_SetValuestring(cJSON_GetObjectItem(root, "one"), short_valuestring);
656     TEST_ASSERT_NOT_NULL(return_value);
657     TEST_ASSERT_EQUAL_PTR_MESSAGE(ptr1, return_value, "new valuestring shorter than old should not reallocate memory");
658     TEST_ASSERT_EQUAL_STRING(short_valuestring, cJSON_GetObjectItem(root, "one")->valuestring);
659 
660     /* we needn't to free the original valuestring manually */
661     ptr1 = item1->valuestring;
662     return_value = cJSON_SetValuestring(cJSON_GetObjectItem(root, "one"), long_valuestring);
663     TEST_ASSERT_NOT_NULL(return_value);
664     TEST_ASSERT_NOT_EQUAL_MESSAGE(ptr1, return_value, "new valuestring longer than old should reallocate memory")
665     TEST_ASSERT_EQUAL_STRING(long_valuestring, cJSON_GetObjectItem(root, "one")->valuestring);
666 
667     return_value = cJSON_SetValuestring(cJSON_GetObjectItem(root, "two"), long_valuestring);
668     TEST_ASSERT_NULL_MESSAGE(return_value, "valuestring of reference object should not be changed");
669     TEST_ASSERT_EQUAL_STRING(reference_valuestring, cJSON_GetObjectItem(root, "two")->valuestring);
670 
671     cJSON_Delete(root);
672 }
673 
main(void)674 int CJSON_CDECL main(void)
675 {
676     UNITY_BEGIN();
677 
678     RUN_TEST(cjson_array_foreach_should_loop_over_arrays);
679     RUN_TEST(cjson_array_foreach_should_not_dereference_null_pointer);
680     RUN_TEST(cjson_get_object_item_should_get_object_items);
681     RUN_TEST(cjson_get_object_item_case_sensitive_should_get_object_items);
682     RUN_TEST(cjson_get_object_item_should_not_crash_with_array);
683     RUN_TEST(cjson_get_object_item_case_sensitive_should_not_crash_with_array);
684     RUN_TEST(typecheck_functions_should_check_type);
685     RUN_TEST(cjson_should_not_parse_to_deeply_nested_jsons);
686     RUN_TEST(cjson_set_number_value_should_set_numbers);
687     RUN_TEST(cjson_detach_item_via_pointer_should_detach_items);
688     RUN_TEST(cjson_replace_item_via_pointer_should_replace_items);
689     RUN_TEST(cjson_replace_item_in_object_should_preserve_name);
690     RUN_TEST(cjson_functions_should_not_crash_with_null_pointers);
691     RUN_TEST(ensure_should_fail_on_failed_realloc);
692     RUN_TEST(skip_utf8_bom_should_skip_bom);
693     RUN_TEST(skip_utf8_bom_should_not_skip_bom_if_not_at_beginning);
694     RUN_TEST(cjson_get_string_value_should_get_a_string);
695     RUN_TEST(cjson_get_number_value_should_get_a_number);
696     RUN_TEST(cjson_create_string_reference_should_create_a_string_reference);
697     RUN_TEST(cjson_create_object_reference_should_create_an_object_reference);
698     RUN_TEST(cjson_create_array_reference_should_create_an_array_reference);
699     RUN_TEST(cjson_add_item_to_object_or_array_should_not_add_itself);
700     RUN_TEST(cjson_add_item_to_object_should_not_use_after_free_when_string_is_aliased);
701     RUN_TEST(cjson_delete_item_from_array_should_not_broken_list_structure);
702     RUN_TEST(cjson_set_valuestring_to_object_should_not_leak_memory);
703 
704     return UNITY_END();
705 }
706