This is an automated email from the ASF dual-hosted git repository. rmaucher pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit 15d1692edf7f76a8cb18107fe076310974c266fd Author: opencode <[email protected]> AuthorDate: Thu Oct 15 09:16:29 2026 +0200 Parse out-of-range native JSON numbers as BigInteger With native numbers enabled, integers were converted with Long.valueOf while the grammar admits integers of arbitrary digit count, so values outside the long range caused an unchecked NumberFormatException rather than being parsed. Such integers now fall back to BigInteger, matching the behaviour of the default non-native mode which already uses BigInteger. Values within the long range continue to produce Long instances. The change is made in the grammar (JSONParser.jjt) and mirrored in the checked-in generated parser, with regression tests for both sides of the boundary. --- java/org/apache/tomcat/util/json/JSONParser.java | 16 +++++++++++++--- java/org/apache/tomcat/util/json/JSONParser.jjt | 8 +++++++- test/org/apache/tomcat/util/json/TestJSONParser.java | 20 ++++++++++++++++++++ 3 files changed, 40 insertions(+), 4 deletions(-) diff --git a/java/org/apache/tomcat/util/json/JSONParser.java b/java/org/apache/tomcat/util/json/JSONParser.java index b798831c1e..534692eb20 100644 --- a/java/org/apache/tomcat/util/json/JSONParser.java +++ b/java/org/apache/tomcat/util/json/JSONParser.java @@ -459,9 +459,19 @@ public class JSONParser implements JSONParserConstants { case NUMBER_INTEGER: { t = jj_consume_token(NUMBER_INTEGER); if (nativeNumbers) { - { - if ("" != null) { - return Long.valueOf(t.image); + try { + { + if ("" != null) { + return Long.valueOf(t.image); + } + } + } catch (NumberFormatException nfe) { + { + // The grammar admits integers that do not fit a long. Fall back to BigInteger rather + // than failing the parse, matching the behaviour of the non-native path. + if ("" != null) { + return new java.math.BigInteger(t.image); + } } } } else { diff --git a/java/org/apache/tomcat/util/json/JSONParser.jjt b/java/org/apache/tomcat/util/json/JSONParser.jjt index 7504ef110f..561d8fda2d 100644 --- a/java/org/apache/tomcat/util/json/JSONParser.jjt +++ b/java/org/apache/tomcat/util/json/JSONParser.jjt @@ -412,7 +412,13 @@ Number number(): { t = <NUMBER_INTEGER> { if (nativeNumbers) { - return Long.valueOf(t.image); + try { + return Long.valueOf(t.image); + } catch (NumberFormatException nfe) { + // The grammar admits integers that do not fit a long. Fall back to BigInteger rather than + // failing the parse, matching the behaviour of the non-native path. + return new java.math.BigInteger(t.image); + } } else { return new java.math.BigInteger(substringBefore(t.image, '.')); } diff --git a/test/org/apache/tomcat/util/json/TestJSONParser.java b/test/org/apache/tomcat/util/json/TestJSONParser.java index bd8f7abfb3..c4067226d6 100644 --- a/test/org/apache/tomcat/util/json/TestJSONParser.java +++ b/test/org/apache/tomcat/util/json/TestJSONParser.java @@ -17,6 +17,8 @@ package org.apache.tomcat.util.json; import java.io.StringReader; +import java.math.BigInteger; +import java.util.List; import org.junit.Assert; import org.junit.Test; @@ -55,6 +57,24 @@ public class TestJSONParser { Assert.assertNotNull(parser.parse()); } + @Test + public void testNativeNumbersBeyondLongRange() throws ParseException { + JSONParser parser = new JSONParser("[9223372036854775808, -9223372036854775809]"); + parser.setNativeNumbers(true); + List<Object> values = parser.parseArray(); + Assert.assertEquals(new BigInteger("9223372036854775808"), values.get(0)); + Assert.assertEquals(new BigInteger("-9223372036854775809"), values.get(1)); + } + + @Test + public void testNativeNumbersWithinLongRange() throws ParseException { + JSONParser parser = new JSONParser("[9223372036854775807, -9223372036854775808]"); + parser.setNativeNumbers(true); + List<Object> values = parser.parseArray(); + Assert.assertEquals(Long.valueOf(Long.MAX_VALUE), values.get(0)); + Assert.assertEquals(Long.valueOf(Long.MIN_VALUE), values.get(1)); + } + private static String nest(int depth) { StringBuilder result = new StringBuilder(depth * 2); for (int i = 0; i < depth; i++) { --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
