@@ -760,8 +760,29 @@ public boolean getBoolean(String key) throws JSONException {
760760 * be converted to BigInteger.
761761 */
762762 public BigInteger getBigInteger (String key ) throws JSONException {
763+ return this .getBigInteger (key , new JSONParserConfiguration ());
764+ }
765+
766+ /**
767+ * Get the BigInteger value associated with a key.
768+ *
769+ * @param key
770+ * A key string.
771+ * @param jsonParserConfiguration
772+ * A configuration whose {@code maxNumberLength} bounds the number of
773+ * decimal digits in the returned integer. Values exceeding this length
774+ * are treated as unconvertible. Pass a configuration with
775+ * {@link ParserConfiguration#UNDEFINED_MAXIMUM_NUMBER_LENGTH} to disable
776+ * this check.
777+ * @return The numeric value.
778+ * @throws JSONException
779+ * if the key is not found or if the value cannot
780+ * be converted to BigInteger.
781+ */
782+ public BigInteger getBigInteger (String key , JSONParserConfiguration jsonParserConfiguration )
783+ throws JSONException {
763784 Object object = this .get (key );
764- BigInteger ret = objectToBigInteger (object , null );
785+ BigInteger ret = objectToBigInteger (object , null , jsonParserConfiguration );
765786 if (ret != null ) {
766787 return ret ;
767788 }
@@ -1381,8 +1402,31 @@ static BigDecimal objectToBigDecimal(Object val, BigDecimal defaultValue, boolea
13811402 * @return An object which is the value.
13821403 */
13831404 public BigInteger optBigInteger (String key , BigInteger defaultValue ) {
1405+ return this .optBigInteger (key , defaultValue , new JSONParserConfiguration ());
1406+ }
1407+
1408+ /**
1409+ * Get an optional BigInteger associated with a key, or the defaultValue if
1410+ * there is no such key or if its value is not a number. If the value is a
1411+ * string, an attempt will be made to evaluate it as a number.
1412+ *
1413+ * @param key
1414+ * A key string.
1415+ * @param defaultValue
1416+ * The default.
1417+ * @param jsonParserConfiguration
1418+ * A configuration whose {@code maxNumberLength} bounds the number of
1419+ * decimal digits in the returned integer. Values exceeding this length
1420+ * are treated as unconvertible and {@code defaultValue} is returned.
1421+ * Pass a configuration with
1422+ * {@link ParserConfiguration#UNDEFINED_MAXIMUM_NUMBER_LENGTH} to disable
1423+ * this check.
1424+ * @return An object which is the value.
1425+ */
1426+ public BigInteger optBigInteger (String key , BigInteger defaultValue ,
1427+ JSONParserConfiguration jsonParserConfiguration ) {
13841428 Object val = this .opt (key );
1385- return objectToBigInteger (val , defaultValue );
1429+ return objectToBigInteger (val , defaultValue , jsonParserConfiguration );
13861430 }
13871431
13881432 /**
@@ -1392,14 +1436,43 @@ public BigInteger optBigInteger(String key, BigInteger defaultValue) {
13921436 * to convert.
13931437 */
13941438 static BigInteger objectToBigInteger (Object val , BigInteger defaultValue ) {
1439+ return objectToBigInteger (val , defaultValue , new JSONParserConfiguration ());
1440+ }
1441+
1442+ /**
1443+ * @param val value to convert
1444+ * @param defaultValue default value to return is the conversion doesn't work or is null.
1445+ * @param jsonParserConfiguration parser configuration whose {@code maxNumberLength}
1446+ * bounds the number of decimal digits in the resulting integer. Values whose
1447+ * integer part would exceed this length are treated as unconvertible and
1448+ * {@code defaultValue} is returned. Pass a configuration with
1449+ * {@link ParserConfiguration#UNDEFINED_MAXIMUM_NUMBER_LENGTH} to disable this check.
1450+ * @return BigInteger conversion of the original value, or the defaultValue if unable
1451+ * to convert.
1452+ */
1453+ static BigInteger objectToBigInteger (Object val , BigInteger defaultValue ,
1454+ JSONParserConfiguration jsonParserConfiguration ) {
13951455 if (NULL .equals (val )) {
13961456 return defaultValue ;
13971457 }
1458+ if (jsonParserConfiguration == null ) {
1459+ jsonParserConfiguration = new JSONParserConfiguration ();
1460+ }
1461+ final int maxNumberLength = jsonParserConfiguration .getMaxNumberLength ();
13981462 if (val instanceof BigInteger ){
13991463 return (BigInteger ) val ;
14001464 }
14011465 if (val instanceof BigDecimal ){
1402- return ((BigDecimal ) val ).toBigInteger ();
1466+ BigDecimal bd = (BigDecimal ) val ;
1467+ // Same ceiling as the parse-time maxNumberLength guard: refuse to
1468+ // materialise an integer whose decimal representation would exceed
1469+ // maxNumberLength digits. Prevents DoS via short exponent literals
1470+ // like 1e100000000 (CVE-2026-59171, see issue #1063).
1471+ if (maxNumberLength != ParserConfiguration .UNDEFINED_MAXIMUM_NUMBER_LENGTH
1472+ && (long ) bd .precision () - bd .scale () > maxNumberLength ) {
1473+ return defaultValue ;
1474+ }
1475+ return bd .toBigInteger ();
14031476 }
14041477 if (val instanceof Double || val instanceof Float ){
14051478 if (!numberIsFinite ((Number )val )) {
@@ -1411,6 +1484,18 @@ static BigInteger objectToBigInteger(Object val, BigInteger defaultValue) {
14111484 || val instanceof Short || val instanceof Byte ){
14121485 return BigInteger .valueOf (((Number ) val ).longValue ());
14131486 }
1487+ return attemptConversionToBigInteger (val , defaultValue , maxNumberLength );
1488+ }
1489+
1490+ /**
1491+ * Convenience method to attempt conversion of value to BigInteger.
1492+ * Added to reduce complexity of objectToBigInteger()
1493+ * @param val the value to be converted
1494+ * @param defaultValue the default value to use if conversion is not attempted or fails
1495+ * @param maxNumberLength the max length allowed for BigIntegers
1496+ * @return the converted value, or the defaultValue
1497+ */
1498+ private static BigInteger attemptConversionToBigInteger (Object val , BigInteger defaultValue , int maxNumberLength ) {
14141499 // don't check if it's a string in case of unchecked Number subclasses
14151500 try {
14161501 /**
@@ -1422,7 +1507,12 @@ static BigInteger objectToBigInteger(Object val, BigInteger defaultValue) {
14221507 */
14231508 final String valStr = val .toString ();
14241509 if (isDecimalNotation (valStr )) {
1425- return new BigDecimal (valStr ).toBigInteger ();
1510+ BigDecimal bd = new BigDecimal (valStr );
1511+ if (maxNumberLength != ParserConfiguration .UNDEFINED_MAXIMUM_NUMBER_LENGTH
1512+ && (long ) bd .precision () - bd .scale () > maxNumberLength ) {
1513+ return defaultValue ;
1514+ }
1515+ return bd .toBigInteger ();
14261516 }
14271517 return new BigInteger (valStr );
14281518 } catch (Exception e ) {
@@ -2667,16 +2757,33 @@ protected static boolean isDecimalNotation(final String val) {
26672757 /**
26682758 * Try to convert a string into a number, boolean, or null. If the string
26692759 * can't be converted, return the string.
2760+ * Warning! stringToValue(String) uses the default max number length. If you want to override it,
2761+ * use a suitable initialized JSONParserConfiguration and the method: stringToValue(String, JSONParserConfiguration).
26702762 *
2671- * @param string
2672- * A String. can not be null.
2763+ * @param str A String. can not be null.
26732764 * @return A simple JSON value.
26742765 * @throws NullPointerException
26752766 * Thrown if the string is null.
26762767 */
26772768 // Changes to this method must be copied to the corresponding method in
26782769 // the XML class to keep full support for Android
2679- public static Object stringToValue (String string ) {
2770+ public static Object stringToValue (String str ) {
2771+ return stringToValue (str , new JSONParserConfiguration ());
2772+ }
2773+
2774+ /**
2775+ * Try to convert a string into a number, boolean, or null. If the string
2776+ * can't be converted, return the string.
2777+ *
2778+ * @param string A String. can not be null.
2779+ * @param jsonParserConfiguration the parser config
2780+ * @return A simple JSON value. If the string represents a number that is too large,
2781+ * a string will be returned.
2782+ * @throws NullPointerException Thrown if the string is null.
2783+ */
2784+ // Changes to this method must be copied to the corresponding method in
2785+ // the XML class to keep full support for Android
2786+ public static Object stringToValue (String string , JSONParserConfiguration jsonParserConfiguration ) {
26802787 if ("" .equals (string )) {
26812788 return string ;
26822789 }
@@ -2700,7 +2807,14 @@ public static Object stringToValue(String string) {
27002807 char initial = string .charAt (0 );
27012808 if ((initial >= '0' && initial <= '9' ) || initial == '-' ) {
27022809 try {
2703- if (string .length () <= 1000 ) {
2810+ if (jsonParserConfiguration == null ) {
2811+ jsonParserConfiguration = new JSONParserConfiguration ();
2812+ }
2813+ // user declines max number checking
2814+ if (jsonParserConfiguration .getMaxNumberLength () == ParserConfiguration .UNDEFINED_MAXIMUM_NUMBER_LENGTH ) {
2815+ return stringToNumber (string );
2816+ }
2817+ if (string .length () <= jsonParserConfiguration .getMaxNumberLength ()) {
27042818 return stringToNumber (string );
27052819 }
27062820 } catch (Exception ignore ) {
0 commit comments