Skip to content

fix: grow strBuf when reading long escaped strings, for issue #7671 - #7676

Merged
wenshao merged 1 commit into
alibaba:mainfrom
kamilkrzywanski:fix-issue-7671
Aug 2, 2026
Merged

fix: grow strBuf when reading long escaped strings, for issue #7671#7676
wenshao merged 1 commit into
alibaba:mainfrom
kamilkrzywanski:fix-issue-7671

Conversation

@kamilkrzywanski

@kamilkrzywanski kamilkrzywanski commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

What this PR does / why we need it?

Keep JSONReaderUTF16.strBuf in sync when the local buffer is grown mid-loop while reading escaped strings.

Issue #7671 reported ArrayIndexOutOfBoundsException on 2.0.61 when a long escaped string followed a shorter one that had already initialized strBuf (e.g. char[512]). The live crash path is already fixed on main by #3989 (else if (stroff > strBuf.length) before the initial arraycopy, released in 2.0.62). This change is a buffer-reuse / consistency follow-up: when strBuf is resized inside the escape loop, write the grown array back to this.strBuf so later reads reuse the larger buffer instead of re-growing from the stale smaller one.

Summary of your change

Please indicate you've done the following:

  • Made sure tests are passing and test coverage is added if needed.
  • Made sure commit message follow the rule of Conventional Commits specification.
  • Considered the docs impact and opened a new docs issue or PR with docs changes if needed.

@wenshao wenshao left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed — no blockers. The change is correct and correctly scoped: the hoisted and mid-loop this.strBuf = strBuf assignments are equivalent/safe, and JSONReaderUTF16 is the only reader with this reusable-buffer pattern (JSONReaderUTF8 writes the grown buffer back to its thread-local cache; the ASCII/Str paths don't use strBuf). Build and the new Issue7671 tests pass (verified locally on JDK 17). One non-blocking suggestion inline.

— Qwen Code via Qwen Code /review

Comment on lines +46 to +47
@Test
public void testStrBufGrow() {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Suggestion] These regression tests don't gate the source change — both pass identically with the two mid-loop this.strBuf = strBuf; assignments reverted. Verified empirically: reverting only the source edits and running Issue7671 gives Tests run: 2, Failures: 0 (test() and testStrBufGrow() both green). The pre-existing else if (stroff > strBuf.length) guard (added in commit bdfe92f for issue #3989) already prevents the original ArrayIndexOutOfBoundsException at the initial arraycopy, and the parsed result is always built from the correctly-grown local strBuf; so on current main this is a buffer-reuse/consistency improvement rather than a live crash fix. In testStrBufGrow the two added lines never even execute: key "b" has a leading run stroff=600 > 512, so the else if grows the buffer, and the total 651 < newCapacity(600,512)=768, so neither mid-loop guard fires. — Concrete cost: a future revert of the two lines would not be caught by these tests. Consider a white-box assertion (e.g. via reflection) that strBuf capacity grows after parsing consecutive long escaped strings, or a short note that this is a reuse/consistency follow-up to #3989 rather than a new crash fix. (The getBytes(UTF_8) path uses JSONReaderUTF8, which writes the grown buffer back to its cache, so it doesn't exercise the changed code.)

— Qwen Code via Qwen Code /review

JSONReaderUTF16 grew a local strBuf while decoding escaped strings but
did not always write the larger array back to this.strBuf. Later reads
then re-grew from a stale smaller buffer. Always assign this.strBuf after
allocate/grow (including mid-loop) so the reusable buffer stays in sync.

The AIOOBE reported in alibaba#7671 on 2.0.61 is already fixed on main by alibaba#3989;
this is a buffer-reuse follow-up.

@wenshao wenshao left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed. Suggestions are inline.

— qwen3.8-max-preview via Qwen Code /review

Comment on lines 3272 to +3273
strBuf = Arrays.copyOf(strBuf, newCapacity(stroff + 4, strBuf.length));
this.strBuf = strBuf;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Suggestion] No test gates these buffer-reuse write-backs (here and the twin at line 3302): removing either this.strBuf = strBuf; leaves the entire test suite green — utf16test1() creates a fresh JSONReader per iteration, Issue3989 asserts only one integer field, and no test references strBuf or parses two consecutive long escaped strings through the same reader instance. — Failure scenario: a future refactor of the mid-loop growth logic drops one of the assignments → every subsequent readString() on the same reader that needs a large buffer re-allocates from the stale smaller buffer instead of reusing the grown one (increased GC pressure / p99 latency for workloads parsing many long escaped strings), with no test detecting it; output correctness is unaffected.

Fix: add a test that parses two consecutive long escaped strings (e.g. >1024 \\ pairs) through a single JSONReaderUTF16 instance and asserts via reflection on the private strBuf field that the grown buffer was retained (reference equality, or length ≥ the second parse's requirement).

(Follow-up to the now-outdated thread on the removed Issue7671.java — the underlying gap persists, as the PR description acknowledges.)

— qwen3.8-max-preview via Qwen Code /review

@wenshao wenshao left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found. LGTM! ✅

— qwen3.8-max-preview via Qwen Code /review

@wenshao wenshao left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found. LGTM! ✅

— qwen3.8-max-preview via Qwen Code /review

@wenshao
wenshao merged commit 1836c7b into alibaba:main Aug 2, 2026
30 checks passed
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.

2 participants