[prev in list] [next in list] [prev in thread] [next in thread] 

List:       tar-bug
Subject:    Re: [Bug-tar] segfault on solaris 11.1 with --remove-files in current directory
From:       Paul Eggert <eggert () cs ! ucla ! edu>
Date:       2014-04-29 21:30:23
Message-ID: 536019EF.3090903 () cs ! ucla ! edu
[Download RAW message or body]

Thanks for reporting that.  It's a bug on GNU/Linux too.  I installed 
the attached patch; please give it a try if you have the time.

I should mention that older versions of GNU tar did not try to remove 
directories in this case, which explains why you didn't see a problem 
with tar trying to remove ".".   With the fix, tar will complain that it 
can't remove ".", which is arguably the correct behavior.  To have the 
fixed tar remove "." without complaining, please use the -C option, 
e.g., something like this:

$ mkdir test
$ touch test/foo
$ tar --remove-files -cf test.tar -C test .
$ ls -al test
ls: cannot access test: No such file or directory
$ tar -tvf test.tar
drwxr-xr-x eggert/eggert     0 2014-04-29 14:26 ./
-rw-r--r-- eggert/eggert     0 2014-04-29 14:26 ./foo


["0001-tar-do-not-dereference-NULL-pointer-with-remove-file.patch" (text/x-patch)]

From e2a40974221b9be70b0efe46eeebdd7c2db3550c Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
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 <http://www.gnu.org/licenses/>.
+
+# 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])
-- 
1.9.0



[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic