]> git.ipfire.org Git - thirdparty/tar.git/commitdiff
Check if the dumpdir read from the archive is well-formed before using it. master
authorSergey Poznyakoff <gray@gnu.org>
Tue, 21 Jul 2026 19:49:04 +0000 (22:49 +0300)
committerSergey Poznyakoff <gray@gnu.org>
Tue, 21 Jul 2026 19:49:04 +0000 (22:49 +0300)
* src/common.h (dumpdir_ok): New proto.
* src/incremen.c (dumpdir_ok): Take size as the second argument.
Verify if the last byte is 0 and the dumpdir contains 0 or more
nul-terminated strings.
(get_gnu_dumpdir): Check if the obtained dumpdir is ok. Clear the
is_dumpdir flag if it is not.
* src/xheader.c (dumpdir_decoder) Verify if the obtained dumpdir is
ok.

src/common.h
src/incremen.c
src/xheader.c

index e835d8881cd77d2c20e6121774a86e40be48ddfc..e1332a512f3aac09730c1e6999f6b7c8025c6314 100644 (file)
@@ -589,6 +589,7 @@ void purge_directory (char const *directory_name);
 void list_dumpdir (char *buffer, idx_t size);
 void update_parent_directory (struct tar_stat_info *st);
 
 void list_dumpdir (char *buffer, idx_t size);
 void update_parent_directory (struct tar_stat_info *st);
 
+bool dumpdir_ok (char const *dumpdir, idx_t size);
 idx_t dumpdir_size (const char *p);
 bool is_dumpdir (struct tar_stat_info *stat_info);
 void clear_directory_table (void);
 idx_t dumpdir_size (const char *p);
 bool is_dumpdir (struct tar_stat_info *stat_info);
 void clear_directory_table (void);
index 53c6b3f32d706a7c937c7b1699873b890d17d9e0..d946b0d22c1e9f4b3ac4b6a6da9360065bd368bd 100644 (file)
@@ -123,6 +123,7 @@ dir_set_flag (struct directory *d, int f)
 {
   d->flags |= f;
 }
 {
   d->flags |= f;
 }
+
 static void
 dir_clear_flag (struct directory *d, int f)
 {
 static void
 dir_clear_flag (struct directory *d, int f)
 {
@@ -1525,6 +1526,12 @@ get_gnu_dumpdir (struct tar_stat_info *stat_info)
 
   mv_end ();
 
 
   mv_end ();
 
+  if (!dumpdir_ok (archive_dir, stat_info->stat.st_size))
+    {
+      stat_info->is_dumpdir = false;
+      free (archive_dir);
+      archive_dir = NULL;
+    }
   stat_info->dumpdir = archive_dir;
   stat_info->skipped = true; /* For skip_member() and friends
                                to work correctly */
   stat_info->dumpdir = archive_dir;
   stat_info->skipped = true; /* For skip_member() and friends
                                to work correctly */
@@ -1541,13 +1548,20 @@ is_dumpdir (struct tar_stat_info *stat_info)
   return stat_info->is_dumpdir;
 }
 
   return stat_info->is_dumpdir;
 }
 
-static bool
-dumpdir_ok (char *dumpdir)
+bool
+dumpdir_ok (char const *dumpdir, idx_t size)
 {
 {
-  char *p;
+  char const *p;
   bool has_tempdir = false;
   char expect = '\0';
 
   bool has_tempdir = false;
   char expect = '\0';
 
+  if (!(size > 0 &&
+       dumpdir[size-1] == 0 && (size == 1 || dumpdir[size-2] == 0)))
+    {
+      paxerror (0, _("Malformed dumpdir: missing terminator"));
+      return false;
+    }
+
   for (p = dumpdir; *p; p += strlen (p) + 1)
     {
       if (expect && *p != expect)
   for (p = dumpdir; *p; p += strlen (p) + 1)
     {
       if (expect && *p != expect)
@@ -1640,10 +1654,6 @@ purge_directory (char const *directory_name)
        case, we don't have to delete any files out of it.  */
     return;
 
        case, we don't have to delete any files out of it.  */
     return;
 
-  /* Verify if dump directory is sane */
-  if (!dumpdir_ok (current_stat_info.dumpdir))
-    return;
-
   /* Process renames */
   for (arc = current_stat_info.dumpdir; *arc; arc += strlen (arc) + 1)
     {
   /* Process renames */
   for (arc = current_stat_info.dumpdir; *arc; arc += strlen (arc) + 1)
     {
index 05f905ed70753c77d1935c6eaf18e29beca3e3e9..09d43995a783a71e7c1316bfda82990afda65e9a 100644 (file)
@@ -1483,8 +1483,13 @@ dumpdir_decoder (struct tar_stat_info *st,
                 char const *arg,
                 idx_t size)
 {
                 char const *arg,
                 idx_t size)
 {
-  st->dumpdir = ximalloc (size);
-  memcpy (st->dumpdir, arg, size);
+  if (dumpdir_ok (arg, size))
+    {
+      st->dumpdir = ximalloc (size);
+      memcpy (st->dumpdir, arg, size);
+    }
+  else
+   paxerror (0, _("Malformed dumpdir: missing terminator"));
 }
 
 static void
 }
 
 static void