summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Doc/library/io.rst13
-rw-r--r--Lib/_pyio.py6
-rw-r--r--Lib/test/test_memoryio.py7
-rw-r--r--Misc/NEWS3
-rw-r--r--Modules/_io/bytesio.c1
5 files changed, 23 insertions, 7 deletions
diff --git a/Doc/library/io.rst b/Doc/library/io.rst
index b0b1af3..634bf58 100644
--- a/Doc/library/io.rst
+++ b/Doc/library/io.rst
@@ -578,7 +578,8 @@ than raw I/O does.
.. class:: BytesIO([initial_bytes])
A stream implementation using an in-memory bytes buffer. It inherits
- :class:`BufferedIOBase`.
+ :class:`BufferedIOBase`. The buffer is discarded when the
+ :meth:`~IOBase.close` method is called.
The argument *initial_bytes* contains optional initial :class:`bytes` data.
@@ -599,7 +600,7 @@ than raw I/O does.
.. note::
As long as the view exists, the :class:`BytesIO` object cannot be
- resized.
+ resized or closed.
.. versionadded:: 3.2
@@ -607,6 +608,7 @@ than raw I/O does.
Return :class:`bytes` containing the entire contents of the buffer.
+
.. method:: read1()
In :class:`BytesIO`, this is the same as :meth:`read`.
@@ -880,7 +882,8 @@ Text I/O
.. class:: StringIO(initial_value='', newline='\\n')
- An in-memory stream for text I/O.
+ An in-memory stream for text I/O. The text buffer is discarded when the
+ :meth:`~IOBase.close` method is called.
The initial value of the buffer (an empty string by default) can be set by
providing *initial_value*. The *newline* argument works like that of
@@ -892,9 +895,7 @@ Text I/O
.. method:: getvalue()
- Return a ``str`` containing the entire contents of the buffer at any
- time before the :class:`StringIO` object's :meth:`close` method is
- called.
+ Return a ``str`` containing the entire contents of the buffer.
Example usage::
diff --git a/Lib/_pyio.py b/Lib/_pyio.py
index 3614644..98b87f7 100644
--- a/Lib/_pyio.py
+++ b/Lib/_pyio.py
@@ -852,8 +852,14 @@ class BytesIO(BufferedIOBase):
def getbuffer(self):
"""Return a readable and writable view of the buffer.
"""
+ if self.closed:
+ raise ValueError("getbuffer on closed file")
return memoryview(self._buffer)
+ def close(self):
+ self._buffer.clear()
+ super().close()
+
def read(self, size=None):
if self.closed:
raise ValueError("read from closed file")
diff --git a/Lib/test/test_memoryio.py b/Lib/test/test_memoryio.py
index ab67cf3..24d282a 100644
--- a/Lib/test/test_memoryio.py
+++ b/Lib/test/test_memoryio.py
@@ -399,14 +399,19 @@ class BytesIOMixin:
# raises a BufferError.
self.assertRaises(BufferError, memio.write, b'x' * 100)
self.assertRaises(BufferError, memio.truncate)
+ self.assertRaises(BufferError, memio.close)
+ self.assertFalse(memio.closed)
# Mutating the buffer updates the BytesIO
buf[3:6] = b"abc"
self.assertEqual(bytes(buf), b"123abc7890")
self.assertEqual(memio.getvalue(), b"123abc7890")
- # After the buffer gets released, we can resize the BytesIO again
+ # After the buffer gets released, we can resize and close the BytesIO
+ # again
del buf
support.gc_collect()
memio.truncate()
+ memio.close()
+ self.assertRaises(ValueError, memio.getbuffer)
class PyBytesIOTest(MemoryTestMixin, MemorySeekTestMixin,
diff --git a/Misc/NEWS b/Misc/NEWS
index 62e5794..7a3a5ae 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -232,6 +232,9 @@ Core and Builtins
Library
-------
+- Issue #23099: Closing io.BytesIO with exported buffer is rejected now to
+ prevent corrupting exported buffer.
+
- Issue #23326: Removed __ne__ implementations. Since fixing default __ne__
implementation in issue #21408 they are redundant.
diff --git a/Modules/_io/bytesio.c b/Modules/_io/bytesio.c
index 801ddcd..7bbcb6e 100644
--- a/Modules/_io/bytesio.c
+++ b/Modules/_io/bytesio.c
@@ -779,6 +779,7 @@ PyDoc_STRVAR(close_doc,
static PyObject *
bytesio_close(bytesio *self)
{
+ CHECK_EXPORTS(self);
reset(self);
Py_RETURN_NONE;
}