Skip to content

Fix decode_pointer_inplace ~1 escape and minify_string escape handling#993

Open
srijan-at-qwertystars wants to merge 1 commit intoDaveGamble:masterfrom
srijan-at-qwertystars:fix/decode-pointer-and-minify-escapes
Open

Fix decode_pointer_inplace ~1 escape and minify_string escape handling#993
srijan-at-qwertystars wants to merge 1 commit intoDaveGamble:masterfrom
srijan-at-qwertystars:fix/decode-pointer-and-minify-escapes

Conversation

@srijan-at-qwertystars
Copy link

Summary

Two correctness bugs fixed in escape sequence handling:

Bug 1: decode_pointer_inplace() incorrect ~1 decoding (cJSON_Utils.c)

Per RFC 6901 §3, the ~1 escape in JSON Pointers must decode to /. The current code writes to decoded_string[1] instead of decoded_string[0] (line 377), causing the decoded character to be placed at the wrong offset.

Additionally, when decoded_string falls behind string after processing an escape, subsequent non-escape characters are not copied to the output position.

Impact: JSON Patch operations (cJSONUtils_ApplyPatches) with ~1 in path components silently fail or operate on wrong object keys.

Reproduction:

cJSON *json = cJSON_Parse("{\"a/b\": \"original\"}");
cJSON *patch = cJSON_Parse("[{\"op\":\"replace\", \"path\":\"/a~1b\", \"value\":\"patched\"}]");
int result = cJSONUtils_ApplyPatchesCaseSensitive(json, patch);
// result is 13 (error) instead of 0 (success)

Bug 2: minify_string() doesn't handle \\\\ escape (cJSON.c)

The escape check in minify_string() only handles \\\" (escaped quote) but not other JSON escapes like \\\\ (escaped backslash). When a JSON string ends with \\\\, the closing " is misidentified as an escaped quote, causing the function to read past the string boundary and absorb subsequent JSON tokens into the string.

Impact: cJSON_Minify produces incorrect output for JSON containing strings that end with escaped backslashes.

Reproduction:

char json[] = "{ \"key\" : \"value\\\\\" , \"other\" : \"data\" }";
cJSON_Minify(json);
// Expected: {"key":"value\\\\","other":"data"}
// Actual:   {"key":"value\\\\" , "other" : "data" }

Changes

  • cJSON_Utils.c: Fix decoded_string[1]decoded_string[0] for ~1 case; add else clause to copy non-escape characters
  • cJSON.c: Change escape check from (*input)[1] == '"' to (*input)[1] != '\0' to handle all escape sequences

Testing

All 19 existing tests pass. Both fixes are minimal (6 lines added, 2 lines changed).

Two bugs fixed:

1. cJSON_Utils.c decode_pointer_inplace(): The ~1 JSON Pointer escape
   (RFC 6901 §3) was writing to decoded_string[1] instead of
   decoded_string[0], causing incorrect decoding. Additionally,
   non-escape characters after escape sequences were not being copied
   when the decoded output pointer fell behind the input pointer.
   This caused JSON Patch operations with ~1 in paths to silently
   fail or operate on wrong keys.

2. cJSON.c minify_string(): The escape handling only checked for \"
   (escaped quote) but not \\ (escaped backslash) or other escapes.
   A string ending with \\ caused the closing quote to be
   misidentified as an escaped quote, making the function read past
   the string boundary and absorb subsequent JSON tokens into the
   string value.

Both fixes are minimal and include bounds checking. All 19 existing
tests pass with these changes.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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.

2 participants