From 69ffa9bfdf1de7890377c2db660b6968a8467a28 Mon Sep 17 00:00:00 2001 From: Max Moroz Date: Thu, 26 Apr 2018 07:17:44 -0700 Subject: [PATCH] [infra] Invoke run_fuzzer from bad_build_check for regression testing (fixes #1355). (#1357) * [infra] Invoke run_fuzzer from bad_build_check for regression testing (fixes #1355). * Address review comments. --- infra/base-images/base-runner/bad_build_check | 27 ++++++++++++++++++- infra/base-images/base-runner/run_fuzzer | 19 ++++++------- infra/base-images/base-runner/test_all | 11 -------- infra/gcb/build.py | 4 --- 4 files changed, 34 insertions(+), 27 deletions(-) diff --git a/infra/base-images/base-runner/bad_build_check b/infra/base-images/base-runner/bad_build_check index 5e83f26e4..84ef7edb6 100755 --- a/infra/base-images/base-runner/bad_build_check +++ b/infra/base-images/base-runner/bad_build_check @@ -54,7 +54,7 @@ function check_instrumentation { return 1 fi - local NUMBER_OF_EDGES=$(grep -Po "INFO: Loaded [[:digit:]]+ module.*\(.*counters|guards\):[[:space:]]+\K[[:digit:]]+" $FUZZER_OUTPUT) + local NUMBER_OF_EDGES=$(grep -Po "INFO: Loaded [[:digit:]]+ module.*\(.*(counters|guards)\):[[:space:]]+\K[[:digit:]]+" $FUZZER_OUTPUT) if (( $NUMBER_OF_EDGES < $THRESHOLD_FOR_NUMBER_OF_EDGES )); then echo "BAD BUILD: the target seems to have only partial coverage instrumentation." @@ -165,6 +165,30 @@ function check_mixed_sanitizers { fi } +# Verify that the given fuzz target doesn't crash on the seed corpus. +function check_seed_corpus { + local FUZZER=$1 + local FUZZER_NAME="$(basename $FUZZER)" + local FUZZER_OUTPUT="/tmp/$FUZZER_NAME.output" + + if [[ "$FUZZING_ENGINE" != libfuzzer ]]; then + return + fi + + # Set up common fuzzing arguments, otherwise "run_fuzzer" errors out. + if [ -z "$FUZZER_ARGS" ]; then + export FUZZER_ARGS="-rss_limit_mb=2048 -timeout=25" + fi + + bash -c "run_fuzzer $FUZZER_NAME -runs=0" &> $FUZZER_OUTPUT + + # Don't output anything if fuzz target hasn't crashed. + if [ $? -ne 0 ]; then + echo "$FUZZER_NAME has a crash input in its seed coprpus:" + cat $FUZZER_OUTPUT + fi +} + function main { local FUZZER=$1 @@ -172,6 +196,7 @@ function main { check_instrumentation $FUZZER check_mixed_sanitizers $FUZZER check_startup_crash $FUZZER + check_seed_corpus $FUZZER } diff --git a/infra/base-images/base-runner/run_fuzzer b/infra/base-images/base-runner/run_fuzzer index b32637973..34f1d936f 100755 --- a/infra/base-images/base-runner/run_fuzzer +++ b/infra/base-images/base-runner/run_fuzzer @@ -24,14 +24,14 @@ cd $OUT FUZZER=$1 shift -rm -rf /tmp/input/ && mkdir /tmp/input/ +CORPUS_DIR="/tmp/${FUZZER}_corpus" + +rm -rf $CORPUS_DIR && mkdir $CORPUS_DIR -CORPUS= SEED_CORPUS="${FUZZER}_seed_corpus.zip" if [ -f $SEED_CORPUS ]; then echo "Using seed corpus: $SEED_CORPUS" - unzip -d /tmp/input/ $SEED_CORPUS > /dev/null - CORPUS=/tmp/input + unzip -d ${CORPUS_DIR}/ $SEED_CORPUS > /dev/null fi if [[ "$FUZZING_ENGINE" = afl ]]; then @@ -43,14 +43,11 @@ if [[ "$FUZZING_ENGINE" = afl ]]; then export AFL_SKIP_CPUFREQ=1 rm -rf /tmp/afl_output && mkdir /tmp/afl_output # AFL expects at least 1 file in the input dir. - echo input > /tmp/input/input - CMD_LINE="$OUT/afl-fuzz $AFL_FUZZER_ARGS -i /tmp/input -o /tmp/afl_output $@ $OUT/$FUZZER" + echo input > ${CORPUS_DIR}/input + CMD_LINE="$OUT/afl-fuzz $AFL_FUZZER_ARGS -i $CORPUS_DIR -o /tmp/afl_output $@ $OUT/$FUZZER" elif [[ "$FUZZING_ENGINE" = honggfuzz ]]; then - if [ -z "$CORPUS" ]; then - CORPUS=/tmp/input - fi # Honggfuzz expects at least 1 file in the input dir. - echo input > $CORPUS/input + echo input > $CORPUS_DIR/input rm -rf /tmp/honggfuzz_workdir && mkdir /tmp/honggfuzz_workdir # --exit_upon_crash: exit whith a first crash seen # -R (report): save report file to this location @@ -62,7 +59,7 @@ elif [[ "$FUZZING_ENGINE" = honggfuzz ]]; then # -n: number of fuzzing threads (and processes) CMD_LINE="$OUT/honggfuzz -n 1 --exit_upon_crash -R /tmp/HONGGFUZZ.REPORT.TXT -W /tmp/honggfuzz_workdir -v -z -P -f \"$CORPUS\" $@ -- \"$OUT/$FUZZER\"" else - CMD_LINE="$OUT/$FUZZER $FUZZER_ARGS $@ $CORPUS" + CMD_LINE="$OUT/$FUZZER $FUZZER_ARGS $@ $CORPUS_DIR" OPTIONS_FILE="${FUZZER}.options" if [ -f $OPTIONS_FILE ]; then diff --git a/infra/base-images/base-runner/test_all b/infra/base-images/base-runner/test_all index 4b0ec79a9..6a071c1ef 100755 --- a/infra/base-images/base-runner/test_all +++ b/infra/base-images/base-runner/test_all @@ -46,17 +46,6 @@ for FUZZER_BINARY in $(find $OUT/ -executable -type f); do continue fi - if [ "$SKIP_TEST_TARGET_RUN" != "1" ]; then - if [[ "$FUZZING_ENGINE" = honggfuzz ]]; then - timeout --preserve-status -s INT 20s run_fuzzer $FUZZER - elif [[ "$FUZZING_ENGINE" = libfuzzer ]]; then - run_fuzzer $FUZZER -max_total_time=20 - else - export AFL_NO_UI=1 - timeout --preserve-status -s INT 20s run_fuzzer $FUZZER - fi - fi - echo "INFO: performing bad build checks for $FUZZER_BINARY." LOG_PATH_FOR_BROKEN_TARGET="${BROKEN_TARGETS_DIR}/${FUZZER}" diff --git a/infra/gcb/build.py b/infra/gcb/build.py index 5fec82f00..d86735cd5 100755 --- a/infra/gcb/build.py +++ b/infra/gcb/build.py @@ -195,10 +195,6 @@ def get_build_steps(project_yaml, dockerfile_path): env.append('OUT=' + out) env.append('MSAN_LIBS_PATH=/workspace/msan') - # To disable running of all fuzz targets while doing |test_all| step, as - # that step is currently being used for performing bad build checks only. - env.append('SKIP_TEST_TARGET_RUN=1') - workdir = workdir_from_dockerfile(dockerfile_path) if not workdir: workdir = '/src'