fix: validate JSONB decimal dump markers - #7823
Open
DarrenChangJR wants to merge 1 commit into
Open
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this PR does and why
JSONB.toJSONString()currently mishandles twoBC_DECIMALunscaled-valuepaths in
JSONBDump.First, the dump has already consumed
BC_INT32when it callsreadInt32Value(). The reader then treats the first raw payload byte as a newmarker. Writer-produced decimals can consequently change value (
26214.4becomes
0.0, and-26214.5becomes-0.1) or throw instead of dumping.Second, the default decimal arm assumes every otherwise unsupported nested
marker is
BC_BIGINT. Dynamic strings are accepted as integers made from theirencoded bytes, while many other marker families leak
NumberFormatExceptionfrom a zero-length BigInteger.
This change rewinds to the
BC_INT32marker before callingreadInt32Value(). It also makes the byte-length branch explicit forBC_BIGINTand rejects other unsupported unscaled-value markers withJSONException. Compact int32, int64,BC_BIGINT_LONG, and validBC_BIGINTbehavior is preserved.
Tests
BC_INT32,BC_INT64,BC_BIGINT_LONG, andBC_BIGINT;or threw;
0/19 safe on 2.0.64/current main; all three groups fully safe on this branch;
Exact upstream searches on 2026-08-22 found no active duplicate. Closed issues
#1652 and #1831 are older text JSON BigDecimal defects; #2084 is an unrelated
JSONWriterUTF8.writeDecimaloverflow.中文说明
修改内容和原因
JSONB.toJSONString()的JSONBDump在处理BC_DECIMALunscaled value 时存在两类问题。
第一,进入
BC_INT32分支前 marker 已经被消费,但代码直接调用readInt32Value(),导致该方法把第一个原始 payload 字节当成新的 marker。writer 生成的 decimal 因此可能改变值(
26214.4变成0.0,-26214.5变成-0.1),也可能直接抛异常。第二,decimal 的 default 分支把所有未处理 marker 都当成
BC_BIGINT。动态字符串会被错误解释成由编码字节构造的整数,其他多种 marker 则从 zero-length
BigInteger 泄漏
NumberFormatException。本修改在调用
readInt32Value()前回退到BC_INT32marker,并且只允许显式BC_BIGINT进入 byte-length 分支;其他不支持的 unscaled-value marker 统一抛出JSONException。compact int32、int64、BC_BIGINT_LONG和合法BC_BIGINT行为保持不变。
测试覆盖 16 个 canonical decimal、四个原先会改值/抛错的 full-int32 边界、七种
字符串编码的八种内容,以及 19 类其他 marker。独立矩阵在 2.0.64/current main
分别只有 12/16、1/56、0/19 safe,本分支三个 group 全部通过。focused test 在
JDK 11/17/21 全部通过,clean JDK 21 full core 7,977 项也全部通过,无 failure、
error 或 skip。2026-08-22 的精确上游检索没有发现 active duplicate。