From 071499ac0d8e33e6f269437c3ce4fab52cc43f90 Mon Sep 17 00:00:00 2001
From: RedworkDE <10944644+RedworkDE@users.noreply.github.com>
Date: Tue, 14 Feb 2023 17:29:35 +0100
Subject: [PATCH] Fix ZIPReader failing to open empty zip files

---
 .../minizip/patches/empty-zip-fix.patch       | 193 ++++++++++++++++++
 thirdparty/minizip/unzip.c                    |  92 +++++++--
 2 files changed, 263 insertions(+), 22 deletions(-)
 create mode 100644 thirdparty/minizip/patches/empty-zip-fix.patch

diff --git a/thirdparty/minizip/patches/empty-zip-fix.patch b/thirdparty/minizip/patches/empty-zip-fix.patch
new file mode 100644
index 00000000000..7885d4c3a39
--- /dev/null
+++ b/thirdparty/minizip/patches/empty-zip-fix.patch
@@ -0,0 +1,193 @@
+diff --git a/thirdparty/minizip/unzip.c b/thirdparty/minizip/unzip.c
+index e83aff2773..af73f06137 100644
+--- a/thirdparty/minizip/unzip.c
++++ b/thirdparty/minizip/unzip.c
+@@ -408,6 +408,12 @@ extern int ZEXPORT unzStringFileNameCompare (const char*  fileName1,
+ #define BUFREADCOMMENT (0x400)
+ #endif
+ 
++/* GODOT start */
++#ifndef CENTRALDIRINVALID
++#define CENTRALDIRINVALID (0xffffffffffffffff)
++#endif
++/* GODOT end */
++
+ /*
+   Locate the Central directory of a zipfile (at the end, just before
+     the global comment)
+@@ -419,10 +425,14 @@ local ZPOS64_T unz64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_f
+     ZPOS64_T uSizeFile;
+     ZPOS64_T uBackRead;
+     ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */
+-    ZPOS64_T uPosFound=0;
++    /* GODOT start */
++    ZPOS64_T uPosFound=CENTRALDIRINVALID;
++    /* GODOT end */
+ 
+     if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
+-        return 0;
++        /* GODOT start */
++        return CENTRALDIRINVALID;
++        /* GODOT end */
+ 
+ 
+     uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream);
+@@ -432,7 +442,9 @@ local ZPOS64_T unz64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_f
+ 
+     buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
+     if (buf==NULL)
+-        return 0;
++        /* GODOT start */
++        return CENTRALDIRINVALID;
++        /* GODOT end */
+ 
+     uBackRead = 4;
+     while (uBackRead<uMaxBack)
+@@ -462,7 +474,9 @@ local ZPOS64_T unz64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_f
+                 break;
+             }
+ 
+-        if (uPosFound!=0)
++        /* GODOT start */
++        if (uPosFound!=CENTRALDIRINVALID)
++        /* GODOT end */
+             break;
+     }
+     TRYFREE(buf);
+@@ -485,12 +499,16 @@ local ZPOS64_T unz64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib
+     ZPOS64_T uSizeFile;
+     ZPOS64_T uBackRead;
+     ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */
+-    ZPOS64_T uPosFound=0;
++    /* GODOT start */
++    ZPOS64_T uPosFound=CENTRALDIRINVALID;
++    /* GODOT end */
+     uLong uL;
+                 ZPOS64_T relativeOffset;
+ 
+     if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
+-        return 0;
++        /* GODOT start */
++        return CENTRALDIRINVALID;
++        /* GODOT end */
+ 
+ 
+     uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream);
+@@ -500,7 +518,9 @@ local ZPOS64_T unz64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib
+ 
+     buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
+     if (buf==NULL)
+-        return 0;
++        /* GODOT start */
++        return CENTRALDIRINVALID;
++        /* GODOT end */
+ 
+     uBackRead = 4;
+     while (uBackRead<uMaxBack)
+@@ -530,47 +550,71 @@ local ZPOS64_T unz64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib
+                 break;
+             }
+ 
+-        if (uPosFound!=0)
++        /* GODOT start */
++        if (uPosFound!=CENTRALDIRINVALID)
++        /* GODOT end */
+             break;
+     }
+     TRYFREE(buf);
+-    if (uPosFound == 0)
+-        return 0;
++    /* GODOT start */
++    if (uPosFound == CENTRALDIRINVALID)
++        return CENTRALDIRINVALID;
++    /* GODOT end */
+ 
+     /* Zip64 end of central directory locator */
+     if (ZSEEK64(*pzlib_filefunc_def,filestream, uPosFound,ZLIB_FILEFUNC_SEEK_SET)!=0)
+-        return 0;
++        /* GODOT start */
++        return CENTRALDIRINVALID;
++        /* GODOT end */
+ 
+     /* the signature, already checked */
+     if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
+-        return 0;
++        /* GODOT start */
++        return CENTRALDIRINVALID;
++        /* GODOT end */
+ 
+     /* number of the disk with the start of the zip64 end of  central directory */
+     if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
+-        return 0;
++        /* GODOT start */
++        return CENTRALDIRINVALID;
++        /* GODOT end */
+     if (uL != 0)
+-        return 0;
++        /* GODOT start */
++        return CENTRALDIRINVALID;
++        /* GODOT end */
+ 
+     /* relative offset of the zip64 end of central directory record */
+     if (unz64local_getLong64(pzlib_filefunc_def,filestream,&relativeOffset)!=UNZ_OK)
+-        return 0;
++        /* GODOT start */
++        return CENTRALDIRINVALID;
++        /* GODOT end */
+ 
+     /* total number of disks */
+     if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
+-        return 0;
++        /* GODOT start */
++        return CENTRALDIRINVALID;
++        /* GODOT end */
+     if (uL != 1)
+-        return 0;
++        /* GODOT start */
++        return CENTRALDIRINVALID;
++        /* GODOT end */
+ 
+     /* Goto end of central directory record */
+     if (ZSEEK64(*pzlib_filefunc_def,filestream, relativeOffset,ZLIB_FILEFUNC_SEEK_SET)!=0)
+-        return 0;
++        /* GODOT start */
++        return CENTRALDIRINVALID;
++        /* GODOT end */
+ 
+      /* the signature */
+     if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
+-        return 0;
++        /* GODOT start */
++        return CENTRALDIRINVALID;
++        /* GODOT end */
+ 
+     if (uL != 0x06064b50)
+-        return 0;
++        /* GODOT start */
++        return CENTRALDIRINVALID;
++        /* GODOT end */
+ 
+     return relativeOffset;
+ }
+@@ -625,7 +669,9 @@ local unzFile unzOpenInternal (const void *path,
+         return NULL;
+ 
+     central_pos = unz64local_SearchCentralDir64(&us.z_filefunc,us.filestream);
+-    if (central_pos)
++    /* GODOT start */
++    if (central_pos != CENTRALDIRINVALID)
++    /* GODOT end */
+     {
+         uLong uS;
+         ZPOS64_T uL64;
+@@ -687,7 +733,9 @@ local unzFile unzOpenInternal (const void *path,
+     else
+     {
+         central_pos = unz64local_SearchCentralDir(&us.z_filefunc,us.filestream);
+-        if (central_pos==0)
++        /* GODOT start */
++        if (central_pos==CENTRALDIRINVALID)
++        /* GODOT end */
+             err=UNZ_ERRNO;
+ 
+         us.isZip64 = 0;
diff --git a/thirdparty/minizip/unzip.c b/thirdparty/minizip/unzip.c
index e83aff2773d..f72bf3974f3 100644
--- a/thirdparty/minizip/unzip.c
+++ b/thirdparty/minizip/unzip.c
@@ -408,6 +408,12 @@ extern int ZEXPORT unzStringFileNameCompare (const char*  fileName1,
 #define BUFREADCOMMENT (0x400)
 #endif
 
+/* GODOT start */
+#ifndef CENTRALDIRINVALID
+#define CENTRALDIRINVALID (0xffffffffffffffff)
+#endif
+/* GODOT end */
+
 /*
   Locate the Central directory of a zipfile (at the end, just before
     the global comment)
@@ -419,10 +425,14 @@ local ZPOS64_T unz64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_f
     ZPOS64_T uSizeFile;
     ZPOS64_T uBackRead;
     ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */
-    ZPOS64_T uPosFound=0;
+    /* GODOT start */
+    ZPOS64_T uPosFound=CENTRALDIRINVALID;
+    /* GODOT end */
 
     if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
-        return 0;
+        /* GODOT start */
+        return CENTRALDIRINVALID;
+        /* GODOT end */
 
 
     uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream);
@@ -432,7 +442,9 @@ local ZPOS64_T unz64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_f
 
     buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
     if (buf==NULL)
-        return 0;
+        /* GODOT start */
+        return CENTRALDIRINVALID;
+        /* GODOT end */
 
     uBackRead = 4;
     while (uBackRead<uMaxBack)
@@ -462,7 +474,9 @@ local ZPOS64_T unz64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_f
                 break;
             }
 
-        if (uPosFound!=0)
+        /* GODOT start */
+        if (uPosFound!=CENTRALDIRINVALID)
+        /* GODOT end */
             break;
     }
     TRYFREE(buf);
@@ -485,12 +499,16 @@ local ZPOS64_T unz64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib
     ZPOS64_T uSizeFile;
     ZPOS64_T uBackRead;
     ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */
-    ZPOS64_T uPosFound=0;
+    /* GODOT start */
+    ZPOS64_T uPosFound=CENTRALDIRINVALID;
+    /* GODOT end */
     uLong uL;
                 ZPOS64_T relativeOffset;
 
     if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
-        return 0;
+        /* GODOT start */
+        return CENTRALDIRINVALID;
+        /* GODOT end */
 
 
     uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream);
@@ -500,7 +518,9 @@ local ZPOS64_T unz64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib
 
     buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
     if (buf==NULL)
-        return 0;
+        /* GODOT start */
+        return CENTRALDIRINVALID;
+        /* GODOT end */
 
     uBackRead = 4;
     while (uBackRead<uMaxBack)
@@ -530,47 +550,71 @@ local ZPOS64_T unz64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib
                 break;
             }
 
