Skip to content

Commit bb92fda

Browse files
[3.11] gh-111174: Fix crash in getbuffer() called repeatedly for empty BytesIO (GH-111210) (GH-111315)
(cherry picked from commit 9da98c0) Co-authored-by: Serhiy Storchaka <[email protected]>
1 parent d38843a commit bb92fda

File tree

3 files changed

+20
-3
lines changed

3 files changed

+20
-3
lines changed

Lib/test/test_memoryio.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -463,6 +463,20 @@ def test_getbuffer(self):
463463
memio.close()
464464
self.assertRaises(ValueError, memio.getbuffer)
465465

466+
def test_getbuffer_empty(self):
467+
memio = self.ioclass()
468+
buf = memio.getbuffer()
469+
self.assertEqual(bytes(buf), b"")
470+
# Trying to change the size of the BytesIO while a buffer is exported
471+
# raises a BufferError.
472+
self.assertRaises(BufferError, memio.write, b'x')
473+
buf2 = memio.getbuffer()
474+
self.assertRaises(BufferError, memio.write, b'x')
475+
buf.release()
476+
self.assertRaises(BufferError, memio.write, b'x')
477+
buf2.release()
478+
memio.write(b'x')
479+
466480
def test_read1(self):
467481
buf = self.buftype("1234567890")
468482
self.assertEqual(self.ioclass(buf).read1(), buf)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix crash in :meth:`io.BytesIO.getbuffer` called repeatedly for empty
2+
BytesIO.

Modules/_io/bytesio.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -124,12 +124,13 @@ unshare_buffer(bytesio *self, size_t size)
124124
static int
125125
resize_buffer(bytesio *self, size_t size)
126126
{
127+
assert(self->buf != NULL);
128+
assert(self->exports == 0);
129+
127130
/* Here, unsigned types are used to avoid dealing with signed integer
128131
overflow, which is undefined in C. */
129132
size_t alloc = PyBytes_GET_SIZE(self->buf);
130133

131-
assert(self->buf != NULL);
132-
133134
/* For simplicity, stay in the range of the signed type. Anyway, Python
134135
doesn't allow strings to be longer than this. */
135136
if (size > PY_SSIZE_T_MAX)
@@ -1083,7 +1084,7 @@ bytesiobuf_getbuffer(bytesiobuf *obj, Py_buffer *view, int flags)
10831084
"bytesiobuf_getbuffer: view==NULL argument is obsolete");
10841085
return -1;
10851086
}
1086-
if (SHARED_BUF(b)) {
1087+
if (b->exports == 0 && SHARED_BUF(b)) {
10871088
if (unshare_buffer(b, b->string_size) < 0)
10881089
return -1;
10891090
}

0 commit comments

Comments
 (0)