https://github.com/python/cpython/commit/f0986f385ecac3e82bd387e3e6dc420e1d4e653f commit: f0986f385ecac3e82bd387e3e6dc420e1d4e653f branch: 3.15 author: Miss Islington (bot) <[email protected]> committer: JelleZijlstra <[email protected]> date: 2026-10-20T11:13:39-07:00 summary:
[3.15] gh-159739: Handle overlapping buffers in BytesIO.readinto (GH-159777) (#159902) (cherry picked from commit 17df836e6d4ba3ce0a28cfe98efedf7c7b4f0e49) Co-authored-by: Jelle Zijlstra <[email protected]> Co-authored-by: Jelle Zijlstra <[email protected]> files: A Misc/NEWS.d/next/Library/2026-10-19-20-38-17.gh-issue-159739.a81270.rst M Lib/test/test_io/test_memoryio.py M Modules/_io/bytesio.c diff --git a/Lib/test/test_io/test_memoryio.py b/Lib/test/test_io/test_memoryio.py index 7f2eddd7ae7839e..2ee3a1d1562c8b4 100644 --- a/Lib/test/test_io/test_memoryio.py +++ b/Lib/test/test_io/test_memoryio.py @@ -859,6 +859,12 @@ class CBytesIOTest(PyBytesIOTest): ioclass = io.BytesIO UnsupportedOperation = io.UnsupportedOperation + def test_readinto_overlapping_buffer(self): + with self.ioclass(b'abcd') as stream: + with stream.getbuffer()[1:] as target: + self.assertEqual(stream.readinto(target), 3) + self.assertEqual(stream.getvalue(), b'aabc') + def test_getstate(self): memio = self.ioclass() state = memio.__getstate__() diff --git a/Misc/NEWS.d/next/Library/2026-10-19-20-38-17.gh-issue-159739.a81270.rst b/Misc/NEWS.d/next/Library/2026-10-19-20-38-17.gh-issue-159739.a81270.rst new file mode 100644 index 000000000000000..413fc0d7f18f680 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-10-19-20-38-17.gh-issue-159739.a81270.rst @@ -0,0 +1 @@ +Fix :class:`io.BytesIO` reads into overlapping views of the same buffer. diff --git a/Modules/_io/bytesio.c b/Modules/_io/bytesio.c index 9ea197d29f30960..17ae3a82acad2fe 100644 --- a/Modules/_io/bytesio.c +++ b/Modules/_io/bytesio.c @@ -670,7 +670,7 @@ _io_BytesIO_readinto_impl(bytesio *self, Py_buffer *buffer) assert(self->pos + len <= PY_SSIZE_T_MAX); assert(len >= 0); - memcpy(buffer->buf, PyBytes_AS_STRING(self->buf) + self->pos, len); + memmove(buffer->buf, PyBytes_AS_STRING(self->buf) + self->pos, len); self->pos += len; return PyLong_FromSsize_t(len); _______________________________________________ Python-checkins mailing list -- [email protected] To unsubscribe send an email to [email protected] https://mail.python.org/mailman3//lists/python-checkins.python.org Member address: [email protected]
