From 59dac4e82cd6766fc31a9389d573d732580eaab5 Mon Sep 17 00:00:00 2001 From: Bob Ippolito Date: Tue, 4 Apr 2023 10:59:13 -0700 Subject: SJ-PT-23-03: Backport integer string length limitation to limit quadratic parsing --- simplejson/__init__.py | 4 ++-- simplejson/decoder.py | 15 ++++++++++++++- simplejson/tests/test_decode.py | 8 ++++++++ 3 files changed, 24 insertions(+), 3 deletions(-) (limited to 'simplejson') 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') -- cgit v1.2.1