|
|
58251f |
From f667f381486371ccb19f2b1e7307a695cf3a5279 Mon Sep 17 00:00:00 2001
|
|
|
58251f |
From: Tim Kientzle <kientzle@acm.org>
|
|
|
58251f |
Date: Sun, 3 Apr 2016 11:03:22 -0700
|
|
|
58251f |
Subject: [PATCH] Issue 550: Fix out-of-bounds read in mtree.
|
|
|
58251f |
|
|
|
58251f |
The mtree parser scanned from the end of the string to identify
|
|
|
58251f |
the filename when the filename is the last element of the line.
|
|
|
58251f |
If the filename was the entire line, the logic would scan back
|
|
|
58251f |
to before the start of the string.
|
|
|
58251f |
|
|
|
58251f |
The revised logic scans from the beginning of the string
|
|
|
58251f |
and remembers the last separator position to locate the
|
|
|
58251f |
trailing filename.
|
|
|
58251f |
---
|
|
|
58251f |
libarchive/archive_read_support_format_mtree.c | 53 ++++++++++++++------------
|
|
|
58251f |
1 file changed, 29 insertions(+), 24 deletions(-)
|
|
|
58251f |
|
|
|
58251f |
diff --git a/libarchive/archive_read_support_format_mtree.c b/libarchive/archive_read_support_format_mtree.c
|
|
|
58251f |
index 397bfee..a672cb3 100644
|
|
|
58251f |
--- a/libarchive/archive_read_support_format_mtree.c
|
|
|
58251f |
+++ b/libarchive/archive_read_support_format_mtree.c
|
|
|
58251f |
@@ -826,8 +826,8 @@ process_add_entry(struct archive_read *a, struct mtree *mtree,
|
|
|
58251f |
struct mtree_entry *entry;
|
|
|
58251f |
struct mtree_option *iter;
|
|
|
58251f |
const char *next, *eq, *name, *end;
|
|
|
58251f |
- size_t len;
|
|
|
58251f |
- int r;
|
|
|
58251f |
+ size_t name_len, len;
|
|
|
58251f |
+ int r, i;
|
|
|
58251f |
|
|
|
58251f |
if ((entry = malloc(sizeof(*entry))) == NULL) {
|
|
|
58251f |
archive_set_error(&a->archive, errno, "Can't allocate memory");
|
|
|
58251f |
@@ -847,43 +847,48 @@ process_add_entry(struct archive_read *a, struct mtree *mtree,
|
|
|
58251f |
*last_entry = entry;
|
|
|
58251f |
|
|
|
58251f |
if (is_form_d) {
|
|
|
58251f |
- /*
|
|
|
58251f |
- * This form places the file name as last parameter.
|
|
|
58251f |
- */
|
|
|
58251f |
- name = line + line_len -1;
|
|
|
58251f |
+ /* Filename is last item on line. */
|
|
|
58251f |
+ /* Adjust line_len to trim trailing whitespace */
|
|
|
58251f |
while (line_len > 0) {
|
|
|
58251f |
- if (*name != '\r' && *name != '\n' &&
|
|
|
58251f |
- *name != '\t' && *name != ' ')
|
|
|
58251f |
+ char last_character = line[line_len - 1];
|
|
|
58251f |
+ if (last_character == '\r'
|
|
|
58251f |
+ || last_character == '\n'
|
|
|
58251f |
+ || last_character == '\t'
|
|
|
58251f |
+ || last_character == ' ') {
|
|
|
58251f |
+ line_len--;
|
|
|
58251f |
+ } else {
|
|
|
58251f |
break;
|
|
|
58251f |
- name--;
|
|
|
58251f |
- line_len--;
|
|
|
58251f |
+ }
|
|
|
58251f |
}
|
|
|
58251f |
- len = 0;
|
|
|
58251f |
- while (line_len > 0) {
|
|
|
58251f |
- if (*name == '\r' || *name == '\n' ||
|
|
|
58251f |
- *name == '\t' || *name == ' ') {
|
|
|
58251f |
- name++;
|
|
|
58251f |
- break;
|
|
|
58251f |
+ /* Name starts after the last whitespace separator */
|
|
|
58251f |
+ name = line;
|
|
|
58251f |
+ for (i = 0; i < line_len; i++) {
|
|
|
58251f |
+ if (line[i] == '\r'
|
|
|
58251f |
+ || line[i] == '\n'
|
|
|
58251f |
+ || line[i] == '\t'
|
|
|
58251f |
+ || line[i] == ' ') {
|
|
|
58251f |
+ name = line + i + 1;
|
|
|
58251f |
}
|
|
|
58251f |
- name--;
|
|
|
58251f |
- line_len--;
|
|
|
58251f |
- len++;
|
|
|
58251f |
}
|
|
|
58251f |
+ name_len = line + line_len - name;
|
|
|
58251f |
end = name;
|
|
|
58251f |
} else {
|
|
|
58251f |
- len = strcspn(line, " \t\r\n");
|
|
|
58251f |
+ /* Filename is first item on line */
|
|
|
58251f |
+ name_len = strcspn(line, " \t\r\n");
|
|
|
58251f |
name = line;
|
|
|
58251f |
- line += len;
|
|
|
58251f |
+ line += name_len;
|
|
|
58251f |
end = line + line_len;
|
|
|
58251f |
}
|
|
|
58251f |
+ /* name/name_len is the name within the line. */
|
|
|
58251f |
+ /* line..end brackets the entire line except the name */
|
|
|
58251f |
|
|
|
58251f |
- if ((entry->name = malloc(len + 1)) == NULL) {
|
|
|
58251f |
+ if ((entry->name = malloc(name_len + 1)) == NULL) {
|
|
|
58251f |
archive_set_error(&a->archive, errno, "Can't allocate memory");
|
|
|
58251f |
return (ARCHIVE_FATAL);
|
|
|
58251f |
}
|
|
|
58251f |
|
|
|
58251f |
- memcpy(entry->name, name, len);
|
|
|
58251f |
- entry->name[len] = '\0';
|
|
|
58251f |
+ memcpy(entry->name, name, name_len);
|
|
|
58251f |
+ entry->name[name_len] = '\0';
|
|
|
58251f |
parse_escapes(entry->name, entry);
|
|
|
58251f |
|
|
|
58251f |
for (iter = *global; iter != NULL; iter = iter->next) {
|
|
|
58251f |
--
|
|
|
58251f |
2.7.4
|
|
|
58251f |
|