From bc437743d592d3d9a2e37ef46633532102d1e629 Mon Sep 17 00:00:00 2001 From: griffin Date: Tue, 31 Aug 2021 14:36:33 +0000 Subject: Patch to fix zipfs mkimg bug. --- generic/tclZipfs.c | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/generic/tclZipfs.c b/generic/tclZipfs.c index c77e8db..da46acd 100644 --- a/generic/tclZipfs.c +++ b/generic/tclZipfs.c @@ -1191,7 +1191,8 @@ ZipFSFindTOC( const unsigned char *p, *q; const unsigned char *start = zf->data; const unsigned char *end = zf->data + zf->length; - + size_t pass_offset; + /* * Scan backwards from the end of the file for the signature. This is * necessary because ZIP archives aren't the only things that get tagged @@ -1224,6 +1225,11 @@ ZipFSFindTOC( goto error; } + /* + * Remember passOffset + */ + pass_offset = p - zf->data; + /* * How many files in the archive? If that's bogus, we're done here. */ @@ -1300,6 +1306,12 @@ ZipFSFindTOC( zf->passOffset -= i ? (5 + i) : 0; } } + + /* + * Restore passOffset + */ + zf->passOffset = pass_offset; + return TCL_OK; error: @@ -3108,6 +3120,22 @@ ZipFSMkZipOrImg( * Copy everything up to the ZIP-related suffix. */ + if (zf->passOffset == 0) { + /* + * Hmm, this mounted archive is local (in this image), but + * zf->passOffset does not have a valid value. Let's open + * this image and find the passOffset so as to copy the image + * correctly. + */ + + ZipFile zflocal; + memset(&zflocal, 0, sizeof(ZipFile)); + if (ZipFSOpenArchive(interp, imgName, 0, &zflocal) == TCL_OK) { + zf->passOffset = zflocal.passOffset; + ZipFSCloseArchive(interp, &zflocal); + } + } + if ((size_t) Tcl_Write(out, (char *) zf->data, zf->passOffset) != zf->passOffset) { memset(passBuf, 0, sizeof(passBuf)); -- cgit v0.12 From 34e7d9999e042408f6eef02bbd690d43f25b9fde Mon Sep 17 00:00:00 2001 From: griffin Date: Wed, 13 Oct 2021 00:22:20 +0000 Subject: Corrected offset calculations --- generic/tclZipfs.c | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/generic/tclZipfs.c b/generic/tclZipfs.c index da46acd..4d40da3 100644 --- a/generic/tclZipfs.c +++ b/generic/tclZipfs.c @@ -1187,11 +1187,10 @@ ZipFSFindTOC( int needZip, ZipFile *zf) { - size_t i; + size_t i, minoff; const unsigned char *p, *q; const unsigned char *start = zf->data; const unsigned char *end = zf->data + zf->length; - size_t pass_offset; /* * Scan backwards from the end of the file for the signature. This is @@ -1225,11 +1224,6 @@ ZipFSFindTOC( goto error; } - /* - * Remember passOffset - */ - pass_offset = p - zf->data; - /* * How many files in the archive? If that's bogus, we're done here. */ @@ -1251,6 +1245,8 @@ ZipFSFindTOC( q = zf->data + ZipReadInt(start, end, p + ZIP_CENTRAL_DIRSTART_OFFS); p -= ZipReadInt(start, end, p + ZIP_CENTRAL_DIRSIZE_OFFS); + zf->baseOffset = zf->passOffset = (p>q) ? p - q : 0; + zf->directoryOffset = q - zf->data + zf->baseOffset; if ((p < q) || (p < zf->data) || (p > zf->data + zf->length) || (q < zf->data) || (q > zf->data + zf->length)) { if (!needZip) { @@ -1266,11 +1262,11 @@ ZipFSFindTOC( * Read the central directory. */ - zf->baseOffset = zf->passOffset = p - q; - zf->directoryOffset = p - zf->data; q = p; + minoff = zf->length; for (i = 0; i < zf->numFiles; i++) { int pathlen, comlen, extra; + size_t localhdr_off = zf->length; if (q + ZIP_CENTRAL_HEADER_LEN > end) { ZIPFS_ERROR(interp, "wrong header length"); @@ -1285,16 +1281,27 @@ ZipFSFindTOC( pathlen = ZipReadShort(start, end, q + ZIP_CENTRAL_PATHLEN_OFFS); comlen = ZipReadShort(start, end, q + ZIP_CENTRAL_FCOMMENTLEN_OFFS); extra = ZipReadShort(start, end, q + ZIP_CENTRAL_EXTRALEN_OFFS); + localhdr_off = ZipReadInt(start, end, q + ZIP_CENTRAL_LOCALHDR_OFFS); + if (ZipReadInt(start, end, zf->data + zf->baseOffset + localhdr_off) != ZIP_LOCAL_HEADER_SIG) { + ZIPFS_ERROR(interp, "Failed to find local header"); + ZIPFS_ERROR_CODE(interp, "LCL_HDR"); + goto error; + } + if (localhdr_off < minoff) { + minoff = localhdr_off; + } q += pathlen + comlen + extra + ZIP_CENTRAL_HEADER_LEN; } + zf->passOffset = minoff + zf->baseOffset; + /* * If there's also an encoded password, extract that too (but don't decode * yet). */ - q = zf->data + zf->baseOffset; - if ((zf->baseOffset >= 6) && + q = zf->data + zf->passOffset; + if ((zf->passOffset >= 6) && (start < q-4) && (ZipReadInt(start, end, q - 4) == ZIP_PASSWORD_END_SIG)) { const unsigned char *passPtr; @@ -1307,11 +1314,6 @@ ZipFSFindTOC( } } - /* - * Restore passOffset - */ - zf->passOffset = pass_offset; - return TCL_OK; error: -- cgit v0.12 From 2812109f17b5854a23b1f0b63d0fd99b1f56965a Mon Sep 17 00:00:00 2001 From: griffin Date: Wed, 13 Oct 2021 16:34:46 +0000 Subject: Remove unnecessary change --- generic/tclZipfs.c | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/generic/tclZipfs.c b/generic/tclZipfs.c index 4d40da3..ae4c8c4 100644 --- a/generic/tclZipfs.c +++ b/generic/tclZipfs.c @@ -3122,22 +3122,6 @@ ZipFSMkZipOrImg( * Copy everything up to the ZIP-related suffix. */ - if (zf->passOffset == 0) { - /* - * Hmm, this mounted archive is local (in this image), but - * zf->passOffset does not have a valid value. Let's open - * this image and find the passOffset so as to copy the image - * correctly. - */ - - ZipFile zflocal; - memset(&zflocal, 0, sizeof(ZipFile)); - if (ZipFSOpenArchive(interp, imgName, 0, &zflocal) == TCL_OK) { - zf->passOffset = zflocal.passOffset; - ZipFSCloseArchive(interp, &zflocal); - } - } - if ((size_t) Tcl_Write(out, (char *) zf->data, zf->passOffset) != zf->passOffset) { memset(passBuf, 0, sizeof(passBuf)); -- cgit v0.12 From 13223fbc3fca082c74336bb13dfb03e115d9f1cd Mon Sep 17 00:00:00 2001 From: griffin Date: Sun, 24 Oct 2021 18:19:16 +0000 Subject: These record locations are not relative offsets, but rather absolute locations. --- generic/tclZipfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/generic/tclZipfs.c b/generic/tclZipfs.c index ae4c8c4..f649588 100644 --- a/generic/tclZipfs.c +++ b/generic/tclZipfs.c @@ -3428,7 +3428,7 @@ SerializeCentralDirectoryEntry( ZipWriteShort(start, end, buf + ZIP_CENTRAL_IATTR_OFFS, 0); ZipWriteInt(start, end, buf + ZIP_CENTRAL_EATTR_OFFS, 0); ZipWriteInt(start, end, buf + ZIP_CENTRAL_LOCALHDR_OFFS, - z->offset - dataStartOffset); + z->offset); } static void @@ -3455,7 +3455,7 @@ SerializeCentralDirectorySuffix( ZipWriteInt(start, end, buf + ZIP_CENTRAL_DIRSIZE_OFFS, suffixStartOffset - directoryStartOffset); ZipWriteInt(start, end, buf + ZIP_CENTRAL_DIRSTART_OFFS, - directoryStartOffset - dataStartOffset); + directoryStartOffset); ZipWriteShort(start, end, buf + ZIP_CENTRAL_COMMENTLEN_OFFS, 0); } -- cgit v0.12