diff options
author | griffin <briang42@easystreet.net> | 2021-11-04 17:52:22 (GMT) |
---|---|---|
committer | griffin <briang42@easystreet.net> | 2021-11-04 17:52:22 (GMT) |
commit | c6971d961df38b5e6585ab4aef66b59a1631b956 (patch) | |
tree | 55a330f2743c899c28092e805c03aa6e2af636ef /generic | |
parent | 52e7c8c7c41e9ce16cfaf2ea5923c61a6c12a606 (diff) | |
parent | 0652bd43d5031f22fe2ea78713a7d788c23dabc2 (diff) | |
download | tcl-c6971d961df38b5e6585ab4aef66b59a1631b956.zip tcl-c6971d961df38b5e6585ab4aef66b59a1631b956.tar.gz tcl-c6971d961df38b5e6585ab4aef66b59a1631b956.tar.bz2 |
Merge 8.7
Diffstat (limited to 'generic')
-rw-r--r-- | generic/tclZipfs.c | 30 |
1 files changed, 22 insertions, 8 deletions
diff --git a/generic/tclZipfs.c b/generic/tclZipfs.c index ba63f01..566987b 100644 --- a/generic/tclZipfs.c +++ b/generic/tclZipfs.c @@ -1179,11 +1179,11 @@ 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; - + /* * 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 @@ -1237,6 +1237,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) { @@ -1252,11 +1254,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"); @@ -1271,16 +1273,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; @@ -1292,6 +1305,7 @@ ZipFSFindTOC( zf->passOffset -= i ? (5 + i) : 0; } } + return TCL_OK; error: @@ -3406,7 +3420,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 @@ -3433,7 +3447,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); } |