Issue #23099: Closing io.BytesIO with exported buffer is rejected now to
prevent corrupting exported buffer.
This commit is contained in:
parent
b5e8e57555
commit
c057c3859c
|
@ -563,7 +563,8 @@ than raw I/O does.
|
||||||
.. class:: BytesIO([initial_bytes])
|
.. class:: BytesIO([initial_bytes])
|
||||||
|
|
||||||
A stream implementation using an in-memory bytes buffer. It inherits
|
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.
|
The argument *initial_bytes* contains optional initial :class:`bytes` data.
|
||||||
|
|
||||||
|
@ -584,7 +585,7 @@ than raw I/O does.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
As long as the view exists, the :class:`BytesIO` object cannot be
|
As long as the view exists, the :class:`BytesIO` object cannot be
|
||||||
resized.
|
resized or closed.
|
||||||
|
|
||||||
.. versionadded:: 3.2
|
.. versionadded:: 3.2
|
||||||
|
|
||||||
|
@ -592,6 +593,7 @@ than raw I/O does.
|
||||||
|
|
||||||
Return :class:`bytes` containing the entire contents of the buffer.
|
Return :class:`bytes` containing the entire contents of the buffer.
|
||||||
|
|
||||||
|
|
||||||
.. method:: read1()
|
.. method:: read1()
|
||||||
|
|
||||||
In :class:`BytesIO`, this is the same as :meth:`read`.
|
In :class:`BytesIO`, this is the same as :meth:`read`.
|
||||||
|
@ -858,7 +860,8 @@ Text I/O
|
||||||
|
|
||||||
.. class:: StringIO(initial_value='', newline='\\n')
|
.. 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
|
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
|
providing *initial_value*. The *newline* argument works like that of
|
||||||
|
@ -870,9 +873,7 @@ Text I/O
|
||||||
|
|
||||||
.. method:: getvalue()
|
.. method:: getvalue()
|
||||||
|
|
||||||
Return a ``str`` containing the entire contents of the buffer at any
|
Return a ``str`` containing the entire contents of the buffer.
|
||||||
time before the :class:`StringIO` object's :meth:`close` method is
|
|
||||||
called.
|
|
||||||
|
|
||||||
Example usage::
|
Example usage::
|
||||||
|
|
||||||
|
|
|
@ -833,8 +833,14 @@ class BytesIO(BufferedIOBase):
|
||||||
def getbuffer(self):
|
def getbuffer(self):
|
||||||
"""Return a readable and writable view of the buffer.
|
"""Return a readable and writable view of the buffer.
|
||||||
"""
|
"""
|
||||||
|
if self.closed:
|
||||||
|
raise ValueError("getbuffer on closed file")
|
||||||
return memoryview(self._buffer)
|
return memoryview(self._buffer)
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
self._buffer.clear()
|
||||||
|
super().close()
|
||||||
|
|
||||||
def read(self, size=None):
|
def read(self, size=None):
|
||||||
if self.closed:
|
if self.closed:
|
||||||
raise ValueError("read from closed file")
|
raise ValueError("read from closed file")
|
||||||
|
|
|
@ -398,14 +398,19 @@ class BytesIOMixin:
|
||||||
# raises a BufferError.
|
# raises a BufferError.
|
||||||
self.assertRaises(BufferError, memio.write, b'x' * 100)
|
self.assertRaises(BufferError, memio.write, b'x' * 100)
|
||||||
self.assertRaises(BufferError, memio.truncate)
|
self.assertRaises(BufferError, memio.truncate)
|
||||||
|
self.assertRaises(BufferError, memio.close)
|
||||||
|
self.assertFalse(memio.closed)
|
||||||
# Mutating the buffer updates the BytesIO
|
# Mutating the buffer updates the BytesIO
|
||||||
buf[3:6] = b"abc"
|
buf[3:6] = b"abc"
|
||||||
self.assertEqual(bytes(buf), b"123abc7890")
|
self.assertEqual(bytes(buf), b"123abc7890")
|
||||||
self.assertEqual(memio.getvalue(), 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
|
del buf
|
||||||
support.gc_collect()
|
support.gc_collect()
|
||||||
memio.truncate()
|
memio.truncate()
|
||||||
|
memio.close()
|
||||||
|
self.assertRaises(ValueError, memio.getbuffer)
|
||||||
|
|
||||||
|
|
||||||
class PyBytesIOTest(MemoryTestMixin, MemorySeekTestMixin,
|
class PyBytesIOTest(MemoryTestMixin, MemorySeekTestMixin,
|
||||||
|
|
|
@ -56,6 +56,9 @@ Core and Builtins
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Issue #23099: Closing io.BytesIO with exported buffer is rejected now to
|
||||||
|
prevent corrupting exported buffer.
|
||||||
|
|
||||||
- Issue #23363: Fix possible overflow in itertools.permutations.
|
- Issue #23363: Fix possible overflow in itertools.permutations.
|
||||||
|
|
||||||
- Issue #23364: Fix possible overflow in itertools.product.
|
- Issue #23364: Fix possible overflow in itertools.product.
|
||||||
|
|
|
@ -657,6 +657,7 @@ PyDoc_STRVAR(close_doc,
|
||||||
static PyObject *
|
static PyObject *
|
||||||
bytesio_close(bytesio *self)
|
bytesio_close(bytesio *self)
|
||||||
{
|
{
|
||||||
|
CHECK_EXPORTS(self);
|
||||||
if (self->buf != NULL) {
|
if (self->buf != NULL) {
|
||||||
PyMem_Free(self->buf);
|
PyMem_Free(self->buf);
|
||||||
self->buf = NULL;
|
self->buf = NULL;
|
||||||
|
|
Loading…
Reference in New Issue