GHSA-475m-ph3x-64gp
Oj: Integer Overflow in Oj.load 2GB String Handling
Details
### Summary
`Oj.load` is vulnerable to heap corruption when parsing a JSON string longer than 2 GB. An integer overflow in `buf_append_string` (`buf.h:61`) converts the string length to a large negative `size_t`, causing `memcpy` to copy an astronomically large amount of data out of bounds. This crashes the process and can corrupt adjacent heap memory.
### Version
- **Software**: oj gem - **Affected**: all versions with `ext/oj/buf.h` and `ext/oj/parse.c` - **Latest tested**: 3.17.1 (confirmed present)
### Details
`ext/oj/buf.h`, line 61:
```c inline static void buf_append_string(Buf buf, const char *s, size_t slen) { // ... memcpy(buf->tail, s, slen); // slen derived from 32-bit int that wrapped negative ```
In `parse.c`, escape sequence handling computes the remaining string length as an `int`:
```c // parse.c:402 (read_escaped_str) int slen = (int)(s - str); // ← wraps to negative when string > 2 GB buf_append_string(buf, str, (size_t)slen); // ← (size_t)(-2147483648) = 0x80000000... ```
ASAN report: ``` ==399019==ERROR: AddressSanitizer: negative-size-param: (size=-2147483648) #0 __asan_memcpy #1 buf_append_string /ext/oj/buf.h:61 #2 read_escaped_str /ext/oj/parse.c:402 #3 read_str /ext/oj/parse.c:542 #4 oj_parse2 /ext/oj/parse.c:882 #5 oj_pi_parse /ext/oj/parse.c:1256 #6 oj_object_parse /ext/oj/object.c:701 #7 load /ext/oj/oj.c:1259 0x7f5a26ff0801 is located 1 bytes inside of 2147483657-byte region [0x7f5a26ff0800, 0x7f5aa6ff0809) ```
### Reproduce
```ruby require 'oj' n = 1 << 31 # 2 GB json = '"' + ('A' * n) + 'A"' # >2GB JSON string with a trailing escape Oj.load(json) ```
Are you affected?
Enter the version of the package you're using.