|
|
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 |
|