Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
fix: release buffers and free memory on error paths
Fix memory and buffer leaks on five error paths:

- block/compress: release source and dict Py_buffers on PyMem_Malloc failure
- block/decompress: release source and dict Py_buffers on PyMem_Malloc failure
- frame/compress: release source Py_buffer on block_checksum version error
- frame/compress_begin: free destination buffer on LZ4F_compressBegin failure
  (same pattern as the bug fixed in 43fe65d, not propagated to this site)
- frame/__decompress: free original destination buffer on PyMem_Realloc failure
  (realloc returns NULL without freeing the original pointer)

Found using cext-review-toolkit (https://github.com/devdanzin/cext-review-toolkit).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
  • Loading branch information
devdanzin and claude committed Apr 1, 2026
commit 5867f192dade717c4bdd1fe63d438dc2548c5b2f
4 changes: 4 additions & 0 deletions lz4/block/_block.c
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,8 @@ compress (PyObject * Py_UNUSED (self), PyObject * args, PyObject * kwargs)
dest = PyMem_Malloc (total_size * sizeof * dest);
if (dest == NULL)
{
PyBuffer_Release(&source);
PyBuffer_Release(&dict);
return PyErr_NoMemory();
}

Expand Down Expand Up @@ -349,6 +351,8 @@ decompress (PyObject * Py_UNUSED (self), PyObject * args, PyObject * kwargs)
dest = PyMem_Malloc (dest_size * sizeof * dest);
if (dest == NULL)
{
PyBuffer_Release(&source);
PyBuffer_Release(&dict);
return PyErr_NoMemory();
}

Expand Down
3 changes: 3 additions & 0 deletions lz4/frame/_frame.c
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ compress (PyObject * Py_UNUSED (self), PyObject * args,
}
else if (block_checksum)
{
PyBuffer_Release(&source);
PyErr_SetString (PyExc_RuntimeError,
"block_checksum specified but not supported by LZ4 library version");
return NULL;
Expand Down Expand Up @@ -383,6 +384,7 @@ compress_begin (PyObject * Py_UNUSED (self), PyObject * args,

if (LZ4F_isError (result))
{
PyMem_Free (destination);
PyErr_Format (PyExc_RuntimeError,
"LZ4F_compressBegin failed with code: %s",
LZ4F_getErrorName (result));
Expand Down Expand Up @@ -1115,6 +1117,7 @@ __decompress(LZ4F_dctx * context, char * source, size_t source_size,
buff = PyMem_Realloc (destination, destination_size);
if (buff == NULL)
{
PyMem_Free (destination);
PyErr_SetString (PyExc_RuntimeError,
"Failed to resize buffer");
return NULL;
Expand Down
Loading