While testing injection of memory allocation failures in the _bz2 extension module, I found a bug: PyBytesWriter_Discard() is called twice on a memory allocation failure.
Example:
import _testcapi import bz2 data = bz2.compress(b'x' * 1024) decompressor = bz2.BZ2Decompressor() try: _testcapi.set_nomemory(3,4) try: decompressor.decompress(data) except MemoryError: pass else: raise Exception finally: _testcapi.remove_mem_hooks() print("exit")
The error occurs in decompress_buf():
- OutputBuffer_Finish() => _BlocksOutputBuffer_Finish() => PyBytesWriter_FinishWithSize() => _PyBytes_Resize(): _PyBytes_Resize() fails with a memory allocation failure, then PyBytesWriter_FinishWithSize() calls PyBytesWriter_Discard()
- OutputBuffer_OnError() => _BlocksOutputBuffer_OnError(): call PyBytesWriter_Discard() again
Attached PR clears the writer in _BlocksOutputBuffer_Finish(), so _BlocksOutputBuffer_OnError() does nothing insted of calling PyBytesWriter_Discard() again.