-        if (uPosFound!=0)
+        /* GODOT start */
+        if (uPosFound!=CENTRALDIRINVALID)
+        /* GODOT end */
             break;
     }
     TRYFREE(buf);
-    if (uPosFound == 0)
-        return 0;
+    /* GODOT start */
+    if (uPosFound == CENTRALDIRINVALID)
+        return CENTRALDIRINVALID;
+    /* GODOT end */
 
     /* Zip64 end of central directory locator */
     if (ZSEEK64(*pzlib_filefunc_def,filestream, uPosFound,ZLIB_FILEFUNC_SEEK_SET)!=0)
-        return 0;
+        /* GODOT start */
+        return CENTRALDIRINVALID;
+        /* GODOT end */
 
     /* the signature, already checked */
     if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
-        return 0;
+        /* GODOT start */
+        return CENTRALDIRINVALID;
+        /* GODOT end */
 
     /* number of the disk with the start of the zip64 end of  central directory */
     if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
-        return 0;
+        /* GODOT start */
+        return CENTRALDIRINVALID;
+        /* GODOT end */
     if (uL != 0)
-        return 0;
+        /* GODOT start */
+        return CENTRALDIRINVALID;
+        /* GODOT end */
 
     /* relative offset of the zip64 end of central directory record */
     if (unz64local_getLong64(pzlib_filefunc_def,filestream,&relativeOffset)!=UNZ_OK)
