67 lines
2.4 KiB
Diff
67 lines
2.4 KiB
Diff
|
From 7f17c791dcfd8c0416e2cd2485b19410e47ef126 Mon Sep 17 00:00:00 2001
|
||
|
From: Tim Kientzle <kientzle@acm.org>
|
||
|
Date: Sun, 18 Sep 2016 18:14:58 -0700
|
||
|
Subject: [PATCH] Issue 761: Heap overflow reading corrupted 7Zip files
|
||
|
|
||
|
The sample file that demonstrated this had multiple 'EmptyStream'
|
||
|
attributes. The first one ended up being used to calculate
|
||
|
certain statistics, then was overwritten by the second which
|
||
|
was incompatible with those statistics.
|
||
|
|
||
|
The fix here is to reject any header with multiple EmptyStream
|
||
|
attributes. While here, also reject headers with multiple
|
||
|
EmptyFile, AntiFile, Name, or Attributes markers.
|
||
|
---
|
||
|
libarchive/archive_read_support_format_7zip.c | 10 ++++++++++
|
||
|
1 file changed, 10 insertions(+)
|
||
|
|
||
|
diff --git a/libarchive/archive_read_support_format_7zip.c b/libarchive/archive_read_support_format_7zip.c
|
||
|
index 1dfe52b..c0a536c 100644
|
||
|
--- a/libarchive/archive_read_support_format_7zip.c
|
||
|
+++ b/libarchive/archive_read_support_format_7zip.c
|
||
|
@@ -2431,6 +2431,8 @@ read_Header(struct archive_read *a, struct _7z_header_info *h,
|
||
|
|
||
|
switch (type) {
|
||
|
case kEmptyStream:
|
||
|
+ if (h->emptyStreamBools != NULL)
|
||
|
+ return (-1);
|
||
|
h->emptyStreamBools = calloc((size_t)zip->numFiles,
|
||
|
sizeof(*h->emptyStreamBools));
|
||
|
if (h->emptyStreamBools == NULL)
|
||
|
@@ -2451,6 +2453,8 @@ read_Header(struct archive_read *a, struct _7z_header_info *h,
|
||
|
return (-1);
|
||
|
break;
|
||
|
}
|
||
|
+ if (h->emptyFileBools != NULL)
|
||
|
+ return (-1);
|
||
|
h->emptyFileBools = calloc(empty_streams,
|
||
|
sizeof(*h->emptyFileBools));
|
||
|
if (h->emptyFileBools == NULL)
|
||
|
@@ -2465,6 +2469,8 @@ read_Header(struct archive_read *a, struct _7z_header_info *h,
|
||
|
return (-1);
|
||
|
break;
|
||
|
}
|
||
|
+ if (h->antiBools != NULL)
|
||
|
+ return (-1);
|
||
|
h->antiBools = calloc(empty_streams,
|
||
|
sizeof(*h->antiBools));
|
||
|
if (h->antiBools == NULL)
|
||
|
@@ -2491,6 +2497,8 @@ read_Header(struct archive_read *a, struct _7z_header_info *h,
|
||
|
if ((ll & 1) || ll < zip->numFiles * 4)
|
||
|
return (-1);
|
||
|
|
||
|
+ if (zip->entry_names != NULL)
|
||
|
+ return (-1);
|
||
|
zip->entry_names = malloc(ll);
|
||
|
if (zip->entry_names == NULL)
|
||
|
return (-1);
|
||
|
@@ -2543,6 +2551,8 @@ read_Header(struct archive_read *a, struct _7z_header_info *h,
|
||
|
if ((p = header_bytes(a, 2)) == NULL)
|
||
|
return (-1);
|
||
|
allAreDefined = *p;
|
||
|
+ if (h->attrBools != NULL)
|
||
|
+ return (-1);
|
||
|
h->attrBools = calloc((size_t)zip->numFiles,
|
||
|
sizeof(*h->attrBools));
|
||
|
if (h->attrBools == NULL)
|