Skip to content

Fix AIOOBE in readString(Writer) at output buffer boundary - #1673

Open
pjfanning wants to merge 1 commit into
FasterXML:3.1from
pjfanning:fix-readstring-writer-aioobe
Open

Fix AIOOBE in readString(Writer) at output buffer boundary#1673
pjfanning wants to merge 1 commit into
FasterXML:3.1from
pjfanning:fix-readstring-writer-aioobe

Conversation

@pjfanning

@pjfanning pjfanning commented Aug 23, 2026

Copy link
Copy Markdown
Member

JsonParser.readString(Writer) throws ArrayIndexOutOfBoundsException on the two byte-based parsers when a string's plain-ASCII prefix is an exact multiple of the 1024-char streaming buffer and the next character is an escape or a multi-byte UTF-8 char.

_streamString(Writer) in UTF8StreamJsonParser and UTF8DataInputJsonParser only checks outPtr >= outBuf.length inside the ASCII loop, before appending. On exit via break ascii_loop, outPtr can equal the buffer length, and the case 1/2/3/4: decode arms then write outBuf[outPtr++] unchecked.

"aaa...a\n"   (1024 'a's)  -> AIOOBE: Index 1024 out of bounds for length 1024
"aaa...aä"    (1024 'a's)  -> AIOOBE: Index 1024 out of bounds for length 1024

Recurs at every multiple of 1024. ReaderBasedJsonParser checks at the top of each iteration and is unaffected.

Issue appears to be related to #1288 and only affects 3.x releases.

Fix

Add the flush check between the closing-quote test and the switch, covering cases 1-3 and the high surrogate of case 4 (case 4's existing mid-pair check still handles the low surrogate). The flush carries the maxStringLength validation so constraint enforcement stays on the same cadence as the other flush points.

Tests

Two tests added to ReadStringStreamingTest:

  • escapeAtFullOutputBuffer\n escape after an ASCII prefix of exactly 1024 and 2048 chars, across ALL_MODES
  • multiByteAtFullOutputBuffer — same boundary via 2-, 3- and 4-byte UTF-8 characters, across ALL_BINARY_MODES

The file's existing boundary tests used OUT_BUF_SIZE - 1, one char short of the failing case, which is why this slipped through. Both new tests fail without the fix and pass with it; full suite is 1714 tests, 0 failures.

No release-notes entry yet — no issue number filed for this.

Forward merge to 3.2 / 3.x left to a human.

🤖 Generated with Claude Code

https://claude.ai/code/session_0161vnbY6rGfPFAYBMnbv64c

UTF8StreamJsonParser and UTF8DataInputJsonParser flushed the streaming
buffer only inside the ASCII loop, before appending. On exit outPtr could
equal the buffer length, so the escape and multi-byte decode arms wrote
out of bounds. Add a flush check before the switch; ReaderBasedJsonParser
already checked per iteration and is unaffected.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0161vnbY6rGfPFAYBMnbv64c
@github-actions

Copy link
Copy Markdown
Contributor

📈 Overall Code Coverage

Metric Coverage Change
Instructions coverage 83.76% 📉 -0.010%
Branches branches 76.59% 📈 +0.020%

Overall project coverage from JaCoCo test results. Change values compare against the latest base branch build.

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.

1 participant