diff options
| -rw-r--r-- | generic/tclZipfs.c | 22 | ||||
| -rw-r--r-- | tests/zipfs.test | 49 |
2 files changed, 60 insertions, 11 deletions
diff --git a/generic/tclZipfs.c b/generic/tclZipfs.c index 6ed23f7..2297e79 100644 --- a/generic/tclZipfs.c +++ b/generic/tclZipfs.c @@ -227,9 +227,12 @@ typedef struct ZipEntry { int compressMethod; /* Compress method */ int isDirectory; /* Set to 1 if directory, or -1 if root */ int depth; /* Number of slashes in path. */ - int crc32; /* CRC-32 */ + int crc32; /* CRC-32 as stored in ZIP */ int timestamp; /* Modification time */ int isEncrypted; /* True if data is encrypted */ + int flags; +#define ZE_F_CRC_COMPARED 0x1 /* If 1, the CRC has been compared. */ +#define ZE_F_CRC_CORRECT 0x2 /* Only meaningful if ZE_F_CRC_CHECKED is 1 */ unsigned char *data; /* File data if written */ struct ZipEntry *next; /* Next file in the same archive */ struct ZipEntry *tnext; /* Next top-level dir in archive */ @@ -4499,6 +4502,23 @@ ZipChannelOpen( } } + if (z->crc32) { + if (!(z->flags & ZE_F_CRC_COMPARED)) { + int crc = crc32(0, NULL, info->numBytes); + crc = crc32(crc, info->ubuf, info->numBytes); + z->flags |= ZE_F_CRC_COMPARED; + if (crc == z->crc32) { + z->flags |= ZE_F_CRC_CORRECT; + } + } + if (!(z->flags & ZE_F_CRC_CORRECT)) { + ZIPFS_ERROR(interp, "invalid CRC"); + ZIPFS_ERROR_CODE(interp, "CRC_FAILED"); + ckfree(info); + goto error; + } + } + /* * Wrap the ZipChannel into a Tcl_Channel. */ diff --git a/tests/zipfs.test b/tests/zipfs.test index 689fd5f..6c0870e 100644 --- a/tests/zipfs.test +++ b/tests/zipfs.test @@ -494,8 +494,6 @@ namespace eval test_ns_zipfs { testbadmount bad-file-count-high incons-file-count-high.zip "truncated directory" testbadmount bad-file-count-low incons-file-count-low.zip "short file count" - # TODO testbadmount bad-directory-crc incons-central-crc.zip "" - testmount basic test.zip testdir/test2 $defaultMountPoint testmount basic-on-default test.zip testdir/test2 "" testmount basic-on-root test.zip testdir/test2 [zipfs root] @@ -923,7 +921,7 @@ namespace eval test_ns_zipfs { # # Read/uncompress - proc testuncompress {id zippath result args} { + proc testuncompress {id zippath result {filename abac-repeat.txt} args} { variable defaultMountPoint set zippath [zippath $zippath] test zipfs-uncompress-$id $id -setup { @@ -936,16 +934,17 @@ namespace eval test_ns_zipfs { } cleanup } -body { - set fd [open [file join $defaultMountPoint abac-repeat.txt]] + set fd [open [file join $defaultMountPoint $filename]] gets $fd } -result $result {*}$args } - testuncompress deflate testdeflated2.zip aaaaaaaaaaaaaa testuncompress stored teststored.zip aaaaaaaaaaaaaa - testuncompress bzip2 testbzip2.zip {unsupported compression method} -returnCodes error - testuncompress lzma testfile-lzma.zip {unsupported compression method} -returnCodes error - testuncompress xz testfile-xz.zip {unsupported compression method} -returnCodes error - testuncompress zstd testfile-zstd.zip {unsupported compression method} -returnCodes error + testuncompress deflate testdeflated2.zip aaaaaaaaaaaaaa + testuncompress deflate-error broken.zip {decompression error} deflatezliberror -returnCodes error + testuncompress bzip2 testbzip2.zip {unsupported compression method} abac-repeat.txt -returnCodes error + testuncompress lzma testfile-lzma.zip {unsupported compression method} abac-repeat.txt -returnCodes error + testuncompress xz testfile-xz.zip {unsupported compression method} abac-repeat.txt -returnCodes error + testuncompress zstd testfile-zstd.zip {unsupported compression method} abac-repeat.txt -returnCodes error proc testpassword {id filename password result args} { variable defaultMountPoint @@ -977,7 +976,37 @@ namespace eval test_ns_zipfs { testpassword cipher-deflate cipher-deflate.bin password [lseq 100] testpassword cipher-deflate-nopassword cipher-deflate.bin {} "decryption failed" -returnCodes error testpassword cipher-deflate-badpassword cipher-deflate.bin xxx "decryption failed" -returnCodes error -constraints bug-b3c7429255 - + + # + # CRC errors + proc testcrc {id zippath filename result args} { + variable defaultMountPoint + set zippath [zippath $zippath] + test zipfs-crc-$id $id -setup { + unset -nocomplain fd + zipfs mount $zippath $defaultMountPoint + } -cleanup { + # In case mount succeeded when it should not + if {[info exists fd]} { + close $fd + } + cleanup + } -body { + set fd [open [file join $defaultMountPoint $filename]] + } -result $result -returnCodes error {*}$args + + # Mount memory buffer + test zipfs-crc-memory-$id $id -setup { + zipfs mount_data [readbin [zippath $zippath]] $defaultMountPoint + } -cleanup { + cleanup + } -body { + set fd [open [file join $defaultMountPoint $filename]] + } -result $result -returnCodes error {*}$args + } + testcrc local incons-local-crc.zip a "invalid CRC" + testcrc store-crc broken.zip storedcrcerror "invalid CRC" + testcrc deflate-crc broken.zip deflatecrcerror "invalid CRC" # # file stat |
