Skip to content

Commit a8e1f47

Browse files
gh-111495: Test C API functions with extreme sizes and indices (GH-111631)
1 parent f48e669 commit a8e1f47

File tree

4 files changed

+134
-40
lines changed

4 files changed

+134
-40
lines changed

Lib/test/test_capi/test_abstract.py

+35-19
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import unittest
22
from collections import OrderedDict
3-
import _testcapi
3+
from test.support import import_helper
44

5+
_testcapi = import_helper.import_module('_testcapi')
6+
from _testcapi import PY_SSIZE_T_MIN, PY_SSIZE_T_MAX
57

68
NULL = None
79

@@ -574,6 +576,8 @@ def test_sequence_getitem(self):
574576
self.assertEqual(getitem(lst, 1), 'b')
575577
self.assertEqual(getitem(lst, -1), 'c')
576578
self.assertRaises(IndexError, getitem, lst, 3)
579+
self.assertRaises(IndexError, getitem, lst, PY_SSIZE_T_MAX)
580+
self.assertRaises(IndexError, getitem, lst, PY_SSIZE_T_MIN)
577581

578582
self.assertRaises(TypeError, getitem, 42, 1)
579583
self.assertRaises(TypeError, getitem, {}, 1)
@@ -598,6 +602,9 @@ def test_sequence_repeat(self):
598602
self.assertEqual(repeat(('a', 'b'), 2), ('a', 'b', 'a', 'b'))
599603
self.assertEqual(repeat(['a', 'b'], 0), [])
600604
self.assertEqual(repeat(['a', 'b'], -1), [])
605+
self.assertEqual(repeat(['a', 'b'], PY_SSIZE_T_MIN), [])
606+
self.assertEqual(repeat([], PY_SSIZE_T_MAX), [])
607+
self.assertRaises(MemoryError, repeat, ['a', 'b'], PY_SSIZE_T_MAX)
601608

602609
self.assertRaises(TypeError, repeat, set(), 2)
603610
self.assertRaises(TypeError, repeat, 42, 2)
@@ -631,6 +638,9 @@ def test_sequence_inplacerepeat(self):
631638
self.assertEqual(inplacerepeat(('a', 'b'), 2), ('a', 'b', 'a', 'b'))
632639
self.assertEqual(inplacerepeat(['a', 'b'], 0), [])
633640
self.assertEqual(inplacerepeat(['a', 'b'], -1), [])
641+
self.assertEqual(inplacerepeat(['a', 'b'], PY_SSIZE_T_MIN), [])
642+
self.assertEqual(inplacerepeat([], PY_SSIZE_T_MAX), [])
643+
self.assertRaises(MemoryError, inplacerepeat, ['a', 'b'], PY_SSIZE_T_MAX)
634644

635645
self.assertRaises(TypeError, inplacerepeat, set(), 2)
636646
self.assertRaises(TypeError, inplacerepeat, 42, 2)
@@ -647,6 +657,8 @@ def test_sequence_setitem(self):
647657
setitem(lst, 0, NULL)
648658
self.assertEqual(lst, ['x', 'y'])
649659
self.assertRaises(IndexError, setitem, lst, 3, 'x')
660+
self.assertRaises(IndexError, setitem, lst, PY_SSIZE_T_MAX, 'x')
661+
self.assertRaises(IndexError, setitem, lst, PY_SSIZE_T_MIN, 'x')
650662

651663
self.assertRaises(TypeError, setitem, 42, 1, 'x')
652664
self.assertRaises(TypeError, setitem, {}, 1, 'x')
@@ -660,6 +672,8 @@ def test_sequence_delitem(self):
660672
delitem(lst, -1)
661673
self.assertEqual(lst, ['a'])
662674
self.assertRaises(IndexError, delitem, lst, 3)
675+
self.assertRaises(IndexError, delitem, lst, PY_SSIZE_T_MAX)
676+
self.assertRaises(IndexError, delitem, lst, PY_SSIZE_T_MIN)
663677

664678
self.assertRaises(TypeError, delitem, 42, 1)
665679
self.assertRaises(TypeError, delitem, {}, 1)
@@ -669,13 +683,19 @@ def test_sequence_setslice(self):
669683
setslice = _testcapi.sequence_setslice
670684

671685
# Correct case:
672-
data = [1, 2, 3, 4, 5]
673-
data_copy = data.copy()
674-
675-
setslice(data, 1, 3, [8, 9])
676-
data_copy[1:3] = [8, 9]
677-
self.assertEqual(data, data_copy)
678-
self.assertEqual(data, [1, 8, 9, 4, 5])
686+
for start in [*range(-6, 7), PY_SSIZE_T_MIN, PY_SSIZE_T_MAX]:
687+
for stop in [*range(-6, 7), PY_SSIZE_T_MIN, PY_SSIZE_T_MAX]:
688+
data = [1, 2, 3, 4, 5]
689+
data_copy = [1, 2, 3, 4, 5]
690+
setslice(data, start, stop, [8, 9])
691+
data_copy[start:stop] = [8, 9]
692+
self.assertEqual(data, data_copy)
693+
694+
data = [1, 2, 3, 4, 5]
695+
data_copy = [1, 2, 3, 4, 5]
696+
setslice(data, start, stop, NULL)
697+
del data_copy[start:stop]
698+
self.assertEqual(data, data_copy)
679699

