tar: strip '/' from incremental 'X' entries

Problem identified by Michał Majchrowicz and Marcin Wyczechowski,
members of the AFINE Team.
* gnulib.modules: Add mempcpy, which we were already using anyway.
* src/incremen.c (purge_directory):
Use a safer suffix for 'X' entries, too.
Also, do not turn "/" to "//" or "//" to "///" (possible only if -P).
This commit is contained in:
Paul Eggert
2026-04-04 10:50:08 -07:00
parent 9280aa3807
commit 0714d2f082
4 changed files with 13 additions and 5 deletions

6
NEWS
View File

@@ -1,4 +1,4 @@
GNU tar NEWS - User visible changes. 2026-03-12
GNU tar NEWS - User visible changes. 2026-04-04
Please send GNU tar bug reports to <bug-tar@gnu.org>
version 1.35.90 (git)
@@ -43,6 +43,10 @@ option.
** When extracting, tar no longer follows symbolic links to targets
outside the working directory.
** When extracting from an incremental dump, tar now strips leading '/'
from names of temporary directories specified by 'X' entries,
unless --absolute-names (-P) is used.
** Fixed O(n^2) time complexity bug for large numbers of directories when
extracting with --delay-directory-restore or reading incremental archives.

2
THANKS
View File

@@ -333,6 +333,7 @@ Marc Boucher marc@cam.org
Marc Espie marc.espie.openbsd@gmail.com
Marc Ewing marc@redhat.com
Marcin Matuszewski marcin@frodo.nask.org.pl
Marcin Wyczechowski mwyczechowski@afine.com
Marcus Daniels marcus@sysc.pdx.edu
Mark Bynum bynum@cennas.nhmfl.gov
Mark Clements mpc@mbsmm.com
@@ -370,6 +371,7 @@ Michael Schmidt michael@muc.de
Michael Schwingen m.schwingen@stochastik.rwth-aachen.de
Michael Smolsky fnsiguc@astro.weizmann.ac.il
Michal Žejdl zejdl@suas.cz
Michał Majchrowicz mmajchrowicz@afine.com
Mike Muuss mike@brl.mil
Mike Nolan nolan@lpl.arizona.edu
Mike Rogers mike@demon.net

View File

@@ -78,6 +78,7 @@ localcharset
manywarnings
mbrtoc32-regular
mcel-prefer
mempcpy
mkdirat
mkdtemp
mkfifoat

View File

@@ -1649,11 +1649,12 @@ purge_directory (char const *directory_name)
if (*arc == 'X')
{
static char const TEMP_DIR_TEMPLATE[] = "tar.XXXXXX";
idx_t len = strlen (arc + 1);
char *d = safer_name_suffix (arc + 1, false, absolute_names_option);
idx_t len = strlen (d);
temp_stub = xrealloc (temp_stub, len + 1 + sizeof TEMP_DIR_TEMPLATE);
memcpy (temp_stub, arc + 1, len);
temp_stub[len] = '/';
memcpy (temp_stub + len + 1, TEMP_DIR_TEMPLATE,
char *copy_end = mempcpy (temp_stub, d, len);
*copy_end = '/';
memcpy (copy_end + !ISSLASH (copy_end[-1]), TEMP_DIR_TEMPLATE,
sizeof TEMP_DIR_TEMPLATE);
if (!mkdtemp (temp_stub))
{