1 |
jpp |
1.1 |
From 756b671031e0f6158f82186220ebc087c44cd985 Mon Sep 17 00:00:00 2001 |
2 |
|
|
From: Tim Kientzle <kientzle@acm.org> |
3 |
|
|
Date: Sat, 10 Jan 2015 12:24:58 -0800 |
4 |
|
|
Subject: [PATCH] Fix a potential crash issue discovered by Alexander |
5 |
|
|
Cherepanov: |
6 |
|
|
|
7 |
|
|
It seems bsdtar automatically handles stacked compression. This is a |
8 |
|
|
nice feature but it could be problematic when it's completely |
9 |
|
|
unlimited. Most clearly it's illustrated with quines: |
10 |
|
|
|
11 |
|
|
$ curl -sRO http://www.maximumcompression.com/selfgz.gz |
12 |
|
|
$ (ulimit -v 10000000 && bsdtar -tvf selfgz.gz) |
13 |
|
|
bsdtar: Error opening archive: Can't allocate data for gzip decompression |
14 |
|
|
|
15 |
|
|
Without ulimit, bsdtar will eat all available memory. This could also |
16 |
|
|
be a problem for other applications using libarchive. |
17 |
|
|
--- |
18 |
|
|
Makefile.am | 2 ++ |
19 |
|
|
libarchive/archive_read.c | 7 ++-- |
20 |
|
|
libarchive/test/test_read_too_many_filters.c | 45 ++++++++++++++++++++++++ |
21 |
|
|
libarchive/test/test_read_too_many_filters.gz.uu | 15 ++++++++ |
22 |
|
|
4 files changed, 67 insertions(+), 2 deletions(-) |
23 |
|
|
create mode 100644 libarchive/test/test_read_too_many_filters.c |
24 |
|
|
create mode 100644 libarchive/test/test_read_too_many_filters.gz.uu |
25 |
|
|
|
26 |
|
|
diff --git a/Makefile.am b/Makefile.am |
27 |
|
|
index 9b0632b..5cfef49 100644 |
28 |
|
|
--- a/Makefile.am |
29 |
|
|
+++ b/Makefile.am |
30 |
|
|
@@ -294,6 +294,7 @@ libarchive_test_SOURCES= \ |
31 |
|
|
libarchive/test/test_read_large.c \ |
32 |
|
|
libarchive/test/test_read_pax_truncated.c \ |
33 |
|
|
libarchive/test/test_read_position.c \ |
34 |
|
|
+ libarchive/test/test_read_too_many_filters.c \ |
35 |
|
|
libarchive/test/test_read_truncated.c \ |
36 |
|
|
libarchive/test/test_read_uu.c \ |
37 |
|
|
libarchive/test/test_tar_filenames.c \ |
38 |
|
|
@@ -380,6 +381,7 @@ libarchive_test_EXTRA_DIST=\ |
39 |
|
|
libarchive/test/test_read_format_raw.data.uu \ |
40 |
|
|
libarchive/test/test_read_format_tar_empty_filename.tar.uu \ |
41 |
|
|
libarchive/test/test_read_format_zip.zip.uu \ |
42 |
|
|
+ libarchive/test/test_read_too_many_filters.gz.uu \ |
43 |
|
|
libarchive/test/CMakeLists.txt \ |
44 |
|
|
libarchive/test/README |
45 |
|
|
|
46 |
|
|
diff --git a/libarchive/archive_read.c b/libarchive/archive_read.c |
47 |
|
|
index f39f5ce..92d67d9 100644 |
48 |
|
|
--- a/libarchive/archive_read.c |
49 |
|
|
+++ b/libarchive/archive_read.c |
50 |
|
|
@@ -352,13 +352,13 @@ archive_read_open2(struct archive *_a, void *client_data, |
51 |
|
|
static int |
52 |
|
|
build_stream(struct archive_read *a) |
53 |
|
|
{ |
54 |
|
|
- int number_bidders, i, bid, best_bid; |
55 |
|
|
+ int number_bidders, i, bid, best_bid, n; |
56 |
|
|
struct archive_read_filter_bidder *bidder, *best_bidder; |
57 |
|
|
struct archive_read_filter *filter; |
58 |
|
|
ssize_t avail; |
59 |
|
|
int r; |
60 |
|
|
|
61 |
|
|
- for (;;) { |
62 |
|
|
+ for (n = 0; n < 25; ++n) { |
63 |
|
|
number_bidders = sizeof(a->bidders) / sizeof(a->bidders[0]); |
64 |
|
|
|
65 |
|
|
best_bid = 0; |
66 |
|
|
@@ -402,6 +402,9 @@ build_stream(struct archive_read *a) |
67 |
|
|
return (ARCHIVE_FATAL); |
68 |
|
|
} |
69 |
|
|
} |
70 |
|
|
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, |
71 |
|
|
+ "Input requires too many filters for decoding"); |
72 |
|
|
+ return (ARCHIVE_FATAL); |
73 |
|
|
} |
74 |
|
|
|
75 |
|
|
/* |
76 |
|
|
diff --git a/libarchive/test/test_read_too_many_filters.c b/libarchive/test/test_read_too_many_filters.c |
77 |
|
|
new file mode 100644 |
78 |
|
|
index 0000000..37cab24 |
79 |
|
|
--- /dev/null |
80 |
|
|
+++ b/libarchive/test/test_read_too_many_filters.c |
81 |
|
|
@@ -0,0 +1,45 @@ |
82 |
|
|
+/*- |
83 |
|
|
+ * Copyright (c) 2003-2008,2015 Tim Kientzle |
84 |
|
|
+ * All rights reserved. |
85 |
|
|
+ * |
86 |
|
|
+ * Redistribution and use in source and binary forms, with or without |
87 |
|
|
+ * modification, are permitted provided that the following conditions |
88 |
|
|
+ * are met: |
89 |
|
|
+ * 1. Redistributions of source code must retain the above copyright |
90 |
|
|
+ * notice, this list of conditions and the following disclaimer. |
91 |
|
|
+ * 2. Redistributions in binary form must reproduce the above copyright |
92 |
|
|
+ * notice, this list of conditions and the following disclaimer in the |
93 |
|
|
+ * documentation and/or other materials provided with the distribution. |
94 |
|
|
+ * |
95 |
|
|
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR |
96 |
|
|
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
97 |
|
|
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
98 |
|
|
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, |
99 |
|
|
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
100 |
|
|
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
101 |
|
|
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
102 |
|
|
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
103 |
|
|
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
104 |
|
|
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
105 |
|
|
+ */ |
106 |
|
|
+#include "test.h" |
107 |
|
|
+ |
108 |
|
|
+DEFINE_TEST(test_read_too_many_filters) |
109 |
|
|
+{ |
110 |
|
|
+ const char *name = "test_read_too_many_filters.gz"; |
111 |
|
|
+ struct archive *a; |
112 |
|
|
+ int r; |
113 |
|
|
+ |
114 |
|
|
+ assert((a = archive_read_new()) != NULL); |
115 |
|
|
+ r = archive_read_support_compression_gzip(a); |
116 |
|
|
+ if (r == ARCHIVE_WARN) { |
117 |
|
|
+ skipping("gzip reading not fully supported on this platform"); |
118 |
|
|
+ } |
119 |
|
|
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); |
120 |
|
|
+ extract_reference_file(name); |
121 |
|
|
+ assertEqualIntA(a, ARCHIVE_FATAL, |
122 |
|
|
+ archive_read_open_filename(a, name, 200)); |
123 |
|
|
+ |
124 |
|
|
+ assertEqualInt(ARCHIVE_OK, archive_read_close(a)); |
125 |
|
|
+ assertEqualInt(ARCHIVE_OK, archive_read_finish(a)); |
126 |
|
|
+} |
127 |
|
|
diff --git a/libarchive/test/test_read_too_many_filters.gz.uu b/libarchive/test/test_read_too_many_filters.gz.uu |
128 |
|
|
new file mode 100644 |
129 |
|
|
index 0000000..6bf6614 |
130 |
|
|
--- /dev/null |
131 |
|
|
+++ b/libarchive/test/test_read_too_many_filters.gz.uu |
132 |
|
|
@@ -0,0 +1,15 @@ |
133 |
|
|
+This is a valid gzip file that decompresses to itself, from |
134 |
|
|
+ http://www.maximumcompression.com/selfgz.gz |
135 |
|
|
+ |
136 |
|
|
+This is used in test_read_too_many_filters to try to |
137 |
|
|
+crash libarchive by forcing it to spawn an unending |
138 |
|
|
+list of gunzip filters. |
139 |
|
|
+ |
140 |
|
|
+begin 644 test_read_too_many_filters.gz |
141 |
|
|
+M'XL(`````````P`/`/#_'XL(`````````P`/`/#_````__\```#__X)QH5P` |
142 |
|
|
+M`!X`X?\```#__P```/__@G&A7```'@#A_P```/__````__\```#__P```/__ |
143 |
|
|
+M````__\```#__\(FAF`!`!0`Z_\```#__P```/__PB:&8`$`%`#K_\(FAF`! |
144 |
|
|
+M`!0`Z_^9(#6-B"@Q,C,T`K/`+```%`#K_P*SP"P``!0`Z_]"B"'$`````/__ |
145 |
|
|
+>`P!#2DTAT@```$*((<0`````__\#`$-*32'2```` |
146 |
|
|
+` |
147 |
|
|
+end |
148 |
|
|
-- |
149 |
|
|
2.7.4 |
150 |
|
|
|