Fix integer overflow in vendored json-parser allocation size - #1296
Open
Ion (Socialpranker) wants to merge 2 commits into
Open
Fix integer overflow in vendored json-parser allocation size#1296Ion (Socialpranker) wants to merge 2 commits into
Ion (Socialpranker) wants to merge 2 commits into
Conversation
new_value() in clients/cloud/c/json.c multiplies value->u.array.length and value->u.object.length by sizeof(json_value*) / sizeof(json_object_entry) before passing the result to json_alloc(), with no check that the multiplication itself fits in the allocator's size type. On a platform where this overflows, the allocation comes back undersized while the parser still writes array.length / object.length elements into it, producing a heap buffer overflow from attacker-controlled JSON input. json_alloc() already guards against overflowing the running memory total via state->ulong_max, but that only helps once the multiplied size is passed in - it doesn't stop the multiplication from wrapping first. This adds an explicit bound check before each multiplication, using the same state->ulong_max the file already computes for this purpose, matching the existing style. Verified: reviewed clients/cloud/c/json.c against upstream json-parser/json-parser, where this exact class of overflow was fixed via a similar bounds check. Compiled clients/cloud/c/json.c standalone with gcc -Wall -Wextra; no new warnings versus the unpatched file.
The previous guard compared length against ulong_max, but values_size that stores the multiplication result is declared as a plain int, so a length between INT_MAX/sizeof(entry) and ulong_max/sizeof(entry) still overflows values_size itself before the ulong_max check would ever catch it. Guard against INT_MAX/sizeof(entry) instead, matching the type that actually holds the product.
Author
|
Pushed a follow-up commit: the object-branch guard checked against |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This patch was written by Claude Sonnet 5 (Anthropic); I reviewed the change and the reasoning before submitting.
clients/cloud/c/json.c vendors the json-parser library. In new_value(), the array and object branches multiply value->u.array.length and value->u.object.length by sizeof(json_value*) and sizeof(json_object_entry) respectively before passing the result to json_alloc(). Neither multiplication is checked for overflow first. If it wraps, json_alloc() receives a small size, the allocation succeeds, and the parser then writes length elements into a buffer that is too small for them, a heap buffer overflow driven entirely by the JSON input being parsed.
json_alloc() does guard state->used_memory against wrapping via state->ulong_max, but that check only runs after the multiplication has already happened, so it cannot catch an overflow in the multiplication itself.
The fix adds a bound check in both branches before the multiplication, using the same state->ulong_max field json_alloc() already computes for the same purpose, so the guard follows the existing convention in the file rather than introducing a new one. On failure it returns 0, which is exactly how allocation failure is already signaled everywhere else in new_value(). The diff is intentionally limited to these two checks, no other code in the file was touched.
I compiled clients/cloud/c/json.c standalone with gcc -Wall -Wextra -std=c99 before and after the change; the warning output is identical (two pre-existing unused-parameter warnings in default_alloc/default_free, unrelated to this fix). I did not build consumer.c/producer.c through the Makefile because that requires librdkafka, which isn't installed in the environment I used, but json.c has no dependency on librdkafka and compiles cleanly on its own.