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

995285
From 9ef77b3d5e04de8323bdc61c1cb7ea77613e4a38 Mon Sep 17 00:00:00 2001
995285
From: Tim Kientzle <kientzle@acm.org>
995285
Date: Sat, 8 Aug 2015 21:47:43 -0700
995285
Subject: [PATCH] This is a combination of 2 commits. == The first commit's
995285
 message is: ==
995285
995285
Issue 547:  problems with compress bidder
995285
995285
The code previously was not very careful about verifying the
995285
compression parameters.  This led to cases where it failed to
995285
reject invalid compressed data at the beginning.  The invalid
995285
left shift was one symptom of this.
995285
995285
The code is now more careful:  It verifies that the compression
995285
parameter byte exists and verifies that the maximum code size
995285
is <= 16 bits.
995285
995285
This also includes some new tests to verify that truncated or
995285
otherwise invalid compressed data is rejected.
995285
995285
== This is the 2nd commit message: ==
995285
995285
add missing tests to automake
995285
---
995285
 Makefile.am                                       |  1 +
995285
 libarchive/archive_read_support_filter_compress.c | 21 ++++--
995285
 libarchive/test/test_read_filter_compress.c       | 80 +++++++++++++++++++++++
995285
 3 files changed, 96 insertions(+), 6 deletions(-)
995285
 create mode 100644 libarchive/test/test_read_filter_compress.c
995285
995285
diff --git a/Makefile.am b/Makefile.am
995285
index fb90b9c..e088b75 100644
995285
--- a/Makefile.am
995285
+++ b/Makefile.am
995285
@@ -364,6 +364,7 @@ libarchive_test_SOURCES=					\
995285
 	libarchive/test/test_read_disk_entry_from_file.c	\
995285
 	libarchive/test/test_read_extract.c			\
995285
 	libarchive/test/test_read_file_nonexistent.c		\
995285
+	libarchive/test/test_read_filter_compress.c		\
995285
 	libarchive/test/test_read_filter_grzip.c		\
995285
 	libarchive/test/test_read_filter_lrzip.c		\
995285
 	libarchive/test/test_read_filter_lzop.c			\
995285
diff --git a/libarchive/archive_read_support_filter_compress.c b/libarchive/archive_read_support_filter_compress.c
995285
index 3f5d1f3..6fa9993 100644
995285
--- a/libarchive/archive_read_support_filter_compress.c
995285
+++ b/libarchive/archive_read_support_filter_compress.c
995285
@@ -185,19 +185,22 @@ compress_bidder_bid(struct archive_read_filter_bidder *self,
995285
 
995285
 	(void)self; /* UNUSED */
995285
 
995285
-	buffer = __archive_read_filter_ahead(filter, 2, &avail);
995285
+	/* Shortest valid compress file is 3 bytes. */
995285
+	buffer = __archive_read_filter_ahead(filter, 3, &avail);
995285
 
995285
 	if (buffer == NULL)
995285
 		return (0);
995285
 
995285
 	bits_checked = 0;
995285
+	/* First two bytes are the magic value */
995285
 	if (buffer[0] != 0x1F || buffer[1] != 0x9D)
995285
 		return (0);
995285
-	bits_checked += 16;
995285
-
995285
-	/*
995285
-	 * TODO: Verify more.
995285
-	 */
995285
+	/* Third byte holds compression parameters. */
995285
+	if (buffer[2] & 0x20) /* Reserved bit, must be zero. */
995285
+		return (0);
995285
+	if (buffer[2] & 0x40) /* Reserved bit, must be zero. */
995285
+		return (0);
995285
+	bits_checked += 18;
995285
 
995285
 	return (bits_checked);
995285
 }
995285
@@ -239,7 +242,13 @@ compress_bidder_init(struct archive_read_filter *self)
995285
 	(void)getbits(self, 8); /* Skip first signature byte. */
995285
 	(void)getbits(self, 8); /* Skip second signature byte. */
995285
 
995285
+	/* Get compression parameters. */
995285
 	code = getbits(self, 8);
995285
+	if ((code & 0x1f) > 16) {
995285
+		archive_set_error(&self->archive->archive, -1,
995285
+		    "Invalid compressed data");
995285
+		return (ARCHIVE_FATAL);
995285
+	}
995285
 	state->maxcode_bits = code & 0x1f;
995285
 	state->maxcode = (1 << state->maxcode_bits);
995285
 	state->use_reset_code = code & 0x80;
995285
diff --git a/libarchive/test/test_read_filter_compress.c b/libarchive/test/test_read_filter_compress.c
995285
new file mode 100644
995285
index 0000000..03a1d5f
995285
--- /dev/null
995285
+++ b/libarchive/test/test_read_filter_compress.c
995285
@@ -0,0 +1,80 @@
995285
+/*-
995285
+ * Copyright (c) 2003-2008 Tim Kientzle
995285
+ * All rights reserved.
995285
+ *
995285
+ * Redistribution and use in source and binary forms, with or without
995285
+ * modification, are permitted provided that the following conditions
995285
+ * are met:
995285
+ * 1. Redistributions of source code must retain the above copyright
995285
+ *    notice, this list of conditions and the following disclaimer.
995285
+ * 2. Redistributions in binary form must reproduce the above copyright
995285
+ *    notice, this list of conditions and the following disclaimer in the
995285
+ *    documentation and/or other materials provided with the distribution.
995285
+ *
995285
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
995285
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
995285
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
995285
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
995285
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
995285
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
995285
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
995285
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
995285
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
995285
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
995285
+ */
995285
+#include "test.h"
995285
+
995285
+DEFINE_TEST(test_read_filter_compress_truncated)
995285
+{
995285
+	const char data[] = {0x1f, 0x9d};
995285
+	struct archive *a;
995285
+
995285
+	assert((a = archive_read_new()) != NULL);
995285
+	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_compress(a));
995285
+	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
995285
+	assertEqualIntA(a, ARCHIVE_FATAL,
995285
+	    archive_read_open_memory(a, data, sizeof(data)));
995285
+
995285
+	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
995285
+	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
995285
+}
995285
+
995285
+
995285
+DEFINE_TEST(test_read_filter_compress_empty2)
995285
+{
995285
+	const char data[] = {0x1f, 0x9d, 0x10};
995285
+	struct archive *a;
995285
+	struct archive_entry *ae;
995285
+
995285
+	assert((a = archive_read_new()) != NULL);
995285
+	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_compress(a));
995285
+	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
995285
+	assertEqualIntA(a, ARCHIVE_OK,
995285
+	    archive_read_open_memory(a, data, sizeof(data)));
995285
+
995285
+	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae);;
995285
+
995285
+	/* Verify that the format detection worked. */
995285
+	assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_COMPRESS);
995285
+	assertEqualString(archive_filter_name(a, 0), "compress (.Z)");
995285
+	assertEqualInt(archive_format(a), ARCHIVE_FORMAT_EMPTY);
995285
+
995285
+	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
995285
+	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
995285
+}
995285
+
995285
+
995285
+DEFINE_TEST(test_read_filter_compress_invalid)
995285
+{
995285
+	const char data[] = {0x1f, 0x9d, 0x11};
995285
+	struct archive *a;
995285
+
995285
+	assert((a = archive_read_new()) != NULL);
995285
+	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_compress(a));
995285
+	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
995285
+	assertEqualIntA(a, ARCHIVE_FATAL,
995285
+	    archive_read_open_memory(a, data, sizeof(data)));
995285
+
995285
+	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
995285
+	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
995285
+}
995285
-- 
995285
2.7.4
995285