File CVE-2015-8920.patch of Package libarchive.2786

commit 97f964e3e0ce3ae34bfb4c366a37ba7c0d9610a6
Author: Tim Kientzle <kientzle@acm.org>
Date:   Sat Feb 7 12:35:33 2015 -0800

    Issue 403: Buffer underflow parsing 'ar' header
    
    While pruning trailing text from ar filenames, we did not
    check for an empty filename.  This results in reading the byte
    before the filename on the stack.
    
    While here, change a number of ar format issues from WARN to FATAL.
    It's better to abort on a damaged file than risk reading garbage.
    No doubt, this will require additional tuning in the future.

Index: libarchive-3.1.2/libarchive/archive_read_support_format_ar.c
===================================================================
--- libarchive-3.1.2.orig/libarchive/archive_read_support_format_ar.c
+++ libarchive-3.1.2/libarchive/archive_read_support_format_ar.c
@@ -178,7 +178,7 @@ _ar_read_header(struct archive_read *a,
 	if (strncmp(h + AR_fmag_offset, "`\n", 2) != 0) {
 		archive_set_error(&a->archive, EINVAL,
 		    "Incorrect file header signature");
-		return (ARCHIVE_WARN);
+		return (ARCHIVE_FATAL);
 	}
 
 	/* Copy filename into work buffer. */
@@ -237,8 +237,15 @@ _ar_read_header(struct archive_read *a,
 	 * and are not terminated in '/', so we don't trim anything
 	 * that starts with '/'.)
 	 */
-	if (filename[0] != '/' && *p == '/')
+	if (filename[0] != '/' && p > filename && *p == '/') {
 		*p = '\0';
+	}
+
+	if (p < filename) {
+		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+		    "Found entry with empty filename");
+		return (ARCHIVE_FATAL);
+	}
 
 	/*
 	 * '//' is the GNU filename table.
@@ -260,12 +267,12 @@ _ar_read_header(struct archive_read *a,
 		if (entry_size == 0) {
 			archive_set_error(&a->archive, EINVAL,
 			    "Invalid string table");
-			return (ARCHIVE_WARN);
+			return (ARCHIVE_FATAL);
 		}
 		if (ar->strtab != NULL) {
 			archive_set_error(&a->archive, EINVAL,
 			    "More than one string tables exist");
-			return (ARCHIVE_WARN);
+			return (ARCHIVE_FATAL);
 		}
 
 		/* Read the filename table into memory. */
@@ -309,11 +316,11 @@ _ar_read_header(struct archive_read *a,
 		 */
 		if (ar->strtab == NULL || number > ar->strtab_size) {
 			archive_set_error(&a->archive, EINVAL,
-			    "Can't find long filename for entry");
+			    "Can't find long filename for GNU/SVR4 archive entry");
 			archive_entry_copy_pathname(entry, filename);
 			/* Parse the time, owner, mode, size fields. */
 			ar_parse_common_header(ar, entry, h);
-			return (ARCHIVE_WARN);
+			return (ARCHIVE_FATAL);
 		}
 
 		archive_entry_copy_pathname(entry, &ar->strtab[(size_t)number]);
@@ -571,7 +578,7 @@ bad_string_table:
 	    "Invalid string table");
 	free(ar->strtab);
 	ar->strtab = NULL;
-	return (ARCHIVE_WARN);
+	return (ARCHIVE_FATAL);
 }
 
 static uint64_t
openSUSE Build Service is sponsored by