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]

Reply via email to