summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2018-11-24 17:49:25 +0200
committerSergey Poznyakoff <gray@gnu.org>2018-11-24 17:57:32 +0200
commitba472050da0c91f23d475ba43f8e940058f27f20 (patch)
tree1ba6bd701711676dfdcf9ce26cc8c9f840398461
parentf6e2860e8aec35aa56a2a4bc08e6e71715214eb1 (diff)
downloadtar-ba472050da0c91f23d475ba43f8e940058f27f20.tar.gz
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.
-rw-r--r--gnulib.modules1
-rw-r--r--src/buffer.c17
-rw-r--r--src/common.h2
-rw-r--r--src/list.c12
-rw-r--r--src/misc.c14
5 files changed, 28 insertions, 18 deletions
diff --git a/gnulib.modules b/gnulib.modules
index f1903873..1bd18b81 100644
--- a/gnulib.modules
+++ b/gnulib.modules
@@ -85,6 +85,7 @@ stdint
stpcpy
strdup-posix
strerror
+strnlen
strtoimax
strtol
strtoul
diff --git a/src/buffer.c b/src/buffer.c
index b710c6a9..ddb63cc9 100644
--- a/src/buffer.c
+++ b/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);
diff --git a/src/common.h b/src/common.h
index bbe167ef..28779751 100644
--- a/src/common.h
+++ b/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);
diff --git a/src/list.c b/src/list.c
index 2cc5d400..ba9c306e 100644
--- a/src/list.c
+++ b/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)
{
diff --git a/src/misc.c b/src/misc.c
index c7e6f2af..5bd2b0f6 100644
--- a/src/misc.c
+++ b/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? */