Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 98 additions & 11 deletions infra/base-images/base-runner/coverage
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,69 @@ function run_javascript_fuzz_target {
nyc_report_converter.py $nyc_json_summary_file $summary_file
}

function is_lua_wrapper {
local target="$1"
[[ -f "$OUT/$target" ]] || return 1
head -1 "$OUT/$target" 2>/dev/null | grep -q "^#!.*bash" || return 1
grep -q "^# LUA_RUNTIME_BINARY:" "$OUT/$target" 2>/dev/null
}

function get_lua_runtime_binary {
local target="$1"
grep "^# LUA_RUNTIME_BINARY:" "$OUT/$target" | head -1 | sed 's/^# LUA_RUNTIME_BINARY: *//'
}

function run_lua_fuzz_target {
local target=$1
local lua_runtime=$2

local profraw_file="$DUMPS_DIR/$target.%1m.profraw"
local profraw_file_mask="$DUMPS_DIR/$target.*.profraw"
local profdata_file="$DUMPS_DIR/$target.profdata"
local corpus_real="$CORPUS_DIR/${target}"

local corpus_dummy="$OUT/dummy_corpus_dir_for_${target}"
rm -rf $corpus_dummy && mkdir -p $corpus_dummy

local args="-merge=1 -timeout=100 $corpus_dummy $corpus_real"

export LLVM_PROFILE_FILE=$profraw_file
timeout $TIMEOUT $OUT/$target $args &> $LOGS_DIR/$target.log
cov_retcode=$?

target_error_log="$LOGS_DIR/${target}_error.log"
grep -E "^==[0-9]+== ERROR: libFuzzer:" "$LOGS_DIR/$target.log" > "$target_error_log"
grep_retcode=$?

if (( $cov_retcode != 0 || $grep_retcode == 0 )); then
echo "Error occured while running $target:"
echo "Cov returncode: $cov_retcode, grep returncode: $grep_retcode"
cat $LOGS_DIR/$target.log
fi

rm -rf $corpus_dummy
if (( $(du -c $profraw_file_mask | tail -n 1 | cut -f 1) == 0 )); then
return 0
fi

# Use the actual Lua runtime binary, not the shell wrapper.
profraw_update.py $OUT/$lua_runtime -i $profraw_file_mask
llvm-profdata merge -j=1 -sparse $profraw_file_mask -o $profdata_file

rm $profraw_file_mask

shared_libraries=$(coverage_helper shared_libs -build-dir=$OUT -object=$lua_runtime)

llvm-cov export -summary-only -instr-profile=$profdata_file -object=$lua_runtime \
$shared_libraries $LLVM_COV_COMMON_ARGS > $FUZZER_STATS_DIR/$target.json

if (( $cov_retcode != 0 || $grep_retcode == 0 )); then
mv "$target_error_log" "$FUZZER_STATS_DIR/${target}_error.log";
fi

llvm-cov show -instr-profile=$profdata_file -object=$lua_runtime -line-coverage-gt=0 $shared_libraries $BRANCH_COV_ARGS $LLVM_COV_COMMON_ARGS > ${TEXTCOV_REPORT_DIR}/$target.covreport
}

