]> git.ipfire.org Git - thirdparty/tar.git/commitdiff
Don't try to read past the end of header string fields
authorSergey Poznyakoff <gray@gnu.org>
Sat, 24 Nov 2018 15:49:25 +0000 (17:49 +0200)
committerSergey Poznyakoff <gray@gnu.org>
Sat, 24 Nov 2018 15:57:32 +0000 (17:57 +0200)
* src/common.h (assign_string_n): New proto.
(ASSIGN_STRING_N): New macro.
* src/misc.c (assign_string_n): New function.
* gnulib.modules: Add strnlen.
* src/buffer.c: Use assign_string_n where appropriate.
* src/list.c: Likewise.

gnulib.modules
src/buffer.c
src/common.h
src/list.c
src/misc.c

index f1903873849b1e4bed508dbfbd29ebebbb10cacc..1bd18b816ba54e1a932dd739224d1959ec082f0c 100644 (file)
@@ -85,6 +85,7 @@ stdint
 stpcpy
 strdup-posix
 strerror
+strnlen
 strtoimax
 strtol
 strtoul
index b710c6a9dca56d0e6ef12b8e05c894b7ae71b6ac..ddb63cc98defb1f47b99636b874af067ec119e57 100644 (file)
@@ -1503,7 +1503,7 @@ try_new_volume (void)
       if (!read_header0 (&dummy))
         return false;
       tar_stat_destroy (&dummy);
-      assign_string (&volume_label, current_header->header.name);
+      ASSIGN_STRING_N (&volume_label, current_header->header.name);
       set_next_block_after (header);
       header = find_next_block ();
       if (header->header.typeflag != GNUTYPE_MULTIVOL)
@@ -1513,7 +1513,7 @@ try_new_volume (void)
       if (!read_header0 (&dummy))
         return false;
       tar_stat_destroy (&dummy);
-      assign_string (&continued_file_name, current_header->header.name);
+      ASSIGN_STRING_N (&continued_file_name, current_header->header.name);
       continued_file_size =
         UINTMAX_FROM_HEADER (current_header->header.size);
       continued_file_offset =
@@ -1656,15 +1656,7 @@ match_volume_label (void)
                      quote (volume_label_option)));
       if (label->header.typeflag == GNUTYPE_VOLHDR)
        {
-         if (memchr (label->header.name, '\0', sizeof label->header.name))
-           assign_string (&volume_label, label->header.name);
-         else
-           {
-             volume_label = xmalloc (sizeof (label->header.name) + 1);
-             memcpy (volume_label, label->header.name,
-                     sizeof (label->header.name));
-             volume_label[sizeof (label->header.name)] = 0;
-           }
+         ASSIGN_STRING_N (&volume_label, label->header.name);
        }
       else if (label->header.typeflag == XGLTYPE)
        {
@@ -1700,8 +1692,7 @@ _write_volume_label (const char *str)
       memset (label, 0, BLOCKSIZE);
 
       strcpy (label->header.name, str);
-      assign_string (&current_stat_info.file_name,
-                     label->header.name);
+      assign_string (&current_stat_info.file_name, label->header.name);
       current_stat_info.had_trailing_slash =
         strip_trailing_slashes (current_stat_info.file_name);
 
index bbe167efd4e59e92452a7e570c4a35fa842e66cd..28779751f4c88f8bfb707b9c65b722719e3b5e19 100644 (file)
@@ -628,6 +628,8 @@ void skip_member (void);
 
 char const *quote_n_colon (int n, char const *arg);
 void assign_string (char **dest, const char *src);
+void assign_string_n (char **string, const char *value, size_t n);
+#define ASSIGN_STRING_N(s,v) assign_string_n (s, v, sizeof (v))
 int unquote_string (char *str);
 char *zap_slashes (char *name);
 char *normalize_filename (int cdidx, const char *name);
index 2cc5d400a91c2271d393c7ab9b22dcc7d188c689..ba9c306e9aa0a33ef963397ce147c0ffd5892ef0 100644 (file)
@@ -631,10 +631,12 @@ decode_header (union block *header, struct tar_stat_info *stat_info,
   stat_info->stat.st_mode = mode;
   stat_info->mtime.tv_sec = TIME_FROM_HEADER (header->header.mtime);
   stat_info->mtime.tv_nsec = 0;
-  assign_string (&stat_info->uname,
-                header->header.uname[0] ? header->header.uname : NULL);
-  assign_string (&stat_info->gname,
-                header->header.gname[0] ? header->header.gname : NULL);
+  assign_string_n (&stat_info->uname,
+                  header->header.uname[0] ? header->header.uname : NULL,
+                  sizeof (header->header.uname));
+  assign_string_n (&stat_info->gname,
+                  header->header.gname[0] ? header->header.gname : NULL,
+                  sizeof (header->header.gname));
 
   xheader_xattr_init (stat_info);
 
@@ -1439,7 +1441,7 @@ test_archive_label (void)
       decode_header (current_header,
                     &current_stat_info, &current_format, 0);
       if (current_header->header.typeflag == GNUTYPE_VOLHDR)
-       assign_string (&volume_label, current_header->header.name);
+       ASSIGN_STRING_N (&volume_label, current_header->header.name);
 
       if (volume_label)
        {
index c7e6f2af8f26e7090f8b4d044148d60768eaf1ff..5bd2b0f66c3012ae1cd9489bdde692dffa774a3f 100644 (file)
@@ -50,6 +50,20 @@ assign_string (char **string, const char *value)
   *string = value ? xstrdup (value) : 0;
 }
 
+void
+assign_string_n (char **string, const char *value, size_t n)
+{
+  free (*string);
+  if (value)
+    {
+      size_t l = strnlen (value, n);
+      char *p = xmalloc (l + 1);
+      memcpy (p, value, l);
+      p[l] = 0;
+      *string = p;
+    }
+}
+
 #if 0
 /* This function is currently unused; perhaps it should be removed?  */