Skip to content

Commit 2afb597

Browse files
committed
[3.13] gh-157048: check for buffer errors before mutating in BytesIO.__init__ (GH-157049)
(cherry picked from commit d125f00) Co-authored-by: Nathan Goldbaum <nathan.goldbaum@gmail.com>
1 parent fa7835f commit 2afb597

3 files changed

Lines changed: 19 additions & 4 deletions

File tree

Lib/test/test_memoryio.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -920,6 +920,18 @@ def test_cow_mutable(self):
920920
memio = self.ioclass(ba)
921921
self.assertEqual(sys.getrefcount(ba), old_rc)
922922

923+
def test_write_with_export(self):
924+
memio = self.ioclass(b"abcd")
925+
memio.seek(2)
926+
with memio.getbuffer() as view:
927+
self.assertRaises(BufferError, memio.__init__, b"replacement")
928+
self.assertEqual(memio.tell(), 2)
929+
self.assertEqual(memio.getvalue(), b"abcd")
930+
self.assertEqual(bytes(view), b"abcd")
931+
memio.write(b"X")
932+
self.assertEqual(memio.getvalue(), b"abXd")
933+
934+
923935
class CStringIOTest(PyStringIOTest):
924936
ioclass = io.StringIO
925937
UnsupportedOperation = io.UnsupportedOperation
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Preserve the position and contents of :class:`io.BytesIO` when
2+
:meth:`!BytesIO.__init__` fails because a buffer is exported.

Modules/_io/bytesio.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -943,15 +943,16 @@ static int
943943
_io_BytesIO___init___impl(bytesio *self, PyObject *initvalue)
944944
/*[clinic end generated code: output=65c0c51e24c5b621 input=aac7f31b67bf0fb6]*/
945945
{
946-
/* In case, __init__ is called multiple times. */
947-
self->string_size = 0;
948-
self->pos = 0;
949-
950946
if (self->exports > 0) {
951947
PyErr_SetString(PyExc_BufferError,
952948
"Existing exports of data: object cannot be re-sized");
953949
return -1;
954950
}
951+
952+
/* In case, __init__ is called multiple times. */
953+
self->string_size = 0;
954+
self->pos = 0;
955+
955956
if (initvalue && initvalue != Py_None) {
956957
if (PyBytes_CheckExact(initvalue)) {
957958
Py_XSETREF(self->buf, Py_NewRef(initvalue));

0 commit comments

Comments
 (0)