bzlib: don't leak compressor state when abandoning after an I/O error
BZ2_bzWriteClose64() returns early at its entry ferror() check with
BZ_IO_ERROR before releasing anything, so the EState and its
arr1/arr2/ftab buffers (about 7.5 MB for a blockSize100k of 9), plus
the bzFile itself, are never freed.
BZ2_bzclose() is written to cope with a failing close: when the first,
normal close reports an error it re-invokes BZ2_bzWriteClose() with
abandon=1 to force the resources to be torn down. But that retry hits
the very same ferror() early-return and again frees nothing, so any
write or flush error (a broken pipe, a full filesystem, ...) leaks the
whole compressor state on every close. In a long-running process that
uses libbz2 and can be driven to hit output errors this is an
unbounded, attacker-influenced leak.
Skip the ferror() early-return when abandon is set so the abandon path
proceeds to BZ2_bzCompressEnd()+free() as intended. The normal
(abandon==0) close is unchanged, so the "retry with abandon=1" contract
BZ2_bzclose relies on still frees exactly once and introduces no double
free.
Signed-off-by: Naveed Khan <naveed@digiscrypt.com>
1 file changed