Exclude files and directories matching the given patterns while creating
an archive, using libarchive's matcher for parity with file(ARCHIVE_EXTRACT).
Fixes: #27877.
extract_tar() allocates archive_read, archive_write_disk, and
archive_match handles, but several early-return error paths did not free
them. Most notably, a PATTERNS entry matching nothing leaked all three
handles on every call, which accumulates inside a long-running
configure.
Scope the three handles with std::unique_ptr custom deleters so every
return path releases them automatically. std::unique_ptr does not
invoke the deleter for a null pointer, and the libarchive *_free
functions are themselves no-ops on null, so no explicit guarding is
required. archive_read_free()/archive_write_free() implicitly close the
handle if needed, matching the previous behavior.
Fixes: #27872
Omit archive entries matching the given patterns when extracting or
listing. May be combined with PATTERNS; on overlap the exclusion
takes precedence.
Fixes: #27837
Commit 03f19aa4ea (cmSystemTools: Fix path traversal vulnerability in
archive extraction, 2026-01-06, v4.3.0-rc1~179^2) incidentally
introduced the `ARCHIVE_EXTRACT_SECURE_SYMLINKS` flag when extracting
archives, which prevents extraction of objects whose location would be
altered by a symlink on disk. However, this particular behavior change
was never documented or tested alongside the other changes in the
commit (absolute paths and path traversal components).
Divergent behavior of this flag from `libarchive` on Windows and
non-Windows platforms needs further investigation. In particular, on
Windows, archives cannot be extracted through directory symlinks, but
can be extracted through junctions. On Linux, archives *can* still be
extracted through symlinks, and archives containing symlinks can be
extracted as well.
The symlink change breaks compatibility with many common use cases of
existing projects, e.g., when extracting an archive inside a symlinked
build directory. Revert the flag until this issue can be explored in a
future version of CMake.
Fixes: #27752
Reported-by: scivision <scivision@users.noreply.github.com>
Add security flags to libarchive extraction to prevent path traversal
(Zip Slip) and absolute path attacks:
- ARCHIVE_EXTRACT_SECURE_NODOTDOT: Block ".." path components
- ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS: Block absolute paths
- ARCHIVE_EXTRACT_SECURE_SYMLINKS: Block symlinks escaping extract dir
This hardens both `cmake -E tar` and `file(ARCHIVE_EXTRACT)` against
malicious archives that attempt to write files outside the intended
extraction directory.