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]

Reply via email to