diff -r 731b9653ef6b Lib/_pyio.py --- a/Lib/_pyio.py Mon Dec 22 22:10:10 2014 +0100 +++ b/Lib/_pyio.py Tue Dec 23 09:24:59 2014 +0200 @@ -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 -r 731b9653ef6b Lib/test/test_memoryio.py --- a/Lib/test/test_memoryio.py Mon Dec 22 22:10:10 2014 +0100 +++ b/Lib/test/test_memoryio.py Tue Dec 23 09:24:59 2014 +0200 @@ -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 -r 731b9653ef6b Misc/NEWS --- a/Misc/NEWS Mon Dec 22 22:10:10 2014 +0100 +++ b/Misc/NEWS Tue Dec 23 09:24:59 2014 +0200 @@ -196,6 +196,9 @@ Core and Builtins Library ------- +- Issue #23099: Closing io.BytesIO with exported buffer is rejected now to + prevent corrupting exported buffer. + - Issue #23093: In the io, module allow more operations to work on detached streams. diff -r 731b9653ef6b Modules/_io/bytesio.c --- a/Modules/_io/bytesio.c Mon Dec 22 22:10:10 2014 +0100 +++ b/Modules/_io/bytesio.c Tue Dec 23 09:24:59 2014 +0200 @@ -777,6 +777,7 @@ PyDoc_STRVAR(close_doc, static PyObject * bytesio_close(bytesio *self) { + CHECK_EXPORTS(self); reset(self); Py_RETURN_NONE; }