Skip to content

fix: validate JSONB decimal dump markers - #7823

Open
DarrenChangJR wants to merge 1 commit into
alibaba:mainfrom
DarrenChangJR:fix/jsonb-decimal-dump-markers
Open

fix: validate JSONB decimal dump markers#7823
DarrenChangJR wants to merge 1 commit into
alibaba:mainfrom
DarrenChangJR:fix/jsonb-decimal-dump-markers

Conversation

@DarrenChangJR

Copy link
Copy Markdown

What this PR does and why

JSONB.toJSONString() currently mishandles two BC_DECIMAL unscaled-value
paths in JSONBDump.

First, the dump has already consumed BC_INT32 when it calls
readInt32Value(). The reader then treats the first raw payload byte as a new
marker. Writer-produced decimals can consequently change value (26214.4
becomes 0.0, and -26214.5 becomes -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 their
encoded bytes, while many other marker families leak NumberFormatException
from a zero-length BigInteger.

This change rewinds to the BC_INT32 marker before calling
readInt32Value(). It also makes the byte-length branch explicit for
BC_BIGINT and rejects other unsupported unscaled-value markers with
JSONException. Compact int32, int64, BC_BIGINT_LONG, and valid BC_BIGINT
behavior is preserved.

Tests

  • 16 canonical decimal controls spanning compact int32, full BC_INT32,
    BC_INT64, BC_BIGINT_LONG, and BC_BIGINT;
  • four writer-produced full-int32 boundary cases that previously changed value
    or threw;
  • eight string contents across fixed ASCII and six dynamic encodings;
  • 19 representative unsupported marker families;
  • standalone matrix: canonical 12/16, string markers 1/56, and other markers
    0/19 safe on 2.0.64/current main; all three groups fully safe on this branch;
  • focused tests pass on JDK 11, 17, and 21;
  • clean JDK 21 full core suite: 7,977 tests, no failures, errors, or skips.

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.writeDecimal overflow.

中文说明

修改内容和原因

JSONB.toJSONString()JSONBDump 在处理 BC_DECIMAL unscaled 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_INT32 marker,并且只允许显式
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。

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