commit e79ef306afe332faf22e9b442a2c6b59cb175573
Author: Tim Kientzle <kientzle@acm.org>
Date:   Sun Jun 19 14:14:09 2016 -0700

    Issue #718: Fix TALOS-CAN-152
    
    If a 7-Zip archive declares a rediculously large number of substreams,
    it can overflow an internal counter, leading a subsequent memory
    allocation to be too small for the substream data.
    
    Thanks to the Open Source and Threat Intelligence project at Cisco
    for reporting this issue.

Index: libarchive-3.1.2/libarchive/archive_read_support_format_7zip.c
===================================================================
--- libarchive-3.1.2.orig/libarchive/archive_read_support_format_7zip.c
+++ libarchive-3.1.2/libarchive/archive_read_support_format_7zip.c
@@ -324,6 +324,11 @@ struct _7zip {
 	char			 format_name[64];
 };
 
+/* Maximum entry size. This limitation prevents reading intentional
+ * corrupted 7-zip files on assuming there are not so many entries in
+ * the files. */
+#define UMAX_ENTRY     ARCHIVE_LITERAL_ULL(100000000)
+
 static int	archive_read_format_7zip_bid(struct archive_read *, int);
 static int	archive_read_format_7zip_cleanup(struct archive_read *);
 static int	archive_read_format_7zip_read_data(struct archive_read *,
@@ -1670,7 +1675,7 @@ read_PackInfo(struct archive_read *a, st
 		return (-1);
 	if (pi->numPackStreams == 0)
 		return (-1);
-	if (1000000 < pi->numPackStreams)
+	if (UMAX_ENTRY < pi->numPackStreams)
 		return (-1);
 
 	/*
@@ -1799,12 +1804,12 @@ read_Folder(struct archive_read *a, stru
 			if (parse_7zip_uint64(
 			    a, &(f->coders[i].numInStreams)) < 0)
 				return (-1);
-			if (1000000 < f->coders[i].numInStreams)
+			if (UMAX_ENTRY < f->coders[i].numInStreams)
 				return (-1);
 			if (parse_7zip_uint64(
 			    a, &(f->coders[i].numOutStreams)) < 0)
 				return (-1);
-			if (1000000 < f->coders[i].numOutStreams)
+			if (UMAX_ENTRY < f->coders[i].numOutStreams)
 				return (-1);
 		}
 
@@ -1844,11 +1849,11 @@ read_Folder(struct archive_read *a, stru
 	for (i = 0; i < f->numBindPairs; i++) {
 		if (parse_7zip_uint64(a, &(f->bindPairs[i].inIndex)) < 0)
 			return (-1);
-		if (1000000 < f->bindPairs[i].inIndex)
+		if (UMAX_ENTRY < f->bindPairs[i].inIndex)
 			return (-1);
 		if (parse_7zip_uint64(a, &(f->bindPairs[i].outIndex)) < 0)
 			return (-1);
-		if (1000000 < f->bindPairs[i].outIndex)
+		if (UMAX_ENTRY < f->bindPairs[i].outIndex)
 			return (-1);
 	}
 
@@ -1874,7 +1879,7 @@ read_Folder(struct archive_read *a, stru
 		for (i = 0; i < f->numPackedStreams; i++) {
 			if (parse_7zip_uint64(a, &(f->packedStreams[i])) < 0)
 				return (-1);
-			if (1000000 < f->packedStreams[i])
+			if (UMAX_ENTRY < f->packedStreams[i])
 				return (-1);
 		}
 	}
@@ -1916,8 +1921,8 @@ read_CodersInfo(struct archive_read *a,
 	 */
 	if (parse_7zip_uint64(a, &(ci->numFolders)) < 0)
 		goto failed;
-	if (1000000 < ci->numFolders)
-			return (-1);
+	if (UMAX_ENTRY < ci->numFolders)
+		return (-1);
 
 	/*
 	 * Read External.
@@ -1938,7 +1943,7 @@ read_CodersInfo(struct archive_read *a,
 	case 1:
 		if (parse_7zip_uint64(a, &(ci->dataStreamIndex)) < 0)
 			return (-1);
-		if (1000000 < ci->dataStreamIndex)
+		if (UMAX_ENTRY < ci->dataStreamIndex)
 			return (-1);
 		if (ci->numFolders > 0) {
 			archive_set_error(&a->archive, -1,
@@ -2052,8 +2057,11 @@ read_SubStreamsInfo(struct archive_read
 		for (i = 0; i < numFolders; i++) {
 			if (parse_7zip_uint64(a, &(f[i].numUnpackStreams)) < 0)
 				return (-1);
-			if (1000000 < f[i].numUnpackStreams)
+			if (UMAX_ENTRY < f[i].numUnpackStreams)
 				return (-1);
+			if (unpack_streams > SIZE_MAX - UMAX_ENTRY) {
+			        return (-1);
+			}
 			unpack_streams += (size_t)f[i].numUnpackStreams;
 		}
 		if ((p = header_bytes(a, 1)) == NULL)
@@ -2301,8 +2309,8 @@ read_Header(struct archive_read *a, stru
 
 	if (parse_7zip_uint64(a, &(zip->numFiles)) < 0)
 		return (-1);
-	if (1000000 < zip->numFiles)
-			return (-1);
+	if (UMAX_ENTRY < zip->numFiles)
+		return (-1);
 
 	zip->entries = calloc((size_t)zip->numFiles, sizeof(*zip->entries));
 	if (zip->entries == NULL)
@@ -2600,7 +2608,7 @@ read_Times(struct archive_read *a, struc
 	if (*p) {
 		if (parse_7zip_uint64(a, &(h->dataIndex)) < 0)
 			goto failed;
-		if (1000000 < h->dataIndex)
+		if (UMAX_ENTRY < h->dataIndex)
 			goto failed;
 	}
 
