Skip to content

Commit 0ad0f28

Browse files
committed
Refactor tests
1 parent e865d0d commit 0ad0f28

File tree

1 file changed

+54
-56
lines changed

1 file changed

+54
-56
lines changed

Lib/test/test_array.py

Lines changed: 54 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from test.support import import_helper
99
from test.support import os_helper
1010
from test.support import _2G
11+
from test.support import subTests
1112
import weakref
1213
import pickle
1314
import operator
@@ -1680,63 +1681,60 @@ def test_gh_128961(self):
16801681
it.__setstate__(0)
16811682
self.assertRaises(StopIteration, next, it)
16821683

1683-
def test_array_validity_after_call_user_method(self):
1684+
@subTests(
1685+
("dtype", "items"),
1686+
[
1687+
("b", [0] * 64),
1688+
("B", [1, 2, 3]),
1689+
("h", [1, 2, 3]),
1690+
("H", [1, 2, 3]),
1691+
("i", [1, 2, 3]),
1692+
("l", [1, 2, 3]),
1693+
("q", [1, 2, 3]),
1694+
("I", [1, 2, 3]),
1695+
("L", [1, 2, 3]),
1696+
("Q", [1, 2, 3]),
1697+
],
1698+
)
1699+
def test_setitem_use_after_clear_with_int_data(self, dtype, items):
16841700
# gh-142555: Test for null pointer dereference in array.__setitem__
1685-
# via re-entrant __index__ or __float__.
1686-
1687-
def test_clear_array(victim):
1688-
class EvilIndex:
1689-
def __index__(self):
1690-
# Re-entrant mutation: clear the array while __setitem__
1691-
# still holds a pointer to the pre-clear buffer.
1692-
victim.clear()
1693-
return 0
1694-
1695-
with self.assertRaises(IndexError):
1696-
victim[1] = EvilIndex()
1697-
1698-
self.assertEqual(len(victim), 0)
1699-
1700-
def test_shrink_array(victim):
1701-
class ShrinkIndex:
1702-
def __index__(self):
1703-
# Re-entrant mutation: change the array size while
1704-
# __setitem__ still keep the original size.
1705-
victim.pop()
1706-
victim.pop()
1707-
return 0
1708-
1709-
with self.assertRaises(IndexError):
1710-
victim[1] = ShrinkIndex()
1711-
1712-
test_clear_array(array.array('b', [0] * 64))
1713-
test_shrink_array(array.array('b', [1, 2, 3]))
1714-
test_clear_array(array.array('B', [1, 2, 3]))
1715-
test_clear_array(array.array('h', [1, 2, 3]))
1716-
test_clear_array(array.array('H', [1, 2, 3]))
1717-
test_clear_array(array.array('i', [1, 2, 3]))
1718-
test_clear_array(array.array('l', [1, 2, 3]))
1719-
test_clear_array(array.array('q', [1, 2, 3]))
1720-
test_clear_array(array.array('I', [1, 2, 3]))
1721-
test_clear_array(array.array('L', [1, 2, 3]))
1722-
test_clear_array(array.array('Q', [1, 2, 3]))
1723-
1724-
def test_clear_array_float(victim):
1725-
"""Test array clearing scenario using __float__ method"""
1726-
class EvilFloat:
1727-
def __float__(self):
1728-
# Re-entrant mutation: clear the array while __setitem__
1729-
# still holds a pointer to the pre-clear buffer.
1730-
victim.clear()
1731-
return 0.0
1732-
1733-
with self.assertRaises(IndexError):
1734-
victim[1] = EvilFloat()
1735-
1736-
self.assertEqual(len(victim), 0)
1737-
1738-
test_clear_array_float(array.array('f', [1.0, 2.0, 3.0]))
1739-
test_clear_array_float(array.array('d', [1.0, 2.0, 3.0]))
1701+
# via re-entrant __index__ that clears the array.
1702+
victim = array.array(dtype, items)
1703+
1704+
class Index:
1705+
def __index__(self):
1706+
victim.clear()
1707+
return 0
1708+
1709+
self.assertRaises(IndexError, victim.__setitem__, 1, Index())
1710+
self.assertEqual(len(victim), 0)
1711+
1712+
def test_setitem_use_after_shrink_with_int_data(self):
1713+
# gh-142555: Test for null pointer dereference in array.__setitem__
1714+
# via re-entrant __index__ that shrinks the array.
1715+
victim = array.array('b', [1, 2, 3])
1716+
1717+
class Index:
1718+
def __index__(self):
1719+
victim.pop()
1720+
victim.pop()
1721+
return 0
1722+
1723+
self.assertRaises(IndexError, victim.__setitem__, 1, Index())
1724+
1725+
@subTests("dtype", ["f", "d"])
1726+
def test_setitem_use_after_clear_with_float_data(self, dtype):
1727+
# gh-142555: Test for null pointer dereference in array.__setitem__
1728+
# via re-entrant __float__ that clears the array.
1729+
victim = array.array(dtype, [1.0, 2.0, 3.0])
1730+
1731+
class Float:
1732+
def __float__(self):
1733+
victim.clear()
1734+
return 0.0
1735+
1736+
self.assertRaises(IndexError, victim.__setitem__, 1, Float())
1737+
self.assertEqual(len(victim), 0)
17401738

17411739

17421740
if __name__ == "__main__":

0 commit comments

Comments
 (0)