changeset: 94481:b9d4c013b09a parent: 94479:4cb316fe6bf2 parent: 94480:e62d54128bd3 user: Serhiy Storchaka date: Tue Feb 03 09:30:51 2015 +0200 files: Doc/library/io.rst Lib/_pyio.py Lib/test/test_memoryio.py Misc/NEWS Modules/_io/bytesio.c description: Issue #23099: Closing io.BytesIO with exported buffer is rejected now to prevent corrupting exported buffer. diff -r 4cb316fe6bf2 -r b9d4c013b09a Doc/library/io.rst --- a/Doc/library/io.rst Tue Feb 03 01:50:31 2015 +0200 +++ b/Doc/library/io.rst Tue Feb 03 09:30:51 2015 +0200 @@ -578,7 +578,8 @@ .. 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 @@ .. note:: As long as the view exists, the :class:`BytesIO` object cannot be - resized. + resized or closed. .. versionadded:: 3.2 @@ -607,6 +608,7 @@ 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 @@ .. 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 @@ .. 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 -r 4cb316fe6bf2 -r b9d4c013b09a Lib/_pyio.py --- a/Lib/_pyio.py Tue Feb 03 01:50:31 2015 +0200 +++ b/Lib/_pyio.py Tue Feb 03 09:30:51 2015 +0200 @@ -852,8 +852,14 @@ 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 -r 4cb316fe6bf2 -r b9d4c013b09a Lib/test/test_memoryio.py --- a/Lib/test/test_memoryio.py Tue Feb 03 01:50:31 2015 +0200 +++ b/Lib/test/test_memoryio.py Tue Feb 03 09:30:51 2015 +0200 @@ -399,14 +399,19 @@ # 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 -r 4cb316fe6bf2 -r b9d4c013b09a Misc/NEWS --- a/Misc/NEWS Tue Feb 03 01:50:31 2015 +0200 +++ b/Misc/NEWS Tue Feb 03 09:30:51 2015 +0200 @@ -232,6 +232,9 @@ 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 -r 4cb316fe6bf2 -r b9d4c013b09a Modules/_io/bytesio.c --- a/Modules/_io/bytesio.c Tue Feb 03 01:50:31 2015 +0200 +++ b/Modules/_io/bytesio.c Tue Feb 03 09:30:51 2015 +0200 @@ -779,6 +779,7 @@ static PyObject * bytesio_close(bytesio *self) { + CHECK_EXPORTS(self); reset(self); Py_RETURN_NONE; }