Issue #23099: Closing io.BytesIO with exported buffer is rejected now to

prevent corrupting exported buffer.
This commit is contained in:
Serhiy Storchaka 2015-02-03 09:30:51 +02:00
commit 32ca3dcb97
5 changed files with 23 additions and 7 deletions

View File

@ -578,7 +578,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.
@ -599,7 +600,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
@ -607,6 +608,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`.
@ -880,7 +882,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
@ -892,9 +895,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::

View File

@ -852,8 +852,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")

View File

@ -399,14 +399,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,

View File

@ -232,6 +232,9 @@ Core and Builtins
Library 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__ - Issue #23326: Removed __ne__ implementations. Since fixing default __ne__
implementation in issue #21408 they are redundant. implementation in issue #21408 they are redundant.

View File

@ -779,6 +779,7 @@ PyDoc_STRVAR(close_doc,
static PyObject * static PyObject *
bytesio_close(bytesio *self) bytesio_close(bytesio *self)
{ {
CHECK_EXPORTS(self);
reset(self); reset(self);
Py_RETURN_NONE; Py_RETURN_NONE;
} }