Skip to content

Commit d125f00

Browse files
authored
gh-157048: check for buffer errors before mutating in BytesIO.__init__ (#157049)
1 parent 09117bc commit d125f00

3 files changed

Lines changed: 19 additions & 4 deletions

File tree

Lib/test/test_io/test_memoryio.py

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

1028+
def test_write_with_export(self):
1029+
memio = self.ioclass(b"abcd")
1030+
memio.seek(2)
1031+
with memio.getbuffer() as view:
1032+
self.assertRaises(BufferError, memio.__init__, b"replacement")
1033+
self.assertEqual(memio.tell(), 2)
1034+
self.assertEqual(memio.getvalue(), b"abcd")
1035+
self.assertEqual(bytes(view), b"abcd")
1036+
memio.write(b"X")
1037+
self.assertEqual(memio.getvalue(), b"abXd")
1038+
1039+
10281040
class CStringIOTest(PyStringIOTest):
10291041
ioclass = io.StringIO
10301042
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
@@ -1126,15 +1126,16 @@ static int
11261126
_io_BytesIO___init___impl(bytesio *self, PyObject *initvalue)
11271127
/*[clinic end generated code: output=65c0c51e24c5b621 input=3da5a74ee4c4f1ac]*/
11281128
{
1129-
/* In case, __init__ is called multiple times. */
1130-
self->string_size = 0;
1131-
self->pos = 0;
1132-
11331129
if (FT_ATOMIC_LOAD_SSIZE_RELAXED(self->exports) > 0) {
11341130
PyErr_SetString(PyExc_BufferError,
11351131
"Existing exports of data: object cannot be re-sized");
11361132
return -1;
11371133
}
1134+
1135+
/* In case, __init__ is called multiple times. */
1136+
self->string_size = 0;
1137+
self->pos = 0;
1138+
11381139
if (initvalue && initvalue != Py_None) {
11391140
if (PyBytes_CheckExact(initvalue)) {
11401141
Py_XSETREF(self->buf, Py_NewRef(initvalue));

0 commit comments

Comments
 (0)