-        return 0;
+        /* GODOT start */
+        return CENTRALDIRINVALID;
+        /* GODOT end */
 
     /* total number of disks */
     if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
-        return 0;
+        /* GODOT start */
+        return CENTRALDIRINVALID;
+        /* GODOT end */
     if (uL != 1)
-        return 0;
+        /* GODOT start */
+        return CENTRALDIRINVALID;
+        /* GODOT end */
 
     /* Goto end of central directory record */
     if (ZSEEK64(*pzlib_filefunc_def,filestream, relativeOffset,ZLIB_FILEFUNC_SEEK_SET)!=0)
-        return 0;
+        /* GODOT start */
+        return CENTRALDIRINVALID;
+        /* GODOT end */
 
      /* the signature */
     if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
-        return 0;
+        /* GODOT start */
+        return CENTRALDIRINVALID;
+        /* GODOT end */
 
     if (uL != 0x06064b50)
-        return 0;
+        /* GODOT start */
+        return CENTRALDIRINVALID;
+        /* GODOT end */
 
     return relativeOffset;
 }
@@ -625,7 +669,9 @@ local unzFile unzOpenInternal (const void *path,
         return NULL;
 
     central_pos = unz64local_SearchCentralDir64(&us.z_filefunc,us.filestream);
-    if (central_pos)
+    /* GODOT start */
+    if (central_pos != CENTRALDIRINVALID)
+    /* GODOT end */
     {
         uLong uS;
         ZPOS64_T uL64;
@@ -687,7 +733,9 @@ local unzFile unzOpenInternal (const void *path,
     else
     {
         central_pos = unz64local_SearchCentralDir(&us.z_filefunc,us.filestream);
-        if (central_pos==0)
+        /* GODOT start */
+        if (central_pos==CENTRALDIRINVALID)
+        /* GODOT end */
             err=UNZ_ERRNO;
 
         us.isZip64 = 0;