From c3cb1c568ebf9e8f7f478cfc0356ae54e99712b0 Mon Sep 17 00:00:00 2001
From: elhananhaenel <elhanan.haenel@mail.huji.ac.il>
Date: Sat, 7 Mar 2026 22:14:23 +0200
Subject: [PATCH] iso9660: validate pz_log2_bs in parse_rockridge_ZF1()

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.

CVE: CVE-2026-4426
Upstream-Status: Backport [https://github.com/libarchive/libarchive/commit/c3cb1c568ebf9e8f7f478cfc0356ae54e99712b0]
Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
---
 libarchive/archive_read_support_format_iso9660.c | 15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/libarchive/archive_read_support_format_iso9660.c b/libarchive/archive_read_support_format_iso9660.c
index 7d3655a..477aae9 100644
--- a/libarchive/archive_read_support_format_iso9660.c
+++ b/libarchive/archive_read_support_format_iso9660.c
@@ -2756,11 +2756,16 @@ parse_rockridge_ZF1(struct file_info *file, const unsigned char *data,
 {
 
 	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
-- 
2.50.1

