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

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