diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2018-11-24 17:49:25 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2018-11-24 17:57:32 +0200 |
commit | ba472050da0c91f23d475ba43f8e940058f27f20 (patch) | |
tree | 1ba6bd701711676dfdcf9ce26cc8c9f840398461 | |
parent | f6e2860e8aec35aa56a2a4bc08e6e71715214eb1 (diff) | |
download | tar-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.modules | 1 | ||||
-rw-r--r-- | src/buffer.c | 17 | ||||
-rw-r--r-- | src/common.h | 2 | ||||
-rw-r--r-- | src/list.c | 12 | ||||
-rw-r--r-- | src/misc.c | 14 |
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 (¤t_stat_info.file_name, - label->header.name); + assign_string (¤t_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); @@ -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, ¤t_stat_info, ¤t_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) { @@ -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? */ |