Skip to content

Commit 14514d9

Browse files
ZackerySpytzvadmium
authored andcommitted
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]>
1 parent 870b035 commit 14514d9

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
@@ -746,7 +746,7 @@ def test_extended_getslice(self):
746746
# Test extended slicing by comparing with list slicing
747747
# (Assumes list conversion works correctly, too)
748748
a = array.array(self.typecode, self.example)
749-
indices = (0, None, 1, 3, 19, 100, -1, -2, -31, -100)
749+
indices = (0, None, 1, 3, 19, 100, sys.maxsize, -1, -2, -31, -100)
750750
for start in indices:
751751
for stop in indices:
752752
# Everything except the initial 0 (invalid step)
@@ -844,7 +844,7 @@ def test_setslice(self):
844844
self.assertRaises(TypeError, a.__setitem__, slice(0, 1), b)
845845

846846
def test_extended_set_del_slice(self):
847-
indices = (0, None, 1, 3, 19, 100, -1, -2, -31, -100)
847+
indices = (0, None, 1, 3, 19, 100, sys.maxsize, -1, -2, -31, -100)
848848
for start in indices:
849849
for stop in indices:
850850
# 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
@@ -285,7 +285,7 @@ def test_extended_getslice(self):
285285
# Test extended slicing by comparing with list slicing.
286286
L = list(range(255))
287287
b = self.type2test(L)
288-
indices = (0, None, 1, 3, 19, 100, -1, -2, -31, -100)
288+
indices = (0, None, 1, 3, 19, 100, sys.maxsize, -1, -2, -31, -100)
289289
for start in indices:
290290
for stop in indices:
291291
# Skip step 0 (invalid)
@@ -1242,7 +1242,8 @@ def test_del_expand(self):
12421242
self.assertLessEqual(sys.getsizeof(b), size)
12431243

12441244
def test_extended_set_del_slice(self):
1245-
indices = (0, None, 1, 3, 19, 300, 1<<333, -1, -2, -31, -300)
1245+
indices = (0, None, 1, 3, 19, 300, 1<<333, sys.maxsize,
1246+
-1, -2, -31, -300)
12461247
for start in indices:
12471248
for stop in indices:
12481249
# Skip invalid step 0

Lib/test/test_mmap.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -439,7 +439,7 @@ def test_extended_getslice(self):
439439
m = mmap.mmap(-1, len(s))
440440
m[:] = s
441441
self.assertEqual(m[:], s)
442-
indices = (0, None, 1, 3, 19, 300, -1, -2, -31, -300)
442+
indices = (0, None, 1, 3, 19, 300, sys.maxsize, -1, -2, -31, -300)
443443
for start in indices:
444444
for stop in indices:
445445
# Skip step 0 (invalid)
@@ -451,7 +451,7 @@ def test_extended_set_del_slice(self):
451451
# Test extended slicing by comparing with list slicing.
452452
s = bytes(reversed(range(256)))
453453
m = mmap.mmap(-1, len(s))
454-
indices = (0, None, 1, 3, 19, 300, -1, -2, -31, -300)
454+
indices = (0, None, 1, 3, 19, 300, sys.maxsize, -1, -2, -31, -300)
455455
for start in indices:
456456
for stop in indices:
457457
# 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
@@ -4487,7 +4487,8 @@ Array_subscript(PyObject *myself, PyObject *item)
44874487
StgDictObject *stgdict, *itemdict;
44884488
PyObject *proto;
44894489
PyObject *np;
4490-
Py_ssize_t start, stop, step, slicelen, cur, i;
4490+
Py_ssize_t start, stop, step, slicelen, i;
4491+
size_t cur;
44914492

44924493
if (PySlice_Unpack(item, &start, &stop, &step) < 0) {
44934494
return NULL;
@@ -4627,7 +4628,8 @@ Array_ass_subscript(PyObject *myself, PyObject *item, PyObject *value)
46274628
return Array_ass_item(myself, i, value);
46284629
}
46294630
else if (PySlice_Check(item)) {
4630-
Py_ssize_t start, stop, step, slicelen, otherlen, i, cur;
4631+
Py_ssize_t start, stop, step, slicelen, otherlen, i;
4632+
size_t cur;
46314633

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

Modules/_elementtree.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1809,7 +1809,8 @@ element_subscr(PyObject* self_, PyObject* item)
18091809
return element_getitem(self_, i);
18101810
}
18111811
else if (PySlice_Check(item)) {
1812-
Py_ssize_t start, stop, step, slicelen, cur, i;
1812+
Py_ssize_t start, stop, step, slicelen, i;
1813+
size_t cur;
18131814
PyObject* list;
18141815

18151816
if (!self->extra)
@@ -1861,7 +1862,8 @@ element_ass_subscr(PyObject* self_, PyObject* item, PyObject* value)
18611862
return element_setitem(self_, i, value);
18621863
}
18631864
else if (PySlice_Check(item)) {
1864-
Py_ssize_t start, stop, step, slicelen, newlen, cur, i;
1865+
Py_ssize_t start, stop, step, slicelen, newlen, i;
1866+
size_t cur;
18651867

18661868
PyObject* recycle = NULL;
18671869
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)