浏览代码

Don't try to read past the end of header string fields

* 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.
Sergey Poznyakoff 6 年之前
父节点
当前提交
ba472050da
共有 5 个文件被更改,包括 28 次插入18 次删除
  1. 1 0
      gnulib.modules
  2. 4 13
      src/buffer.c
  3. 2 0
      src/common.h
  4. 7 5
      src/list.c
  5. 14 0
      src/misc.c

+ 1 - 0
gnulib.modules

@@ -85,6 +85,7 @@ stdint
 stpcpy
 strdup-posix
 strerror
+strnlen
 strtoimax
 strtol
 strtoul

+ 4 - 13
src/buffer.c

@@ -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);
 

+ 2 - 0
src/common.h

@@ -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);

+ 7 - 5
src/list.c

@@ -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)
 	{

+ 14 - 0
src/misc.c

@@ -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?  */