quazip
quazip copied to clipboard
quazip fails to unzip zip64 archive with extra leading data (e.g. self-extractor)
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.
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.
Hi, Did you manage to resolve this please?
There was no PR, as of the moment.
Ok. Could you please provide some more information on what you fixed locally?
Is your issue also similar to this? https://github.com/stachenov/quazip/issues/117
Thanks
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)

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
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...
ok - thanks for helping anyways.