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_should_not_follow_too_deep_circular_references(void)222 static void cjson_should_not_follow_too_deep_circular_references(void)
223 {
224 cJSON *o = cJSON_CreateArray();
225 cJSON *a = cJSON_CreateArray();
226 cJSON *b = cJSON_CreateArray();
227 cJSON *x;
228
229 cJSON_AddItemToArray(o, a);
230 cJSON_AddItemToArray(a, b);
231 cJSON_AddItemToArray(b, o);
232
233 x = cJSON_Duplicate(o, 1);
234 TEST_ASSERT_NULL(x);
235 cJSON_DetachItemFromArray(b, 0);
236 cJSON_Delete(o);
237 }
238
cjson_set_number_value_should_set_numbers(void)239 static void cjson_set_number_value_should_set_numbers(void)
240 {
241 cJSON number[1] = {{NULL, NULL, NULL, cJSON_Number, NULL, 0, 0, NULL}};
242
243 cJSON_SetNumberValue(number, 1.5);
244 TEST_ASSERT_EQUAL(1, number->valueint);
245 TEST_ASSERT_EQUAL_DOUBLE(1.5, number->valuedouble);
246
247 cJSON_SetNumberValue(number, -1.5);
248 TEST_ASSERT_EQUAL(-1, number->valueint);
249 TEST_ASSERT_EQUAL_DOUBLE(-1.5, number->valuedouble);
250
251 cJSON_SetNumberValue(number, 1 + (double)INT_MAX);
252 TEST_ASSERT_EQUAL(INT_MAX, number->valueint);
253 TEST_ASSERT_EQUAL_DOUBLE(1 + (double)INT_MAX, number->valuedouble);
254
255 cJSON_SetNumberValue(number, -1 + (double)INT_MIN);
256 TEST_ASSERT_EQUAL(INT_MIN, number->valueint);
257 TEST_ASSERT_EQUAL_DOUBLE(-1 + (double)INT_MIN, number->valuedouble);
258 }
259
cjson_detach_item_via_pointer_should_detach_items(void)260 static void cjson_detach_item_via_pointer_should_detach_items(void)
261 {
262 cJSON list[4];
263 cJSON parent[1];
264
265 memset(list, '\0', sizeof(list));
266
267 /* link the list */
268 list[0].next = &(list[1]);
269 list[1].next = &(list[2]);
270 list[2].next = &(list[3]);
271
272 list[3].prev = &(list[2]);
273 list[2].prev = &(list[1]);
274 list[1].prev = &(list[0]);
275 list[0].prev = &(list[3]);
276
277 parent->child = &list[0];
278
279 /* detach in the middle (list[1]) */
280 TEST_ASSERT_TRUE_MESSAGE(cJSON_DetachItemViaPointer(parent, &(list[1])) == &(list[1]), "Failed to detach in the middle.");
281 TEST_ASSERT_TRUE_MESSAGE((list[1].prev == NULL) && (list[1].next == NULL), "Didn't set pointers of detached item to NULL.");
282 TEST_ASSERT_TRUE((list[0].next == &(list[2])) && (list[2].prev == &(list[0])));
283
284 /* detach beginning (list[0]) */
285 TEST_ASSERT_TRUE_MESSAGE(cJSON_DetachItemViaPointer(parent, &(list[0])) == &(list[0]), "Failed to detach beginning.");
286 TEST_ASSERT_TRUE_MESSAGE((list[0].prev == NULL) && (list[0].next == NULL), "Didn't set pointers of detached item to NULL.");
287 TEST_ASSERT_TRUE_MESSAGE((list[2].prev == &(list[3])) && (parent->child == &(list[2])), "Didn't set the new beginning.");
288
289 /* detach end (list[3])*/
290 TEST_ASSERT_TRUE_MESSAGE(cJSON_DetachItemViaPointer(parent, &(list[3])) == &(list[3]), "Failed to detach end.");
291 TEST_ASSERT_TRUE_MESSAGE((list[3].prev == NULL) && (list[3].next == NULL), "Didn't set pointers of detached item to NULL.");
292 TEST_ASSERT_TRUE_MESSAGE((list[2].next == NULL) && (parent->child == &(list[2])), "Didn't set the new end");
293
294 /* detach single item (list[2]) */
295 TEST_ASSERT_TRUE_MESSAGE(cJSON_DetachItemViaPointer(parent, &list[2]) == &list[2], "Failed to detach single item.");
296 TEST_ASSERT_TRUE_MESSAGE((list[2].prev == NULL) && (list[2].next == NULL), "Didn't set pointers of detached item to NULL.");
297 TEST_ASSERT_NULL_MESSAGE(parent->child, "Child of the parent wasn't set to NULL.");
298 }
299
cjson_replace_item_via_pointer_should_replace_items(void)300 static void cjson_replace_item_via_pointer_should_replace_items(void)
301 {
302 cJSON replacements[3];
303 cJSON *beginning = NULL;
304 cJSON *middle = NULL;
305 cJSON *end = NULL;
306 cJSON *array = NULL;
307
308 beginning = cJSON_CreateNull();
309 TEST_ASSERT_NOT_NULL(beginning);
310 middle = cJSON_CreateNull();
311 TEST_ASSERT_NOT_NULL(middle);
312 end = cJSON_CreateNull();
313 TEST_ASSERT_NOT_NULL(end);
314
315 array = cJSON_CreateArray();
316 TEST_ASSERT_NOT_NULL(array);
317
318 cJSON_AddItemToArray(array, beginning);
319 cJSON_AddItemToArray(array, middle);
320 cJSON_AddItemToArray(array, end);
321
322 memset(replacements, '\0', sizeof(replacements));
323
324 /* replace beginning */
325 TEST_ASSERT_TRUE(cJSON_ReplaceItemViaPointer(array, beginning, &(replacements[0])));
326 TEST_ASSERT_TRUE(replacements[0].prev == end);
327 TEST_ASSERT_TRUE(replacements[0].next == middle);
328 TEST_ASSERT_TRUE(middle->prev == &(replacements[0]));
329 TEST_ASSERT_TRUE(array->child == &(replacements[0]));
330
331 /* replace middle */
332 TEST_ASSERT_TRUE(cJSON_ReplaceItemViaPointer(array, middle, &(replacements[1])));
333 TEST_ASSERT_TRUE(replacements[1].prev == &(replacements[0]));
334 TEST_ASSERT_TRUE(replacements[1].next == end);
335 TEST_ASSERT_TRUE(end->prev == &(replacements[1]));
336
337 /* replace end */
338 TEST_ASSERT_TRUE(cJSON_ReplaceItemViaPointer(array, end, &(replacements[2])));
339 TEST_ASSERT_TRUE(replacements[2].prev == &(replacements[1]));
340 TEST_ASSERT_NULL(replacements[2].next);
341 TEST_ASSERT_TRUE(replacements[1].next == &(replacements[2]));
342
343 cJSON_free(array);
344 }
345
cjson_replace_item_in_object_should_preserve_name(void)346 static void cjson_replace_item_in_object_should_preserve_name(void)
347 {
348 cJSON root[1] = {{NULL, NULL, NULL, 0, NULL, 0, 0, NULL}};
349 cJSON *child = NULL;
350 cJSON *replacement = NULL;
351 cJSON_bool flag = false;
352
353 child = cJSON_CreateNumber(1);
354 TEST_ASSERT_NOT_NULL(child);
355 replacement = cJSON_CreateNumber(2);
356 TEST_ASSERT_NOT_NULL(replacement);
357
358 flag = cJSON_AddItemToObject(root, "child", child);
359 TEST_ASSERT_TRUE_MESSAGE(flag, "add item to object failed");
360 cJSON_ReplaceItemInObject(root, "child", replacement);
361
362 TEST_ASSERT_TRUE(root->child == replacement);
363 TEST_ASSERT_EQUAL_STRING("child", replacement->string);
364
365 cJSON_Delete(replacement);
366 }
367
cjson_functions_should_not_crash_with_null_pointers(void)368 static void cjson_functions_should_not_crash_with_null_pointers(void)
369 {
370 char buffer[10];
371 cJSON *item = cJSON_CreateString("item");
372 cJSON *array = cJSON_CreateArray();
373 cJSON *item1 = cJSON_CreateString("item1");
374 cJSON *item2 = cJSON_CreateString("corrupted array item3");
375 cJSON *corruptedString = cJSON_CreateString("corrupted");
376 struct cJSON *originalPrev;
377
378 add_item_to_array(array, item1);
379 add_item_to_array(array, item2);
380
381 originalPrev = item2->prev;
382 item2->prev = NULL;
383 free(corruptedString->valuestring);
384 corruptedString->valuestring = NULL;
385
386 cJSON_InitHooks(NULL);
387 TEST_ASSERT_NULL(cJSON_Parse(NULL));
388 TEST_ASSERT_NULL(cJSON_ParseWithOpts(NULL, NULL, true));
389 TEST_ASSERT_NULL(cJSON_Print(NULL));
390 TEST_ASSERT_NULL(cJSON_PrintUnformatted(NULL));
391 TEST_ASSERT_NULL(cJSON_PrintBuffered(NULL, 10, true));
392 TEST_ASSERT_FALSE(cJSON_PrintPreallocated(NULL, buffer, sizeof(buffer), true));
393 TEST_ASSERT_FALSE(cJSON_PrintPreallocated(item, NULL, 1, true));
394 cJSON_Delete(NULL);
395 cJSON_GetArraySize(NULL);
396 TEST_ASSERT_NULL(cJSON_GetArrayItem(NULL, 0));
397 TEST_ASSERT_NULL(cJSON_GetObjectItem(NULL, "item"));
398 TEST_ASSERT_NULL(cJSON_GetObjectItem(item, NULL));
399 TEST_ASSERT_NULL(cJSON_GetObjectItemCaseSensitive(NULL, "item"));
400 TEST_ASSERT_NULL(cJSON_GetObjectItemCaseSensitive(item, NULL));
401 TEST_ASSERT_FALSE(cJSON_HasObjectItem(NULL, "item"));
402 TEST_ASSERT_FALSE(cJSON_HasObjectItem(item, NULL));
403 TEST_ASSERT_FALSE(cJSON_IsInvalid(NULL));
404 TEST_ASSERT_FALSE(cJSON_IsFalse(NULL));
405 TEST_ASSERT_FALSE(cJSON_IsTrue(NULL));
406 TEST_ASSERT_FALSE(cJSON_IsBool(NULL));
407 TEST_ASSERT_FALSE(cJSON_IsNull(NULL));
408 TEST_ASSERT_FALSE(cJSON_IsNumber(NULL));
409 TEST_ASSERT_FALSE(cJSON_IsString(NULL));
410 TEST_ASSERT_FALSE(cJSON_IsArray(NULL));
411 TEST_ASSERT_FALSE(cJSON_IsObject(NULL));
412 TEST_ASSERT_FALSE(cJSON_IsRaw(NULL));
413 TEST_ASSERT_NULL(cJSON_CreateString(NULL));
414 TEST_ASSERT_NULL(cJSON_CreateRaw(NULL));
415 TEST_ASSERT_NULL(cJSON_CreateIntArray(NULL, 10));
416 TEST_ASSERT_NULL(cJSON_CreateFloatArray(NULL, 10));
417 TEST_ASSERT_NULL(cJSON_CreateDoubleArray(NULL, 10));
418 TEST_ASSERT_NULL(cJSON_CreateStringArray(NULL, 10));
419 cJSON_AddItemToArray(NULL, item);
420 cJSON_AddItemToArray(item, NULL);
421 cJSON_AddItemToObject(item, "item", NULL);
422 cJSON_AddItemToObject(item, NULL, item);
423 cJSON_AddItemToObject(NULL, "item", item);
424 cJSON_AddItemToObjectCS(item, "item", NULL);
425 cJSON_AddItemToObjectCS(item, NULL, item);
426 cJSON_AddItemToObjectCS(NULL, "item", item);
427 cJSON_AddItemReferenceToArray(NULL, item);
428 cJSON_AddItemReferenceToArray(item, NULL);
429 cJSON_AddItemReferenceToObject(item, "item", NULL);
430 cJSON_AddItemReferenceToObject(item, NULL, item);
431 cJSON_AddItemReferenceToObject(NULL, "item", item);
432 TEST_ASSERT_NULL(cJSON_DetachItemViaPointer(NULL, item));
433 TEST_ASSERT_NULL(cJSON_DetachItemViaPointer(item, NULL));
434 TEST_ASSERT_NULL(cJSON_DetachItemFromArray(NULL, 0));
435 cJSON_DeleteItemFromArray(NULL, 0);
436 TEST_ASSERT_NULL(cJSON_DetachItemFromObject(NULL, "item"));
437 TEST_ASSERT_NULL(cJSON_DetachItemFromObject(item, NULL));
438 TEST_ASSERT_NULL(cJSON_DetachItemFromObjectCaseSensitive(NULL, "item"));
439 TEST_ASSERT_NULL(cJSON_DetachItemFromObjectCaseSensitive(item, NULL));
440 cJSON_DeleteItemFromObject(NULL, "item");
441 cJSON_DeleteItemFromObject(item, NULL);
442 cJSON_DeleteItemFromObjectCaseSensitive(NULL, "item");
443 cJSON_DeleteItemFromObjectCaseSensitive(item, NULL);
444 TEST_ASSERT_FALSE(cJSON_InsertItemInArray(array, 0, NULL));
445 TEST_ASSERT_FALSE(cJSON_InsertItemInArray(array, 1, item));
446 TEST_ASSERT_FALSE(cJSON_InsertItemInArray(NULL, 0, item));
447 TEST_ASSERT_FALSE(cJSON_InsertItemInArray(item, 0, NULL));
448 TEST_ASSERT_FALSE(cJSON_ReplaceItemViaPointer(NULL, item, item));
449 TEST_ASSERT_FALSE(cJSON_ReplaceItemViaPointer(item, NULL, item));
450 TEST_ASSERT_FALSE(cJSON_ReplaceItemViaPointer(item, item, NULL));
451 TEST_ASSERT_FALSE(cJSON_ReplaceItemInArray(item, 0, NULL));
452 TEST_ASSERT_FALSE(cJSON_ReplaceItemInArray(NULL, 0, item));
453 TEST_ASSERT_FALSE(cJSON_ReplaceItemInObject(NULL, "item", item));
454 TEST_ASSERT_FALSE(cJSON_ReplaceItemInObject(item, NULL, item));
455 TEST_ASSERT_FALSE(cJSON_ReplaceItemInObject(item, "item", NULL));
456 TEST_ASSERT_FALSE(cJSON_ReplaceItemInObjectCaseSensitive(NULL, "item", item));
457 TEST_ASSERT_FALSE(cJSON_ReplaceItemInObjectCaseSensitive(item, NULL, item));
458 TEST_ASSERT_FALSE(cJSON_ReplaceItemInObjectCaseSensitive(item, "item", NULL));
459 TEST_ASSERT_NULL(cJSON_Duplicate(NULL, true));
460 TEST_ASSERT_FALSE(cJSON_Compare(item, NULL, false));
461 TEST_ASSERT_FALSE(cJSON_Compare(NULL, item, false));
462 TEST_ASSERT_NULL(cJSON_SetValuestring(NULL, "test"));
463 TEST_ASSERT_NULL(cJSON_SetValuestring(corruptedString, "test"));
464 cJSON_Minify(NULL);
465 /* skipped because it is only used via a macro that checks for NULL */
466 /* cJSON_SetNumberHelper(NULL, 0); */
467
468 /* restore corrupted item2 to delete it */
469 item2->prev = originalPrev;
470 cJSON_Delete(corruptedString);
471 cJSON_Delete(array);
472 cJSON_Delete(item);
473 }
474
failing_realloc(void * pointer,size_t size)475 static void *CJSON_CDECL failing_realloc(void *pointer, size_t size)
476 {
477 (void)size;
478 (void)pointer;
479 return NULL;
480 }
481
ensure_should_fail_on_failed_realloc(void)482 static void ensure_should_fail_on_failed_realloc(void)
483 {
484 printbuffer buffer = {NULL, 10, 0, 0, false, false, {&malloc, &free, &failing_realloc}};
485 buffer.buffer = (unsigned char *)malloc(100);
486 TEST_ASSERT_NOT_NULL(buffer.buffer);
487
488 TEST_ASSERT_NULL_MESSAGE(ensure(&buffer, 200), "Ensure didn't fail with failing realloc.");
489 }
490
skip_utf8_bom_should_skip_bom(void)491 static void skip_utf8_bom_should_skip_bom(void)
492 {
493 const unsigned char string[] = "\xEF\xBB\xBF{}";
494 parse_buffer buffer = {0, 0, 0, 0, {0, 0, 0}};
495 buffer.content = string;
496 buffer.length = sizeof(string);
497 buffer.hooks = global_hooks;
498
499 TEST_ASSERT_TRUE(skip_utf8_bom(&buffer) == &buffer);
500 TEST_ASSERT_EQUAL_UINT(3U, (unsigned int)buffer.offset);
501 }
502
skip_utf8_bom_should_not_skip_bom_if_not_at_beginning(void)503 static void skip_utf8_bom_should_not_skip_bom_if_not_at_beginning(void)
504 {
505 const unsigned char string[] = " \xEF\xBB\xBF{}";
506 parse_buffer buffer = {0, 0, 0, 0, {0, 0, 0}};
507 buffer.content = string;
508 buffer.length = sizeof(string);
509 buffer.hooks = global_hooks;
510 buffer.offset = 1;
511
512 TEST_ASSERT_NULL(skip_utf8_bom(&buffer));
513 }
514
cjson_get_string_value_should_get_a_string(void)515 static void cjson_get_string_value_should_get_a_string(void)
516 {
517 cJSON *string = cJSON_CreateString("test");
518 cJSON *number = cJSON_CreateNumber(1);
519
520 TEST_ASSERT_TRUE(cJSON_GetStringValue(string) == string->valuestring);
521 TEST_ASSERT_NULL(cJSON_GetStringValue(number));
522 TEST_ASSERT_NULL(cJSON_GetStringValue(NULL));
523
524 cJSON_Delete(number);
525 cJSON_Delete(string);
526 }
527
cjson_get_number_value_should_get_a_number(void)528 static void cjson_get_number_value_should_get_a_number(void)
529 {
530 cJSON *string = cJSON_CreateString("test");
531 cJSON *number = cJSON_CreateNumber(1);
532
533 TEST_ASSERT_EQUAL_DOUBLE(cJSON_GetNumberValue(number), number->valuedouble);
534 TEST_ASSERT_DOUBLE_IS_NAN(cJSON_GetNumberValue(string));
535 TEST_ASSERT_DOUBLE_IS_NAN(cJSON_GetNumberValue(NULL));
536
537 cJSON_Delete(number);
538 cJSON_Delete(string);
539 }
540
cjson_create_string_reference_should_create_a_string_reference(void)541 static void cjson_create_string_reference_should_create_a_string_reference(void)
542 {
543 const char *string = "I am a string!";
544
545 cJSON *string_reference = cJSON_CreateStringReference(string);
546 TEST_ASSERT_TRUE(string_reference->valuestring == string);
547 TEST_ASSERT_EQUAL_INT(cJSON_IsReference | cJSON_String, string_reference->type);
548
549 cJSON_Delete(string_reference);
550 }
551
cjson_create_object_reference_should_create_an_object_reference(void)552 static void cjson_create_object_reference_should_create_an_object_reference(void)
553 {
554 cJSON *number_reference = NULL;
555 cJSON *number_object = cJSON_CreateObject();
556 cJSON *number = cJSON_CreateNumber(42);
557 const char key[] = "number";
558
559 TEST_ASSERT_TRUE(cJSON_IsNumber(number));
560 TEST_ASSERT_TRUE(cJSON_IsObject(number_object));
561 cJSON_AddItemToObjectCS(number_object, key, number);
562
563 number_reference = cJSON_CreateObjectReference(number);
564 TEST_ASSERT_TRUE(number_reference->child == number);
565 TEST_ASSERT_EQUAL_INT(cJSON_Object | cJSON_IsReference, number_reference->type);
566
567 cJSON_Delete(number_object);
568 cJSON_Delete(number_reference);
569 }
570
cjson_create_array_reference_should_create_an_array_reference(void)571 static void cjson_create_array_reference_should_create_an_array_reference(void)
572 {
573 cJSON *number_reference = NULL;
574 cJSON *number_array = cJSON_CreateArray();
575 cJSON *number = cJSON_CreateNumber(42);
576
577 TEST_ASSERT_TRUE(cJSON_IsNumber(number));
578 TEST_ASSERT_TRUE(cJSON_IsArray(number_array));
579 cJSON_AddItemToArray(number_array, number);
580
581 number_reference = cJSON_CreateArrayReference(number);
582 TEST_ASSERT_TRUE(number_reference->child == number);
583 TEST_ASSERT_EQUAL_INT(cJSON_Array | cJSON_IsReference, number_reference->type);
584
585 cJSON_Delete(number_array);
586 cJSON_Delete(number_reference);
587 }
588
cjson_add_item_to_object_or_array_should_not_add_itself(void)589 static void cjson_add_item_to_object_or_array_should_not_add_itself(void)
590 {
591 cJSON *object = cJSON_CreateObject();
592 cJSON *array = cJSON_CreateArray();
593 cJSON_bool flag = false;
594
595 flag = cJSON_AddItemToObject(object, "key", object);
596 TEST_ASSERT_FALSE_MESSAGE(flag, "add an object to itself should fail");
597
598 flag = cJSON_AddItemToArray(array, array);
599 TEST_ASSERT_FALSE_MESSAGE(flag, "add an array to itself should fail");
600
601 cJSON_Delete(object);
602 cJSON_Delete(array);
603 }
604
cjson_add_item_to_object_should_not_use_after_free_when_string_is_aliased(void)605 static void cjson_add_item_to_object_should_not_use_after_free_when_string_is_aliased(void)
606 {
607 cJSON *object = cJSON_CreateObject();
608 cJSON *number = cJSON_CreateNumber(42);
609 char *name = (char *)cJSON_strdup((const unsigned char *)"number", &global_hooks);
610
611 TEST_ASSERT_NOT_NULL(object);
612 TEST_ASSERT_NOT_NULL(number);
613 TEST_ASSERT_NOT_NULL(name);
614
615 number->string = name;
616
617 /* The following should not have a use after free
618 * that would show up in valgrind or with AddressSanitizer */
619 cJSON_AddItemToObject(object, number->string, number);
620
621 cJSON_Delete(object);
622 }
623
cjson_delete_item_from_array_should_not_broken_list_structure(void)624 static void cjson_delete_item_from_array_should_not_broken_list_structure(void)
625 {
626 const char expected_json1[] = "{\"rd\":[{\"a\":\"123\"}]}";
627 const char expected_json2[] = "{\"rd\":[{\"a\":\"123\"},{\"b\":\"456\"}]}";
628 const char expected_json3[] = "{\"rd\":[{\"b\":\"456\"}]}";
629 char *str1 = NULL;
630 char *str2 = NULL;
631 char *str3 = NULL;
632
633 cJSON *root = cJSON_Parse("{}");
634
635 cJSON *array = cJSON_AddArrayToObject(root, "rd");
636 cJSON *item1 = cJSON_Parse("{\"a\":\"123\"}");
637 cJSON *item2 = cJSON_Parse("{\"b\":\"456\"}");
638
639 cJSON_AddItemToArray(array, item1);
640 str1 = cJSON_PrintUnformatted(root);
641 TEST_ASSERT_EQUAL_STRING(expected_json1, str1);
642 free(str1);
643
644 cJSON_AddItemToArray(array, item2);
645 str2 = cJSON_PrintUnformatted(root);
646 TEST_ASSERT_EQUAL_STRING(expected_json2, str2);
647 free(str2);
648
649 /* this should not broken list structure */
650 cJSON_DeleteItemFromArray(array, 0);
651 str3 = cJSON_PrintUnformatted(root);
652 TEST_ASSERT_EQUAL_STRING(expected_json3, str3);
653 free(str3);
654
655 cJSON_Delete(root);
656 }
657
cjson_set_valuestring_to_object_should_not_leak_memory(void)658 static void cjson_set_valuestring_to_object_should_not_leak_memory(void)
659 {
660 cJSON *root = cJSON_Parse("{}");
661 const char *stringvalue = "valuestring could be changed safely";
662 const char *reference_valuestring = "reference item should be freed by yourself";
663 const char *short_valuestring = "shorter valuestring";
664 const char *long_valuestring = "new valuestring which much longer than previous should be changed safely";
665 cJSON *item1 = cJSON_CreateString(stringvalue);
666 cJSON *item2 = cJSON_CreateStringReference(reference_valuestring);
667 char *ptr1 = NULL;
668 char *return_value = NULL;
669
670 cJSON_AddItemToObject(root, "one", item1);
671 cJSON_AddItemToObject(root, "two", item2);
672
673 ptr1 = item1->valuestring;
674 return_value = cJSON_SetValuestring(cJSON_GetObjectItem(root, "one"), short_valuestring);
675 TEST_ASSERT_NOT_NULL(return_value);
676 TEST_ASSERT_EQUAL_PTR_MESSAGE(ptr1, return_value, "new valuestring shorter than old should not reallocate memory");
677 TEST_ASSERT_EQUAL_STRING(short_valuestring, cJSON_GetObjectItem(root, "one")->valuestring);
678
679 /* we needn't to free the original valuestring manually */
680 ptr1 = item1->valuestring;
681 return_value = cJSON_SetValuestring(cJSON_GetObjectItem(root, "one"), long_valuestring);
682 TEST_ASSERT_NOT_NULL(return_value);
683 TEST_ASSERT_NOT_EQUAL_MESSAGE(ptr1, return_value, "new valuestring longer than old should reallocate memory")
684 TEST_ASSERT_EQUAL_STRING(long_valuestring, cJSON_GetObjectItem(root, "one")->valuestring);
685
686 return_value = cJSON_SetValuestring(cJSON_GetObjectItem(root, "two"), long_valuestring);
687 TEST_ASSERT_NULL_MESSAGE(return_value, "valuestring of reference object should not be changed");
688 TEST_ASSERT_EQUAL_STRING(reference_valuestring, cJSON_GetObjectItem(root, "two")->valuestring);
689
690 cJSON_Delete(root);
691 }
692
cjson_set_bool_value_must_not_break_objects(void)693 static void cjson_set_bool_value_must_not_break_objects(void)
694 {
695 cJSON *bobj, *sobj, *oobj, *refobj = NULL;
696
697 TEST_ASSERT_TRUE((cJSON_SetBoolValue(refobj, 1) == cJSON_Invalid));
698
699 bobj = cJSON_CreateFalse();
700 TEST_ASSERT_TRUE(cJSON_IsFalse(bobj));
701 TEST_ASSERT_TRUE((cJSON_SetBoolValue(bobj, 1) == cJSON_True));
702 TEST_ASSERT_TRUE(cJSON_IsTrue(bobj));
703 cJSON_SetBoolValue(bobj, 1);
704 TEST_ASSERT_TRUE(cJSON_IsTrue(bobj));
705 TEST_ASSERT_TRUE((cJSON_SetBoolValue(bobj, 0) == cJSON_False));
706 TEST_ASSERT_TRUE(cJSON_IsFalse(bobj));
707 cJSON_SetBoolValue(bobj, 0);
708 TEST_ASSERT_TRUE(cJSON_IsFalse(bobj));
709
710 sobj = cJSON_CreateString("test");
711 TEST_ASSERT_TRUE(cJSON_IsString(sobj));
712 cJSON_SetBoolValue(sobj, 1);
713 TEST_ASSERT_TRUE(cJSON_IsString(sobj));
714 cJSON_SetBoolValue(sobj, 0);
715 TEST_ASSERT_TRUE(cJSON_IsString(sobj));
716
717 oobj = cJSON_CreateObject();
718 TEST_ASSERT_TRUE(cJSON_IsObject(oobj));
719 cJSON_SetBoolValue(oobj, 1);
720 TEST_ASSERT_TRUE(cJSON_IsObject(oobj));
721 cJSON_SetBoolValue(oobj, 0);
722 TEST_ASSERT_TRUE(cJSON_IsObject(oobj));
723
724 refobj = cJSON_CreateStringReference("conststring");
725 TEST_ASSERT_TRUE(cJSON_IsString(refobj));
726 TEST_ASSERT_TRUE(refobj->type & cJSON_IsReference);
727 cJSON_SetBoolValue(refobj, 1);
728 TEST_ASSERT_TRUE(cJSON_IsString(refobj));
729 TEST_ASSERT_TRUE(refobj->type & cJSON_IsReference);
730 cJSON_SetBoolValue(refobj, 0);
731 TEST_ASSERT_TRUE(cJSON_IsString(refobj));
732 TEST_ASSERT_TRUE(refobj->type & cJSON_IsReference);
733 cJSON_Delete(refobj);
734
735 refobj = cJSON_CreateObjectReference(oobj);
736 TEST_ASSERT_TRUE(cJSON_IsObject(refobj));
737 TEST_ASSERT_TRUE(refobj->type & cJSON_IsReference);
738 cJSON_SetBoolValue(refobj, 1);
739 TEST_ASSERT_TRUE(cJSON_IsObject(refobj));
740 TEST_ASSERT_TRUE(refobj->type & cJSON_IsReference);
741 cJSON_SetBoolValue(refobj, 0);
742 TEST_ASSERT_TRUE(cJSON_IsObject(refobj));
743 TEST_ASSERT_TRUE(refobj->type & cJSON_IsReference);
744 cJSON_Delete(refobj);
745
746 cJSON_Delete(oobj);
747 cJSON_Delete(bobj);
748 cJSON_Delete(sobj);
749 }
750
cjson_parse_big_numbers_should_not_report_error(void)751 static void cjson_parse_big_numbers_should_not_report_error(void)
752 {
753 cJSON *valid_big_number_json_object1 = cJSON_Parse("{\"a\": true, \"b\": [ null,9999999999999999999999999999999999999999999999912345678901234567]}");
754 cJSON *valid_big_number_json_object2 = cJSON_Parse("{\"a\": true, \"b\": [ null,999999999999999999999999999999999999999999999991234567890.1234567E3]}");
755 const char *invalid_big_number_json1 = "{\"a\": true, \"b\": [ null,99999999999999999999999999999999999999999999999.1234567890.1234567]}";
756 const char *invalid_big_number_json2 = "{\"a\": true, \"b\": [ null,99999999999999999999999999999999999999999999999E1234567890e1234567]}";
757
758 TEST_ASSERT_NOT_NULL(valid_big_number_json_object1);
759 TEST_ASSERT_NOT_NULL(valid_big_number_json_object2);
760 TEST_ASSERT_NULL_MESSAGE(cJSON_Parse(invalid_big_number_json1), "Invalid big number JSONs should not be parsed.");
761 TEST_ASSERT_NULL_MESSAGE(cJSON_Parse(invalid_big_number_json2), "Invalid big number JSONs should not be parsed.");
762
763 cJSON_Delete(valid_big_number_json_object1);
764 cJSON_Delete(valid_big_number_json_object2);
765 }
766
main(void)767 int CJSON_CDECL main(void)
768 {
769 UNITY_BEGIN();
770
771 RUN_TEST(cjson_array_foreach_should_loop_over_arrays);
772 RUN_TEST(cjson_array_foreach_should_not_dereference_null_pointer);
773 RUN_TEST(cjson_get_object_item_should_get_object_items);
774 RUN_TEST(cjson_get_object_item_case_sensitive_should_get_object_items);
775 RUN_TEST(cjson_get_object_item_should_not_crash_with_array);
776 RUN_TEST(cjson_get_object_item_case_sensitive_should_not_crash_with_array);
777 RUN_TEST(typecheck_functions_should_check_type);
778 RUN_TEST(cjson_should_not_parse_to_deeply_nested_jsons);
779 RUN_TEST(cjson_should_not_follow_too_deep_circular_references);
780 RUN_TEST(cjson_set_number_value_should_set_numbers);
781 RUN_TEST(cjson_detach_item_via_pointer_should_detach_items);
782 RUN_TEST(cjson_replace_item_via_pointer_should_replace_items);
783 RUN_TEST(cjson_replace_item_in_object_should_preserve_name);
784 RUN_TEST(cjson_functions_should_not_crash_with_null_pointers);
785 RUN_TEST(ensure_should_fail_on_failed_realloc);
786 RUN_TEST(skip_utf8_bom_should_skip_bom);
787 RUN_TEST(skip_utf8_bom_should_not_skip_bom_if_not_at_beginning);
788 RUN_TEST(cjson_get_string_value_should_get_a_string);
789 RUN_TEST(cjson_get_number_value_should_get_a_number);
790 RUN_TEST(cjson_create_string_reference_should_create_a_string_reference);
791 RUN_TEST(cjson_create_object_reference_should_create_an_object_reference);
792 RUN_TEST(cjson_create_array_reference_should_create_an_array_reference);
793 RUN_TEST(cjson_add_item_to_object_or_array_should_not_add_itself);
794 RUN_TEST(cjson_add_item_to_object_should_not_use_after_free_when_string_is_aliased);
795 RUN_TEST(cjson_delete_item_from_array_should_not_broken_list_structure);
796 RUN_TEST(cjson_set_valuestring_to_object_should_not_leak_memory);
797 RUN_TEST(cjson_set_bool_value_must_not_break_objects);
798 RUN_TEST(cjson_parse_big_numbers_should_not_report_error);
799
800 return UNITY_END();
801 }
802