CJSON_PUBLIC(char *) cJSONUtils_FindPointerFromObjectTo(const cJSON * const object, const cJSON * const target) { size_t child_index = 0; cJSON *current_child = 0; if (object == target) { /* found */ return (char*)cJSONUtils_strdup((const unsigned char*)""); } /* recursively search all children of the object or array */ for (current_child = object->child; current_child != NULL; (void)(current_child = current_child->next), child_index++) { unsigned char *target_pointer = (unsigned char*)cJSONUtils_FindPointerFromObjectTo(current_child, target); /* found the target? */ if (target_pointer != NULL) { if (cJSON_IsArray(object)) { /* reserve enough memory for a 64 bit integer + '/' and '\0' */ unsigned char *full_pointer = (unsigned char*)cJSON_malloc(strlen((char*)target_pointer) + 20 + sizeof("/")); /* check if conversion to unsigned long is valid * This should be eliminated at compile time by dead code elimination * if size_t is an alias of unsigned long, or if it is bigger */ if (child_index > ULONG_MAX) { cJSON_free(target_pointer); return NULL; } sprintf((char*)full_pointer, "/%lu%s", (unsigned long)child_index, target_pointer); /* /<array_index><path> */ cJSON_free(target_pointer); return (char*)full_pointer; } if (cJSON_IsObject(object)) { unsigned char *full_pointer = (unsigned char*)cJSON_malloc(strlen((char*)target_pointer) + pointer_encoded_length((unsigned char*)current_child->string) + 2); full_pointer[0] = '/'; encode_string_as_pointer(full_pointer + 1, (unsigned char*)current_child->string); strcat((char*)full_pointer, (char*)target_pointer); cJSON_free(target_pointer); return (char*)full_pointer; } /* reached leaf of the tree, found nothing */ cJSON_free(target_pointer); return NULL; } } /* not found */ return NULL; }
CJSON_PUBLIC(char *) cJSONUtils_FindPointerFromObjectTo(cJSON *object, cJSON *target) { size_t c = 0; cJSON *obj = 0; if (object == target) { /* found */ return (char*)cJSONUtils_strdup((const unsigned char*)""); } /* recursively search all children of the object */ for (obj = object->child; obj; (void)(obj = obj->next), c++) { unsigned char *found = (unsigned char*)cJSONUtils_FindPointerFromObjectTo(obj, target); if (found) { if (cJSON_IsArray(object)) { /* reserve enough memory for a 64 bit integer + '/' and '\0' */ unsigned char *ret = (unsigned char*)malloc(strlen((char*)found) + 23); /* check if conversion to unsigned long is valid * This should be eliminated at compile time by dead code elimination * if size_t is an alias of unsigned long, or if it is bigger */ if (c > ULONG_MAX) { free(found); return NULL; } sprintf((char*)ret, "/%lu%s", (unsigned long)c, found); /* /<array_index><path> */ free(found); return (char*)ret; } else if (cJSON_IsObject(object)) { unsigned char *ret = (unsigned char*)malloc(strlen((char*)found) + cJSONUtils_PointerEncodedstrlen((unsigned char*)obj->string) + 2); *ret = '/'; cJSONUtils_PointerEncodedstrcpy(ret + 1, (unsigned char*)obj->string); strcat((char*)ret, (char*)found); free(found); return (char*)ret; } /* reached leaf of the tree, found nothing */ free(found); return NULL; } } /* not found */ return NULL; }
static void cjson_utils_functions_shouldnt_crash_with_null_pointers(void) { cJSON *item = cJSON_CreateString("item"); TEST_ASSERT_NOT_NULL(item); TEST_ASSERT_NULL(cJSONUtils_GetPointer(item, NULL)); TEST_ASSERT_NULL(cJSONUtils_GetPointer(NULL, "pointer")); TEST_ASSERT_NULL(cJSONUtils_GetPointerCaseSensitive(NULL, "pointer")); TEST_ASSERT_NULL(cJSONUtils_GetPointerCaseSensitive(item, NULL)); TEST_ASSERT_NULL(cJSONUtils_GeneratePatches(item, NULL)); TEST_ASSERT_NULL(cJSONUtils_GeneratePatches(NULL, item)); TEST_ASSERT_NULL(cJSONUtils_GeneratePatchesCaseSensitive(item, NULL)); TEST_ASSERT_NULL(cJSONUtils_GeneratePatchesCaseSensitive(NULL, item)); cJSONUtils_AddPatchToArray(item, "path", "add", NULL); cJSONUtils_AddPatchToArray(item, "path", NULL, item); cJSONUtils_AddPatchToArray(item, NULL, "add", item); cJSONUtils_AddPatchToArray(NULL, "path", "add", item); cJSONUtils_ApplyPatches(item, NULL); cJSONUtils_ApplyPatches(NULL, item); cJSONUtils_ApplyPatchesCaseSensitive(item, NULL); cJSONUtils_ApplyPatchesCaseSensitive(NULL, item); TEST_ASSERT_NULL(cJSONUtils_MergePatch(item, NULL)); item = cJSON_CreateString("item"); TEST_ASSERT_NULL(cJSONUtils_MergePatchCaseSensitive(item, NULL)); item = cJSON_CreateString("item"); /* these calls are actually valid */ /* cJSONUtils_MergePatch(NULL, item); */ /* cJSONUtils_MergePatchCaseSensitive(NULL, item);*/ /* cJSONUtils_GenerateMergePatch(item, NULL); */ /* cJSONUtils_GenerateMergePatch(NULL, item); */ /* cJSONUtils_GenerateMergePatchCaseSensitive(item, NULL); */ /* cJSONUtils_GenerateMergePatchCaseSensitive(NULL, item); */ TEST_ASSERT_NULL(cJSONUtils_FindPointerFromObjectTo(item, NULL)); TEST_ASSERT_NULL(cJSONUtils_FindPointerFromObjectTo(NULL, item)); cJSONUtils_SortObject(NULL); cJSONUtils_SortObjectCaseSensitive(NULL); cJSON_Delete(item); }
char *cJSONUtils_FindPointerFromObjectTo(cJSON *object, cJSON *target) { int type = object->type; int c = 0; cJSON *obj = 0; if (object == target) { /* found */ return cJSONUtils_strdup(""); } /* recursively search all children of the object */ for (obj = object->child; obj; obj = obj->next, c++) { char *found = cJSONUtils_FindPointerFromObjectTo(obj, target); if (found) { if (type == cJSON_Array) { /* reserve enough memory for a 64 bit integer + '/' and '\0' */ char *ret = (char*)malloc(strlen(found) + 23); sprintf(ret, "/%d%s", c, found); /* /<array_index><path> */ free(found); return ret; } else if (type == cJSON_Object) { char *ret = (char*)malloc(strlen(found) + cJSONUtils_PointerEncodedstrlen(obj->string) + 2); *ret = '/'; cJSONUtils_PointerEncodedstrcpy(ret + 1, obj->string); strcat(ret, found); free(found); return ret; } /* reached leaf of the tree, found nothing */ free(found); return 0; } } /* not found */ return 0; }