summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Lib/test/test_memoryio.py14
-rw-r--r--Misc/NEWS.d/next/Library/2023-10-23-13-53-58.gh-issue-111174.Oohmzd.rst2
-rw-r--r--Modules/_io/bytesio.c7
3 files changed, 20 insertions, 3 deletions
diff --git a/Lib/test/test_memoryio.py b/Lib/test/test_memoryio.py
index cd2faba..7312992 100644
--- a/Lib/test/test_memoryio.py
+++ b/Lib/test/test_memoryio.py
@@ -463,6 +463,20 @@ class PyBytesIOTest(MemoryTestMixin, MemorySeekTestMixin, unittest.TestCase):
memio.close()
self.assertRaises(ValueError, memio.getbuffer)
+ def test_getbuffer_empty(self):
+ memio = self.ioclass()
+ buf = memio.getbuffer()
+ self.assertEqual(bytes(buf), b"")
+ # Trying to change the size of the BytesIO while a buffer is exported
+ # raises a BufferError.
+ self.assertRaises(BufferError, memio.write, b'x')
+ buf2 = memio.getbuffer()
+ self.assertRaises(BufferError, memio.write, b'x')
+ buf.release()
+ self.assertRaises(BufferError, memio.write, b'x')
+ buf2.release()
+ memio.write(b'x')
+
def test_read1(self):
buf = self.buftype("1234567890")
self.assertEqual(self.ioclass(buf).read1(), buf)
diff --git a/Misc/NEWS.d/next/Library/2023-10-23-13-53-58.gh-issue-111174.Oohmzd.rst b/Misc/NEWS.d/next/Library/2023-10-23-13-53-58.gh-issue-111174.Oohmzd.rst
new file mode 100644
index 0000000..95c3154
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-10-23-13-53-58.gh-issue-111174.Oohmzd.rst
@@ -0,0 +1,2 @@
+Fix crash in :meth:`io.BytesIO.getbuffer` called repeatedly for empty
+BytesIO.
diff --git a/Modules/_io/bytesio.c b/Modules/_io/bytesio.c
index 8077305..7636394 100644
--- a/Modules/_io/bytesio.c
+++ b/Modules/_io/bytesio.c
@@ -124,12 +124,13 @@ unshare_buffer(bytesio *self, size_t size)
static int
resize_buffer(bytesio *self, size_t size)
{
+ assert(self->buf != NULL);
+ assert(self->exports == 0);
+
/* Here, unsigned types are used to avoid dealing with signed integer
overflow, which is undefined in C. */
size_t alloc = PyBytes_GET_SIZE(self->buf);
- assert(self->buf != NULL);
-
/* For simplicity, stay in the range of the signed type. Anyway, Python
doesn't allow strings to be longer than this. */
if (size > PY_SSIZE_T_MAX)
@@ -1072,7 +1073,7 @@ bytesiobuf_getbuffer(bytesiobuf *obj, Py_buffer *view, int flags)
"bytesiobuf_getbuffer: view==NULL argument is obsolete");
return -1;
}
- if (SHARED_BUF(b)) {
+ if (b->exports == 0 && SHARED_BUF(b)) {
if (unshare_buffer(b, b->string_size) < 0)
return -1;
}