Blame SOURCES/libarchive-3.1.2-CVE-2015-8928.patch

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