You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
compose_patch() in cJSON_Utils.c dereferences the return value of cJSON_malloc() without first checking whether the allocation succeeded. If cJSON_malloc returns NULL (e.g. under memory pressure), the subsequent sprintf and encode_string_as_pointer calls write through a null pointer, causing undefined behaviour / segmentation fault.
When the suffix parameter is non-NULL (the else branch at line 1116), compose_patch allocates full_path via cJSON_malloc. However, there is no NULL check between the allocation and its first use. If the allocator returns NULL, the code immediately writes to address 0 + offset, causing a null pointer dereference.
This is a classic "missing NULL check after malloc" pattern.
Call Chain
compose_patch is called from multiple places, most notably:
Any path through create_patches that produces a "remove", "add", or "move" patch with a non-NULL suffix can trigger this bug.
Minimal Reproducer
#include<stdlib.h>#include"cJSON.h"#include"cJSON_Utils.h"/* Force the next malloc call to fail */staticintfail_next=0;
staticvoid*failing_malloc(size_tsize) {
if (fail_next--) returnNULL;
returnmalloc(size);
}
staticvoidfailing_free(void*ptr) { free(ptr); }
intmain(void) {
cJSON_Hookshooks= { failing_malloc, failing_free };
cJSON_InitHooks(&hooks);
cJSON*from=cJSON_Parse("{\"a\":1}");
cJSON*to=cJSON_Parse("{\"a\":1,\"b\":2}");
/* Trigger patch generation; compose_patch will call malloc for full_path. * With a failing allocator this crashes at the sprintf line. */fail_next=6; /* let a few allocs succeed, then fail on full_path */cJSON*patches=cJSONUtils_GeneratePatches(from, to); /* segfault here */cJSON_Delete(patches);
cJSON_Delete(from);
cJSON_Delete(to);
return0;
}
Expected Behaviour
compose_patch should check the return value of cJSON_malloc and return early (silently or propagating an error) if the allocation fails. This is consistent with the rest of the codebase where allocation failures are handled gracefully.
Note: The early return also requires freeing patch to avoid a memory leak, similar to how other allocation failures in this file are handled.
Additional Notes
A similar missing-NULL-check pattern exists in create_patches() at line 1246 (new_path) and line 1175 (new_path for arrays), though those are within void functions that silently drop patches on failure—arguably acceptable but still inconsistent.
This bug was found by manual code review of cJSON v1.7.19.
Summary
compose_patch()incJSON_Utils.cdereferences the return value ofcJSON_malloc()without first checking whether the allocation succeeded. IfcJSON_mallocreturnsNULL(e.g. under memory pressure), the subsequentsprintfandencode_string_as_pointercalls write through a null pointer, causing undefined behaviour / segmentation fault.Affected Version
cJSON v1.7.19(latest release)Affected File & Lines
File:
cJSON_Utils.cFunction:
compose_patch()(static)Lines: 1120–1123
Root Cause
When the
suffixparameter is non-NULL (theelsebranch at line 1116),compose_patchallocatesfull_pathviacJSON_malloc. However, there is no NULL check between the allocation and its first use. If the allocator returnsNULL, the code immediately writes to address0 + offset, causing a null pointer dereference.This is a classic "missing NULL check after malloc" pattern.
Call Chain
compose_patchis called from multiple places, most notably:Any path through
create_patchesthat produces a "remove", "add", or "move" patch with a non-NULL suffix can trigger this bug.Minimal Reproducer
Expected Behaviour
compose_patchshould check the return value ofcJSON_mallocand return early (silently or propagating an error) if the allocation fails. This is consistent with the rest of the codebase where allocation failures are handled gracefully.Suggested Fix
Additional Notes
create_patches()at line 1246 (new_path) and line 1175 (new_pathfor arrays), though those are withinvoidfunctions that silently drop patches on failure—arguably acceptable but still inconsistent.cJSON v1.7.19.Environment