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