The test runner already lists available tests if it fails to parse the
command line, but add a -l option to explicitly do this without also
printing an error message and a summary of options.
tree_reopen() and tree_dup() return NULL only of they
are unable to allocate memory. Otherwise libarchive enters
ARCHIVE_FATAL if trying to walk an enterable but unreadable
directory.
__archive_ensure_cloexec_flag() operates only on fd >= 0
so there is no need to skip it
Uses the sed-like way (and Java-like, and .Net-like, and Javascript-like…) to fix this issue of advancing the string to be processed by one if the match is zero-length.
Fixes libarchive/libarchive#2725 and solves libarchive/libarchive#2438.
Skip over LZ4/zstd skippable frames when detecting data format
Since LZ4 and zstd share the same format for skippable frames, we need
to skip over these frames when trying to detect the format of compressed
data. Let's read up to something like 64kb of data when performing this
scanning.
Note that the LZ4 specification advises against starting with a skippable
frame, but doesn't forbid it:
> For the purpose of facilitating identification, it is discouraged to
> start a flow of concatenated frames with a skippable frame. If there
> is a need to start such a flow with some user data encapsulated into
> a skippable frame, it's recommended to start with a zero-byte LZ4
> frame followed by a skippable frame. This will make it easier for
> file type identifiers.
Test that we can read lz4 data with leading skippable frames
This is expected to fail until a followup commit, because lz4 and zstd
skippable frames are the same format and we don't skip over those when
performing format detection (yet).
Whenever we need to create a temporary file while writing to disk on a
POSIX system, try to create it in the same directory as the final file
instead of the current working directory. The target directory can
reasonably be expected to be writable (and if it isn't, creating the
file will fail anyway), but the current working directory may not be.
While here, consistently use __archive_mkstemp(), and increase the
template from six to eight random characters.
Raise the maximum size of Mac metadata from 4 MiB to 10 MiB, as that is
the value used by Apple themselves in the version of libarchive included
in Darwin.
Provide preprocessor macros for two recurring magic numbers in the zip
support code: the length of the local file header (30 bytes) and the
maximum allowable size for Mac metadata (4 MiB).
In archive_util.c, we have a private function named get_tempdir() which
is used by __archive_mktemp() to get the temporary directory if the
caller did not pass one.
In archive_read_disk_entry_from_file.c, we use the same logic with a
slight twist (don't trust the environment if setugid) to create a
temporary file for metadata.
Merge the two by renaming get_tempdir() to __archive_get_tempdir() and
unstaticizing it (with a prototype in archive_private.h).
dependabot[bot] [Mon, 6 Oct 2025 16:07:23 +0000 (16:07 +0000)]
CI: Bump the all-actions group across 1 directory with 3 updates
Bumps the all-actions group with 3 updates in the / directory: [actions/checkout](https://github.com/actions/checkout), [github/codeql-action](https://github.com/github/codeql-action) and [ossf/scorecard-action](https://github.com/ossf/scorecard-action).
Updates `actions/checkout` from 4.2.2 to 5.0.0
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/11bd71901bbe5b1630ceea73d27597364c9af683...08c6903cd8c0fde910a37f88322edcfb5dd907a8)
Updates `github/codeql-action` from 3.28.18 to 3.29.8
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/ff0a06e83cb2de871e5a09832bc6a81e7276941f...76621b61decf072c1cee8dd1ce2d2a82d33c17ed)
Updates `ossf/scorecard-action` from 2.4.1 to 2.4.2
- [Release notes](https://github.com/ossf/scorecard-action/releases)
- [Changelog](https://github.com/ossf/scorecard-action/blob/main/RELEASE.md)
- [Commits](https://github.com/ossf/scorecard-action/compare/f49aabe0b5af0936a0987cfb85d86b75731b0186...05b42c624433fc40578a4040d5cf5e36ddca8cde)
Chris McGee [Mon, 22 Sep 2025 14:58:38 +0000 (10:58 -0400)]
Add a clang module map for libarchive
When compiling libarchive using clang in module mode a special
module.modulemap file describes the structure of the header files
so that they can be imported modularly. Having this file makes
it easier for modular uses of the library out of the box so that
clients don't need to write their own, potentially making errors
in doing so.
Add a module.modulemap in the public header file location so that
clang and related tools can find it easily.
Tim Kientzle [Tue, 16 Sep 2025 15:25:57 +0000 (08:25 -0700)]
Fix an infinite loop when parsing `V` headers
Our tar header parsing tracks a count of bytes that need to be
consumed from the input. After each header, we skip this many bytes,
discard them, and reset the count to zero. The `V` header parsing
added the size of the `V` entry body to this count, but failed to
check whether that size was negative. A negative size (from
overflowing the 64-bit signed number parsing) would decrement this
count, potentially leading us to consume zero bytes and leading to an
infinite loop parsing the same header over and over.
There are two fixes here:
* Check for a negative size for the `V` body
* Check for errors when skipping the bytes that
need to be consumed
Thanks to Zhang Tianyi from Wuhan University for finding
and reporting this issue.
Tim Kientzle [Sat, 13 Sep 2025 19:30:03 +0000 (12:30 -0700)]
Rename err.h to avoid conflict with system header
Depending on header search path ordering, we can easily
confuse libarchive_fe/err.h with the system header.
Rename ours to lafe_err.h to avoid the confusion.
Rename libarchive_fe/err.c to match.
Tim Kientzle [Fri, 12 Sep 2025 16:01:13 +0000 (09:01 -0700)]
Ignore overlong gzip original_filename
We reuse the compression buffer to format the gzip header,
but didn't check for an overlong gzip original_filename.
This adds that check. If the original_filename is
over 32k (or bigger than the buffer in case someone shrinks
the buffer someday), we WARN and ignore the filename.
archive_write: Set archive state to fatal if format or filters fail
In archive_write_header(), if the format method or a filter flush method
fails, we set the archive state to fatal, but we did not do this in
archive_write_data() or archive_write_finish_entry(). There is no good
reason for this discrepancy. Not setting the archive state to fatal
means a subsequent archive_write_free() will invoke archive_write_close()
which may retry the operation and cause archive_write_free() to return
an unexpected ARCHIVE_FATAL.
write_add_filter_bzip2: End compression in the freer
If a fatal error occurs, the closer will not be called, so neither will
BZ2_bzCompressEnd(), and we will leak memory. Fix this by calling it a
second time from the freer. This is harmless in the non-error case as
it will see that the compression state has already been cleared and
immediately return BZ_PARAM_ERROR, which we simply ignore.
archive_write_client: Free state in freer, not in closer
The closer will not be called if a fatal error occurs, so the current
arrangement results in a memory leak. The downside is that the freer
may be called even if we were not fully constructed, so it needs to
perform additional checks. On the other hand, knowing that the freer
always gets called and will free the client state simplifies error
handling in the opener.