/src/wuffs/fuzz/c/std/bzip2_fuzzer.c
Line  | Count  | Source (jump to first uncovered line)  | 
1  |  | // Copyright 2022 The Wuffs Authors.  | 
2  |  | //  | 
3  |  | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or  | 
4  |  | // https://www.apache.org/licenses/LICENSE-2.0> or the MIT license  | 
5  |  | // <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your  | 
6  |  | // option. This file may not be copied, modified, or distributed  | 
7  |  | // except according to those terms.  | 
8  |  | //  | 
9  |  | // SPDX-License-Identifier: Apache-2.0 OR MIT  | 
10  |  |  | 
11  |  | // ----------------  | 
12  |  |  | 
13  |  | // Silence the nested slash-star warning for the next comment's command line.  | 
14  |  | #pragma clang diagnostic push  | 
15  |  | #pragma clang diagnostic ignored "-Wcomment"  | 
16  |  |  | 
17  |  | /*  | 
18  |  | This fuzzer (the fuzz function) is typically run indirectly, by a framework  | 
19  |  | such as https://github.com/google/oss-fuzz calling LLVMFuzzerTestOneInput.  | 
20  |  |  | 
21  |  | When working on the fuzz implementation, or as a coherence check, defining  | 
22  |  | WUFFS_CONFIG__FUZZLIB_MAIN will let you manually run fuzz over a set of files:  | 
23  |  |  | 
24  |  | gcc -DWUFFS_CONFIG__FUZZLIB_MAIN bzip2_fuzzer.c  | 
25  |  | ./a.out ../../../test/data/*.bzip2  | 
26  |  | rm -f ./a.out  | 
27  |  |  | 
28  |  | It should print "PASS", amongst other information, and exit(0).  | 
29  |  | */  | 
30  |  |  | 
31  |  | #pragma clang diagnostic pop  | 
32  |  |  | 
33  |  | // Wuffs ships as a "single file C library" or "header file library" as per  | 
34  |  | // https://github.com/nothings/stb/blob/master/docs/stb_howto.txt  | 
35  |  | //  | 
36  |  | // To use that single file as a "foo.c"-like implementation, instead of a  | 
37  |  | // "foo.h"-like header, #define WUFFS_IMPLEMENTATION before #include'ing or  | 
38  |  | // compiling it.  | 
39  |  | #define WUFFS_IMPLEMENTATION  | 
40  |  |  | 
41  |  | #if defined(WUFFS_CONFIG__FUZZLIB_MAIN)  | 
42  |  | // Defining the WUFFS_CONFIG__STATIC_FUNCTIONS macro is optional, but when  | 
43  |  | // combined with WUFFS_IMPLEMENTATION, it demonstrates making all of Wuffs'  | 
44  |  | // functions have static storage.  | 
45  |  | //  | 
46  |  | // This can help the compiler ignore or discard unused code, which can produce  | 
47  |  | // faster compiles and smaller binaries. Other motivations are discussed in the  | 
48  |  | // "ALLOW STATIC IMPLEMENTATION" section of  | 
49  |  | // https://raw.githubusercontent.com/nothings/stb/master/docs/stb_howto.txt  | 
50  |  | #define WUFFS_CONFIG__STATIC_FUNCTIONS  | 
51  |  | #endif  // defined(WUFFS_CONFIG__FUZZLIB_MAIN)  | 
52  |  |  | 
53  |  | // Defining the WUFFS_CONFIG__MODULE* macros are optional, but it lets users of  | 
54  |  | // release/c/etc.c choose which parts of Wuffs to build. That file contains the  | 
55  |  | // entire Wuffs standard library, implementing a variety of codecs and file  | 
56  |  | // formats. Without this macro definition, an optimizing compiler or linker may  | 
57  |  | // very well discard Wuffs code for unused codecs, but listing the Wuffs  | 
58  |  | // modules we use makes that process explicit. Preprocessing means that such  | 
59  |  | // code simply isn't compiled.  | 
60  |  | #define WUFFS_CONFIG__MODULES  | 
61  |  | #define WUFFS_CONFIG__MODULE__BASE  | 
62  |  | #define WUFFS_CONFIG__MODULE__BZIP2  | 
63  |  |  | 
64  |  | // If building this program in an environment that doesn't easily accommodate  | 
65  |  | // relative includes, you can use the script/inline-c-relative-includes.go  | 
66  |  | // program to generate a stand-alone C file.  | 
67  |  | #include "../../../release/c/wuffs-unsupported-snapshot.c"  | 
68  |  | #include "../fuzzlib/fuzzlib.c"  | 
69  |  |  | 
70  |  | // 64 KiB.  | 
71  | 10.7k  | #define DST_BUFFER_ARRAY_SIZE 65536  | 
72  |  |  | 
73  |  | // Wuffs allows either statically or dynamically allocated work buffers. This  | 
74  |  | // program exercises static allocation.  | 
75  |  | #define WORK_BUFFER_ARRAY_SIZE \  | 
76  | 65.3k  |   WUFFS_BZIP2__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE  | 
77  |  | #if WORK_BUFFER_ARRAY_SIZE > 0  | 
78  |  | uint8_t g_work_buffer_array[WORK_BUFFER_ARRAY_SIZE];  | 
79  |  | #else  | 
80  |  | // Not all C/C++ compilers support 0-length arrays.  | 
81  |  | uint8_t g_work_buffer_array[1];  | 
82  |  | #endif  | 
83  |  |  | 
84  |  | const char*  //  | 
85  | 10.7k  | fuzz(wuffs_base__io_buffer* src, uint64_t hash) { | 
86  | 10.7k  |   wuffs_bzip2__decoder dec;  | 
87  | 10.7k  |   wuffs_base__status status = wuffs_bzip2__decoder__initialize(  | 
88  | 10.7k  |       &dec, sizeof dec, WUFFS_VERSION,  | 
89  | 10.7k  |       (hash & 1) ? WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED : 0);  | 
90  | 10.7k  |   if (!wuffs_base__status__is_ok(&status)) { | 
91  | 0  |     return wuffs_base__status__message(&status);  | 
92  | 0  |   }  | 
93  |  |  | 
94  |  |   // Ignore the checksum for 99.99%-ish of all input. When fuzzers generate  | 
95  |  |   // random input, the checkum is very unlikely to match. Still, it's useful to  | 
96  |  |   // verify that checksumming does not lead to e.g. buffer overflows.  | 
97  | 10.7k  |   wuffs_bzip2__decoder__set_quirk(&dec, WUFFS_BASE__QUIRK_IGNORE_CHECKSUM,  | 
98  | 10.7k  |                                   hash & 0xFFFE);  | 
99  |  |  | 
100  | 10.7k  |   static uint8_t dst_buffer[DST_BUFFER_ARRAY_SIZE];  | 
101  | 10.7k  |   wuffs_base__io_buffer dst =  | 
102  | 10.7k  |       wuffs_base__ptr_u8__writer(&dst_buffer[0], DST_BUFFER_ARRAY_SIZE);  | 
103  |  |  | 
104  | 65.3k  |   while (true) { | 
105  | 65.3k  |     dst.meta.wi = 0;  | 
106  | 65.3k  |     status = wuffs_bzip2__decoder__transform_io(  | 
107  | 65.3k  |         &dec, &dst, src,  | 
108  | 65.3k  |         wuffs_base__make_slice_u8(g_work_buffer_array, WORK_BUFFER_ARRAY_SIZE));  | 
109  | 65.3k  |     if (status.repr != wuffs_base__suspension__short_write) { | 
110  | 10.7k  |       break;  | 
111  | 10.7k  |     }  | 
112  | 54.6k  |     if (dst.meta.wi == 0) { | 
113  | 0  |       fprintf(stderr, "wuffs_bzip2__decoder__transform_io made no progress\n");  | 
114  | 0  |       intentional_segfault();  | 
115  | 0  |     }  | 
116  | 54.6k  |   }  | 
117  | 10.7k  |   return wuffs_base__status__message(&status);  | 
118  | 10.7k  | }  |