aboutsummaryrefslogtreecommitdiff
path: root/infra/base-images/base-runner/run_fuzzer
blob: b9bc8d9d679932176992a45db193bb9bb1dba3cd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
#!/bin/bash -eu
# Copyright 2016 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
################################################################################

# Fuzzer runner. Appends .options arguments and seed corpus to users args.
# Usage: $0 <fuzzer_name> <fuzzer_args>

export PATH=$OUT:$PATH
cd $OUT

DEBUGGER=${DEBUGGER:-}

FUZZER=$1
shift

CORPUS_DIR=${CORPUS_DIR:-"/tmp/${FUZZER}_corpus"}

SANITIZER=${SANITIZER:-}
if [ -z $SANITIZER ]; then
  # If $SANITIZER is not specified (e.g. calling from `reproduce` command), it
  # is not important and can be set to any value.
  SANITIZER="default"
fi

if [[ "$RUN_FUZZER_MODE" = interactive ]]; then
  FUZZER_OUT="$OUT/${FUZZER}_${FUZZING_ENGINE}_${SANITIZER}_out"
else
  FUZZER_OUT="/tmp/${FUZZER}_${FUZZING_ENGINE}_${SANITIZER}_out"
fi

function get_dictionary() {
  local options_file="$FUZZER.options"
  local dict_file="$FUZZER.dict"
  local dict=""
  if [[ -f "$options_file" ]]; then
    dict=$(sed -n 's/^\s*dict\s*=\s*\(.*\)/\1/p' "$options_file" | tail -1)
  fi
  if [[ -z "$dict" && -f "$dict_file" ]]; then
    dict="$dict_file"
  fi
  [[ -z "$dict" ]] && return
  if [[ "$FUZZING_ENGINE" = "libfuzzer" ]]; then
     printf -- "-dict=%s" "$dict"
  elif [[ "$FUZZING_ENGINE" = "afl" ]]; then
     printf -- "-x %s" "$dict"
  elif [[ "$FUZZING_ENGINE" = "honggfuzz" ]]; then
     printf -- "--dict %s" "$dict"
  else
     printf "Unexpected FUZZING_ENGINE: $FUZZING_ENGINE, ignoring\n" >&2
  fi
}

rm -rf $CORPUS_DIR && mkdir -p $CORPUS_DIR
rm -rf $FUZZER_OUT && mkdir -p $FUZZER_OUT

SEED_CORPUS="${FUZZER}_seed_corpus.zip"

if [ -f $SEED_CORPUS ] && [ -z ${SKIP_SEED_CORPUS:-} ]; then
  echo "Using seed corpus: $SEED_CORPUS"
  unzip -d ${CORPUS_DIR}/ $SEED_CORPUS > /dev/null
fi

OPTIONS_FILE="${FUZZER}.options"
CUSTOM_LIBFUZZER_OPTIONS=""

if [ -f $OPTIONS_FILE ]; then
  custom_asan_options=$(parse_options.py $OPTIONS_FILE asan)
  if [ ! -z $custom_asan_options ]; then
    export ASAN_OPTIONS="$ASAN_OPTIONS:$custom_asan_options"
  fi

  custom_msan_options=$(parse_options.py $OPTIONS_FILE msan)
  if [ ! -z $custom_msan_options ]; then
    export MSAN_OPTIONS="$MSAN_OPTIONS:$custom_msan_options"
  fi

  custom_ubsan_options=$(parse_options.py $OPTIONS_FILE ubsan)
  if [ ! -z $custom_ubsan_options ]; then
    export UBSAN_OPTIONS="$UBSAN_OPTIONS:$custom_ubsan_options"
  fi

  CUSTOM_LIBFUZZER_OPTIONS=$(parse_options.py $OPTIONS_FILE libfuzzer)
fi

if [[ "$FUZZING_ENGINE" = afl ]]; then

  # Set afl++ environment options.
  export ASAN_OPTIONS="$ASAN_OPTIONS:abort_on_error=1:symbolize=0:detect_odr_violation=0:"
  export MSAN_OPTIONS="$MSAN_OPTIONS:exit_code=86:symbolize=0"
  export UBSAN_OPTIONS="$UBSAN_OPTIONS:symbolize=0"
  export AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1
  export AFL_SKIP_CPUFREQ=1
  export AFL_NO_AFFINITY=1
  export AFL_FAST_CAL=1
  # If $OUT/afl_cmplog.txt is present this means the target was compiled for
  # CMPLOG. So we have to add the proper parameters to afl-fuzz. `-l 2` is
  # CMPLOG level 2, which will colorize larger files but not huge files and
  # not enable transform analysis unless there have been several cycles without
  # any finds.
  test -e "$OUT/afl_cmplog.txt" && AFL_FUZZER_ARGS="$AFL_FUZZER_ARGS -l 2 -c $OUT/$FUZZER"
  # If $OUT/afl++.dict we load it as a dictionary for afl-fuzz.
  test -e "$OUT/afl++.dict" && AFL_FUZZER_ARGS="$AFL_FUZZER_ARGS -x $OUT/afl++.dict"
  # Ensure timeout is a bit large than 1sec as some of the OSS-Fuzz fuzzers
  # are slower than this. 
  AFL_FUZZER_ARGS="$AFL_FUZZER_ARGS -t 5000+"
  # AFL expects at least 1 file in the input dir.
  echo input > ${CORPUS_DIR}/input
  echo afl++ setup:
  env|grep AFL_
  cat "$OUT/afl_options.txt"
  CMD_LINE="$OUT/afl-fuzz $AFL_FUZZER_ARGS -i $CORPUS_DIR -o $FUZZER_OUT $(get_dictionary) $* -- $OUT/$FUZZER"

elif [[ "$FUZZING_ENGINE" = honggfuzz ]]; then

  # Honggfuzz expects at least 1 file in the input dir.
  echo input > $CORPUS_DIR/input
  # --exit_upon_crash: exit whith a first crash seen
  # -R (report): save report file to this location
  # -W (working dir): where the crashes go
  # -v (verbose): don't use VTE UI, just stderr
  # -z: use software-instrumentation of clang (trace-pc-guard....)
  # -P: use persistent mode of fuzzing (i.e. LLVMFuzzerTestOneInput)
  # -f: location of the initial (and destination) file corpus
  # -n: number of fuzzing threads (and processes)
  CMD_LINE="$OUT/honggfuzz -n 1 --exit_upon_crash -R /tmp/${FUZZER}_honggfuzz.report -W $FUZZER_OUT -v -z -P -f \"$CORPUS_DIR\" $(get_dictionary) $* -- \"$OUT/$FUZZER\""

else

  CMD_LINE="$OUT/$FUZZER $FUZZER_ARGS $*"

  if [ -z ${SKIP_SEED_CORPUS:-} ]; then
    CMD_LINE="$CMD_LINE $CORPUS_DIR"
  fi

  if [ ! -z $CUSTOM_LIBFUZZER_OPTIONS ]; then
    CMD_LINE="$CMD_LINE $CUSTOM_LIBFUZZER_OPTIONS"
  fi

  if [[ ! "$CMD_LINE" =~ "-dict=" ]]; then
    if [ -f "$FUZZER.dict" ]; then
      CMD_LINE="$CMD_LINE -dict=$FUZZER.dict"
    fi
  fi

  CMD_LINE="$CMD_LINE < /dev/null"

fi

echo $CMD_LINE

# Unset OUT so the fuzz target can't rely on it.
unset OUT

if [ ! -z "$DEBUGGER" ]; then
  CMD_LINE="$DEBUGGER $CMD_LINE"
fi

bash -c "$CMD_LINE"