https://github.com/python/cpython/commit/c6af0c4c0a94822728203147f79cf98052cc4248
commit: c6af0c4c0a94822728203147f79cf98052cc4248
branch: 3.14
author: Miss Islington (bot) <[email protected]>
committer: ngoldbaum <[email protected]>
date: 2026-09-07T10:03:53-06:00
summary:
[3.14] gh-157048: check for buffer errors before mutating in BytesIO.__init__
(GH-157049) (#157068)
files:
A Misc/NEWS.d/next/Library/2026-09-06-15-23-24.gh-issue-157048.UtFyiJ.rst
M Lib/test/test_memoryio.py
M Modules/_io/bytesio.c
diff --git a/Lib/test/test_memoryio.py b/Lib/test/test_memoryio.py
index 464fbf67a84b83d..8780796ce831ee1 100644
--- a/Lib/test/test_memoryio.py
+++ b/Lib/test/test_memoryio.py
@@ -923,6 +923,18 @@ def test_cow_mutable(self):
memio = self.ioclass(ba)
self.assertEqual(sys.getrefcount(ba), old_rc)
+ def test_write_with_export(self):
+ memio = self.ioclass(b"abcd")
+ memio.seek(2)
+ with memio.getbuffer() as view:
+ self.assertRaises(BufferError, memio.__init__, b"replacement")
+ self.assertEqual(memio.tell(), 2)
+ self.assertEqual(memio.getvalue(), b"abcd")
+ self.assertEqual(bytes(view), b"abcd")
+ memio.write(b"X")
+ self.assertEqual(memio.getvalue(), b"abXd")
+
+
class CStringIOTest(PyStringIOTest):
ioclass = io.StringIO
UnsupportedOperation = io.UnsupportedOperation
diff --git
a/Misc/NEWS.d/next/Library/2026-09-06-15-23-24.gh-issue-157048.UtFyiJ.rst
b/Misc/NEWS.d/next/Library/2026-09-06-15-23-24.gh-issue-157048.UtFyiJ.rst
new file mode 100644
index 000000000000000..1638968e475ca4a
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-09-06-15-23-24.gh-issue-157048.UtFyiJ.rst
@@ -0,0 +1,2 @@
+Preserve the position and contents of :class:`io.BytesIO` when
+:meth:`!BytesIO.__init__` fails because a buffer is exported.
diff --git a/Modules/_io/bytesio.c b/Modules/_io/bytesio.c
index 73241471f69d6c9..6ed88357220c944 100644
--- a/Modules/_io/bytesio.c
+++ b/Modules/_io/bytesio.c
@@ -1078,15 +1078,16 @@ static int
_io_BytesIO___init___impl(bytesio *self, PyObject *initvalue)
/*[clinic end generated code: output=65c0c51e24c5b621 input=3da5a74ee4c4f1ac]*/
{
- /* In case, __init__ is called multiple times. */
- self->string_size = 0;
- self->pos = 0;
-
if (FT_ATOMIC_LOAD_SSIZE_RELAXED(self->exports) > 0) {
PyErr_SetString(PyExc_BufferError,
"Existing exports of data: object cannot be re-sized");
return -1;
}
+
+ /* In case, __init__ is called multiple times. */
+ self->string_size = 0;
+ self->pos = 0;
+
if (initvalue && initvalue != Py_None) {
if (PyBytes_CheckExact(initvalue)) {
Py_XSETREF(self->buf, Py_NewRef(initvalue));
_______________________________________________
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]