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