zip_get_name() returns NULL on a corrupted central directory entry;
several call sites passed its result straight into endsWith(),
std::string construction, or the fileAllowed() lambda (which calls
HasParentDirComponent()/strchr()/strrchr() on it) without checking -
undefined behavior on a malformed/malicious zip (game/homebrew/texture
pack installs, or a downloaded ISO zip).
zip_stat_index() can likewise fail, leaving its output zip_stat
uninitialized; ZipReadFileByIndex, DetectTexturePackDest, and
ExtractFile all used the result (zstat.size, to size a buffer or check
a texture-pack size limit) without checking the call succeeded first,
using an initialized zip_stat via zip_stat_init() so the failure case
reads a known-zero size instead of stack garbage that could drive a
huge buffer.resize() or bypass the texture-pack size limit check.
ZipReadFileByIndex also didn't check zip_fopen_index()'s return before
passing it to zip_fread().
ExtractZipContents wrote every entry's declared size with no ceiling, so
a small high-ratio zip could decompress to fill the storage device.
- Add a maxTotalSize parameter to ExtractZipContents (default 4GB) and
ExtractFile.
- Bail out in the size-summation pass when the total declared size
exceeds the limit, and again per write chunk in case declared sizes
are inaccurate.
A crafted zip with a parent-directory ("..") entry name could escape the
destination directory during extraction, writing arbitrary files on the
host (e.g. into startup/autostart folders). ExtractZipContents built the
output path by concatenating the raw zip entry name onto the destination
with no traversal check.
Changes:
- Add HasParentDirComponent() utility in Core/Util/PathUtil and use it in
GameManager::ExtractZipContents to reject entries with a ".." component.
Guard both the directory-creation and file-writing passes.
- Expose ExtractZipContents as public for testing.
- Add unittest/TestZipSlip which crafts a zip with a "../evil.txt" entry
and verifies it is not written outside the destination directory.
* Rename LogType to Log
* Explicitly use the Log:: enum when logging. Allows for autocomplete when editing.
* Mac/ARM64 buildfix
* Do the same with the hle result log macros
* Rename the log names to mixed case while at it.
* iOS buildfix
* Qt buildfix attempt, ARM32 buildfix