bug-tar
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Bug-tar] [PATCH] Option to treat tarbombs as errors


From: Connor Behan
Subject: [Bug-tar] [PATCH] Option to treat tarbombs as errors
Date: Sat, 17 Aug 2013 16:28:52 -0700

There has been recent discussion around whether GNU tar should have an
option to deal with archives that do not follow the practice of having
everything in one directory. As an alternative to more involved patches
that have been proposed, this simply adds a new error to help the user
not see as many unpleasant surprises. Various workarounds could then be
used on an individual basis.

Signed-off-by: Connor Behan <address@hidden>
---
 doc/tar.texi  |  7 +++++++
 src/common.h  |  3 +++
 src/extract.c | 23 +++++++++++++++++++++++
 src/tar.c     |  7 +++++++
 4 files changed, 40 insertions(+)

diff --git a/doc/tar.texi b/doc/tar.texi
index 2661174..ef76cfe 100644
--- a/doc/tar.texi
+++ b/doc/tar.texi
@@ -3270,6 +3270,13 @@ the archive creation operations it instructs 
@command{tar} to list the
 member names stored in the archive, as opposed to the actual file
 names.  @xref{listing member and file names}.
 
address@hidden
address@hidden --single-top-level
+
+Tells @command{tar} to extract only one name from the archive into its
+parent directory or the one specified with @option{-C}. A fatal error is
+thrown if a second one is found.
+
 @opsummary{skip-old-files}
 @item --skip-old-files
 
diff --git a/src/common.h b/src/common.h
index 21df8c1..0cf7da3 100644
--- a/src/common.h
+++ b/src/common.h
@@ -270,6 +270,9 @@ GLOBAL size_t strip_name_components;
 
 GLOBAL bool show_omitted_dirs_option;
 
+/* Refuse to extract more than one name that does not contain a slash  */
+GLOBAL bool single_top_level_option;
+
 GLOBAL bool sparse_option;
 GLOBAL unsigned tar_sparse_major;
 GLOBAL unsigned tar_sparse_minor;
diff --git a/src/extract.c b/src/extract.c
index 319aaa8..8f77a88 100644
--- a/src/extract.c
+++ b/src/extract.c
@@ -1559,6 +1559,25 @@ prepare_to_extract (char const *file_name, int typeflag, 
tar_extractor_t *fun)
   return 1;
 }
 
+/* Throws an error if passed file name is the second top-level name.  */
+void
+top_level_check (char *file_name)
+{
+  static bool has_top_level = false;
+  int i;
+
+  for (i = 0; i < strlen (file_name); i++)
+   if (ISSLASH (file_name[i])) break;
+
+  if (i == strlen (file_name))
+    {
+      if (has_top_level)
+        FATAL_ERROR ((0, 0, _("More than one top-level name found, exiting")));
+
+      has_top_level = true;
+    }
+}
+
 /* Extract a file from the archive.  */
 void
 extract_archive (void)
@@ -1604,6 +1623,10 @@ extract_archive (void)
        return;
       }
 
+  /* Ensure that we are not extracting more than one top-level file.  */
+  if (single_top_level_option)
+      top_level_check (current_stat_info.file_name);
+
   /* Extract the archive entry according to its type.  */
   /* KLUDGE */
   typeflag = sparse_member_p (&current_stat_info) ?
diff --git a/src/tar.c b/src/tar.c
index c3c2459..1f4c9da 100644
--- a/src/tar.c
+++ b/src/tar.c
@@ -338,6 +338,7 @@ enum
   SHOW_DEFAULTS_OPTION,
   SHOW_OMITTED_DIRS_OPTION,
   SHOW_TRANSFORMED_NAMES_OPTION,
+  SINGLE_TOP_LEVEL_OPTION,
   SKIP_OLD_FILES_OPTION,
   SPARSE_VERSION_OPTION,
   STRIP_COMPONENTS_OPTION,
@@ -484,6 +485,8 @@ static struct argp_option options[] = {
   {"overwrite-dir", OVERWRITE_DIR_OPTION, 0, 0,
    N_("overwrite metadata of existing directories when extracting (default)"),
    GRID+1 },
+  {"single-top-level", SINGLE_TOP_LEVEL_OPTION, 0, 0,
+   N_("allow at most one top-level name when extracting"), GRID+1 },
 #undef GRID
 
 #define GRID 40
@@ -1548,6 +1551,10 @@ parse_opt (int key, char *arg, struct argp_state *state)
       sparse_option = true;
       break;
 
+    case SINGLE_TOP_LEVEL_OPTION:
+      single_top_level_option = true;
+      break;
+
     case SKIP_OLD_FILES_OPTION:
       old_files_option = SKIP_OLD_FILES;
       break;
-- 
1.8.3.4




reply via email to

[Prev in Thread] Current Thread [Next in Thread]