cJSONUtils_ApplyPatches* dereferences NULL object on root-level add/replace

Open Beginner friendly
#1,010 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
72/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Quiet
Tech stack
c
Domain
backend

Research direction

Start in cJSON_Utils.c at cJSONUtils_ApplyPatches(), cJSONUtils_ApplyPatchesCaseSensitive(), and apply_patch(), then build and run the provided poc_object_null.c command. Verify that a NULL object with a root-level add or replace returns an error code without crashing.

Written by the indexing model from the issue text.

Description

Summary

cJSONUtils_ApplyPatches() and cJSONUtils_ApplyPatchesCaseSensitive() do not validate that the object argument is non-NULL before passing it to apply_patch().

When a patch targets the root path ("") with an add or replace operation, this leads to an unconditional dereference of object, causing a crash.

Affected version

  • cJSON 1.7.19
  • Code path: cJSONUtils_ApplyPatches() / cJSONUtils_ApplyPatchesCaseSensitive()

Details

The public API forwards object directly to apply_patch() without validation:

CJSON_PUBLIC(int) cJSONUtils_ApplyPatches(cJSON * const object, const cJSON * const patches)
{
    ...
    while (current_patch != NULL)
    {
        status = apply_patch(object, current_patch, false);
        ...
    }
}

In apply_patch(), when handling a root-level path (""), object is dereferenced:

if (path->valuestring[0] == '\0')
{
    ...
    if ((opcode == REPLACE) || (opcode == ADD))
    {
        ...
        overwrite_item(object, *value);
        ...
        if (object->string != NULL)
        {
            cJSON_free(object->string);
            object->string = NULL;
        }
    }
}

While overwrite_item() itself tolerates NULL, the subsequent access to object->string does not.

Proof of Concept

#include "cJSON.h"
#include "cJSON_Utils.h"

int main(void)
{
    cJSON *patches = cJSON_CreateArray();
    cJSON *patch = cJSON_CreateObject();

    cJSON_AddItemToObject(patch, "op", cJSON_CreateString("add"));
    cJSON_AddItemToObject(patch, "path", cJSON_CreateString(""));
    cJSON_AddItemToObject(patch, "value", cJSON_CreateNumber(1));
    cJSON_AddItemToArray(patches, patch);

    return cJSONUtils_ApplyPatches(NULL, patches);
}

Build and run

gcc poc_object_null.c cJSON.c cJSON_Utils.c -o poc_object_null
./poc_object_null

On Windows with MinGW, this results in an access violation (0xC0000005).

Expected behavior

The API should handle invalid input gracefully. Passing a NULL object should not result in a crash; instead, the function should return an error code.

Suggested fix

One option is to validate the input at the public API boundary:

if (object == NULL)
{
    return 1;
}

Alternatively, apply_patch() could reject object == NULL before performing any operation-specific logic.

Adding a check at the public entry points would make the API behavior more predictable and consistent with defensive handling of invalid inputs.

Dominant language
C
Stars
13k
Forks
3.5k
PR merge metrics
No merged PRs in 30d

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from DaveGamble/cJSON

All issues in DaveGamble/cJSON

Similar issues

More C issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.