function generate_html {
local profdata=$1
local shared_libraries=$2
Expand Down Expand Up @@ -467,18 +530,26 @@ for fuzz_target in $FUZZ_TARGETS; do
echo ${fuzz_target} >> $COVERAGE_TARGET_FILE

# Run the coverage collection.
run_fuzz_target $fuzz_target &

# Rewrite object if its a FUZZTEST target
if [[ $fuzz_target == *"@"* ]]; then
# Extract fuzztest binary name from fuzztest wrapper script.
fuzz_target=(${fuzz_target//@/ }[0])
fi
if [[ -z $objects ]]; then
# The first object needs to be passed without -object= flag.
objects="$fuzz_target"
# Detect Lua/luzer wrapper targets and handle them separately,
# using the actual Lua runtime binary for llvm-cov analysis.
if is_lua_wrapper $fuzz_target; then
lua_runtime=$(get_lua_runtime_binary $fuzz_target)
run_lua_fuzz_target $fuzz_target $lua_runtime &
echo "$lua_runtime" >> "$DUMPS_DIR/lua_runtime_binaries.txt"
else
objects="$objects -object=$fuzz_target"
run_fuzz_target $fuzz_target &

# Rewrite object if its a FUZZTEST target
if [[ $fuzz_target == *"@"* ]]; then
# Extract fuzztest binary name from fuzztest wrapper script.
fuzz_target=(${fuzz_target//@/ }[0])
fi
if [[ -z $objects ]]; then
# The first object needs to be passed without -object= flag.
objects="$fuzz_target"
else
objects="$objects -object=$fuzz_target"
fi
fi
fi

Expand Down Expand Up @@ -622,6 +693,17 @@ else
rm -f $PROFILE_FILE
llvm-profdata merge -sparse $DUMPS_DIR/*.profdata -o $PROFILE_FILE

# Add Lua runtime binaries to the objects list for llvm-cov.
if [[ -f "$DUMPS_DIR/lua_runtime_binaries.txt" ]]; then
for runtime in $(sort -u "$DUMPS_DIR/lua_runtime_binaries.txt"); do
if [[ -z $objects ]]; then
objects="$runtime"
else
objects="$objects -object=$runtime"
fi
done
fi

# TODO(mmoroz): add script from Chromium for rendering directory view reports.
# The first path in $objects does not have -object= prefix (llvm-cov format).
shared_libraries=$(coverage_helper shared_libs -build-dir=$OUT -object=$objects)
Expand All @@ -645,6 +727,11 @@ else
continue
fi

# For Lua/luzer wrapper targets, use the runtime binary as the
# llvm-cov object instead of the shell wrapper script.
if is_lua_wrapper $fuzz_target; then
fuzz_target=$(get_lua_runtime_binary $fuzz_target)
fi
generate_html $profdata_path "$shared_libraries" "$fuzz_target" "$report_dir"
done

Expand Down
1 change: 1 addition & 0 deletions projects/lua-example/compile_lua_fuzzer
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ echo "#!/bin/bash

# LLVMFuzzerTestOneInput so that the wrapper script is recognized
# as a fuzz target for 'check_build'.
# LUA_RUNTIME_BINARY: $lua_runtime
project_dir=\$(dirname \$(realpath \"\$0\"))

luarocks=\$(type -p luarocks)
Expand Down
10 changes: 4 additions & 6 deletions projects/lua/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,11 @@ FUZZER_ARGS=""
#
# 1. https://github.com/ligurio/lunapark/issues/180.
LAPI_TESTING="ON"
if [[ "$FUZZING_ENGINE" != "libfuzzer" ]] ||
[[ "$SANITIZER" == "coverage" ]]; then
if [[ "$FUZZING_ENGINE" != "libfuzzer" ]]; then
FUZZER_ARGS="-DDISABLE_LIBFUZZER_STATIC_LINKAGE=ON"
LAPI_TESTING="OFF"
elif [[ "$SANITIZER" == "coverage" ]]; then
FUZZER_ARGS="-DDISABLE_LIBFUZZER_STATIC_LINKAGE=ON"
fi

cmake_args=(
Expand Down Expand Up @@ -142,10 +143,7 @@ done

# Finish execution if libFuzzer is not used, because luzer
# is libFuzzer-based.
# Code coverage is not supported,
# see https://github.com/google/oss-fuzz/issues/14859.
if [[ "$FUZZING_ENGINE" != libfuzzer ]] ||
[[ "$SANITIZER" == "coverage" ]]; then
if [[ "$FUZZING_ENGINE" != libfuzzer ]]; then
echo "Lua API testing is not supported."
exit
fi
Expand Down
1 change: 1 addition & 0 deletions projects/lua/compile_lua_fuzzer
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ echo "#!/bin/bash

# LLVMFuzzerTestOneInput so that the wrapper script is recognized
# as a fuzz target for 'check_build'.
# LUA_RUNTIME_BINARY: $lua_runtime
project_dir=\$(dirname \$(realpath \"\$0\"))

luarocks=\$(type -p luarocks)
Expand Down
5 changes: 1 addition & 4 deletions projects/tarantool/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -117,10 +117,7 @@ done

# Finish execution if libFuzzer is not used, because luzer
# is libFuzzer-based.
# Code coverage is not supported,
# see https://github.com/google/oss-fuzz/issues/14859.
if [[ "$FUZZING_ENGINE" != libfuzzer ]] ||
[[ "$SANITIZER" == "coverage" ]]; then
if [[ "$FUZZING_ENGINE" != libfuzzer ]]; then
exit
fi

Expand Down
1 change: 1 addition & 0 deletions projects/tarantool/compile_lua_fuzzer
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ echo "#!/bin/bash

# LLVMFuzzerTestOneInput so that the wrapper script is recognized
# as a fuzz target for 'check_build'.
# LUA_RUNTIME_BINARY: $lua_runtime
project_dir=\$(dirname \$(realpath \"\$0\"))

luarocks=\$(type -p luarocks)
Expand Down
Loading