From c58246b43c9dac85eb30edebc7a07dea66e138d0 Mon Sep 17 00:00:00 2001 From: John Reiser Date: Tue, 4 Jun 2024 08:32:26 -0700 Subject: [PATCH] Detect compressed length too short https://github.com/upx/upx/issues/827 modified: p_unix.cpp --- src/p_unix.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/p_unix.cpp b/src/p_unix.cpp index 13e28621..608bde53 100644 --- a/src/p_unix.cpp +++ b/src/p_unix.cpp @@ -660,10 +660,14 @@ void PackUnix::unpack(OutputFile *fo) throwCompressedDataViolation(); break; } - if (sz_unc <= 0 || sz_cpr <= 0) - throwCompressedDataViolation(); - if (sz_cpr > sz_unc || sz_unc > blocksize) - throwCompressedDataViolation(); + // Minimum compressed length: LZMA has 5-byte info header. + // NRV_d8 has 1-byte initial 8 flag bits, plus end-of-block marker + // (32 bit look-back offset of all 1s: encoded as 24 pairs of bits + // {not last, 1} then low 8-bits of 0xff; total: 8 + 2*24 + 8 bits + // ==> 8 bytes) + if (sz_unc <= 0 || sz_cpr <= 5u + || sz_cpr > sz_unc || sz_unc > blocksize) + throwCantUnpack("corrupt b_info %#x %#x", sz_unc, sz_cpr); // Compressed output has control bytes such as the 32-bit // first flag bits of NRV_d32, the 5-byte info of LZMA, etc. @@ -671,7 +675,7 @@ void PackUnix::unpack(OutputFile *fo) // Use some OVERHEAD for safety. i = blocksize + OVERHEAD - upx::umax(12u, sz_cpr); if (i < 0) - throwCantUnpack("corrupt b_info"); + throwCantUnpack("corrupt b_info %#x %#x", sz_cpr, blocksize); fi->readx(buf+i, sz_cpr); // update checksum of compressed data c_adler = upx_adler32(buf + i, sz_cpr, c_adler);