Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

quazip fails to unzip zip64 archive with extra leading data (e.g. self-extractor) #14

Open
chazste opened this issue Nov 20, 2018 · 8 comments

Comments

@chazste
Copy link

chazste commented Nov 20, 2018

quazip will correctly unzip a normal (32-bit) zip archive even if the self-extractor is pre-pended. However if the archive is large are requires ZIP64 extensions then the extraction will fail. The search for ZIP64 end of central directory fails if the correct signature is not found pointed to by the ECL record, for non-ZIP64 archives the analogous routine will actually search backward for the central directory.

The Info-Zip version of unzip will make a guess that the ZIP64 End of Central directory is exactly 56 bytes before the locator record if the lookup using the explicit offset fails. I have implemented a similar solution for libquazip for use in my application. It seems to work well for me. I will issue a pull request for this change if you wish.

The issue is that unz64local_SearchCentralDir64 does not have any other options on line 574 if the signature check fails.

@stachenov
Copy link
Owner

PRs are always welcome, provided they maintain backwards API and ABI compatibility. Since the routine you mention is purely an implementation detail, it should be fine.

@perseedossrajiv
Copy link

Hi,
Did you manage to resolve this please?

@stachenov
Copy link
Owner

There was no PR, as of the moment.

@perseedossrajiv
Copy link

Ok. Could you please provide some more information on what you fixed locally?

Is your issue also similar to this? #117

Thanks

@chazste
Copy link
Author

chazste commented Apr 28, 2021

This appears to be similar to #117. At least this failure would return error -103. I ended up not actually needing to fix this issue and since the unit tests seemed like they would take a long time to run since they needed to create several 4GB archives I decided not to pursue submitting a PR.

Here is my local change

diff --git a/../../quazip-0.7.2/quazip/unzip.c b/unzip.c
old mode 100644
new mode 100755
index bca03f8..57f6468
--- a/../../quazip-0.7.2/quazip/unzip.c
+++ b/unzip.c
@@ -487,12 +487,11 @@ local ZPOS64_T unz64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib
     ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */
     ZPOS64_T uPosFound=0;
     uLong uL;
-                ZPOS64_T relativeOffset;
+    ZPOS64_T relativeOffset;
 
     if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
         return 0;
 
-
     uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream);
 
     if (uMaxBack>uSizeFile)
@@ -570,7 +569,22 @@ local ZPOS64_T unz64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib
         return 0;
 
     if (uL != 0x06064b50)
-        return 0;
+	{
+		// Not where expected so just look back a fixed size (assumed size of ECDIR64)
+		relativeOffset = (uPosFound - 56);
+
+		/* Try again - Goto end of central directory record 64 */
+		if (ZSEEK64(*pzlib_filefunc_def, filestream, relativeOffset, ZLIB_FILEFUNC_SEEK_SET) != 0)
+			return 0;
+
+		/* the signature */
+		if (unz64local_getLong(pzlib_filefunc_def, filestream, &uL) != UNZ_OK)
+			return 0;
+
+		/* check again */
+		if (uL != 0x06064b50)
+			return 0;
+	}
 
     return relativeOffset;
 }
@@ -625,7 +639,7 @@ extern unzFile unzOpenInternal (voidpf file,
         return NULL;
 
     central_pos = unz64local_SearchCentralDir64(&us.z_filefunc,us.filestream);
-    if (central_pos)
+	if (central_pos)
     {
         uLong uS;
         ZPOS64_T uL64;
@@ -913,7 +927,6 @@ local int unz64local_GetCurrentFileInfoInternal (unzFile file,
               ZLIB_FILEFUNC_SEEK_SET)!=0)
         err=UNZ_ERRNO;
 
-
     /* we check the magic */
     if (err==UNZ_OK)
     {
@@ -922,50 +935,35 @@ local int unz64local_GetCurrentFileInfoInternal (unzFile file,
         else if (uMagic!=0x02014b50)
             err=UNZ_BADZIPFILE;
     }
-
     if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK)
         err=UNZ_ERRNO;
-
     if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK)
         err=UNZ_ERRNO;
-
     if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK)
         err=UNZ_ERRNO;
-
     if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK)
         err=UNZ_ERRNO;
-
     if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.dosDate) != UNZ_OK)
         err=UNZ_ERRNO;
-
     unz64local_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date);
-
     if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.crc) != UNZ_OK)
         err=UNZ_ERRNO;
-
     if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK)
         err=UNZ_ERRNO;
     file_info.compressed_size = uL;
-
     if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK)
         err=UNZ_ERRNO;
     file_info.uncompressed_size = uL;
-
     if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_filename) != UNZ_OK)
         err=UNZ_ERRNO;
-
     if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_extra) != UNZ_OK)
         err=UNZ_ERRNO;
-
     if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_comment) != UNZ_OK)
         err=UNZ_ERRNO;
-
     if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK)
         err=UNZ_ERRNO;
-
     if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.internal_fa) != UNZ_OK)
         err=UNZ_ERRNO;
-
     if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK)
         err=UNZ_ERRNO;
 
@@ -1000,7 +998,6 @@ local int unz64local_GetCurrentFileInfoInternal (unzFile file,
             uSizeRead = file_info.size_file_extra;
         else
             uSizeRead = extraFieldBufferSize;
-
         if (llSeek!=0)
         {
             if (ZSEEK64(s->z_filefunc, s->filestream,llSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)

@perseedossrajiv
Copy link

perseedossrajiv commented Apr 29, 2021

Quazip4gbError

Hello,
I tried the above patch but i still get the same error sadly.

I do not know what else to do here.
@stachenov any idea please?

Thanks

@stachenov
Copy link
Owner

No ideas at the moment, and I'm a bit busy currently to look into it deeper. I don't expect to have enough free time for this until at least August. Sad, but true...

@perseedossrajiv
Copy link

ok - thanks for helping anyways.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants