oss-fuzz/projects/testing-native-go-fuzzing/build.sh

183 lines
6.8 KiB
Bash
Executable File

#!/bin/bash -eu
# Copyright 2021 Google LLC
#
# 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.
#
################################################################################
cd $SRC
# Build main binary
git clone https://github.com/AdamKorcz/go-118-fuzz-build
cd go-118-fuzz-build
go build
# Build addimport binary
cd addimport
go build
cd $SRC/vitess
# Remove existing non-native fuzzers to not deal with them
rm go/vt/vtgate/vindexes/fuzz.go
# backup vtctl_fuzzer.go
cp go/test/fuzzing/vtctl_fuzzer.go /tmp/
rm -r go/test/fuzzing/*
mv $SRC/parser_fuzzer_test.go $SRC/vitess/go/test/fuzzing/
mv $SRC/ast_fuzzer_test.go $SRC/vitess/go/test/fuzzing/
mv $SRC/tablet_manager_fuzzer_test.go $SRC/vitess/go/test/fuzzing/
# Disable logging for mysql conn
# This affects the mysql fuzzers
sed -i '/log.Errorf/c\\/\/log.Errorf' $SRC/vitess/go/mysql/conn.go
sed -i '/log.Warningf/c\\/\/log.Warningf' $SRC/vitess/go/vt/sqlparser/parser.go
mv ./go/vt/vttablet/tabletmanager/vreplication/framework_test.go \
./go/vt/vttablet/tabletmanager/vreplication/framework_fuzz.go
#consistent_lookup_test.go is needed for loggingVCursor
mv ./go/vt/vtgate/vindexes/consistent_lookup_test.go \
./go/vt/vtgate/vindexes/consistent_lookup_test_fuzz.go
# fake_vcursor_test.go is needed for loggingVCursor
mv ./go/vt/vtgate/engine/fake_vcursor_test.go \
./go/vt/vtgate/engine/fake_vcursor.go
# plan_test.go is needed for vschemaWrapper
mv ./go/vt/vtgate/planbuilder/plan_test.go \
./go/vt/vtgate/planbuilder/plan_test_fuzz.go
# tabletserver fuzzer
mv ./go/vt/vttablet/tabletserver/testutils_test.go \
./go/vt/vttablet/tabletserver/testutils_fuzz.go
# collation fuzzer
mv ./go/mysql/collations/uca_test.go \
./go/mysql/collations/uca_test_fuzz.go
mv $SRC/vitess/go/vt/vtgate/grpcvtgateconn/suite_test.go \
$SRC/vitess/go/vt/vtgate/grpcvtgateconn/suite_test_fuzz.go
mv $SRC/vitess/go/vt/vtgate/grpcvtgateconn/fuzz_flaky_test.go \
$SRC/vitess/go/vt/vtgate/grpcvtgateconn/fuzz.go
# build_go_fuzz_harness rewrites a copy of the
# fuzzer to allow for libFuzzer instrumentation
function rewrite_go_fuzz_harness() {
fuzzer_filename=$1
# Create a copy of the fuzzer to not modify the existing fuzzer
cp $fuzzer_filename "${fuzzer_filename}"_fuzz_.go
mv $fuzzer_filename /tmp/
# replace *testing.F with *go118fuzzbuildutils.F
echo "replacing *testing.F"
sed -i 's/f \*testing\.F/f \*go118fuzzbuildutils\.F/g' "${fuzzer_filename}"_fuzz_.go
# import https://github.com/AdamKorcz/go-118-fuzz-build
# This changes the line numbers from the original fuzzer
$SRC/go-118-fuzz-build/addimport/addimport -path "${fuzzer_filename}"_fuzz_.go
}
function compile_native_go_fuzzer() {
fuzzer=$1
function=$2
path=$3
tags="-tags gofuzz"
if [[ $SANITIZER = *coverage* ]]; then
echo "here we perform coverage build"
fuzzed_package=`go list $tags -f '{{.Name}}' $path`
abspath=`go list $tags -f {{.Dir}} $path`
cd $abspath
cp $SRC/native_ossfuzz_coverage_runnger.go ./"${function,,}"_test.go
sed -i -e 's/FuzzFunction/'$function'/' ./"${function,,}"_test.go
sed -i -e 's/mypackagebeingfuzzed/'$fuzzed_package'/' ./"${function,,}"_test.go
sed -i -e 's/TestFuzzCorpus/Test'$function'Corpus/' ./"${function,,}"_test.go
# The repo is the module path/name, which is already created above in case it doesn't exist,
# but not always the same as the module path. This is necessary to handle SIV properly.
fuzzed_repo=$(go list $tags -f {{.Module}} "$path")
abspath_repo=`go list -m $tags -f {{.Dir}} $fuzzed_repo || go list $tags -f {{.Dir}} $fuzzed_repo`
# give equivalence to absolute paths in another file, as go test -cover uses golangish pkg.Dir
echo "s=$fuzzed_repo"="$abspath_repo"= > $OUT/$fuzzer.gocovpath
ls
gotip test -run Test${function}Corpus -v $tags -coverpkg $fuzzed_repo/... -c -o $OUT/$fuzzer $path
rm ./"${function,,}"_test.go
else
$SRC/go-118-fuzz-build/go-118-fuzz-build -o $fuzzer.a -func $function $abs_file_dir
$CXX $CXXFLAGS $LIB_FUZZING_ENGINE $fuzzer.a -o $OUT/$fuzzer
fi
}
# build_go_fuzzer will be the api used by users
# The api is now placed in this build script
# but will be moved to the base image once it
# has reached sufficient maturity.
function build_go_fuzzer () {
path=$1
function=$2
fuzzer=$3
tags="-tags gofuzz"
# Get absolute path
abs_file_dir=$(go list $tags -f {{.Dir}} $path)
# TODO: Get rid of "-r" flag here
fuzzer_filename=$(grep -r -l -s "$function" "${abs_file_dir}")
# test if file contains a line with "func $function" and "testing.F"
if [ $(grep -r "func $function" $fuzzer_filename | grep "testing.F" | wc -l) -eq 1 ]
then
# we are dealing with a native harness
# Install more dependencies
gotip get github.com/AdamKorcz/go-118-fuzz-build/utils
gotip get google.golang.org/grpc/internal/channelz@v1.39.0
echo "Native harness"
rewrite_go_fuzz_harness $fuzzer_filename
compile_native_go_fuzzer $fuzzer $function $abs_file_dir
# clean up
rm "${fuzzer_filename}_fuzz_.go"
mv /tmp/$(basename $fuzzer_filename) $fuzzer_filename
else
# we are dealing with a go-fuzz harness
echo "go-fuzz harness"
compile_go_fuzzer $path $function $fuzzer $tags
fi
}
# build native fuzzers
build_go_fuzzer vitess.io/vitess/go/test/fuzzing FuzzTabletManager_ExecuteFetchAsDba fuzz_tablet_manager_execute_fetch_as_dba
build_go_fuzzer vitess.io/vitess/go/test/fuzzing FuzzParser parser_fuzzer
build_go_fuzzer vitess.io/vitess/go/test/fuzzing FuzzIsDML is_dml_fuzzer
build_go_fuzzer vitess.io/vitess/go/test/fuzzing FuzzNormalizer normalizer_fuzzer
build_go_fuzzer vitess.io/vitess/go/test/fuzzing FuzzNodeFormat normalizer_fuzzer
build_go_fuzzer vitess.io/vitess/go/test/fuzzing FuzzSplitStatementToPieces fuzz_split_statement_to_pieces
build_go_fuzzer vitess.io/vitess/go/test/fuzzing FuzzEqualsSQLNode fuzz_equals_sql_node
# Delete all the native fuzzers before building the go-fuzz fuzzer(s)
# this will not be necessary when Go 1.18 is released. The reason this
# is needed is because go114-fuzz-build calls "go" instead of "gotip",
# and an error will be thrown because testing.F is not recognized.
rm $SRC/vitess/go/test/fuzzing/*_test.go
# build go-fuzz fuzzers
mv /tmp/vtctl_fuzzer.go $SRC/vitess/go/test/fuzzing/
build_go_fuzzer vitess.io/vitess/go/test/fuzzing Fuzz vtctl_fuzzer