summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--generic/tclZipfs.c22
-rw-r--r--tests/zipfs.test49
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