]> wimlib.net Git - wimlib/blob - tools/libFuzzer/fuzz.sh
Improve fuzz testing
[wimlib] / tools / libFuzzer / fuzz.sh
1 #!/bin/bash
2
3 set -e -u -o pipefail
4
5 cd "$(dirname "$0")"
6 TOPDIR=../..
7 SCRIPTDIR=$PWD
8
9 read -r -a AVAILABLE_TARGETS < <(echo */fuzz.c | sed 's@/fuzz.c@@g')
10
11 usage()
12 {
13         cat << EOF
14 Usage: $0 [OPTION]... FUZZ_TARGET
15
16 Fuzz wimlib with LLVM's libFuzzer.
17
18 Options:
19    --asan          Enable AddressSanitizer
20    --input=INPUT   Test a single input file only
21    --msan          Enable MemorySanitizer
22    --time=SECONDS  Stop after the given time has passed
23    --ubsan         Enable UndefinedBehaviorSanitizer
24
25 Available fuzz targets: ${AVAILABLE_TARGETS[*]}
26 EOF
27 }
28
29 die()
30 {
31         echo "$*" 1>&2
32         exit 1
33 }
34
35 run_cmd()
36 {
37         echo "$*"
38         "$@"
39 }
40
41 EXTRA_SANITIZERS=
42 EXTRA_FUZZER_ARGS=()
43 INPUT=
44
45 longopts_array=(
46 asan
47 help
48 input:
49 msan
50 time:
51 ubsan
52 )
53 longopts=$(echo "${longopts_array[@]}" | tr ' ' ',')
54
55 if ! options=$(getopt -o "" -l "$longopts" -- "$@"); then
56         usage 1>&2
57         exit 1
58 fi
59 eval set -- "$options"
60 while true; do
61         case "$1" in
62         --asan)
63                 EXTRA_SANITIZERS+=",address"
64                 ;;
65         --help)
66                 usage
67                 exit 0
68                 ;;
69         --input)
70                 INPUT=$2
71                 shift
72                 ;;
73         --time)
74                 EXTRA_FUZZER_ARGS+=("-max_total_time=$2")
75                 shift
76                 ;;
77         --msan)
78                 EXTRA_SANITIZERS+=",memory"
79                 ;;
80         --ubsan)
81                 EXTRA_SANITIZERS+=",undefined"
82                 ;;
83         --)
84                 shift
85                 break
86                 ;;
87         *)
88                 echo 1>&2 "Invalid option '$1'"
89                 usage 1>&2
90                 exit 1
91         esac
92         shift
93 done
94
95 if (( $# != 1 )); then
96         echo 1>&2 "No fuzz target specified!"
97         usage 1>&2
98         exit 1
99 fi
100 TARGET=$1
101 if [ ! -e "$TARGET/fuzz.c" ]; then
102         echo 1>&2 "'$TARGET' is not a valid fuzz target!"
103         usage 1>&2
104         exit 1
105 fi
106 cd "$TOPDIR"
107 cflags="-g -O1 -Wall -Werror"
108 cflags+=" -fsanitize=fuzzer-no-link$EXTRA_SANITIZERS"
109 if [ -n "$EXTRA_SANITIZERS" ]; then
110         cflags+=" -fno-sanitize-recover=${EXTRA_SANITIZERS#,}"
111 fi
112 if ! [ -e config.log ] || ! grep -q -- "'CFLAGS=$cflags'" config.log; then
113         run_cmd ./configure --enable-test-support --without-fuse --without-ntfs-3g \
114                 CC=clang CFLAGS="$cflags"
115 fi
116 run_cmd make "-j$(getconf _NPROCESSORS_ONLN)"
117 cd "$SCRIPTDIR"
118 if [ -n "$INPUT" ]; then
119         run_cmd clang -g -O1 -fsanitize=fuzzer-no-link$EXTRA_SANITIZERS -Wall -Werror \
120                 -I "$TOPDIR/include" "$TARGET/fuzz.c" test-one-input.c fault-injection.c \
121                 "$TOPDIR/.libs/libwim.a" -o test-one-input
122         run_cmd ./test-one-input "$INPUT"
123 else
124         run_cmd clang -g -O1 -fsanitize=fuzzer$EXTRA_SANITIZERS -Wall -Werror \
125                 -I "$TOPDIR/include" "$TARGET/fuzz.c" fault-injection.c \
126                 "$TOPDIR/.libs/libwim.a" -o "$TARGET/fuzz"
127         run_cmd "$TARGET/fuzz" "${EXTRA_FUZZER_ARGS[@]}" "$TARGET/corpus"
128 fi