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

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