If run as root (as is the case in CI), switch to an unprivileged user
(default: nobody) before running each test, and switch back after.
This makes it possible to write tests that rely on file permissions.
Note that tests that use the UID or GID must now check the EUID / EGID
instead as they will be different while the test is running. The only
way to avoid that is to run each test case in a child process, which
would hugely increase the complexity of test_run().
When create_dir() fails to create a directory, it immediately checks to
see if the directory already exists, which can happen if it's been given
something like foo/../foo. Unfortunately, this clobbers errno, which
means that create_dir() always reports ENOENT, regardless of the actual
error. Fix this by only performing this extra check if errno is EEXIST,
then reset errno to either EEXIST or ENOTDIR depending on the outcome.
Tim Kientzle [Sun, 1 Mar 2026 21:45:50 +0000 (13:45 -0800)]
Reject LHA archives with ridiculously large headers
The header is a series of blocks, most of which contain
values of just a few bytes (sizes, times, etc). The only
exceptions are the filename and directory name attributes,
which will be limited by the MSDOS/Windows maximum file length
limit. So it seems unlikely that this will ever exceed 64k.
(If we find counter-examples, we can easily extend this limit.)
Tim Kientzle [Sun, 1 Mar 2026 20:17:05 +0000 (12:17 -0800)]
Prune FreeBSD CI from 10 variations down to 3
Previously, we tested many combinations of FreeBSD version, build system, and filesystem.
In practice, that's redundant, and we've started seeing these excessive requests get throttled by Cirrus.
Cutting back to just 3 combinations should suffice and reduce the risk of throttling.
Brad King [Fri, 27 Feb 2026 19:35:55 +0000 (14:35 -0500)]
7zip: Fix out-of-bounds access on ELF 64-bit header
The ELF specification's `Elf64_Ehdr` type is 64 bytes [1].
`find_elf_data_sec` accesses the last field, `e_shstrndx`.
Make sure we read enough data to populate it.
If an incorrect option value has been passed to a filter, it is possible
that library operations continue without even printing a warning.
This can happen because the special value "ARCHIVE_WARN - 1" is only
checked for filter issues, not format issues. Since this special value
is larger than ARCHIVE_FAILED, such failures are silently discarded.
Fix this by checking for this magic value for formats as well.
Vijay D'Silva [Thu, 12 Feb 2026 03:51:51 +0000 (03:51 +0000)]
7zip: Fix SEGV in check_7zip_header_in_sfx via ELF offset validation
The crash reported in this issue is caused by a segmentation fault
that happens when a pointer `p` passed to `check_7zip_header_in_sfx`
is dereferenced. That argument `p` is defined as `p = buff + offset` in
`archive_read_format_7zip_bid` with `offset` determined by a call
to `find_elf_data_sec`.
Within `find_elf_data_sec`, a 64-bit ELF section offset is cast
to `ssize_t`. For a sufficiently large offset, such as an unsigned
64-bit value exceeding `SSIZE_MAX`, the `ssize_t` will be negative,
which leads to `p` to point before the start of the buffer.
This patch eliminates the problem by:
1. Reading the ELF section offset into a `uint64_t`.
2. Validating that the offset does not exceed `SSIZE_MAX`.
3. If the offset is invalid, breaking the loop to retain the safe
default `SFX_MIN_ADDR`.
These checks ensure that `min_addr` is always within the bounds of the buffer.
This PR includes a regression test `test_malformed3` in
`test_read_format_7zip_malformed.c` using a crafted reproducer file.
CodeMender verified with AddressSanitizer that the crash is resolved and the
test suite passes.
zhangjy1014 [Mon, 9 Feb 2026 03:20:18 +0000 (11:20 +0800)]
Add test for malformed "default" ACL prefix (issue #2744)
Verify that archive_entry_acl_from_text() and
archive_entry_acl_from_text_w() return ARCHIVE_WARN instead of
crashing when given a bare "d" or "default" string with no
subsequent tag field.
Without the accompanying fix in archive_acl.c this test triggers
a NULL-pointer dereference (SEGV) in archive_acl_from_text_w().
zhangjy1014 [Sun, 8 Feb 2026 09:18:43 +0000 (17:18 +0800)]
Fix NULL pointer dereference in archive_acl_from_text_w()
When parsing a short "default" ACL prefix (e.g. L"d") with no
subsequent tag field, field[n] is left as {NULL, NULL} and the
code dereferences it unconditionally in the switch statement,
causing a SEGV.
Add a zero-length check after computing the field length so that
malformed entries are skipped with ARCHIVE_WARN, matching the
documented contract. Also move the st pointer computation after
the guard to avoid dereferencing a NULL start pointer.
Brad King [Wed, 4 Feb 2026 21:35:03 +0000 (16:35 -0500)]
archive_write: Fix crash on failure to convert WCS/UTF-8 pathname to MBS
If an entry pathname is set only by WCS or UTF-8, it may not have any
MBS representation in the archive's hdrcharset. Do not crash or create
an archive with an empty pathname. Furthermore, the entry pathname may
not have any MBS representation in the current locale. Do not report a
`(null)` pathname in the error message.
Brad King [Wed, 4 Feb 2026 21:42:26 +0000 (16:42 -0500)]
archive_string_append_from_wcs: Fix silently lossy conversions on Windows
On Windows, since commit ae54394104 (Implement a string conversion
interface..., 2011-05-09, v3.0.0a~398), `archive_string_append_from_wcs`
no longer returns an error on use of replacement characters in non-C
locales. Restore the error to avoid silent use of replacement
characters, and for consistency across platforms.
Brad King [Wed, 4 Feb 2026 21:22:39 +0000 (16:22 -0500)]
archive_mstring_get_mbs_l: Restore error on failure to convert from WCS/UTF-8
Prior to commit c30f279475 (Complete support for UTF8 encoding
conversion, 2020-05-31, v3.5.0~32^2), `archive_mstring_get_mbs_l` returned
an error on failure to convert WCS to MBS. Restore the error so callers
can distinguish conversion failure from having no string in any form.
On Windows, `archive_mstring_get_mbs_l` from WCS with `sconv != NULL`
internally calls `archive_string_append_from_wcs_in_codepage` more than
once, with both `sconv != NULL` and `sconv == NULL`. Due to another bug
in the `sconv == NULL` case, we cannot enable all test combinations yet.
This happens because `--gc-sections` isn't supported on illumos `ld`.
This patch updates CMakeLists.txt to skip unsupported linker options on
illumos. The flags used on other operating systems are optimizations
that don't affect correctness, so this change is safe.
dependabot[bot] [Thu, 25 Dec 2025 08:53:17 +0000 (08:53 +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), [actions/upload-artifact](https://github.com/actions/upload-artifact) and [github/codeql-action](https://github.com/github/codeql-action).
Updates `actions/checkout` from 5.0.0 to 5.0.1
- [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/08c6903cd8c0fde910a37f88322edcfb5dd907a8...93cb6efe18208431cddfb8368fd83d5badbf9bfd)
Leslie P. Polzer [Mon, 22 Dec 2025 04:53:06 +0000 (04:53 +0000)]
Refactor all fuzzers to use shared fuzz_helpers.h
Complete the refactoring of all 25 fuzzers:
- Remove duplicate Buffer struct definitions from 15 format fuzzers
- Remove duplicate DataConsumer class from 7 API fuzzers
- Update consume_bytes() calls to match new signature
- All fuzzers now use shared helpers from fuzz_helpers.h
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.