Skip to content

Fix memory leak in cJSON_AddItemReferenceToObject on string alloc failure#1008

Open
icsfy wants to merge 1 commit intoDaveGamble:masterfrom
icsfy:fix-reference-leak
Open

Fix memory leak in cJSON_AddItemReferenceToObject on string alloc failure#1008
icsfy wants to merge 1 commit intoDaveGamble:masterfrom
icsfy:fix-reference-leak

Conversation

@icsfy
Copy link
Copy Markdown

@icsfy icsfy commented Apr 18, 2026

Bug description

There is a potential memory leak in cJSON_AddItemReferenceToObject that occurs in low-memory situations. If the allocation for the key string fails inside add_item_to_object, the memory dynamically allocated for the reference object is leaked.

Code analysis

In cJSON.c, cJSON_AddItemReferenceToObject is implemented via chained function calls:

CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item)
{
    if ((object == NULL) || (string == NULL)) return false;

    // The reference is allocated here and passed straight into add_item_to_object
    return add_item_to_object(object, string, create_reference(item, &global_hooks), &global_hooks, false);
}

If we look at add_item_to_object() when constant_key is false:

    else
    {
        new_key = (char*)cJSON_strdup((const unsigned char*)string, hooks);
        if (new_key == NULL)
        {
            return false; // <--- LEAK: returns without freeing 'item'
        }
        // ...

If cJSON_strdup returns NULL due to out-of-memory, it returns false. However, the item (which was freshly allocated by create_reference) is neither freed in add_item_to_object, nor in the parent function cJSON_AddItemReferenceToObject. The pointer is lost, resulting in a memory leak.

Contrast this with cJSON_AddNullToObject and similar functions which safely capture the created node and call cJSON_Delete(null) if add_item_to_object returns false.

Proposed Fix

The fix is to separate the node creation from the attachment, and explicitly manage its lifecycle upon failure:

CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item)
{
    cJSON *reference = NULL;

    if ((object == NULL) || (string == NULL))
    {
        return false;
    }

    reference = create_reference(item, &global_hooks);
    if (reference == NULL)
    {
        return false;
    }

    if (!add_item_to_object(object, string, reference, &global_hooks, false))
    {
        cJSON_Delete(reference);
        return false;
    }

    return true;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant