Skip to content

Commit e7e42e9

Browse files
authored
Merge pull request #771 from pjbgf/fix-broken-fuzz
build: Fix cifuzz tests and improve fuzz tests' reliability
2 parents ee8c46a + c636df0 commit e7e42e9

File tree

4 files changed

+114
-57
lines changed

4 files changed

+114
-57
lines changed

controllers/kustomization_fuzzer_test.go

+28-9
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
//go:build gofuzz
2-
// +build gofuzz
1+
//go:build gofuzz_libfuzzer
2+
// +build gofuzz_libfuzzer
33

44
/*
55
Copyright 2021 The Flux authors
@@ -20,28 +20,47 @@ limitations under the License.
2020
package controllers
2121

2222
import (
23+
"archive/tar"
24+
"compress/gzip"
2325
"context"
26+
"crypto/sha1"
27+
"crypto/sha256"
28+
"embed"
2429
"errors"
2530
"fmt"
31+
"io"
32+
"io/fs"
33+
"math/rand"
2634
"os"
2735
"os/exec"
36+
"path/filepath"
2837
"strings"
2938
"sync"
39+
"testing"
3040
"time"
3141

32-
"embed"
33-
"io/fs"
34-
3542
securejoin "github.com/cyphar/filepath-securejoin"
36-
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta2"
37-
"github.com/fluxcd/pkg/apis/meta"
38-
"github.com/fluxcd/pkg/runtime/testenv"
39-
sourcev1 "github.com/fluxcd/source-controller/api/v1beta2"
43+
"github.com/hashicorp/vault/api"
44+
"github.com/ory/dockertest"
4045
corev1 "k8s.io/api/core/v1"
4146
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
4247
"k8s.io/apimachinery/pkg/types"
48+
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
49+
"k8s.io/client-go/kubernetes/scheme"
50+
ctrl "sigs.k8s.io/controller-runtime"
51+
"sigs.k8s.io/controller-runtime/pkg/client"
52+
"sigs.k8s.io/controller-runtime/pkg/envtest"
53+
controllerLog "sigs.k8s.io/controller-runtime/pkg/log"
54+
"sigs.k8s.io/controller-runtime/pkg/log/zap"
55+
56+
"github.com/fluxcd/pkg/apis/meta"
57+
"github.com/fluxcd/pkg/runtime/controller"
58+
"github.com/fluxcd/pkg/runtime/testenv"
59+
"github.com/fluxcd/pkg/testserver"
60+
sourcev1 "github.com/fluxcd/source-controller/api/v1beta2"
4361

4462
fuzz "github.com/AdaLogics/go-fuzz-headers"
63+
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta2"
4564
)
4665

4766
var (

tests/fuzz/README.md

+16
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,23 @@ Run fuzzer inside a container:
3939
/out/fuzz_conditions_match
4040
```
4141

42+
### Running oss-fuzz locally
43+
44+
The `make fuzz-smoketest` is meant to be an easy way to reproduce errors that may occur
45+
upstream. If our checks ever run out of sync with upstream, the upstream tests can be
46+
executed locally with:
47+
48+
```
49+
git clone --depth 1 https://github.com/google/oss-fuzz
50+
cd oss-fuzz
51+
python infra/helper.py build_image fluxcd
52+
python infra/helper.py build_fuzzers --sanitizer address --architecture x86_64 fluxcd
53+
python infra/helper.py check_build --sanitizer address --architecture x86_64 fluxcd
54+
```
55+
56+
For latest info on testing oss-fuzz locally, refer to the [upstream guide].
4257

4358
[oss fuzz]: https://github.com/google/oss-fuzz
4459
[oss-fuzz repository]: https://github.com/google/oss-fuzz/tree/master/projects/fluxcd
4560
[github workflow]: .github/workflows/cifuzz.yaml
61+
[upstream guide]: https://google.github.io/oss-fuzz/getting-started/new-project-guide/#testing-locally

tests/fuzz/oss_fuzz_build.sh

+45-48
Original file line numberDiff line numberDiff line change
@@ -16,69 +16,66 @@
1616

1717
set -euxo pipefail
1818

19+
# This file aims for:
20+
# - Dynamically discover and build all fuzz tests within the repository.
21+
# - Work for both local make fuzz-smoketest and the upstream oss-fuzz.
22+
1923
GOPATH="${GOPATH:-/root/go}"
2024
GO_SRC="${GOPATH}/src"
2125
PROJECT_PATH="github.com/fluxcd/kustomize-controller"
22-
TMP_DIR=$(mktemp -d /tmp/oss_fuzz-XXXXXX)
23-
24-
cleanup(){
25-
rm -rf "${TMP_DIR}"
26-
}
27-
trap cleanup EXIT
2826

27+
# install_deps installs all dependencies needed for upstream oss-fuzz.
28+
# Unfortunately we can't pin versions here, as we want to always
29+
# have the latest, so that we can reproduce errors occuring upstream.
2930
install_deps(){
30-
if ! command -v go-118-fuzz-build &> /dev/null || ! command -v addimport &> /dev/null; then
31-
mkdir -p "${TMP_DIR}/go-118-fuzz-build"
32-
33-
git clone https://github.com/AdamKorcz/go-118-fuzz-build "${TMP_DIR}/go-118-fuzz-build"
34-
cd "${TMP_DIR}/go-118-fuzz-build"
35-
go build -o "${GOPATH}/bin/go-118-fuzz-build"
36-
37-
cd addimport
38-
go build -o "${GOPATH}/bin/addimport"
39-
fi
40-
41-
if ! command -v goimports &> /dev/null; then
42-
go install golang.org/x/tools/cmd/goimports@latest
31+
if ! command -v go-118-fuzz-build &> /dev/null; then
32+
go install github.com/AdamKorcz/go-118-fuzz-build@latest
4333
fi
4434
}
4535

46-
# Removes the content of test funcs which could cause the Fuzz
47-
# tests to break.
48-
remove_test_funcs(){
49-
filename=$1
50-
51-
echo "removing co-located *testing.T"
52-
sed -i -e '/func Test.*testing.T) {$/ {:r;/\n}/!{N;br}; s/\n.*\n/\n/}' "${filename}"
53-
# Remove gomega reference as it is not used by Fuzz tests.
54-
sed -i 's;. "github.com/onsi/gomega";;g' "${filename}"
55-
56-
# After removing the body of the go testing funcs, consolidate the imports.
57-
goimports -w "${filename}"
58-
}
59-
6036
install_deps
6137

6238
cd "${GO_SRC}/${PROJECT_PATH}"
6339

64-
go get github.com/AdamKorcz/go-118-fuzz-build/utils
40+
# Ensure any project-specific requirements are catered for ahead of
41+
# the generic build process.
42+
if [ -f "tests/fuzz/oss_fuzz_prebuild.sh" ]; then
43+
tests/fuzz/oss_fuzz_prebuild.sh
44+
fi
45+
46+
modules=$(find . -mindepth 1 -maxdepth 4 -type f -name 'go.mod' | cut -c 3- | sed 's|/[^/]*$$||' | sort -u | sed 's;/go.mod;;g' | sed 's;go.mod;.;g')
6547

66-
mkdir -p controllers/testdata/crd
67-
cp config/crd/bases/*.yaml controllers/testdata/crd
48+
for module in ${modules}; do
6849

69-
# Iterate through all Go Fuzz targets, compiling each into a fuzzer.
70-
test_files=$(grep -r --include='**_test.go' --files-with-matches 'func Fuzz' .)
71-
for file in ${test_files}
72-
do
73-
remove_test_funcs "${file}"
50+
cd "${GO_SRC}/${PROJECT_PATH}/${module}"
7451

75-
targets=$(grep -oP 'func \K(Fuzz\w*)' "${file}")
76-
for target_name in ${targets}
77-
do
78-
fuzzer_name=$(echo "${target_name}" | tr '[:upper:]' '[:lower:]')
79-
target_dir=$(dirname "${file}")
52+
# TODO: stop ignoring recorder_fuzzer_test.go. Temporary fix for fuzzing building issues.
53+
test_files=$(grep -r --include='**_test.go' --files-with-matches 'func Fuzz' . || echo "")
54+
if [ -z "${test_files}" ]; then
55+
continue
56+
fi
8057

81-
echo "Building ${file}.${target_name} into ${fuzzer_name}"
82-
compile_native_go_fuzzer "${target_dir}" "${target_name}" "${fuzzer_name}"
58+
go get github.com/AdamKorcz/go-118-fuzz-build/testing
59+
60+
# Iterate through all Go Fuzz targets, compiling each into a fuzzer.
61+
for file in ${test_files}; do
62+
# If the subdir is a module, skip this file, as it will be handled
63+
# at the next iteration of the outer loop.
64+
if [ -f "$(dirname "${file}")/go.mod" ]; then
65+
continue
66+
fi
67+
68+
targets=$(grep -oP 'func \K(Fuzz\w*)' "${file}")
69+
for target_name in ${targets}; do
70+
# Transform module path into module name (e.g. git/libgit2 to git_libgit2).
71+
module_name=$(echo ${module} | tr / _)
72+
# Compose fuzzer name based on the lowercase version of the func names.
73+
# The module name is added after the fuzz prefix, for better discoverability.
74+
fuzzer_name=$(echo "${target_name}" | tr '[:upper:]' '[:lower:]' | sed "s;fuzz_;fuzz_${module_name}_;g")
75+
target_dir=$(dirname "${file}")
76+
77+
echo "Building ${file}.${target_name} into ${fuzzer_name}"
78+
compile_native_go_fuzzer "${target_dir}" "${target_name}" "${fuzzer_name}"
79+
done
8380
done
8481
done

tests/fuzz/oss_fuzz_prebuild.sh

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#!/usr/bin/env bash
2+
3+
# Copyright 2022 The Flux authors
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
set -euxo pipefail
18+
19+
# This file is executed by upstream oss-fuzz for any requirements that
20+
# are specific for building this project.
21+
22+
# Some tests requires embedded resources. Embedding does not allow
23+
# for traversing into ascending dirs, therefore we copy those contents here:
24+
mkdir -p controllers/testdata/crd
25+
cp config/crd/bases/*.yaml controllers/testdata/crd

0 commit comments

Comments
 (0)