summaryrefslogtreecommitdiffstats
path: root/Lib/test
diff options
context:
space:
mode:
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>2022-06-18 14:40:39 (GMT)
committerGitHub <noreply@github.com>2022-06-18 14:40:39 (GMT)
commit2eff55cd46a55c1eefa8c57b6ab85655dd261fe7 (patch)
treec5ee825c6ec3689d05095917ed520a81d85cde73 /Lib/test
parent6c8eb9503c9ae3af87f534397e1dea69c64615d2 (diff)
downloadcpython-2eff55cd46a55c1eefa8c57b6ab85655dd261fe7.zip
cpython-2eff55cd46a55c1eefa8c57b6ab85655dd261fe7.tar.gz
cpython-2eff55cd46a55c1eefa8c57b6ab85655dd261fe7.tar.bz2
gh-92888: Fix memoryview bad `__index__` use after free (GH-92946)
Co-authored-by: chilaxan <35645806+chilaxan@users.noreply.github.com> Co-authored-by: Serhiy Storchaka <3659035+serhiy-storchaka@users.noreply.github.com> (cherry picked from commit 11190c4ad0d3722b8d263758ac802985131a5462) Co-authored-by: Ken Jin <kenjin@python.org>
Diffstat (limited to 'Lib/test')
-rw-r--r--Lib/test/test_memoryview.py101
1 files changed, 101 insertions, 0 deletions
diff --git a/Lib/test/test_memoryview.py b/Lib/test/test_memoryview.py
index d7e3f0c..9d1e1f3 100644
--- a/Lib/test/test_memoryview.py
+++ b/Lib/test/test_memoryview.py
@@ -545,6 +545,107 @@ class OtherTest(unittest.TestCase):
with self.assertRaises(TypeError):
pickle.dumps(m, proto)
+ def test_use_released_memory(self):
+ # gh-92888: Previously it was possible to use a memoryview even after
+ # backing buffer is freed in certain cases. This tests that those
+ # cases raise an exception.
+ size = 128
+ def release():
+ m.release()
+ nonlocal ba
+ ba = bytearray(size)
+ class MyIndex:
+ def __index__(self):
+ release()
+ return 4
+ class MyFloat:
+ def __float__(self):
+ release()
+ return 4.25
+ class MyBool:
+ def __bool__(self):
+ release()
+ return True
+
+ ba = None
+ m = memoryview(bytearray(b'\xff'*size))
+ with self.assertRaises(ValueError):
+ m[MyIndex()]
+
+ ba = None
+ m = memoryview(bytearray(b'\xff'*size))
+ self.assertEqual(list(m[:MyIndex()]), [255] * 4)
+
+ ba = None
+ m = memoryview(bytearray(b'\xff'*size))
+ self.assertEqual(list(m[MyIndex():8]), [255] * 4)
+
+ ba = None
+ m = memoryview(bytearray(b'\xff'*size)).cast('B', (64, 2))
+ with self.assertRaisesRegex(ValueError, "operation forbidden"):
+ m[MyIndex(), 0]
+
+ ba = None
+ m = memoryview(bytearray(b'\xff'*size)).cast('B', (2, 64))
+ with self.assertRaisesRegex(ValueError, "operation forbidden"):
+ m[0, MyIndex()]
+
+ ba = None
+ m = memoryview(bytearray(b'\xff'*size))
+ with self.assertRaisesRegex(ValueError, "operation forbidden"):
+ m[MyIndex()] = 42
+ self.assertEqual(ba[:8], b'\0'*8)
+
+ ba = None
+ m = memoryview(bytearray(b'\xff'*size))
+ with self.assertRaisesRegex(ValueError, "operation forbidden"):
+ m[:MyIndex()] = b'spam'
+ self.assertEqual(ba[:8], b'\0'*8)
+
+ ba = None
+ m = memoryview(bytearray(b'\xff'*size))
+ with self.assertRaisesRegex(ValueError, "operation forbidden"):
+ m[MyIndex():8] = b'spam'
+ self.assertEqual(ba[:8], b'\0'*8)
+
+ ba = None
+ m = memoryview(bytearray(b'\xff'*size)).cast('B', (64, 2))
+ with self.assertRaisesRegex(ValueError, "operation forbidden"):
+ m[MyIndex(), 0] = 42
+ self.assertEqual(ba[8:16], b'\0'*8)
+ ba = None
+ m = memoryview(bytearray(b'\xff'*size)).cast('B', (2, 64))
+ with self.assertRaisesRegex(ValueError, "operation forbidden"):
+ m[0, MyIndex()] = 42
+ self.assertEqual(ba[:8], b'\0'*8)
+
+ ba = None
+ m = memoryview(bytearray(b'\xff'*size))
+ with self.assertRaisesRegex(ValueError, "operation forbidden"):
+ m[0] = MyIndex()
+ self.assertEqual(ba[:8], b'\0'*8)
+
+ for fmt in 'bhilqnBHILQN':
+ with self.subTest(fmt=fmt):
+ ba = None
+ m = memoryview(bytearray(b'\xff'*size)).cast(fmt)
+ with self.assertRaisesRegex(ValueError, "operation forbidden"):
+ m[0] = MyIndex()
+ self.assertEqual(ba[:8], b'\0'*8)
+
+ for fmt in 'fd':
+ with self.subTest(fmt=fmt):
+ ba = None
+ m = memoryview(bytearray(b'\xff'*size)).cast(fmt)
+ with self.assertRaisesRegex(ValueError, "operation forbidden"):
+ m[0] = MyFloat()
+ self.assertEqual(ba[:8], b'\0'*8)
+
+ ba = None
+ m = memoryview(bytearray(b'\xff'*size)).cast('?')
+ with self.assertRaisesRegex(ValueError, "operation forbidden"):
+ m[0] = MyBool()
+ self.assertEqual(ba[:8], b'\0'*8)
if __name__ == "__main__":
unittest.main()