From dd0c880a734ebb04d3a5b788575d5d2b072f31d2 Mon Sep 17 00:00:00 2001
From: yuncang123 <1050706328@qq.com>
Date: Thu, 29 Aug 2024 16:08:44 +0800
Subject: [PATCH] backport disable zzip_use_file_header_zip64_offset

---
 zzip/fetch.h   |  1 +
 zzip/mmapped.c | 33 ++++++++++++++++++++++++++-------
 2 files changed, 27 insertions(+), 7 deletions(-)

diff --git a/zzip/fetch.h b/zzip/fetch.h
index 0e4c94d..89cd9d9 100644
--- a/zzip/fetch.h
+++ b/zzip/fetch.h
@@ -308,6 +308,7 @@ extern void     __zzip_set64(zzip_byte_t * s, uint64_t v);
 #define zzip_disk_trailer_to_endoffile(__p)   ((void*) \
         (zzip_disk_trailer_to_comment(__p) + zzip_disk_trailer_comment(__p)))
 
+#define zzip_use_file_header_zip64_offset 0
 #define zzip_extra_zip64_csize(__p)   ((zzip_size_t) \
         zzip_extra_zip64_get_csize(__p))
 #define zzip_extra_zip64_usize(__p)   ((zzip_size_t) \
diff --git a/zzip/mmapped.c b/zzip/mmapped.c
index 2071882..5d9dd98 100644
--- a/zzip/mmapped.c
+++ b/zzip/mmapped.c
@@ -276,7 +276,8 @@ struct zzip_file_header *
 zzip_disk_entry_to_file_header(ZZIP_DISK * disk, struct zzip_disk_entry *entry)
 {
     zzip_byte_t *const ptr = disk->buffer + zzip_disk_entry_fileoffset(entry);
-    if (disk->buffer > ptr || ptr >= disk->endbuf)
+    zzip_byte_t *const end = ptr + sizeof(struct zzip_file_header);
+    if (disk->buffer > ptr || end >= disk->endbuf || (void*)end <= NULL)
     {
         debug2("file header: offset out of bounds (0x%llx)", (long long unsigned)(disk->buffer));
         errno = EBADMSG;
@@ -661,19 +662,37 @@ zzip_disk_entry_fopen(ZZIP_DISK * disk, ZZIP_DISK_ENTRY * entry)
 
     ___ /* a ZIP64 extended block may follow. */
     size_t csize = zzip_file_header_csize(header);
-    off_t offset = zzip_file_header_to_data(header);
+    zzip_byte_t*  start = zzip_file_header_to_data(header);
     if (csize == 0xFFFFu) {
         struct zzip_extra_zip64* zip64 =
-           zzip_file_header_to_extras(header);
+            (struct zzip_extra_zip64*) zzip_file_header_to_extras(header);
         if (ZZIP_EXTRA_ZIP64_CHECK(zip64)) {
             csize = zzip_extra_zip64_csize(zip64);
         }
     }
-    if (offset == 0xFFFFu) {
+
+    if (((unsigned long)start) & 0xFFFFu == 0xFFFFu) {
+        /* actually the ZIP64 rootseek in the central directory should have updated the 
+           header start with the data portion to follow right behind it. The usage of
+           this field in a local file header is wrong on a number of levels. Specifically
+           that the zip64 extended field value points to yet another header but it is
+           actually used to point to the actual data portion instead. */
         struct zzip_extra_zip64* zip64 =
-           zzip_file_header_to_extras(header);
+            (struct zzip_extra_zip64*)zzip_file_header_to_extras(header);
         if (ZZIP_EXTRA_ZIP64_CHECK(zip64)) {
-            offset = zzip_extra_zip64_offset(zip64);
+            zzip_off64_t offset = zzip_extra_zip64_offset(zip64); /* offset of local header record */
+            if (offset && zzip_use_file_header_zip64_offset) {
+               start = disk->buffer + offset; /* but points directly to the data portion */
+               if (disk->buffer > start || start+csize >= disk->endbuf) {
+                    debug2("file start: offset out of bounds (0x%llx)", (long long unsigned) (offset));
+                    errno = EBADMSG;
+                    return 0;
+                }
+            } else {
+                debug1("file start: no zip64 local offset");
+                errno = EBADMSG;
+                return 0;
+            }
         }
     }
 
@@ -682,7 +701,7 @@ zzip_disk_entry_fopen(ZZIP_DISK * disk, ZZIP_DISK_ENTRY * entry)
     file->zlib.zalloc = Z_NULL;
     file->zlib.zfree = Z_NULL;
     file->zlib.avail_in = csize;
-    file->zlib.next_in = offset;
+    file->zlib.next_in  = start;
     ____;
 
     DBG2("compressed size %i", (int) file->zlib.avail_in);
-- 
2.43.0

