Problem reported by Pavel Raiskup in:
https://lists.gnu.org/r/bug-tar/2025-11/msg00028.html
* src/extract.c (contains_dot_dot): Bring back this function here,
from its former location in src/names.c. Make it static since
it is used only in this compilation unit.
They can still be useful if -h is used. See Pavel Cahyna in:
https://lists.gnu.org/r/bug-tar/2025-11/msg00026.html
while we’re at it bring them back if -P is used,
as they can still be useful there too.
* src/extract.c (HAVE_BIRTHTIME, BIRTHTIME_EQ):
Bring back these macros.
(struct delayed_link, struct string_list):
Bring back these structs.
(delayed_link_table, delayed_link_head, delayed_link_tail):
Bring back these static vars.
(dl_hash, dl_compare, find_direct_ancestor)
(find_delayed_link_source, create_placeholder_file)
(apply_delayed_link, apply_delayed_links):
Bring back these static functions.
(mark_metadata_set): Rename from mark_after_links. All uses changed.
(extract_link, extract_symlink):
Create placeholders as before, except only if -P or -h are used.
(extract_finish): Deal with delayed links, as before.
* gnulib.modules: Add nstrftime-limited, time_rz. Sort.
* src/checkpoint.c: Include <strftime.h>.
(format_checkpoint_string): Use nstrftime instead of strftime.
Also fix an obscure bug on platforms that lack tm_gmtoff+tm_zone by
calling tzalloc on those platforms; if it fails, fall back on gmtime.
Also, use fwrite instead of fprintf, since we typically know the
length already and this gives us a more-accurate byte count
in case there are partial writes.
C2y plans to introduce a new countof operator that will be
convenient for GNU tar, so start using it now via Gnulib.
* gnulib.modules: Add stdcountof-h.
* lib/wordsplit.c, src/buffer.c, src/suffix.c, src/tar.c:
Include stdcountof.h, and prefer countof (X) to sizeof X / sizeof *X.
Problem found with clang 15.0 on CheriBSD.
* src/names.c (namelist_match, register_match):
Now plain static, not static COMMON_INLINE, since the later
could mean the declaration is ‘static static’ which is not allowed.
* tests/sparse05.at (listing sparse files bigger than 2^33 B):
If there were problems generating BIGFILE remove it,
as it has likely exhausted the file system.
Problem found on Darwin 21.6 APFS.
Stop using the fprintftime module, as as with recent Gnulib changes
it breaks the build on macOS, and fixing this would drag in threading
libraries and macOS-specific libraries that are overkill for tar.
Instead, just use strftime; that’s good enough here and arguably
better in case someone attacks tar with a huge time format string.
* gnulib.modules: Remove fprintftime.
* src/checkpoint.c: Do not include fprintftime.
(format_checkpoint_string): Always output some useful info (a decimal
seconds count), even if localtime fails. Do not output more than
256 bytes of time info, as that’s likely a DoS attack. Stick with
plain strftime, as fprintftime’s extra features are overkill here.
Needed for Apple clang version 14.0.0 (clang-1400.0.29.202).
* src/common.h (intmax): Define macro only if _Generic works, and
use _Generic in it rather that using EXPR_SIGNED. This is needed
to make the first argument of verify_expr an integer constant
expression, which is required for strict C11. Although GCC is
smart enough to treat (1 ? 0 : V) as an integer constant
expression even if V is an integer variable, C11 does not require
support for this sort of thing.
* src/extract.c (HAVE_BIRTHTIME, BIRTHTIME_EQ, struct delayed_link)
(delayed_link_table, delayed_link_head delayed_link_tail)
(struct string_list, dl_hash, dl_compare, find_direct_ancestor)
(find_delayed_link_source, create_placeholder_file, apply_delayed_link)
(apply_delayed_links): Remove. All uses removed.
(struct delayed_set_stat): New member metadata_set,
replacing after_links. All uses changed.
(apply_nonancestor_delayed_set_stat): Arg METADATA_SET replaces
the old AFTER_LINKS. All callers changed.
(extract_archive): Do not worry about "..", since openat2
now does that for us.
* src/names.c (first_dot_dot): Remove. All uses removed.
This addresses CVE-2025-45582.
* gnulib.modules: Add openat2.
* src/misc.c (open_subdir): New static function.
(fdbase_opendir): Use it.
* src/tar.c (open_searchdir_how): New var, replacing and
augmenting open_searchdir_flags. All uses changed.
* tests/extrac31.at: New file.
* tests/Makefile (TESTSUITE_AT), tests/testuite.at: Add it.
This doesn’t change behavior; it is a refactoring for
compatibility with a future patch that will use Linux’s
openat2 syscall, which is pickier about flags.
* src/tar.c (decode_options): When searching directories,
do not use O_NOCTTY, O_NONBLOCK, and O_NOATIME.
openat2 rejects all three flags if O_PATH is used.
The first two flags are definitely irrelevant for directories,
and O_NOATIME probably doesn’t matter either.
* src/misc.c (fdbase_opendir): When the new directory is a
subdirectory of the old one, open relative to the old one rather
than relative all the way back to chdir_fd, and if that open fails
for a non-EMFILE reason, keep rather than discard the old directory.
Although this might help (or hurt) performance, the main
motivation is to make it easier in future commits
to prevent tarballs from escaping the extraction directory.
* src/common.h: (BADFD): New constant.
(struct fdbase): New type.
* src/create.c (dump_file0): Use parent->fd instead of caching
it into a local, as the latter approach is now awkward.
* src/extract.c (extract_link): Don’t save errno unless needed.
* src/misc.c (safer_rmdir): New arg F. All callers changed.
(maybe_backup_file): Construct full after_backup_name, now
that find_backup_file_name no longer does that for us.
(chdir_fd): Now static not extern, as other modules now use fdbase.
(fdbase_cache): New static var.
(fdbase_clear): New function. Call it whenever removing
or renaming directories or symlinks to directories.
(fdbase_opendir): New static function.
(fdbase, fdbase1): New functions. Call them whenever the
code formerly passed chdir_fd to a syscall.
* gnulib.modules: Add issymlinkat, already an indirect dependency.
* src/extract.c: Include issymlink.h.
(is_directory_link, open_output_file):
Prefer issymlinkat to doing it by hand.
* src/exclist.c (excluded_name):
* src/misc.c (normalize_filename_x, must_be_dot_or_slash)
(chdir_arg):
Use dotslash or dotslashlen instead of doing things by hand.
* src/misc.c (slashlen, dotslashlen): New functions.
(safer_rmdir): Do not worry about unlinkat with AT_REMOVEDIR
succeeding on ".", as POSIX prohibits it, and it does not succeed
on any known platform. This simplifies the file name test.
Continue to worry about "/" though, as POSIX does allow
it to be removed.
This prepares for future changes that need directory IDs.
* src/common.h (struct chdir_id): New struct.
* src/extract.c (extract_dir): Use chdir_id to avoid duplicate stats.
* src/misc.c (struct wd): New member ID.
(grow_wd): New function, extracted from chdir_arg and that
also initializes id.err.
(chdir_arg): Use it. Initialize id.err.
(chdir_id): New function.
I ported our fix into Gnulib so there’s no longer a need
for a separate copy.
* doc/Makefile.am (GENDOCS): Now in ../build-aux, not here.
* doc/gendocs.sh, doc/gendocs_template: Remove.
* gnulib.modules: Add gendocs.
Caught by gcc -fsanitize=address.
Inspired by Matthias Andree’s bug report in:
https://lists.gnu.org/r/bug-tar/2025-08/msg00019.html
though I found this bug via a simple "make check"
with sanitization enabled.
* src/common.h (TIMESPEC_STRSIZE_BOUND):
Make room for leading '-', needed in addition to the '-' room
supplied by SYSINT_BUFSIZE due to the way code_timespec works.
This is more portable to non-POSIX systems.
However, don’t bother trying to port to systems
where st_ino is not a scalar of type dev_t,
as these systems no longer seem to be active targets
and it’s not worth the maintenance hassle.
* gnulib.modules: Add same-inode, now that we use it
explicitly rather than indirectly.
* src/compare.c (diff_link):
* src/create.c (compare_links, restore_parent_fd):
* src/incremen.c (compare_directory_meta, procdir):
* src/extract.c (dl_compare, repair_delayed_set_stat)
(apply_nonancestor_delayed_set_stat, extract_link)
(apply_delayed_link):
* src/names.c (add_file_id):
* src/system.c (sys_file_is_archive, sys_detect_dev_null_output):
Include same-inode.h, and prefer its macros and functions
to doing things by hand.
* src/create.c (struct link):
* src/extract.c (struct delayed_set_stat, struct delayed_link):
* src/incremen.c (struct directory):
* src/names.c (struct file_id_list):
Rename members to st_dev and st_ino so that SAME_INODE and
PSAME_INODE can be used on the type. All uses changed.
* src/system.c (sys_compare_links): Remove.
All uses replaced by psame_inode.
Texinfo 7.2 began warning about the '.info' suffix in the manual names
passed to @xref and similar commands. They eventually plan to stop
stripping the '.info' suffix internally which will lead to broken links
in the manuals without this change.
* doc/tar.texi (files): Remove '.info' suffix from manual name.
Problem and fix reported by Pavel Cahyna in
https://lists.gnu.org/r/bug-tar/2025-01/msg00000.html
* src/extract.c (extract_dir): With --no-overwrite-dir,
skip the chmod if the directory already exists.
* tests/extrac23.at (--no-overwrite-dir on empty directory):
Move the part of the test that looks at a nonempty directory ...
* tests/extrac30.at: ... to this new file, because the test now
must be run as non-root. Adjust the test to match the new behavior.
* tests/Makefile.am (TESTSUITE_AT), tests/testsuite.at: Add it.
* src/incremen.c: Include flexmember.h.
(struct dumpdir): contents is now a flexible member, not a pointer.
This is more idiomatic and slightly more efficient.
(dumpdir_create0): Adjust to the new struct dumpdir layout.