The zisofs block size exponent (pz_log2_bs) read from the Rock Ridge ZF
extension entry is used directly in shift expressions without validation.
The zisofs specification only permits values 15, 16, or 17 (corresponding
to 32K, 64K, and 128K block sizes).
When pz_log2_bs >= 64 on 64-bit systems (or >= 32 on 32-bit), the
expression (size_t)1UL << pz_log2_bs is undefined behavior per C11
6.5.7. On 32-bit systems, a large exponent also causes the block pointer
allocation size computation (ceil + 1) * 4 to overflow to zero, leading
to a heap buffer overflow write after malloc(0).
Fix: reject any pz_log2_bs outside the range [15, 17] by disabling
zisofs for the entry (file->pz = 0), which prevents the zisofs
decompression path from executing.
Found by fuzzing with ASAN/UBSAN.
{
if (data[0] == 0x70 && data[1] == 0x7a && data_length == 12) {
- /* paged zlib */
- file->pz = 1;
- file->pz_log2_bs = data[3];
- file->pz_uncompressed_size = archive_le32dec(&data[4]);
- }
+ /* paged zlib */
+ file->pz = 1;
+ file->pz_log2_bs = data[3];
+ if (file->pz_log2_bs < 15 || file->pz_log2_bs > 17) {
+ /* Invalid block size exponent; disable zisofs. */
+ file->pz = 0;
+ return;
+ }
+ file->pz_uncompressed_size = archive_le32dec(&data[4]);
+ }
}
static void