diff options
author | Bob Ippolito <bob@redivi.com> | 2023-04-04 10:59:13 -0700 |
---|---|---|
committer | Bob Ippolito <bob@redivi.com> | 2023-04-04 10:59:13 -0700 |
commit | 59dac4e82cd6766fc31a9389d573d732580eaab5 (patch) | |
tree | 2cba0cbde6419fa11c6111d82f64b989c46455ec /simplejson | |
parent | 1e495c1199f56c2e8e7931f20bda7481842e18ff (diff) | |
download | simplejson-59dac4e82cd6766fc31a9389d573d732580eaab5.tar.gz |
SJ-PT-23-03: Backport integer string length limitation to limit quadratic parsing
Diffstat (limited to 'simplejson')
-rw-r--r-- | simplejson/__init__.py | 4 | ||||
-rw-r--r-- | simplejson/decoder.py | 15 | ||||
-rw-r--r-- | simplejson/tests/test_decode.py | 8 |
3 files changed, 24 insertions, 3 deletions
diff --git a/simplejson/__init__.py b/simplejson/__init__.py index 2f0bebf..92b6009 100644 --- a/simplejson/__init__.py +++ b/simplejson/__init__.py @@ -442,12 +442,12 @@ def load(fp, encoding=None, cls=None, object_hook=None, parse_float=None, takes priority. *parse_float*, if specified, will be called with the string of every - JSON float to be decoded. By default, this is equivalent to + JSON float to be decoded. By default, this is equivalent to ``float(num_str)``. This can be used to use another datatype or parser for JSON floats (e.g. :class:`decimal.Decimal`). *parse_int*, if specified, will be called with the string of every - JSON int to be decoded. By default, this is equivalent to + JSON int to be decoded. By default, this is equivalent to ``int(num_str)``. This can be used to use another datatype or parser for JSON integers (e.g. :class:`float`). diff --git a/simplejson/decoder.py b/simplejson/decoder.py index e1f10ae..c28e445 100644 --- a/simplejson/decoder.py +++ b/simplejson/decoder.py @@ -46,6 +46,19 @@ BACKSLASH = { DEFAULT_ENCODING = "utf-8" +if hasattr(sys, 'get_int_max_str_digits'): + bounded_int = int +else: + def bounded_int(s, INT_MAX_STR_DIGITS=4300): + """Backport of the integer string length conversion limitation + + https://docs.python.org/3/library/stdtypes.html#int-max-str-digits + """ + if len(s) > INT_MAX_STR_DIGITS: + raise ValueError("Exceeds the limit (%s) for integer string conversion: value has %s digits" % (INT_MAX_STR_DIGITS, len(s))) + return int(s) + + def scan_four_digit_hex(s, end, _m=re.compile(r'^[0-9a-fA-F]{4}$').match): """Scan a four digit hex number from s[end:end + 4] """ @@ -349,7 +362,7 @@ class JSONDecoder(object): self.object_hook = object_hook self.object_pairs_hook = object_pairs_hook self.parse_float = parse_float or float - self.parse_int = parse_int or int + self.parse_int = parse_int or bounded_int self.parse_constant = parse_constant or _CONSTANTS.__getitem__ self.strict = strict self.parse_object = JSONObject diff --git a/simplejson/tests/test_decode.py b/simplejson/tests/test_decode.py index 6960ee5..317b4f9 100644 --- a/simplejson/tests/test_decode.py +++ b/simplejson/tests/test_decode.py @@ -2,6 +2,7 @@ from __future__ import absolute_import import decimal from unittest import TestCase +import sys import simplejson as json from simplejson.compat import StringIO, b, binary_type from simplejson import OrderedDict @@ -117,3 +118,10 @@ class TestDecode(TestCase): diff = id(x) - id(y) self.assertRaises(ValueError, j.scan_once, y, diff) self.assertRaises(ValueError, j.raw_decode, y, i) + + def test_bounded_int(self): + # SJ-PT-23-03, limit quadratic number parsing per Python 3.11 + max_str_digits = getattr(sys, 'get_int_max_str_digits', lambda: 4300)() + s = '1' + '0' * (max_str_digits - 1) + self.assertEqual(json.loads(s), int(s)) + self.assertRaises(ValueError, json.loads, s + '0') |