diff options
author | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2019-07-03 14:12:46 +0200 |
---|---|---|
committer | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2019-07-03 14:12:46 +0200 |
commit | b8d4983147141310383d423b1bcb9d19a490977a (patch) | |
tree | c6d00677cfb115e148b2355fa7712de2562861c3 | |
parent | b51a3ab10fad0d00c6fe2aa4d4c1afc6cfcf371f (diff) |
Fix: don't blindly strcpy() the tar header name
If the tar header name is exactely 100 bytes long, it does not have a
trailing null byte. Using strlen/strcpy on it effectively concatenates
the following fields contents to it.
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
-rw-r--r-- | lib/tar/read_header.c | 18 |
1 files changed, 11 insertions, 7 deletions
diff --git a/lib/tar/read_header.c b/lib/tar/read_header.c index 067b1df..1506037 100644 --- a/lib/tar/read_header.c +++ b/lib/tar/read_header.c @@ -199,23 +199,27 @@ fail: static int decode_header(const tar_header_t *hdr, unsigned int set_by_pax, tar_header_decoded_t *out, int version) { + size_t len1, len2; uint64_t field; - size_t count; if (!(set_by_pax & PAX_NAME)) { if (hdr->tail.posix.prefix[0] != '\0' && version == ETV_POSIX) { - count = strlen(hdr->name) + 1; - count += strlen(hdr->tail.posix.prefix) + 1; + len1 = strnlen(hdr->name, sizeof(hdr->name)); + len2 = strnlen(hdr->tail.posix.prefix, + sizeof(hdr->tail.posix.prefix)); - out->name = malloc(count); + out->name = malloc(len1 + 1 + len2 + 1); if (out->name != NULL) { - sprintf(out->name, "%s/%s", - hdr->tail.posix.prefix, hdr->name); + memcpy(out->name, hdr->name, len1); + out->name[len1] = '/'; + memcpy(out->name + len1 + 1, + hdr->tail.posix.prefix, len2); + out->name[len1 + 1 + len2] = '\0'; } } else { - out->name = strdup(hdr->name); + out->name = strndup(hdr->name, sizeof(hdr->name)); } if (out->name == NULL) { |