Summary: | Incorrect handling of zip files with data descriptors | ||
---|---|---|---|
Product: | [Frameworks and Libraries] frameworks-karchive | Reporter: | Lauri Koskela <lk> |
Component: | general | Assignee: | David Faure <faure> |
Status: | RESOLVED FIXED | ||
Severity: | normal | CC: | aacid, elvis.angelaccio, kdelibs-bugs-null, meven29, nate, sunny.bed7466 |
Priority: | NOR | ||
Version First Reported In: | unspecified | ||
Target Milestone: | --- | ||
Platform: | Compiled Sources | ||
OS: | Linux | ||
Latest Commit: | https://invent.kde.org/frameworks/karchive/-/commit/6db83e409131de9f3e00ae18a1cd6113250f9611 | Version Fixed In: | |
Sentry Crash Report: | |||
Attachments: | A zip file that karchive cannot read |
Description
Lauri Koskela
2022-02-20 05:04:41 UTC
A possibly relevant merge request was started @ https://invent.kde.org/frameworks/karchive/-/merge_requests/34 A possibly relevant merge request was started @ https://invent.kde.org/frameworks/karchive/-/merge_requests/109 Git commit ce749a2cb1bccc02f89cfe3536207d71b8cf0657 by Stefan Brüns. Committed on 30/03/2025 at 19:03. Pushed by bruns into branch 'master'. kzip: Add various test cases testZip64NestedStored: Verify KZip does not trip over the signatures of the nested ZIP file, but only uses the signatures/headers of the outer file. testZip64NestedStoredStreamed: Verify KZip does not trip over the signatures of the nested ZIP file, but only uses the signatures/headers of the outer file. Currently fails, as data descriptors of the inner file are taken instead of the outer ones. testZip64EndOfCentralDirectory: Zip64 files may contain "Zip64 end of central directory record"s, with signature "PK\6\6". Currently fails. testZip64DataDescriptor: Zip64 data descriptors use 64 bit fields for compressed and uncompressed size instead of the normal 32 bit fields, thus the next record offset differs by 8 bytes. Currently fails. The new files have been created with Info-ZIP `zip`: > echo -ne "abcd" | zip zip64_end_of_central_directory.zip - > echo -ne "abcd" | zip - - | cat > zip64_datadescriptor.zip > zip - zip64_datadescriptor.zip zip64_end_of_central_directory.zip \ | cat > zip64_nested_stored_streamed.zip Related: bug 403899 A +- -- autotests/data/zip64_datadescriptor.zip A +- -- autotests/data/zip64_end_of_central_directory.zip A +- -- autotests/data/zip64_nested_stored_streamed.zip M +94 -0 autotests/karchivetest.cpp M +4 -0 autotests/karchivetest.h https://invent.kde.org/frameworks/karchive/-/commit/ce749a2cb1bccc02f89cfe3536207d71b8cf0657 Git commit 6db83e409131de9f3e00ae18a1cd6113250f9611 by Stefan Brüns. Committed on 30/03/2025 at 19:03. Pushed by bruns into branch 'master'. kzip: Fix misdetection of nested signatures, handle Zip64 data descriptors In case a zip file entry has an undetermined size in the local header the end of the binary data is marked by a data descriptor, with signature 'PK\7\8'. This will occasionally fail for two different reasons: 1. Compressed data randomly matching the signature 2. Stored, nested ZIP files. In the first case, almost any sanity check for the following data will do. In the second case, the 'compressed size' field of the data descriptor will not match the current position difference. Only for the data descriptor of the outer ZIP file (start position + uncompressed size == current position) will match. Also fix the size of the Zip64 data descriptors, and skip to the next header correctly. Zip64 data descriptors are marked by a "needed version" of 45 or later in the preceding local header. The header seeking is mostly rewritten. Instead of seeking backwards and forwards, and reading one character at a time from the underlying QIODevice, a larger block is read using peek(). Scanning through the block for a 'PK' signature is significantly faster than the one-byte-at-a-time approach. M +0 -2 autotests/karchivetest.cpp M +92 -79 src/kzip.cpp https://invent.kde.org/frameworks/karchive/-/commit/6db83e409131de9f3e00ae18a1cd6113250f9611 |