Fix ZIP member selection - #19256
Merged
LibretroAdmin merged 2 commits intoJul 28, 2026
Merged
Conversation
SaveEditors
force-pushed
the
fix-zip-member-selection
branch
from
July 25, 2026 14:05
d0bf9ce to
ff5e3da
Compare
SaveEditors
force-pushed
the
fix-zip-member-selection
branch
from
July 25, 2026 17:10
ff5e3da to
50b288a
Compare
The sidecar filter sat in file_archive_get_file_list_cb, which meant it
ran once per central-directory entry and only helped the one consumer
that goes through that callback. Move it into the ZIP backend's
directory walk instead.
The callback had to re-derive the backend from the path on every member
to decide whether the archive was a ZIP - a PATH_MAX_LENGTH strlcpy, an
archive-delimiter scan, an extension parse and up to three case-folded
comparisons per entry - and then walk the entry name byte by byte to
find its segment boundaries. Inside zip_parse_file_iterate_step_internal
the format is known and the central-directory name length has already
been read, so the check needs no strlen, no scan of the whole name, and
no backend lookup; the entry is dropped before its name is even copied
out of the directory block.
Doing it in the walk also covers every consumer rather than the listing
callback alone. file_archive_extract_cb selects on extension, so a
"._game.nes" sidecar matched it and cores requiring uncompressed content
were still handed the metadata file:
before file_archive_extract_file(mac.zip, "nes") -> ._game.nes
after file_archive_extract_file(mac.zip, "nes") -> game.nes
An archive holding nothing but sidecars now reports no extractable
content instead of extracting one. The end-of-central-directory record
counts the skipped entries, so step_total is decremented as they are
dropped, keeping the decompress progress denominator honest; a Mac-made
two-entry archive reported 50% at completion before and reports 100% now.
Listing 100,000 entries, -O2, best of 60 per run, 9 interleaved runs:
master 12.39 ms
filter in callback 17.69 ms (+42.8%)
filter in the walk 12.71 ms (+2.6%)
Listing results are unchanged on every fixture tried, including
lookalikes ("My__MACOSX/rom.nes", "__MACOSXX/rom2.nes", "_.nes",
"a._b.nes"), nested sidecars, an explicit "__MACOSX/" directory entry,
a sidecar-only archive and an empty archive. Explicit member reads are
unchanged except that a sidecar can no longer be requested by name,
which follows from the entry no longer being enumerated.
Verified against zlib and against the built-in inflate, with
ARCHIVE_HAVE_ZLIB and ARCHIVE_USE_BUILTIN_DEFLATE forced both ways, and
with HAVE_ZLIB alone. The sample suite passes unmodified, plain and
under ASan/UBSan.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
ZIP file lists can expose macOS AppleDouble metadata before the actual content file. Explicit ZIP member reads also use substring matching, so a request for
game.nescan select__MACOSX/._game.nes.This change ignores
__MACOSXand._metadata entries during ZIP-compatible archive listing. Buffered and incrementalzip#memberreads now require the complete entry name, consistent with the 7z backend.Malformed archives that fail backend initialization now pass through the existing error cleanup before returning. This closes the opened archive stream and clears transfer ownership without changing the iterator's failure result.
The archive sample generates its ZIP inputs and verifies malformed archives, filtered and unfiltered listings, buffered reads, incremental entry-source reads, and initialization-failure cleanup without adding binary fixtures.
Testing
Windows:
make clean allarchive_zip_test.exeMakefile.winbuild with-std=gnu89retroarch-cleanup-test.exe --versionCI:
Build and run libretro-common/sampleswith ASan/UBSanRelated Issues
Fixes #19242.
Related Pull Requests
None.
Reviewers