cJSON icon indicating copy to clipboard operation
cJSON copied to clipboard

Call to cJSONUtils_SortObject() could break adding new fields to the object/array

Open vdcow opened this issue 1 year ago • 4 comments

I have found that cJSONUtils_SortObject(object) call if "object" is unsorted could break adding new fields to the object/array. It happens when the last field in the unsorted array/object becomes the first field.

In this case sorted object will have "object->child->prev" equal to 0 breaking the following assumption in the code

https://github.com/DaveGamble/cJSON/blob/master/cJSON.c#L2008

        /* append to the end */
        if (child->prev) <--------------------------- will be zero for sorted object
        {
            suffix_object(child->prev, item);
            array->child->prev = item;
        }

Another bad thing is that in this case we also have a memory leak since "item" variable is not assigned anywhere.

Moreover any API call from cJSON_Utils that is using sort_object() call internally also could break the input object. I am personally found it when debugging cJSONUtils_ApplyPatches().

Minimal example that reproduces the problem

#include <stdlib.h>
#include <stdio.h>
#include <cJSON.h>
#include <cJSON_Utils.h>

int main() {
    cJSON *object = cJSON_Parse(
        "{\"v1\": 1, \"a2\": 2}");
    char *object_str = cJSON_Print(object);
    printf("object=\n%s\n", object_str);
    free(object_str);

    cJSONUtils_SortObject(object);

    cJSON *v3_value = cJSON_CreateNumber(3);
    cJSON_AddItemToObject(object, "v3", v3_value);

    object_str = cJSON_Print(object);
    printf("object=\n%s\n", object_str);
    free(object_str);

    return 0;
}

Output of the program is

object=
{
        "v1":   1,
        "a2":   2
}
object=
{
        "a2":   2,
        "v1":   1
}

Note that "v3" field is missed in the final JSON.

vdcow avatar Nov 15 '24 15:11 vdcow