Problem reported by Rob Schmidt in: https://lists.gnu.org/r/bug-tar/2026-08/msg00010.html fixup_delayed_set_stat changed the name of an entry in delayed_set_stat_table, which is hashed on that name, without moving the entry to the new name's bucket. A later lookup of the new name missed it and made a second entry, so the older entry's status, including its time stamps, was applied to the renamed directory last. When the entry was later freed, hash_remove looked for it in the new name's bucket, so the table kept pointing to freed memory. The bug was introduced by commit a5afb367655ac6dcbc79ba7802a2479044184b38 (2023-08-21). * src/extract.c (fixup_delayed_set_stat): Remove the entry from delayed_set_stat_table before renaming it, and insert it again after. * tests/incr11.at: Check the mtime of the renamed directory. --- src/extract.c | 3 +++ tests/incr11.at | 6 ++++++ 2 files changed, 9 insertions(+)
diff --git a/src/extract.c b/src/extract.c
index 2bb0e80f..244b91f2 100644
--- a/src/extract.c
+++ b/src/extract.c
@@ -762,9 +762,12 @@ fixup_delayed_set_stat (char const *src, char const *dst)
if (chdir_current == data->change_dir
&& streq (data->file_name, src))
{
+ hash_remove (delayed_set_stat_table, data);
free (data->file_name);
data->file_name = xstrdup (dst);
data->file_name_len = strlen (dst);
+ if (! hash_insert (delayed_set_stat_table, data))
+ xalloc_die ();
return;
}
}
diff --git a/tests/incr11.at b/tests/incr11.at
index c02c2b9e..4e1da5a0 100644
--- a/tests/incr11.at
+++ b/tests/incr11.at
@@ -21,6 +21,8 @@
# Reported by: Alex Efros <[email protected]>
# References: <[email protected]>
# http://lists.gnu.org/archive/html/bug-tar/2015-11/msg00033.html
+# The renamed directory gets its mtime from the second archive.
+# References: https://lists.gnu.org/r/bug-tar/2026-08/msg00010.html
AT_SETUP([concatenated incremental archives (renames)])
AT_KEYWORDS([incremental concat cat incr11 chdir])
@@ -29,10 +31,13 @@ AT_TAR_CHECK([
AT_CHECK_TIMESTAMP
AT_SORT_PREREQ
AT_TAR_MKHIER([data/dir],[file])
+touch -d 2000-01-01T00:00:00 data/dir >/dev/null 2>&1 || AT_SKIP_TEST
decho Level 0
tar -cvf full.tar -g snap -C data .
decho Level 1
mv data/dir data/dir2
+touch data/dir2
+genfile --stat=mtime data/dir2 > ts
tar -cvf incr.tar -g snap -C data .
decho Concat
cp full.tar full2.tar
@@ -42,6 +47,7 @@ mkdir out
tar -xvf full2.tar -g /dev/null -C out
decho List
find out | sort
+genfile --stat=mtime out/dir2 | diff ts -
],
[0],
[Level 0
--
2.53.0
0001-tar-rehash-delayed_set_stat-entry-on-rename.patch
Description: Binary data
