#1063: bound BigDecimal→BigInteger expansion in objectToBigInteger (completes CVE-2026-59171 fix)#1067
Open
mechko wants to merge 2 commits into
Open
Conversation
…teger Completes the CVE-2026-59171 fix started in ab92bb9 / stleary#1065. The 1000-char length guard in stringToValue admits short exponent-notation literals (e.g. 1e100000000, 11 chars) which are stored compactly as BigDecimal and only expand when getBigInteger/optBigInteger calls BigDecimal.toBigInteger(), materialising ~10^8 digits and stalling the thread or throwing OOM. Guard both toBigInteger() sites in objectToBigInteger by rejecting any BigDecimal whose integer part would exceed ParserConfiguration.DEFAULT_MAX_NUMBER_LENGTH decimal digits (precision() - scale(), both O(1) reads). Returns defaultValue on overflow, matching the method's existing behaviour for non-finite and unparseable values. Covers JSONObject.getBigInteger/optBigInteger and JSONArray.getBigInteger/optBigInteger (all delegate to this helper). Adds JSONObjectTest.getBigIntegerHugeExponentReturnsDefault with a 5s timeout so a regression fails fast rather than hanging CI. Co-Authored-By: Claude <noreply@anthropic.com>
…ud java:S108) Co-Authored-By: Claude <noreply@anthropic.com>
|
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.



Follow-up to #1065; see this comment on #1063 for the residual vector. Targets
max-number-length-configper @stleary's request.Problem
JSONObject.objectToBigIntegercallsBigDecimal.toBigInteger()with no bound on the resulting magnitude. A short exponent-notation literal such as1e100000000(11 chars — well under themaxNumberLengthguard) is stored compactly as aBigDecimalat parse time, then expanded to a ~100 000 000-digitBigIntegerwhen the caller invokesgetBigInteger/optBigInteger, stalling the thread for tens of seconds or throwingOutOfMemoryError.Repro against
max-number-length-config@ 90563eb (pre-patch):Fix
Before calling
.toBigInteger(), reject anyBigDecimalwhose integer part would exceedParserConfiguration.DEFAULT_MAX_NUMBER_LENGTHdecimal digits:Applied at both sink sites in
objectToBigInteger(JSONObject.java:1402and:1432).precision()andscale()are O(1) metadata reads, so the check is free.JSONArray.{get,opt}BigIntegerdelegate to the same helper, so all four public accessors are covered.Uses the
DEFAULT_MAX_NUMBER_LENGTHconstant introduced on this branch so the parse-time and accessor-time ceilings stay in sync. The accessors don't carry aParserConfiguration, so per-instance configuration is left as follow-up (#1066) to keep this change minimal for the release window.Behaviour change
For a value whose integer part exceeds
DEFAULT_MAX_NUMBER_LENGTH(1000) digits:optBigInteger(key, dflt)dfltgetBigInteger(key)JSONException("… is not a BigInteger …")Matches how the method already handles other unconvertible values (non-finite doubles, unparseable strings). The
Double/Floatbranch needs no guard — max finitedouble≈ 1.8e308 → 309 digits.Verification
Post-patch, same reproducer:
mvn test: 788 run, 0 fail, 0 error, 6 skipped (pre-existing).Tests
Added
JSONObjectTest.getBigIntegerHugeExponentReturnsDefault(@Test(timeout = 5000)so a regression fails fast rather than hanging CI):{"x":1e100000000}→optBigIntegerreturnsnull,getBigIntegerthrows, both in 0 msput("x", "1e100000000")behaves identicallyJSONArrayaccessor covered{"x":1e999}still returns10^999correctly🤖 Generated with Claude Code