680700
# Custom class:
681701
class Custom:
@@ -701,21 +721,17 @@ def __setitem__(self, index, value):
701721
self.assertRaises(TypeError, setslice, object(), 1, 3, 'xy')
702722
self.assertRaises(SystemError, setslice, NULL, 1, 3, 'xy')
703723

704-
data_copy = data.copy()
705-
setslice(data_copy, 1, 3, NULL)
706-
self.assertEqual(data_copy, [1, 4, 5])
707-
708724
def test_sequence_delslice(self):
709725
delslice = _testcapi.sequence_delslice
710726

711727
# Correct case:
712-
data = [1, 2, 3, 4, 5]
713-
data_copy = data.copy()
714-
715-
delslice(data, 1, 3)
716-
del data_copy[1:3]
717-
self.assertEqual(data, data_copy)
718-
self.assertEqual(data, [1, 4, 5])
728+
for start in [*range(-6, 7), PY_SSIZE_T_MIN, PY_SSIZE_T_MAX]:
729+
for stop in [*range(-6, 7), PY_SSIZE_T_MIN, PY_SSIZE_T_MAX]:
730+
data = [1, 2, 3, 4, 5]
731+
data_copy = [1, 2, 3, 4, 5]
732+
delslice(data, start, stop)
733+
del data_copy[start:stop]
734+
self.assertEqual(data, data_copy)
719735

720736
# Custom class:
721737
class Custom:

Lib/test/test_capi/test_bytearray.py

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import unittest
2-
import sys
32
from test.support import import_helper
43

54
_testcapi = import_helper.import_module('_testcapi')
5+
from _testcapi import PY_SSIZE_T_MIN, PY_SSIZE_T_MAX
66

77
NULL = None
88

@@ -53,10 +53,12 @@ def test_fromstringandsize(self):
5353
self.assertEqual(fromstringandsize(b'', 0), bytearray())
5454
self.assertEqual(fromstringandsize(NULL, 0), bytearray())
5555
self.assertEqual(len(fromstringandsize(NULL, 3)), 3)
56-
self.assertRaises(MemoryError, fromstringandsize, NULL, sys.maxsize)
56+
self.assertRaises(MemoryError, fromstringandsize, NULL, PY_SSIZE_T_MAX)
5757

5858
self.assertRaises(SystemError, fromstringandsize, b'abc', -1)
59+
self.assertRaises(SystemError, fromstringandsize, b'abc', PY_SSIZE_T_MIN)
5960
self.assertRaises(SystemError, fromstringandsize, NULL, -1)
61+
self.assertRaises(SystemError, fromstringandsize, NULL, PY_SSIZE_T_MIN)
6062

6163
def test_fromobject(self):
6264
# Test PyByteArray_FromObject()
@@ -149,8 +151,8 @@ def test_resize(self):
149151
self.assertEqual(resize(ba, 3), 0)
150152
self.assertEqual(ba, bytearray(b'abc'))
151153

152-
self.assertRaises(MemoryError, resize, bytearray(), sys.maxsize)
153-
self.assertRaises(MemoryError, resize, bytearray(1000), sys.maxsize)
154+
self.assertRaises(MemoryError, resize, bytearray(), PY_SSIZE_T_MAX)
155+
self.assertRaises(MemoryError, resize, bytearray(1000), PY_SSIZE_T_MAX)
154156

155157
# CRASHES resize(bytearray(b'abc'), -1)
156158
# CRASHES resize(b'abc', 0)

Lib/test/test_capi/test_bytes.py

+8-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import unittest
2-
import sys
32
from test.support import import_helper
43

54
_testcapi = import_helper.import_module('_testcapi')
5+
from _testcapi import PY_SSIZE_T_MIN, PY_SSIZE_T_MAX
66

77
NULL = None
88

@@ -55,10 +55,13 @@ def test_fromstringandsize(self):
5555
self.assertEqual(fromstringandsize(b'', 0), b'')
5656
self.assertEqual(fromstringandsize(NULL, 0), b'')
5757
self.assertEqual(len(fromstringandsize(NULL, 3)), 3)
58-
self.assertRaises((MemoryError, OverflowError), fromstringandsize, NULL, sys.maxsize)
58+
self.assertRaises((MemoryError, OverflowError),
59+
fromstringandsize, NULL, PY_SSIZE_T_MAX)
5960

6061
self.assertRaises(SystemError, fromstringandsize, b'abc', -1)
62+
self.assertRaises(SystemError, fromstringandsize, b'abc', PY_SSIZE_T_MIN)
6163
self.assertRaises(SystemError, fromstringandsize, NULL, -1)
64+
self.assertRaises(SystemError, fromstringandsize, NULL, PY_SSIZE_T_MIN)
6265

6366
def test_fromstring(self):
6467
# Test PyBytes_FromString()
@@ -208,7 +211,10 @@ def test_decodeescape(self):
208211
self.assertEqual(decodeescape(br'x\xa\xy', 'ignore'), b'xy')
209212
self.assertRaises(ValueError, decodeescape, b'\\', 'spam')
210213
self.assertEqual(decodeescape(NULL), b'')
214+
self.assertRaises(OverflowError, decodeescape, b'abc', NULL, PY_SSIZE_T_MAX)
215+
self.assertRaises(OverflowError, decodeescape, NULL, NULL, PY_SSIZE_T_MAX)
211216

217+
# CRASHES decodeescape(b'abc', NULL, -1)
212218
# CRASHES decodeescape(NULL, NULL, 1)
213219

214220

0 commit comments

Comments
 (0)