Skip to content

Commit f1a230b

Browse files
committed
gh-150587: Guard specialized list-int subscript indices
1 parent 8b1dbb1 commit f1a230b

6 files changed

Lines changed: 66 additions & 0 deletions

File tree

Lib/test/test_opcache.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1879,6 +1879,19 @@ def binary_subscr_list_int():
18791879
"BINARY_OP_SUBSCR_LIST_INT")
18801880
self.assert_no_opcode(binary_subscr_list_int, "BINARY_OP")
18811881

1882+
def binary_subscr_list_int_noncompact(index):
1883+
a = [1, 2, 3]
1884+
return a[index]
1885+
1886+
for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
1887+
self.assertEqual(binary_subscr_list_int_noncompact(0), 1)
1888+
self.assert_specialized(binary_subscr_list_int_noncompact,
1889+
"BINARY_OP_SUBSCR_LIST_INT")
1890+
# 2**30 + 2 is non-compact, but its low digit is 2. The specialized
1891+
# path must fall back instead of reading the low digit as the index.
1892+
with self.assertRaises(IndexError):
1893+
binary_subscr_list_int_noncompact(2**30 + 2)
1894+
18821895
def binary_subscr_tuple_int():
18831896
for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
18841897
a = (1, 2, 3)
@@ -1995,6 +2008,19 @@ def __getitem__(self, item):
19952008
@cpython_only
19962009
@requires_specialization
19972010
def test_store_subscr(self):
2011+
def store_subscr_list_int(index):
2012+
a = [None]
2013+
a[index] = 1
2014+
return a
2015+
2016+
for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
2017+
self.assertEqual(store_subscr_list_int(0), [1])
2018+
self.assert_specialized(store_subscr_list_int, "STORE_SUBSCR_LIST_INT")
2019+
# 2**30 + 2 is non-compact, but its low digit is 2. The specialized
2020+
# path must fall back instead of writing through the low digit index.
2021+
with self.assertRaises(IndexError):
2022+
store_subscr_list_int(2**30 + 2)
2023+
19982024
def store_subscr_dict():
19992025
for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
20002026
a = {1: 2, 2: 3}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix specialized list subscript and store-subscript paths so they fall back for
2+
non-compact ``int`` indices instead of passing them to
3+
``_PyLong_CompactValue()``.

Modules/_testinternalcapi/test_cases.c.h

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/bytecodes.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1142,6 +1142,7 @@ dummy_func(
11421142

11431143
assert(PyLong_CheckExact(sub));
11441144
assert(PyList_CheckExact(list));
1145+
EXIT_IF(!_PyLong_IsNonNegativeCompact((PyLongObject *)sub));
11451146

11461147
Py_ssize_t index = _PyLong_CompactValue((PyLongObject *)sub);
11471148
if (index < 0) {
@@ -1420,6 +1421,7 @@ dummy_func(
14201421

14211422
assert(PyLong_CheckExact(sub));
14221423
assert(PyList_CheckExact(list));
1424+
DEOPT_IF(!_PyLong_IsNonNegativeCompact((PyLongObject *)sub));
14231425

14241426
Py_ssize_t index = _PyLong_CompactValue((PyLongObject *)sub);
14251427
DEOPT_IF(!LOCK_OBJECT(list));

Python/executor_cases.c.h

Lines changed: 15 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/generated_cases.c.h

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)