From the #2852 audit (commit 8e4f200)
Credit for finding these goes to @FranciscoThiesen (#2852); the commit is co-authored accordingly.
| # | Bug | Reproduced on 4.6.10 |
|---|---|---|
| 1 | parse_many silently truncated a root scalar at a window boundary — a number/true/false/null whose token reached the end of a partial window was treated as complete, so 100005 came back as 1 and iteration stopped early
| scalar_at_window_boundary → NUMBER_ERROR
|
| 2 | max_depth == 0 accepted; stage 2 then wrote to element zero of the empty stack (heap OOB write)
| allocation_limits → parser.allocate(64, 0) succeeded
|
| 3 | On-Demand iterator::source() added a batch-relative structural offset to an absolute document index, so from the second batch on the length underflowed and the view spanned ~2^64 bytes
| source_across_batches → src was 1, expected 100009
|
| 4 | Fallback UTF-8 validator allowed idx+N == len before reading buf[idx+N]; the 4-byte case also tested idx+2 where it meant idx+3, so a 4-byte sequence truncated at a window edge reported UTF8_ERROR instead of deferring
| No parse_unpadded on 4.6.x, so the over-read is not reachable from a public API; the observable defect is the 4-byte case, which rejected a valid NDJSON stream with UTF8_ERROR when a 4-byte character straddled a window edge (verified on 4.6.10, fallback kernel, windows 32–35)
|
| 5 | set_capacity() lacked the overflow guards that matter on 32-bit targets, where SIMDJSON_MAXSIZE_BYTES == SIZE_MAX so the existing check never fires
| allocation_limits
|
| 6 | padded_string(size_t) left a null data pointer paired with the requested nonzero size when allocation failed
|