aboutsummaryrefslogtreecommitdiffhomepage
path: root/infra/base-images/base-runner/run_fuzzer
blob: cebcebbd6f7874e59bb95ff067a0b3aad6d1d08e (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
#!/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

FUZZER=$1
shift

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

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 $CORPUS_DIR
rm -rf $FUZZER_OUT && mkdir $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
  # https://chromium.googlesource.com/chromium/src/+/master/third_party/afl/src/docs/env_variables.txt
  export ASAN_OPTIONS="$ASAN_OPTIONS:abort_on_error=1:symbolize=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
  # AFL expects at least 1 file in the input dir.
  echo input > ${CORPUS_DIR}/input
  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 $* $CORPUS_DIR"

  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

bash -c "$CMD_LINE"