Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit aa3ecb8

Browse files
sthserhiy-storchaka
authored andcommitted
bpo-36285: Fix integer overflow in the array module. (GH-12317)
1 parent c1e2c28 commit aa3ecb8

3 files changed

Lines changed: 146 additions & 4 deletions

File tree

Lib/test/test_array.py

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import unittest
66
from test import support
7+
from test.support import _2G
78
import weakref
89
import pickle
910
import operator
@@ -1396,5 +1397,145 @@ def test_alloc_overflow(self):
13961397
self.fail("Array of size > maxsize created - MemoryError expected")
13971398

13981399

1400+
class LargeArrayTest(unittest.TestCase):
1401+
typecode = 'b'
1402+
1403+
def example(self, size):
1404+
# We assess a base memuse of <=2.125 for constructing this array
1405+
base = array.array(self.typecode, [0, 1, 2, 3, 4, 5, 6, 7]) * (size // 8)
1406+
base += array.array(self.typecode, [99]*(size % 8) + [8, 9, 10, 11])
1407+
return base
1408+
1409+
@support.bigmemtest(_2G, memuse=2.125)
1410+
def test_example_data(self, size):
1411+
example = self.example(size)
1412+
self.assertEqual(len(example), size+4)
1413+
1414+
@support.bigmemtest(_2G, memuse=2.125)
1415+
def test_access(self, size):
1416+
example = self.example(size)
1417+
self.assertEqual(example[0], 0)
1418+
self.assertEqual(example[-(size+4)], 0)
1419+
self.assertEqual(example[size], 8)
1420+
self.assertEqual(example[-4], 8)
1421+
self.assertEqual(example[size+3], 11)
1422+
self.assertEqual(example[-1], 11)
1423+
1424+
@support.bigmemtest(_2G, memuse=2.125+1)
1425+
def test_slice(self, size):
1426+
example = self.example(size)
1427+
self.assertEqual(list(example[:4]), [0, 1, 2, 3])
1428+
self.assertEqual(list(example[-4:]), [8, 9, 10, 11])
1429+
part = example[1:-1]
1430+
self.assertEqual(len(part), size+2)
1431+
self.assertEqual(part[0], 1)
1432+
self.assertEqual(part[-1], 10)
1433+
del part
1434+
part = example[::2]
1435+
self.assertEqual(len(part), (size+5)//2)
1436+
self.assertEqual(list(part[:4]), [0, 2, 4, 6])
1437+
if size % 2:
1438+
self.assertEqual(list(part[-2:]), [9, 11])
1439+
else:
1440+
self.assertEqual(list(part[-2:]), [8, 10])
1441+
1442+
@support.bigmemtest(_2G, memuse=2.125)
1443+
def test_count(self, size):
1444+
example = self.example(size)
1445+
self.assertEqual(example.count(0), size//8)
1446+
self.assertEqual(example.count(11), 1)
1447+
1448+
@support.bigmemtest(_2G, memuse=2.125)
1449+
def test_append(self, size):
1450+
example = self.example(size)
1451+
example.append(12)
1452+
self.assertEqual(example[-1], 12)
1453+
1454+
@support.bigmemtest(_2G, memuse=2.125)
1455+
def test_extend(self, size):
1456+
example = self.example(size)
1457+
example.extend(iter([12, 13, 14, 15]))
1458+
self.assertEqual(len(example), size+8)
1459+
self.assertEqual(list(example[-8:]), [8, 9, 10, 11, 12, 13, 14, 15])
1460+
1461+
@support.bigmemtest(_2G, memuse=2.125)
1462+
def test_frombytes(self, size):
1463+
example = self.example(size)
1464+
example.frombytes(b'abcd')
1465+
self.assertEqual(len(example), size+8)
1466+
self.assertEqual(list(example[-8:]), [8, 9, 10, 11] + list(b'abcd'))
1467+
1468+
@support.bigmemtest(_2G, memuse=2.125)
1469+
def test_fromlist(self, size):
1470+
example = self.example(size)
1471+
example.fromlist([12, 13, 14, 15])
1472+
self.assertEqual(len(example), size+8)
1473+
self.assertEqual(list(example[-8:]), [8, 9, 10, 11, 12, 13, 14, 15])
1474+
1475+
@support.bigmemtest(_2G, memuse=2.125)
1476+
def test_index(self, size):
1477+
example = self.example(size)
1478+
self.assertEqual(example.index(0), 0)
1479+
self.assertEqual(example.index(1), 1)
1480+
self.assertEqual(example.index(7), 7)
1481+
self.assertEqual(example.index(11), size+3)
1482+
1483+
@support.bigmemtest(_2G, memuse=2.125)
1484+
def test_insert(self, size):
1485+
example = self.example(size)
1486+
example.insert(0, 12)
1487+
example.insert(10, 13)
1488+
example.insert(size+1, 14)
1489+
self.assertEqual(len(example), size+7)
1490+
self.assertEqual(example[0], 12)
1491+
self.assertEqual(example[10], 13)
1492+
self.assertEqual(example[size+1], 14)
1493+
1494+
@support.bigmemtest(_2G, memuse=2.125)
1495+
def test_pop(self, size):
1496+
example = self.example(size)
1497+
self.assertEqual(example.pop(0), 0)
1498+
self.assertEqual(example[0], 1)
1499+
self.assertEqual(example.pop(size+1), 10)
1500+
self.assertEqual(example[size+1], 11)
1501+
self.assertEqual(example.pop(1), 2)
1502+
self.assertEqual(example[1], 3)
1503+
self.assertEqual(len(example), size+1)
1504+
self.assertEqual(example.pop(), 11)
1505+
self.assertEqual(len(example), size)
1506+
1507+
@support.bigmemtest(_2G, memuse=2.125)
1508+
def test_remove(self, size):
1509+
example = self.example(size)
1510+
example.remove(0)
1511+
self.assertEqual(len(example), size+3)
1512+
self.assertEqual(example[0], 1)
1513+
example.remove(10)
1514+
self.assertEqual(len(example), size+2)
1515+
self.assertEqual(example[size], 9)
1516+
self.assertEqual(example[size+1], 11)
1517+
1518+
@support.bigmemtest(_2G, memuse=2.125)
1519+
def test_reverse(self, size):
1520+
example = self.example(size)
1521+
example.reverse()
1522+
self.assertEqual(len(example), size+4)
1523+
self.assertEqual(example[0], 11)
1524+
self.assertEqual(example[3], 8)
1525+
self.assertEqual(example[-1], 0)
1526+
example.reverse()
1527+
self.assertEqual(len(example), size+4)
1528+
self.assertEqual(list(example[:4]), [0, 1, 2, 3])
1529+
self.assertEqual(list(example[-4:]), [8, 9, 10, 11])
1530+
1531+
# list takes about 9 bytes per element
1532+
@support.bigmemtest(_2G, memuse=2.125+9)
1533+
def test_tolist(self, size):
1534+
example = self.example(size)
1535+
ls = example.tolist()
1536+
self.assertEqual(len(ls), len(example))
1537+
self.assertEqual(ls[:8], list(example[:8]))
1538+
self.assertEqual(ls[-8:], list(example[-8:]))
1539+
13991540
if __name__ == "__main__":
14001541
unittest.main()
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix integer overflows in the array module. Patch by Stephan Hohe.

Modules/arraymodule.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1174,7 +1174,7 @@ static PyObject *
11741174
array_array_remove(arrayobject *self, PyObject *v)
11751175
/*[clinic end generated code: output=bef06be9fdf9dceb input=0b1e5aed25590027]*/
11761176
{
1177-
int i;
1177+
Py_ssize_t i;
11781178

11791179
for (i = 0; i < Py_SIZE(self); i++) {
11801180
PyObject *selfi;
@@ -2029,7 +2029,7 @@ array__array_reconstructor_impl(PyObject *module, PyTypeObject *arraytype,
20292029
switch (mformat_code) {
20302030
case IEEE_754_FLOAT_LE:
20312031
case IEEE_754_FLOAT_BE: {
2032-
int i;
2032+
Py_ssize_t i;
20332033
int le = (mformat_code == IEEE_754_FLOAT_LE) ? 1 : 0;
20342034
Py_ssize_t itemcount = Py_SIZE(items) / 4;
20352035
const unsigned char *memstr =
@@ -2051,7 +2051,7 @@ array__array_reconstructor_impl(PyObject *module, PyTypeObject *arraytype,
20512051
}
20522052
case IEEE_754_DOUBLE_LE:
20532053
case IEEE_754_DOUBLE_BE: {
2054-
int i;
2054+
Py_ssize_t i;
20552055
int le = (mformat_code == IEEE_754_DOUBLE_LE) ? 1 : 0;
20562056
Py_ssize_t itemcount = Py_SIZE(items) / 8;
20572057
const unsigned char *memstr =
@@ -2106,7 +2106,7 @@ array__array_reconstructor_impl(PyObject *module, PyTypeObject *arraytype,
21062106
case UNSIGNED_INT64_BE:
21072107
case SIGNED_INT64_LE:
21082108
case SIGNED_INT64_BE: {
2109-
int i;
2109+
Py_ssize_t i;
21102110
const struct mformatdescr mf_descr =
21112111
mformat_descriptors[mformat_code];
21122112
Py_ssize_t itemcount = Py_SIZE(items) / mf_descr.size;

0 commit comments

Comments
 (0)