From fc58a8bd984eb5334f713ec7ac993bddfe9e77d3 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Tue, 29 Apr 2014 14:22:07 -0700 Subject: [PATCH] tar: do not dereference NULL pointer with '--remove-files .' Problem reported by Thorsten Hirsch in: http://lists.gnu.org/archive/html/bug-tar/2014-04/msg00011.html * src/unlink.c (flush_deferred_unlinks): Do not attempt to find the parent of "." when "." is at the top level. * tests/remfiles10.at: New file. * tests/Makefile.am (TESTSUITE_AT): * tests/testsuite.at: Add it. --- src/unlink.c | 9 +++++---- tests/Makefile.am | 1 + tests/remfiles10.at | 46 +++++++++++++++++++++++++++++++++++++++++++++ tests/testsuite.at | 1 + 4 files changed, 53 insertions(+), 4 deletions(-) create mode 100644 tests/remfiles10.at diff --git a/src/unlink.c b/src/unlink.c index 225d49b..7f86cc5 100644 --- a/src/unlink.c +++ b/src/unlink.c @@ -73,7 +73,7 @@ flush_deferred_unlinks (bool force) { struct deferred_unlink *p, *prev = NULL; int saved_chdir = chdir_current; - + for (p = dunlink_head; p; ) { struct deferred_unlink *next = p->next; @@ -86,15 +86,16 @@ flush_deferred_unlinks (bool force) { const char *fname; - if (p->file_name[0] == 0 || - strcmp (p->file_name, ".") == 0) + if (p->dir_idx + && (p->file_name[0] == 0 + || strcmp (p->file_name, ".") == 0)) { fname = tar_dirname (); chdir_do (p->dir_idx - 1); } else fname = p->file_name; - + if (unlinkat (chdir_fd, fname, AT_REMOVEDIR) != 0) { switch (errno) diff --git a/tests/Makefile.am b/tests/Makefile.am index 3896b72..fd2def5 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -187,6 +187,7 @@ TESTSUITE_AT = \ remfiles09a.at\ remfiles09b.at\ remfiles09c.at\ + remfiles10.at\ same-order01.at\ same-order02.at\ shortfile.at\ diff --git a/tests/remfiles10.at b/tests/remfiles10.at new file mode 100644 index 0000000..b4fe139 --- /dev/null +++ b/tests/remfiles10.at @@ -0,0 +1,46 @@ +# Process this file with autom4te to create testsuite. -*- Autotest -*- +# Test suite for GNU tar. +# Copyright 2014 Free Software Foundation, Inc. +# +# GNU tar is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# GNU tar is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Check --remove-files with . + +AT_SETUP([remove-files]) +AT_KEYWORDS([create remove-files remfiles10]) + +AT_TAR_CHECK([ +mkdir foo +echo foo/file > foo/file +decho A +(cd foo && tar -cvf ../foo.tar --remove-files .) +tar_status=$? +decho B +find foo +exit $tar_status +], +[2], +[A +./ +./file +B +foo +], +[A +tar: .: Cannot rmdir: Invalid argument +tar: Exiting with failure status due to previous errors +B +],[],[],[gnu]) + +AT_CLEANUP diff --git a/tests/testsuite.at b/tests/testsuite.at index 3096e0d..7f8e4c4 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -399,6 +399,7 @@ m4_include([remfiles08c.at]) m4_include([remfiles09a.at]) m4_include([remfiles09b.at]) m4_include([remfiles09c.at]) +m4_include([remfiles10.at]) AT_BANNER([Extended attributes]) m4_include([xattr01.at]) -- 2.43.0