From b8fbae380c74795b42de3e5a569519ab2dc8e8a8 Mon Sep 17 00:00:00 2001 From: fhgffy <102001626+fhgffy@users.noreply.github.com> Date: Fri, 2 Oct 2026 05:25:54 -0700 Subject: [PATCH] Normalize oversized array index conversion errors --- jsonpointer.py | 5 ++++- tests.py | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/jsonpointer.py b/jsonpointer.py index ae1d5c8..4007f71 100644 --- a/jsonpointer.py +++ b/jsonpointer.py @@ -239,7 +239,10 @@ def get_part(cls, doc, part): if not JsonPointer._RE_ARRAY_INDEX.fullmatch(str(part)): raise JsonPointerException("'%s' is not a valid sequence index" % part) - return int(part) + try: + return int(part) + except ValueError as e: + raise JsonPointerException("Invalid sequence index: %s" % (e,)) elif hasattr(doc, '__getitem__'): # Allow indexing via ducktyping diff --git a/tests.py b/tests.py index 13c0561..e836d9f 100755 --- a/tests.py +++ b/tests.py @@ -2,6 +2,7 @@ import copy import doctest +import sys import unittest import jsonpointer @@ -252,6 +253,47 @@ def test_string_not_indexable(self): self.assertRaises(JsonPointerException, ptr.resolve, doc) +@unittest.skipUnless(hasattr(sys, 'get_int_max_str_digits'), + 'Integer string conversion limits are not available') +class LargeIndexTests(unittest.TestCase): + + def setUp(self): + limit = sys.get_int_max_str_digits() + if not limit: + self.skipTest('Integer string conversion limit is disabled') + self.token = '1' * (limit + 1) + self.pointer = '/' + self.token + + def test_resolve_large_index(self): + self.assertRaises(JsonPointerException, resolve_pointer, + [0], self.pointer) + + def test_resolve_large_index_default(self): + default = object() + self.assertIs(resolve_pointer([0], self.pointer, default), default) + self.assertIs(resolve_pointer({'items': [0]}, + '/items' + self.pointer, default), + default) + + def test_to_last_large_index(self): + self.assertRaises(JsonPointerException, + JsonPointer(self.pointer).to_last, [0]) + + def test_set_large_index(self): + for inplace in (True, False): + with self.subTest(inplace=inplace): + doc = [0] + self.assertRaises(JsonPointerException, set_pointer, + doc, self.pointer, 1, inplace=inplace) + self.assertEqual(doc, [0]) + + def test_large_numeric_object_member(self): + doc = {self.token: 'old'} + self.assertEqual(resolve_pointer(doc, self.pointer), 'old') + set_pointer(doc, self.pointer, 'new') + self.assertEqual(doc, {self.token: 'new'}) + + class ToLastTests(unittest.TestCase): def test_empty_path(self):