Skip to content

String deallocated before use #248

Closed
@hhallen

Description

@hhallen

Maybe I'm doing things in a dumb way, but given the method I'm using, there's a problem with the function add_item_to_object(). What I want to do is to parse a number of separate .json files and merge their contents into a single cJSON object. The files may partially duplicate each other. Objects and array items that are already in the result that is being constructed should be skipped during the processing of a .json file, i.e. no duplicate objects or array elements are permitted in the result output.

So, at the top level each file contains one object (always with the same name, "stuff" in the simplified examples below), which in turn contains other objects, which contain arrays of objects. A simple example will illustrate what I want to achieve.

.json file 1:

{
    "stuff": {
        "FOO": [
            {
                "name": "foo_1",
                "value": "11111111"
            },
            {
                "name": "foo_2",
                "value": "11111112"
            }
        ],
        "BAR": [
            {
                "name": "bar_1",
                "value": "22222221"
            },
            {
                "name": "bar_2",
                "value": "22222222"
            }
        ]
    }
}

.json file 2:

{
    "stuff": {
        "FOO": [
            {
                "name": "foo_1",
                "value": "11111111"
            },
            {
                "name": "foo_3",
                "value": "11111113"
            }
        ],
        "BAZ": [
            {
                "name": "baz_1",
                "value": "33333331"
            }
        ]
    }
}

I want the result of the merge operation to be a cJSON object that represents the following .json:

{
    "stuff": {
        "FOO": [
            {
                "name": "foo_1",
                "value": "11111111"
            },
            {
                "name": "foo_2",
                "value": "11111112"
            },
            {
                "name": "foo_3",
                "value": "11111113"
            }
        ],
        "BAR": [
            {
                "name": "bar_1",
                "value": "22222221"
            },
            {
                "name": "bar_2",
                "value": "22222222"
            }
        ],
        "BAZ": [
            {
                "name": "baz_1",
                "value": "33333331"
            }
        ]
    }
}

First, I use cJSON_CreateObject() to start my result object. Then I process each .json file in turn, using cJSON_Parse() to create a cJSON object that represents the file. Then this cJSON object is examined, and if any "stuff" is found, it is moved to the result object, except such objects/array elements as are already present there.

Here is a code snippet that shows how I handle the merge operation for an object at the level directly under "stuff" that is not yet present at all in the result:

            newGroup = cJSON_DetachItemFromObject(newStuff, newGroup->string);
            cJSON_AddItemToObject(resultStuff, newGroup->string, newGroup);

newGroup is a cJSON object from the current .json file, representing for example "BAZ" from the .json files above. I want to move that object from the cJSON object representing the .json file (newStuff) to the cJSON result object under construction (resultStuff).

The problem is that the internal function add_item_to_object() in cJSON assumes that its string argument is valid throughout the function. But when I use newGroup->string, that assumption becomes false, because that string is deallocated before a copy is made and inserted in the item before it's added to the target object. The result (at best) is that the item string will contain garbage.

Perhaps the order of actions in add_item_to_object() could be rearranged, so that a copy of the string argument is made before any deallocations?

Of course, I could allocate memory and make a copy of the string in my own code, but that seems a bit silly. Maybe my method is naive, and a there is a better way of doing what I want that does not run into this kind of problem? If so, please let me know. I'm relatively new to cJSON.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions