Skip to content

Commit eedc052

Browse files
committed
fix(io): reject readonly buffers before reading in _pyio
1 parent 2639fd6 commit eedc052

3 files changed

Lines changed: 20 additions & 0 deletions

File tree

‎Lib/_pyio.py‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -728,6 +728,8 @@ def _readinto(self, b, read1):
728728
if not isinstance(b, memoryview):
729729
b = memoryview(b)
730730
b = b.cast('B')
731+
if b.readonly:
732+
raise TypeError("readinto() argument must be read-write bytes-like object")
731733

732734
if read1:
733735
data = self.read1(len(b))

‎Lib/test/test_io/test_memoryio.py‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,21 @@ def test_readinto(self):
568568
memio.readinto(b)
569569
self.assertEqual(b, b"")
570570

571+
def test_readinto_readonly_buffer(self):
572+
data = b"abcdef"
573+
for method in ("readinto", "readinto1"):
574+
for buffer in (b"xxx", memoryview(b"xxx"),
575+
b"", memoryview(b"")):
576+
for position in (0, 4, 10):
577+
with self.subTest(method=method, buffer=buffer,
578+
position=position):
579+
with self.ioclass(data) as memio:
580+
memio.seek(position)
581+
with self.assertRaises(TypeError):
582+
getattr(memio, method)(buffer)
583+
self.assertEqual(memio.tell(), position)
584+
self.assertEqual(memio.read(), data[position:])
585+
571586
def test_relative_seek(self):
572587
buf = self.buftype("1234567890")
573588
memio = self.ioclass(buf)
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
The pure Python implementation of :meth:`io.BufferedIOBase.readinto` and
2+
:meth:`~io.BufferedIOBase.readinto1` now rejects read-only buffers before
3+
reading input, without changing the stream position.

0 commit comments

Comments
 (0)