Commit 4c94e39 for zlib

commit 4c94e39fc37017055d6fa8b1b3c7f49775c6f592
Author: Mohamed Elnady <elnadym165@gmail.com>
Date:   Thu Oct 15 07:19:43 2026 +0000

    Keep unzip ZIP64 decoding inside the extra-field boundaries.

    unzip.c could look outside the sub-field and overall extra field
    boundaries, finding unrelated and invalid ZIP64 data and misalign
    subsequent data. Now the field and sub-field lengths are honored,
    and a sub-field that does not fit returns UNZ_BADZIPFILE.

diff --git a/contrib/minizip/unzip.c b/contrib/minizip/unzip.c
index 827c23a..7f8d854 100644
--- a/contrib/minizip/unzip.c
+++ b/contrib/minizip/unzip.c
@@ -780,6 +780,8 @@ local int unz64local_GetCurrentFileInfoInternal(unzFile file,
     uLong uMagic;
     long lSeek=0;
     uLong uL;
+    unsigned zip64_required;
+    unsigned zip64_consumed = 0;

     if (file==NULL)
         return UNZ_PARAMERROR;
@@ -850,6 +852,17 @@ local int unz64local_GetCurrentFileInfoInternal(unzFile file,
         err=UNZ_ERRNO;
     file_info_internal.offset_curfile = uL;

+
+    /* Remember ZIP64 requirements before replacing any values. */
+    if (err != UNZ_OK)
+        return err;
+
+    zip64_required =
+        (file_info.uncompressed_size == MAXU32 ? 1U : 0U) |
+        (file_info.compressed_size == MAXU32 ? 2U : 0U) |
+        (file_info_internal.offset_curfile == MAXU32 ? 4U : 0U) |
+        (file_info.disk_num_start == 0xffff ? 8U : 0U);
+
     lSeek+=file_info.size_filename;
     if ((err==UNZ_OK) && (szFileName!=NULL))
     {
@@ -913,51 +926,80 @@ local int unz64local_GetCurrentFileInfoInternal(unzFile file,
         while(acc < file_info.size_file_extra)
         {
             uLong headerId;
-                                                uLong dataSize;
-
-            if (unz64local_getShort(&s->z_filefunc, s->filestream,&headerId) != UNZ_OK)
-                err=UNZ_ERRNO;
+            uLong dataSize;
+            uLong used = 0;
+            uLong remaining = file_info.size_file_extra - acc;
+
+            /* Every extra-field record starts with four bytes. */
+            if (remaining < 4)
+                return UNZ_BADZIPFILE;
+
+            if (unz64local_getShort(&s->z_filefunc, s->filestream,
+                                    &headerId) != UNZ_OK ||
+                unz64local_getShort(&s->z_filefunc, s->filestream,
+                                    &dataSize) != UNZ_OK)
+                return UNZ_ERRNO;

-            if (unz64local_getShort(&s->z_filefunc, s->filestream,&dataSize) != UNZ_OK)
-                err=UNZ_ERRNO;
+            remaining -= 4;
+            if (dataSize > remaining)
+                return UNZ_BADZIPFILE;

-            /* ZIP64 extra fields */
+            /* ZIP64 values must fit within this record. */
             if (headerId == 0x0001)
             {
-                if(file_info.uncompressed_size == MAXU32)
+                if ((zip64_required & 1U) && !(zip64_consumed & 1U))
                 {
-                    if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK)
-                        err=UNZ_ERRNO;
+                    if (dataSize - used < 8)
+                        return UNZ_BADZIPFILE;
+                    if (unz64local_getLong64(&s->z_filefunc, s->filestream,
+                                             &file_info.uncompressed_size) != UNZ_OK)
+                        return UNZ_ERRNO;
+                    used += 8;
+                    zip64_consumed |= 1U;
                 }

-                if(file_info.compressed_size == MAXU32)
+                if ((zip64_required & 2U) && !(zip64_consumed & 2U))
                 {
-                    if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK)
-                        err=UNZ_ERRNO;
+                    if (dataSize - used < 8)
+                        return UNZ_BADZIPFILE;
+                    if (unz64local_getLong64(&s->z_filefunc, s->filestream,
+                                             &file_info.compressed_size) != UNZ_OK)
+                        return UNZ_ERRNO;
+                    used += 8;
+                    zip64_consumed |= 2U;
                 }

-                if(file_info_internal.offset_curfile == MAXU32)
+                if ((zip64_required & 4U) && !(zip64_consumed & 4U))
                 {
-                    /* Relative Header offset */
-                    if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK)
-                        err=UNZ_ERRNO;
+                    if (dataSize - used < 8)
+                        return UNZ_BADZIPFILE;
+                    if (unz64local_getLong64(&s->z_filefunc, s->filestream,
+                                             &file_info_internal.offset_curfile) != UNZ_OK)
+                        return UNZ_ERRNO;
+                    used += 8;
+                    zip64_consumed |= 4U;
                 }

-                if(file_info.disk_num_start == 0xffff)
+                if ((zip64_required & 8U) && !(zip64_consumed & 8U))
                 {
-                    /* Disk Start Number */
-                    if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK)
-                        err=UNZ_ERRNO;
+                    if (dataSize - used < 4)
+                        return UNZ_BADZIPFILE;
+                    if (unz64local_getLong(&s->z_filefunc, s->filestream,
+                                           &file_info.disk_num_start) != UNZ_OK)
+                        return UNZ_ERRNO;
+                    used += 4;
+                    zip64_consumed |= 8U;
                 }
-
-            }
-            else
-            {
-                if (ZSEEK64(s->z_filefunc, s->filestream,dataSize,ZLIB_FILEFUNC_SEEK_CUR)!=0)
-                    err=UNZ_ERRNO;
             }

-            acc += 2 + 2 + dataSize;
+            /* Skip remaining bytes, but never leave this record. */
+            if (used < dataSize &&
+                ZSEEK64(s->z_filefunc, s->filestream,
+                        dataSize - used,
+                        ZLIB_FILEFUNC_SEEK_CUR) != 0)
+                return UNZ_ERRNO;
+
+            acc += 4 + dataSize;
         }
     }