]> CyberLeo.Net >> Repos - FreeBSD/releng/8.0.git/blob - lib/libarchive/test/test_fuzz.c
Adjust to reflect 8.0-RELEASE.
[FreeBSD/releng/8.0.git] / lib / libarchive / test / test_fuzz.c
1 /*-
2  * Copyright (c) 2003-2007 Tim Kientzle
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17  * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
18  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 #include "test.h"
26 __FBSDID("$FreeBSD$");
27
28 /*
29  * This was inspired by an ISO fuzz tester written by Michal Zalewski
30  * and posted to the "vulnwatch" mailing list on March 17, 2005:
31  *    http://seclists.org/vulnwatch/2005/q1/0088.html
32  *
33  * This test simply reads each archive image into memory, pokes
34  * random values into it and runs it through libarchive.  It tries
35  * to damage about 1% of each file and repeats the exercise 100 times
36  * with each file.
37  *
38  * Unlike most other tests, this test does not verify libarchive's
39  * responses other than to ensure that libarchive doesn't crash.
40  *
41  * Due to the deliberately random nature of this test, it may be hard
42  * to reproduce failures.  Because this test deliberately attempts to
43  * induce crashes, there's little that can be done in the way of
44  * post-failure diagnostics.
45  */
46
47 /* Because this works for any archive, I can just re-use the archives
48  * developed for other tests.  I've not included all of the compressed
49  * archives here, though; I don't want to spend all of my test time
50  * testing zlib and bzlib. */
51 static const char *
52 files[] = {
53         "test_fuzz_1.iso",
54         "test_compat_bzip2_1.tbz",
55         "test_compat_gtar_1.tar",
56         "test_compat_tar_hardlink_1.tar",
57         "test_compat_zip_1.zip",
58         "test_read_format_gtar_sparse_1_17_posix10_modified.tar",
59         "test_read_format_tar_empty_filename.tar",
60         "test_read_format_zip.zip",
61         NULL
62 };
63
64 #define UnsupportedCompress(r, a) \
65         (r != ARCHIVE_OK && \
66          (strcmp(archive_error_string(a), \
67             "Unrecognized archive format") == 0 && \
68           archive_compression(a) == ARCHIVE_COMPRESSION_NONE))
69
70 DEFINE_TEST(test_fuzz)
71 {
72         const char **filep;
73         const void *blk;
74         size_t blk_size;
75         off_t blk_offset;
76
77         for (filep = files; *filep != NULL; ++filep) {
78                 struct archive_entry *ae;
79                 struct archive *a;
80                 char *rawimage, *image;
81                 size_t size;
82                 int i, r;
83
84                 extract_reference_file(*filep);
85                 rawimage = slurpfile(&size, *filep);
86                 assert(rawimage != NULL);
87                 image = malloc(size);
88                 assert(image != NULL);
89                 srand(time(NULL));
90
91                 assert((a = archive_read_new()) != NULL);
92                 assert(0 == archive_read_support_compression_all(a));
93                 assert(0 == archive_read_support_format_all(a));
94                 assert(0 == archive_read_open_memory(a, rawimage, size));
95                 r = archive_read_next_header(a, &ae);
96                 if (UnsupportedCompress(r, a)) {
97                         skipping("Skipping GZIP/BZIP2 compression check: "
98                             "This version of libarchive was compiled "
99                             "without gzip/bzip2 support");
100                         assert(0 == archive_read_close(a));
101                         assert(0 == archive_read_finish(a));
102                         continue;
103                 }
104                 assert(0 == r);
105                 if (r == ARCHIVE_OK) {
106                         char buff[20];
107
108                         r = archive_read_data(a, buff, 19);
109                         if (r < ARCHIVE_OK && strcmp(archive_error_string(a),
110                             "libarchive compiled without deflate support (no libz)") == 0) {
111                                 skipping("Skipping ZIP compression check: %s",
112                                     archive_error_string(a));
113                                 assert(0 == archive_read_close(a));
114                                 assert(0 == archive_read_finish(a));
115                                 continue;
116                         }
117                         while (0 == archive_read_data_block(a, &blk,
118                                 &blk_size, &blk_offset))
119                                 continue;
120
121                 }
122                 assert(0 == archive_read_close(a));
123                 assert(0 == archive_read_finish(a));
124
125                 for (i = 0; i < 100; ++i) {
126                         int j, fd, numbytes;
127
128                         /* Fuzz < 1% of the bytes in the archive. */
129                         memcpy(image, rawimage, size);
130                         numbytes = (int)(rand() % (size / 100));
131                         for (j = 0; j < numbytes; ++j)
132                                 image[rand() % size] = (char)rand();
133
134                         /* Save the messed-up image to a file.
135                          * If we crash, that file will be useful. */
136                         fd = open("after.test.failure.send.this.file."
137                             "to.libarchive.maintainers.with.system.details",
138                             O_WRONLY | O_CREAT | O_TRUNC, 0744);
139                         write(fd, image, (off_t)size);
140                         close(fd);
141
142                         assert((a = archive_read_new()) != NULL);
143                         assertEqualIntA(a, ARCHIVE_OK,
144                             archive_read_support_compression_all(a));
145                         assertEqualIntA(a, ARCHIVE_OK,
146                             archive_read_support_format_all(a));
147
148                         if (0 == archive_read_open_memory(a, image, size)) {
149                                 while(0 == archive_read_next_header(a, &ae)) {
150                                         while (0 == archive_read_data_block(a,
151                                                 &blk, &blk_size, &blk_offset))
152                                                 continue;
153                                 }
154                                 archive_read_close(a);
155                                 archive_read_finish(a);
156                         }
157                 }
158                 free(image);
159                 free(rawimage);
160         }
161 }
162
163