Skip to content

Commit f02d1a4

Browse files
bpo-36946: Fix possible signed integer overflow when handling slices. (GH-13375)
The final addition (cur += step) may overflow, so use size_t for "cur". "cur" is always positive (even for negative steps), so it is safe to use size_t here. Co-Authored-By: Martin Panter <[email protected]> (cherry picked from commit 14514d9) Co-authored-by: Zackery Spytz <[email protected]>
1 parent aa73841 commit f02d1a4

File tree

15 files changed

+45
-19
lines changed

15 files changed

+45
-19
lines changed

Lib/ctypes/test/test_arrays.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,17 @@ def test_simple(self):
6969
from operator import delitem
7070
self.assertRaises(TypeError, delitem, ca, 0)
7171

72+
def test_step_overflow(self):
73+
a = (c_int * 5)()
74+
a[3::sys.maxsize] = (1,)
75+
self.assertListEqual(a[3::sys.maxsize], [1])
76+
a = (c_char * 5)()
77+
a[3::sys.maxsize] = b"A"
78+
self.assertEqual(a[3::sys.maxsize], b"A")
79+
a = (c_wchar * 5)()
80+
a[3::sys.maxsize] = u"X"
81+
self.assertEqual(a[3::sys.maxsize], u"X")
82+
7283
def test_numeric_arrays(self):
7384

7485
alen = 5

Lib/test/seq_tests.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,7 @@ def test_getslice(self):
209209
a = self.type2test([0,1,2,3,4])
210210
self.assertEqual(a[ -pow(2,128): 3 ], self.type2test([0,1,2]))
211211
self.assertEqual(a[ 3: pow(2,145) ], self.type2test([3,4]))
212+
self.assertEqual(a[3::sys.maxsize], self.type2test([3]))
212213

213214
def test_contains(self):
214215
u = self.type2test([0, 1, 2])

Lib/test/string_tests.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1135,7 +1135,7 @@ def test_slice(self):
11351135
def test_extended_getslice(self):
11361136
# Test extended slicing by comparing with list slicing.
11371137
s = string.ascii_letters + string.digits
1138-
indices = (0, None, 1, 3, 41, -1, -2, -37)
1138+
indices = (0, None, 1, 3, 41, sys.maxsize, -1, -2, -37)
11391139
for start in indices:
11401140
for stop in indices:
11411141
# Skip step 0 (invalid)

Lib/test/test_array.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -745,7 +745,7 @@ def test_extended_getslice(self):
745745
# Test extended slicing by comparing with list slicing
746746
# (Assumes list conversion works correctly, too)
747747
a = array.array(self.typecode, self.example)
748-
indices = (0, None, 1, 3, 19, 100, -1, -2, -31, -100)
748+
indices = (0, None, 1, 3, 19, 100, sys.maxsize, -1, -2, -31, -100)
749749
for start in indices:
750750
for stop in indices:
751751
# Everything except the initial 0 (invalid step)
@@ -843,7 +843,7 @@ def test_setslice(self):
843843
self.assertRaises(TypeError, a.__setitem__, slice(0, 1), b)
844844

845845
def test_extended_set_del_slice(self):
846-
indices = (0, None, 1, 3, 19, 100, -1, -2, -31, -100)
846+
indices = (0, None, 1, 3, 19, 100, sys.maxsize, -1, -2, -31, -100)
847847
for start in indices:
848848
for stop in indices:
849849
# Everything except the initial 0 (invalid step)

Lib/test/test_bytes.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ def test_extended_getslice(self):
283283
# Test extended slicing by comparing with list slicing.
284284
L = list(range(255))
285285
b = self.type2test(L)
286-
indices = (0, None, 1, 3, 19, 100, -1, -2, -31, -100)
286+
indices = (0, None, 1, 3, 19, 100, sys.maxsize, -1, -2, -31, -100)
287287
for start in indices:
288288
for stop in indices:
289289
# Skip step 0 (invalid)
@@ -1238,7 +1238,8 @@ def test_del_expand(self):
12381238
self.assertLessEqual(sys.getsizeof(b), size)
12391239

12401240
def test_extended_set_del_slice(self):
1241-
indices = (0, None, 1, 3, 19, 300, 1<<333, -1, -2, -31, -300)
1241+
indices = (0, None, 1, 3, 19, 300, 1<<333, sys.maxsize,
1242+
-1, -2, -31, -300)
12421243
for start in indices:
12431244
for stop in indices:
12441245
# Skip invalid step 0

