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); }
static cJSON *cJSONUtils_PatchDetach(cJSON *object, const unsigned char *path) { unsigned char *parentptr = NULL; unsigned char *childptr = NULL; cJSON *parent = NULL; cJSON *ret = NULL; /* copy path and split it in parent and child */ parentptr = cJSONUtils_strdup(path); if (parentptr == NULL) { return NULL; } childptr = (unsigned char*)strrchr((char*)parentptr, '/'); /* last '/' */ if (childptr == NULL) { free(parentptr); return NULL; } /* split strings */ *childptr++ = '\0'; parent = cJSONUtils_GetPointer(object, (char*)parentptr); cJSONUtils_InplaceDecodePointerString(childptr); if (!parent) { /* Couldn't find object to remove child from. */ ret = NULL; } else if (cJSON_IsArray(parent)) { ret = cJSON_DetachItemFromArray(parent, atoi((char*)childptr)); } else if (cJSON_IsObject(parent)) { ret = cJSON_DetachItemFromObject(parent, (char*)childptr); } free(parentptr); /* return the detachted item */ return ret; }
static cJSON *cJSONUtils_PatchDetach(cJSON *object, const char *path) { char *parentptr = 0; char *childptr = 0; cJSON *parent = 0; cJSON *ret = 0; /* copy path and split it in parent and child */ parentptr = cJSONUtils_strdup(path); childptr = strrchr(parentptr, '/'); /* last '/' */ if (childptr) { /* split strings */ *childptr++ = '\0'; } parent = cJSONUtils_GetPointer(object, parentptr); cJSONUtils_InplaceDecodePointerString(childptr); if (!parent) { /* Couldn't find object to remove child from. */ ret = 0; } else if (parent->type == cJSON_Array) { ret = cJSON_DetachItemFromArray(parent, atoi(childptr)); } else if (parent->type == cJSON_Object) { ret = cJSON_DetachItemFromObject(parent, childptr); } free(parentptr); /* return the detachted item */ return ret; }
static int cJSONUtils_ApplyPatch(cJSON *object, cJSON *patch) { cJSON *op = 0; cJSON *path = 0; cJSON *value = 0; cJSON *parent = 0; int opcode = 0; char *parentptr = 0; char *childptr = 0; op = cJSON_GetObjectItem(patch, "op"); path = cJSON_GetObjectItem(patch, "path"); if (!op || !path) { /* malformed patch. */ return 2; } /* decode operation */ if (!strcmp(op->valuestring, "add")) { opcode = 0; } else if (!strcmp(op->valuestring, "remove")) { opcode = 1; } else if (!strcmp(op->valuestring, "replace")) { opcode = 2; } else if (!strcmp(op->valuestring, "move")) { opcode = 3; } else if (!strcmp(op->valuestring, "copy")) { opcode = 4; } else if (!strcmp(op->valuestring, "test")) { /* compare value: {...} with the given path */ return cJSONUtils_Compare(cJSONUtils_GetPointer(object, path->valuestring), cJSON_GetObjectItem(patch, "value")); } else { /* unknown opcode. */ return 3; } /* Remove/Replace */ if ((opcode == 1) || (opcode == 2)) { /* Get rid of old. */ cJSON_Delete(cJSONUtils_PatchDetach(object, path->valuestring)); if (opcode == 1) { /* For Remove, this is job done. */ return 0; } } /* Copy/Move uses "from". */ if ((opcode == 3) || (opcode == 4)) { cJSON *from = cJSON_GetObjectItem(patch, "from"); if (!from) { /* missing "from" for copy/move. */ return 4; } if (opcode == 3) { /* move */ value = cJSONUtils_PatchDetach(object, from->valuestring); } if (opcode == 4) { /* copy */ value = cJSONUtils_GetPointer(object, from->valuestring); } if (!value) { /* missing "from" for copy/move. */ return 5; } if (opcode == 4) { value = cJSON_Duplicate(value, 1); } if (!value) { /* out of memory for copy/move. */ return 6; } } else /* Add/Replace uses "value". */ { value = cJSON_GetObjectItem(patch, "value"); if (!value) { /* missing "value" for add/replace. */ return 7; } value = cJSON_Duplicate(value, 1); if (!value) { /* out of memory for add/replace. */ return 8; } } /* Now, just add "value" to "path". */ /* split pointer in parent and child */ parentptr = cJSONUtils_strdup(path->valuestring); childptr = strrchr(parentptr, '/'); if (childptr) { *childptr++ = '\0'; } parent = cJSONUtils_GetPointer(object, parentptr); cJSONUtils_InplaceDecodePointerString(childptr); /* add, remove, replace, move, copy, test. */ if (!parent) { /* Couldn't find object to add to. */ free(parentptr); cJSON_Delete(value); return 9; } else if (parent->type == cJSON_Array) { if (!strcmp(childptr, "-")) { cJSON_AddItemToArray(parent, value); } else { cJSON_InsertItemInArray(parent, atoi(childptr), value); } } else if (parent->type == cJSON_Object) { cJSON_DeleteItemFromObject(parent, childptr); cJSON_AddItemToObject(parent, childptr, value); } else { cJSON_Delete(value); } free(parentptr); return 0; }