Lib/test/test_mmap.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -452,7 +452,7 @@ def test_extended_getslice(self):
452452
m = mmap.mmap(-1, len(s))
453453
m[:] = s
454454
self.assertEqual(m[:], s)
455-
indices = (0, None, 1, 3, 19, 300, -1, -2, -31, -300)
455+
indices = (0, None, 1, 3, 19, 300, sys.maxsize, -1, -2, -31, -300)
456456
for start in indices:
457457
for stop in indices:
458458
# Skip step 0 (invalid)
@@ -464,7 +464,7 @@ def test_extended_set_del_slice(self):
464464
# Test extended slicing by comparing with list slicing.
465465
s = bytes(reversed(range(256)))
466466
m = mmap.mmap(-1, len(s))
467-
indices = (0, None, 1, 3, 19, 300, -1, -2, -31, -300)
467+
indices = (0, None, 1, 3, 19, 300, sys.maxsize, -1, -2, -31, -300)
468468
for start in indices:
469469
for stop in indices:
470470
# Skip invalid step 0
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix possible signed integer overflow when handling slices.

Modules/_ctypes/_ctypes.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4372,7 +4372,8 @@ Array_subscript(PyObject *myself, PyObject *item)
43724372
StgDictObject *stgdict, *itemdict;
43734373
PyObject *proto;
43744374
PyObject *np;
4375-
Py_ssize_t start, stop, step, slicelen, cur, i;
4375+
Py_ssize_t start, stop, step, slicelen, i;
4376+
size_t cur;
43764377

43774378
if (PySlice_Unpack(item, &start, &stop, &step) < 0) {
43784379
return NULL;
@@ -4512,7 +4513,8 @@ Array_ass_subscript(PyObject *myself, PyObject *item, PyObject *value)
45124513
return Array_ass_item(myself, i, value);
45134514
}
45144515
else if (PySlice_Check(item)) {
4515-
Py_ssize_t start, stop, step, slicelen, otherlen, i, cur;
4516+
Py_ssize_t start, stop, step, slicelen, otherlen, i;
4517+
size_t cur;
45164518

45174519
if (PySlice_Unpack(item, &start, &stop, &step) < 0) {
45184520
return -1;

Modules/_elementtree.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1771,7 +1771,8 @@ element_subscr(PyObject* self_, PyObject* item)
17711771
return element_getitem(self_, i);
17721772
}
17731773
else if (PySlice_Check(item)) {
1774-
Py_ssize_t start, stop, step, slicelen, cur, i;
1774+
Py_ssize_t start, stop, step, slicelen, i;
1775+
size_t cur;
17751776
PyObject* list;
17761777

17771778
if (!self->extra)
@@ -1823,7 +1824,8 @@ element_ass_subscr(PyObject* self_, PyObject* item, PyObject* value)
18231824
return element_setitem(self_, i, value);
18241825
}
18251826
else if (PySlice_Check(item)) {
1826-
Py_ssize_t start, stop, step, slicelen, newlen, cur, i;
1827+
Py_ssize_t start, stop, step, slicelen, newlen, i;
1828+
size_t cur;
18271829

18281830
PyObject* recycle = NULL;
18291831
PyObject* seq;

Modules/arraymodule.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2343,7 +2343,8 @@ array_subscr(arrayobject* self, PyObject* item)
23432343
return array_item(self, i);
23442344
}
23452345
else if (PySlice_Check(item)) {
2346-
Py_ssize_t start, stop, step, slicelength, cur, i;
2346+
Py_ssize_t start, stop, step, slicelength, i;
2347+
size_t cur;
23472348
PyObject* result;
23482349
arrayobject* ar;
23492350
int itemsize = self->ob_descr->itemsize;
@@ -2527,7 +2528,8 @@ array_ass_subscr(arrayobject* self, PyObject* item, PyObject* value)
25272528
return 0;
25282529
}
25292530
else {
2530-
Py_ssize_t cur, i;
2531+
size_t cur;
2532+
Py_ssize_t i;
25312533

25322534
if (needed != slicelength) {
25332535
PyErr_Format(PyExc_ValueError,

0 commit comments

Comments
 (0)