From 283b5db5898555bb3d576f7f9736df1982237bac Mon Sep 17 00:00:00 2001 From: AdamKorcz Date: Fri, 24 Sep 2021 23:24:51 +0100 Subject: [PATCH 1/2] Fuzzing: Initial commit Signed-off-by: AdamKorcz --- fuzz/Dockerfile | 62 +++++++++++++++ fuzz/conditions_fuzzer.go | 161 ++++++++++++++++++++++++++++++++++++++ fuzz/fuzz.go | 91 +++++++++++++++++++++ fuzz/tls_fuzzer.go | 34 ++++++++ 4 files changed, 348 insertions(+) create mode 100644 fuzz/Dockerfile create mode 100644 fuzz/conditions_fuzzer.go create mode 100644 fuzz/fuzz.go create mode 100644 fuzz/tls_fuzzer.go diff --git a/fuzz/Dockerfile b/fuzz/Dockerfile new file mode 100644 index 00000000..31d5e049 --- /dev/null +++ b/fuzz/Dockerfile @@ -0,0 +1,62 @@ +FROM golang:1.16-buster as builder +RUN set -eux; \ + apt-get update \ + && apt-get upgrade -y \ + && apt-get install -y \ + clang \ + curl \ + vim + +RUN git clone https://github.com/fluxcd/pkg /workspace +RUN mkdir /workspace/fuzzing + + +RUN go get -u github.com/dvyukov/go-fuzz/go-fuzz@latest github.com/dvyukov/go-fuzz/go-fuzz-build@latest +RUN go install sigs.k8s.io/controller-runtime/tools/setup-envtest@latest +RUN go get github.com/AdaLogics/go-fuzz-headers + +RUN go get golang.org/x/sync + +WORKDIR /workspace/fuzzing +COPY fuzz.go /workspace/fuzzing/ +COPY conditions_fuzzer.go /workspace/runtime/conditions/ +COPY tls_fuzzer.go /workspace/runtime/tls/ +RUN cd /workspace/fuzzing && go mod init fuzzing && go mod tidy && go mod download && go mod tidy +RUN go mod download github.com/dvyukov/go-fuzz + + +# Build the fuzzers +RUN mkdir /fuzzers + +RUN go-fuzz-build -libfuzzer -func=FuzzUntar\ + && clang -o /fuzzers/FuzzUntar reflect-fuzz.a \ + -fsanitize=fuzzer +RUN go-fuzz-build -libfuzzer -func=FuzzLibGit2Error\ + && clang -o /fuzzers/FuzzLibGit2Error reflect-fuzz.a \ + -fsanitize=fuzzer +RUN go-fuzz-build -libfuzzer -func=FuzzEventInfof\ + && clang -o /fuzzers/FuzzEventInfof reflect-fuzz.a \ + -fsanitize=fuzzer + +WORKDIR /workspace/runtime/tls +RUN go get github.com/AdaLogics/go-fuzz-headers +RUN go get github.com/dvyukov/go-fuzz/go-fuzz-dep +RUN go-fuzz-build -libfuzzer -func=FuzzTlsConfig\ + && clang -o /fuzzers/FuzzTlsConfig reflect-fuzz.a \ + -fsanitize=fuzzer + +WORKDIR /workspace/runtime/conditions +RUN go-fuzz-build -libfuzzer -func=FuzzGetterConditions\ + && clang -o /fuzzers/FuzzGetterConditions reflect-fuzz.a \ + -fsanitize=fuzzer +RUN go-fuzz-build -libfuzzer -func=FuzzConditionsMatch\ + && clang -o /fuzzers/FuzzConditionsMatch reflect-fuzz.a \ + -fsanitize=fuzzer +RUN go-fuzz-build -libfuzzer -func=FuzzPatchApply\ + && clang -o /fuzzers/FuzzPatchApply reflect-fuzz.a \ + -fsanitize=fuzzer +RUN go-fuzz-build -libfuzzer -func=FuzzConditionsUnstructured\ + && clang -o /fuzzers/FuzzConditionsUnstructured reflect-fuzz.a \ + -fsanitize=fuzzer + +#RUN /fuzzers/FuzzLibGit2Error \ No newline at end of file diff --git a/fuzz/conditions_fuzzer.go b/fuzz/conditions_fuzzer.go new file mode 100644 index 00000000..02dd8fcb --- /dev/null +++ b/fuzz/conditions_fuzzer.go @@ -0,0 +1,161 @@ +//go:build gofuzz +// +build gofuzz + +/* +Copyright 2021 The Flux authors +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. +*/ +package conditions + +import ( + fuzz "github.com/AdaLogics/go-fuzz-headers" + "github.com/fluxcd/pkg/runtime/conditions/testdata" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" +) + +// FuzzGetterConditions implements a fuzzer that +// targets SetSummary() +func FuzzGetterConditions(data []byte) int { + f := fuzz.NewConsumer(data) + + // Create slice of metav1.Condition + noOfConditions, err := f.GetInt() + if err != nil { + return 0 + } + maxNoOfConditions := 30 + conditions := make([]metav1.Condition, 0) + + // Add Conditions in the slice + for i := 0; i < noOfConditions%maxNoOfConditions; i++ { + c := metav1.Condition{} + err = f.GenerateStruct(&c) + if err != nil { + return 0 + } + conditions = append(conditions, c) + } + obj := &testdata.Fake{} + obj.SetConditions(conditions) + + targetCondition, err := f.GetString() + if err != nil { + return 0 + } + + // Call the target + SetSummary(obj, targetCondition) + return 1 +} + +// FuzzConditionsMatch implements a fuzzer that +// that targets Match() +func FuzzConditionsMatch(data []byte) int { + f := fuzz.NewConsumer(data) + condition := metav1.Condition{} + err := f.GenerateStruct(&condition) + if err != nil { + return 0 + } + m := MatchCondition(condition) + + actual := metav1.Condition{} + err = f.GenerateStruct(&actual) + if err != nil { + return 0 + } + + // Call the target + _, _ = m.Match(actual) + return 1 +} + +// newGetter allows the fuzzer to create a Getter +// This is just a utility +func newGetter(f *fuzz.ConsumeFuzzer) (Getter, error) { + obj := &testdata.Fake{} + noOfConditions, err := f.GetInt() + if err != nil { + return obj, err + } + maxNoOfConditions := 30 + conditions := make([]metav1.Condition, 0) + for i := 0; i < noOfConditions%maxNoOfConditions; i++ { + c := metav1.Condition{} + err = f.GenerateStruct(&c) + if err != nil { + return obj, err + } + conditions = append(conditions, c) + } + + obj.SetConditions(conditions) + return obj, nil +} + +// newSetter allows the fuzzer to create a Setter +// This is just a utility +func newSetter(f *fuzz.ConsumeFuzzer) (Setter, error) { + obj := &testdata.Fake{} + noOfConditions, err := f.GetInt() + if err != nil { + return obj, err + } + maxNoOfConditions := 30 + conditions := make([]metav1.Condition, 0) + for i := 0; i < noOfConditions%maxNoOfConditions; i++ { + c := metav1.Condition{} + err = f.GenerateStruct(&c) + if err != nil { + return obj, err + } + conditions = append(conditions, c) + } + obj.SetConditions(conditions) + return obj, nil +} + +// FuzzPatchApply implements a fuzzer that targets patch.Apply +func FuzzPatchApply(data []byte) int { + f := fuzz.NewConsumer(data) + + before, err := newGetter(f) + if err != nil { + return 0 + } + after, err := newGetter(f) + if err != nil { + return 0 + } + patch := NewPatch(before, after) + + setter, err := newSetter(f) + if err != nil { + return 0 + } + _ = patch.Apply(setter) + return 1 +} + +// FuzzConditionsUnstructured implements a fuzzer +// that targets GetConditions() +func FuzzConditionsUnstructured(data []byte) int { + u := &unstructured.Unstructured{} + f := fuzz.NewConsumer(data) + err := f.GenerateStruct(u) + if err != nil { + return 0 + } + g := UnstructuredGetter(u) + _ = g.GetConditions() + return 1 +} diff --git a/fuzz/fuzz.go b/fuzz/fuzz.go new file mode 100644 index 00000000..50352817 --- /dev/null +++ b/fuzz/fuzz.go @@ -0,0 +1,91 @@ +//go:build gofuzz +// +build gofuzz + +/* +Copyright 2021 The Flux authors +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. +*/ +package fuzzing + +import ( + "bytes" + "encoding/json" + "errors" + fuzz "github.com/AdaLogics/go-fuzz-headers" + "github.com/fluxcd/pkg/gitutil" + "github.com/fluxcd/pkg/runtime/events" + "github.com/fluxcd/pkg/untar" + "io" + corev1 "k8s.io/api/core/v1" + "net/http" + "net/http/httptest" + "os" +) + +// FuzzUntar implements a fuzzer that +// targets untar.Untar() +func FuzzUntar(data []byte) int { + r := bytes.NewReader(data) + tmpDir, err := os.MkdirTemp("", "dir-") + if err != nil { + return 0 + } + defer os.RemoveAll(tmpDir) + _, _ = untar.Untar(r, tmpDir) + return 1 +} + +// FuzzLibGit2Error implements a fuzzer that +// targets gitutil.LibGit2Error +func FuzzLibGit2Error(data []byte) int { + err := errors.New(string(data)) + _ = gitutil.LibGit2Error(err) + return 1 +} + +// FuzzEventInfof implements a fuzzer that +// targets eventRecorder.EventInfof() +func FuzzEventInfof(data []byte) int { + f := fuzz.NewConsumer(data) + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + b, err := io.ReadAll(r.Body) + if err != nil { + return + } + + var payload events.Event + err = json.Unmarshal(b, &payload) + if err != nil { + return + } + })) + defer ts.Close() + eventRecorder, err := events.NewRecorder(ts.URL, "test-controller") + if err != nil { + return 0 + } + eventRecorder.Client.RetryMax = 2 + obj := corev1.ObjectReference{} + err = f.GenerateStruct(&obj) + if err != nil { + return 0 + } + severity, err := f.GetString() + if err != nil { + return 0 + } + reason, err := f.GetString() + if err != nil { + return 0 + } + _ = eventRecorder.EventInfof(obj, nil, severity, reason, obj.Name) + return 1 +} diff --git a/fuzz/tls_fuzzer.go b/fuzz/tls_fuzzer.go new file mode 100644 index 00000000..d0355937 --- /dev/null +++ b/fuzz/tls_fuzzer.go @@ -0,0 +1,34 @@ +//go:build gofuzz +// +build gofuzz + +/* +Copyright 2021 The Flux authors +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. +*/ +package tls + +import ( + fuzz "github.com/AdaLogics/go-fuzz-headers" + corev1 "k8s.io/api/core/v1" +) + +// FuzzTlsConfig implements a fuzzer that +// targets ConfigFromSecret() +func FuzzTlsConfig(data []byte) int { + secret := &corev1.Secret{} + f := fuzz.NewConsumer(data) + err := f.GenerateStruct(secret) + if err != nil { + return 0 + } + _, _ = ConfigFromSecret(secret) + return 1 +} From ab49d7b6f9edd94b0473b28d1e1713265763d12c Mon Sep 17 00:00:00 2001 From: Paulo Gomes Date: Tue, 11 Jan 2022 18:55:57 +0000 Subject: [PATCH 2/2] Refactor fuzzing Structure the fuzz implementation to be closer to what go native will support. Add Makefile target to enable smoketesting fuzzers. Add github workflow to test and upload crash results. Signed-off-by: Paulo Gomes --- .github/workflows/cifuzz.yaml | 27 ++++ .gitignore | 2 + Makefile | 21 ++++ fuzz/Dockerfile | 62 ---------- fuzz/fuzz.go | 91 -------------- runtime/go.mod | 7 +- runtime/go.sum | 15 ++- tests/fuzz/Dockerfile.builder | 6 + tests/fuzz/README.md | 45 +++++++ {fuzz => tests/fuzz}/conditions_fuzzer.go | 23 ++-- tests/fuzz/events_fuzzer.go | 144 ++++++++++++++++++++++ tests/fuzz/gitutil_fuzzer.go | 28 +++++ tests/fuzz/oss_fuzz_build.sh | 63 ++++++++++ tests/fuzz/oss_fuzz_run.sh | 20 +++ {fuzz => tests/fuzz}/tls_fuzzer.go | 6 +- tests/fuzz/untar_fuzzer.go | 37 ++++++ 16 files changed, 423 insertions(+), 174 deletions(-) create mode 100644 .github/workflows/cifuzz.yaml delete mode 100644 fuzz/Dockerfile delete mode 100644 fuzz/fuzz.go create mode 100644 tests/fuzz/Dockerfile.builder create mode 100644 tests/fuzz/README.md rename {fuzz => tests/fuzz}/conditions_fuzzer.go (88%) create mode 100644 tests/fuzz/events_fuzzer.go create mode 100644 tests/fuzz/gitutil_fuzzer.go create mode 100755 tests/fuzz/oss_fuzz_build.sh create mode 100755 tests/fuzz/oss_fuzz_run.sh rename {fuzz => tests/fuzz}/tls_fuzzer.go (92%) create mode 100644 tests/fuzz/untar_fuzzer.go diff --git a/.github/workflows/cifuzz.yaml b/.github/workflows/cifuzz.yaml new file mode 100644 index 00000000..ea71ebc9 --- /dev/null +++ b/.github/workflows/cifuzz.yaml @@ -0,0 +1,27 @@ +name: CIFuzz +on: + pull_request: + branches: + - main +jobs: + Fuzzing: + runs-on: ubuntu-latest + steps: + - name: Build Fuzzers + id: build + uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master + with: + oss-fuzz-project-name: 'fluxcd' + language: go + - name: Run Fuzzers + uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master + with: + oss-fuzz-project-name: 'fluxcd' + language: go + fuzz-seconds: 60 + - name: Upload Crash + uses: actions/upload-artifact@v1 + if: failure() && steps.build.outcome == 'success' + with: + name: artifacts + path: ./out/artifacts diff --git a/.gitignore b/.gitignore index 66fd13c9..3c964d53 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,5 @@ # Dependency directories (remove the comment below to include it) # vendor/ + +build/ diff --git a/Makefile b/Makefile index 73d39f77..4a02f57b 100644 --- a/Makefile +++ b/Makefile @@ -71,3 +71,24 @@ SETUP_ENVTEST=$(GOBIN)/setup-envtest else SETUP_ENVTEST=$(shell which setup-envtest) endif + + +fuzz-build: + rm -rf $(shell pwd)/build/fuzz/ + mkdir -p $(shell pwd)/build/fuzz/out/ + + docker build . --tag local-fuzzing:latest -f tests/fuzz/Dockerfile.builder + docker run --rm -it \ + -e FUZZING_LANGUAGE=go -e FUZZ_SECONDS=600 -e MODE=batch \ + -e CIFUZZ_DEBUG='True' -e OSS_FUZZ_PROJECT_NAME=fluxcd \ + -e SANITIZER=address \ + -v "$(shell pwd)/build/fuzz/out":/out \ + local-fuzzing:latest + +fuzz-smoketest: fuzz-build + docker run --rm -ti \ + -v "$(shell pwd)/build/fuzz/out":/out \ + -v "$(shell pwd)/tests/fuzz/oss_fuzz_run.sh":/runner.sh \ + -e ENVTEST_BIN_VERSION=$(ENVTEST_BIN_VERSION) \ + gcr.io/oss-fuzz/fluxcd \ + bash -c "/runner.sh" diff --git a/fuzz/Dockerfile b/fuzz/Dockerfile deleted file mode 100644 index 31d5e049..00000000 --- a/fuzz/Dockerfile +++ /dev/null @@ -1,62 +0,0 @@ -FROM golang:1.16-buster as builder -RUN set -eux; \ - apt-get update \ - && apt-get upgrade -y \ - && apt-get install -y \ - clang \ - curl \ - vim - -RUN git clone https://github.com/fluxcd/pkg /workspace -RUN mkdir /workspace/fuzzing - - -RUN go get -u github.com/dvyukov/go-fuzz/go-fuzz@latest github.com/dvyukov/go-fuzz/go-fuzz-build@latest -RUN go install sigs.k8s.io/controller-runtime/tools/setup-envtest@latest -RUN go get github.com/AdaLogics/go-fuzz-headers - -RUN go get golang.org/x/sync - -WORKDIR /workspace/fuzzing -COPY fuzz.go /workspace/fuzzing/ -COPY conditions_fuzzer.go /workspace/runtime/conditions/ -COPY tls_fuzzer.go /workspace/runtime/tls/ -RUN cd /workspace/fuzzing && go mod init fuzzing && go mod tidy && go mod download && go mod tidy -RUN go mod download github.com/dvyukov/go-fuzz - - -# Build the fuzzers -RUN mkdir /fuzzers - -RUN go-fuzz-build -libfuzzer -func=FuzzUntar\ - && clang -o /fuzzers/FuzzUntar reflect-fuzz.a \ - -fsanitize=fuzzer -RUN go-fuzz-build -libfuzzer -func=FuzzLibGit2Error\ - && clang -o /fuzzers/FuzzLibGit2Error reflect-fuzz.a \ - -fsanitize=fuzzer -RUN go-fuzz-build -libfuzzer -func=FuzzEventInfof\ - && clang -o /fuzzers/FuzzEventInfof reflect-fuzz.a \ - -fsanitize=fuzzer - -WORKDIR /workspace/runtime/tls -RUN go get github.com/AdaLogics/go-fuzz-headers -RUN go get github.com/dvyukov/go-fuzz/go-fuzz-dep -RUN go-fuzz-build -libfuzzer -func=FuzzTlsConfig\ - && clang -o /fuzzers/FuzzTlsConfig reflect-fuzz.a \ - -fsanitize=fuzzer - -WORKDIR /workspace/runtime/conditions -RUN go-fuzz-build -libfuzzer -func=FuzzGetterConditions\ - && clang -o /fuzzers/FuzzGetterConditions reflect-fuzz.a \ - -fsanitize=fuzzer -RUN go-fuzz-build -libfuzzer -func=FuzzConditionsMatch\ - && clang -o /fuzzers/FuzzConditionsMatch reflect-fuzz.a \ - -fsanitize=fuzzer -RUN go-fuzz-build -libfuzzer -func=FuzzPatchApply\ - && clang -o /fuzzers/FuzzPatchApply reflect-fuzz.a \ - -fsanitize=fuzzer -RUN go-fuzz-build -libfuzzer -func=FuzzConditionsUnstructured\ - && clang -o /fuzzers/FuzzConditionsUnstructured reflect-fuzz.a \ - -fsanitize=fuzzer - -#RUN /fuzzers/FuzzLibGit2Error \ No newline at end of file diff --git a/fuzz/fuzz.go b/fuzz/fuzz.go deleted file mode 100644 index 50352817..00000000 --- a/fuzz/fuzz.go +++ /dev/null @@ -1,91 +0,0 @@ -//go:build gofuzz -// +build gofuzz - -/* -Copyright 2021 The Flux authors -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. -*/ -package fuzzing - -import ( - "bytes" - "encoding/json" - "errors" - fuzz "github.com/AdaLogics/go-fuzz-headers" - "github.com/fluxcd/pkg/gitutil" - "github.com/fluxcd/pkg/runtime/events" - "github.com/fluxcd/pkg/untar" - "io" - corev1 "k8s.io/api/core/v1" - "net/http" - "net/http/httptest" - "os" -) - -// FuzzUntar implements a fuzzer that -// targets untar.Untar() -func FuzzUntar(data []byte) int { - r := bytes.NewReader(data) - tmpDir, err := os.MkdirTemp("", "dir-") - if err != nil { - return 0 - } - defer os.RemoveAll(tmpDir) - _, _ = untar.Untar(r, tmpDir) - return 1 -} - -// FuzzLibGit2Error implements a fuzzer that -// targets gitutil.LibGit2Error -func FuzzLibGit2Error(data []byte) int { - err := errors.New(string(data)) - _ = gitutil.LibGit2Error(err) - return 1 -} - -// FuzzEventInfof implements a fuzzer that -// targets eventRecorder.EventInfof() -func FuzzEventInfof(data []byte) int { - f := fuzz.NewConsumer(data) - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - b, err := io.ReadAll(r.Body) - if err != nil { - return - } - - var payload events.Event - err = json.Unmarshal(b, &payload) - if err != nil { - return - } - })) - defer ts.Close() - eventRecorder, err := events.NewRecorder(ts.URL, "test-controller") - if err != nil { - return 0 - } - eventRecorder.Client.RetryMax = 2 - obj := corev1.ObjectReference{} - err = f.GenerateStruct(&obj) - if err != nil { - return 0 - } - severity, err := f.GetString() - if err != nil { - return 0 - } - reason, err := f.GetString() - if err != nil { - return 0 - } - _ = eventRecorder.EventInfof(obj, nil, severity, reason, obj.Name) - return 1 -} diff --git a/runtime/go.mod b/runtime/go.mod index 9da6e7c9..ca186f60 100644 --- a/runtime/go.mod +++ b/runtime/go.mod @@ -37,7 +37,7 @@ require ( github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.2 // indirect github.com/google/gofuzz v1.2.0 // indirect - github.com/google/uuid v1.1.2 // indirect + github.com/google/uuid v1.2.0 // indirect github.com/googleapis/gnostic v0.5.5 // indirect github.com/hashicorp/go-cleanhttp v0.5.1 // indirect github.com/imdario/mergo v0.3.12 // indirect @@ -52,14 +52,15 @@ require ( go.uber.org/atomic v1.7.0 // indirect go.uber.org/multierr v1.6.0 // indirect golang.org/x/net v0.0.0-20211215060638-4ddde0e984e9 // indirect - golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f // indirect - golang.org/x/sys v0.0.0-20211029165221-6e7872819dc8 // indirect + golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect + golang.org/x/sys v0.0.0-20211110154304-99a53858aa08 // indirect golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b // indirect golang.org/x/text v0.3.7 // indirect golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/protobuf v1.27.1 // indirect + gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect diff --git a/runtime/go.sum b/runtime/go.sum index 196ecb61..af15ac13 100644 --- a/runtime/go.sum +++ b/runtime/go.sum @@ -236,8 +236,9 @@ github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs= +github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU= @@ -309,6 +310,8 @@ github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -347,7 +350,6 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8m github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= @@ -605,8 +607,9 @@ golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f h1:Qmd2pbz05z7z6lm0DrgQVVPuBm92jqujBKMHMOlOQEw= golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 h1:RerP+noqYHUQ8CMRcPlC2nvTa4dcBIjegkuWdcUDuqg= +golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -682,8 +685,9 @@ golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211029165221-6e7872819dc8 h1:M69LAlWZCshgp0QSzyDcSsSIejIEeuaCVpmwcKwyLMk= golang.org/x/sys v0.0.0-20211029165221-6e7872819dc8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211110154304-99a53858aa08 h1:WecRHqgE09JBkh/584XIE6PMz5KKE/vER4izNUi30AQ= +golang.org/x/sys v0.0.0-20211110154304-99a53858aa08/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b h1:9zKuko04nR4gjZ4+DNjHqRlAJqbJETHwiNKDqTfOjfE= golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -884,8 +888,9 @@ gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLks gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= diff --git a/tests/fuzz/Dockerfile.builder b/tests/fuzz/Dockerfile.builder new file mode 100644 index 00000000..0199be87 --- /dev/null +++ b/tests/fuzz/Dockerfile.builder @@ -0,0 +1,6 @@ +FROM gcr.io/oss-fuzz-base/base-builder-go + +COPY ./ $GOPATH/src/github.com/fluxcd/pkg/ +COPY ./tests/fuzz/oss_fuzz_build.sh $SRC/build.sh + +WORKDIR $SRC diff --git a/tests/fuzz/README.md b/tests/fuzz/README.md new file mode 100644 index 00000000..f2d23396 --- /dev/null +++ b/tests/fuzz/README.md @@ -0,0 +1,45 @@ +# fuzz testing + +Flux is part of Google's [oss fuzz] program which provides continuous fuzzing for +open source projects. + +The long running fuzzing execution is configured in the [oss-fuzz repository]. +Shorter executions are done on a per-PR basis, configured as a [github workflow]. + +For fuzzers to be called, they must be compiled within [oss_fuzz_build.sh](./oss_fuzz_build.sh). + +### Testing locally + +Build fuzzers: + +```bash +make fuzz-build +``` +All fuzzers will be built into `./build/fuzz/out`. + +Smoke test fuzzers: + +```bash +make fuzz-smoketest +``` + +The smoke test runs each fuzzer once to ensure they are fully functional. + +Run fuzzer locally: +```bash +./build/fuzz/out/fuzz_conditions_match +``` + +Run fuzzer inside a container: + +```bash + docker run --rm -ti \ + -v "$(pwd)/build/fuzz/out":/out \ + gcr.io/oss-fuzz/fluxcd \ + /out/fuzz_conditions_match +``` + + +[oss fuzz]: https://github.com/google/oss-fuzz +[oss-fuzz repository]: https://github.com/google/oss-fuzz/tree/master/projects/fluxcd +[github workflow]: .github/workflows/cifuzz.yaml diff --git a/fuzz/conditions_fuzzer.go b/tests/fuzz/conditions_fuzzer.go similarity index 88% rename from fuzz/conditions_fuzzer.go rename to tests/fuzz/conditions_fuzzer.go index 02dd8fcb..2b197a12 100644 --- a/fuzz/conditions_fuzzer.go +++ b/tests/fuzz/conditions_fuzzer.go @@ -3,10 +3,13 @@ /* Copyright 2021 The Flux authors + 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. @@ -22,8 +25,8 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" ) -// FuzzGetterConditions implements a fuzzer that -// targets SetSummary() +// FuzzGetterConditions implements a fuzzer that targets +// conditions.SetSummary(). func FuzzGetterConditions(data []byte) int { f := fuzz.NewConsumer(data) @@ -57,8 +60,8 @@ func FuzzGetterConditions(data []byte) int { return 1 } -// FuzzConditionsMatch implements a fuzzer that -// that targets Match() +// FuzzConditionsMatch implements a fuzzer that that targets +// MatchCondition.Match(). func FuzzConditionsMatch(data []byte) int { f := fuzz.NewConsumer(data) condition := metav1.Condition{} @@ -79,8 +82,7 @@ func FuzzConditionsMatch(data []byte) int { return 1 } -// newGetter allows the fuzzer to create a Getter -// This is just a utility +// newGetter allows the fuzzer to create a Getter. func newGetter(f *fuzz.ConsumeFuzzer) (Getter, error) { obj := &testdata.Fake{} noOfConditions, err := f.GetInt() @@ -102,8 +104,7 @@ func newGetter(f *fuzz.ConsumeFuzzer) (Getter, error) { return obj, nil } -// newSetter allows the fuzzer to create a Setter -// This is just a utility +// newSetter allows the fuzzer to create a Setter. func newSetter(f *fuzz.ConsumeFuzzer) (Setter, error) { obj := &testdata.Fake{} noOfConditions, err := f.GetInt() @@ -124,7 +125,7 @@ func newSetter(f *fuzz.ConsumeFuzzer) (Setter, error) { return obj, nil } -// FuzzPatchApply implements a fuzzer that targets patch.Apply +// FuzzPatchApply implements a fuzzer that targets Patch.Apply. func FuzzPatchApply(data []byte) int { f := fuzz.NewConsumer(data) @@ -146,8 +147,8 @@ func FuzzPatchApply(data []byte) int { return 1 } -// FuzzConditionsUnstructured implements a fuzzer -// that targets GetConditions() +// FuzzConditionsUnstructured implements a fuzzer that targets +// Getter.GetConditions. func FuzzConditionsUnstructured(data []byte) int { u := &unstructured.Unstructured{} f := fuzz.NewConsumer(data) diff --git a/tests/fuzz/events_fuzzer.go b/tests/fuzz/events_fuzzer.go new file mode 100644 index 00000000..4ee293e9 --- /dev/null +++ b/tests/fuzz/events_fuzzer.go @@ -0,0 +1,144 @@ +//go:build gofuzz +// +build gofuzz + +/* +Copyright 2021 The Flux authors + +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. +*/ +package events + +import ( + "encoding/json" + "fmt" + "io" + "net/http" + "net/http/httptest" + "os" + "os/exec" + "sync" + + fuzz "github.com/AdaLogics/go-fuzz-headers" + "github.com/fluxcd/pkg/runtime/testenv" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/runtime" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + ctrl "sigs.k8s.io/controller-runtime" +) + +var ( + doOnce sync.Once + env *testenv.Environment + ts *httptest.Server + ctx = ctrl.SetupSignalHandler() +) + +const defaultBinVersion = "1.23" + +func envtestBinVersion() string { + if binVersion := os.Getenv("ENVTEST_BIN_VERSION"); binVersion != "" { + return binVersion + } + return defaultBinVersion +} + +func ensureDependencies() error { + // only install dependencies when running inside a container + if _, err := os.Stat("/.dockerenv"); os.IsNotExist(err) { + return nil + } + + if os.Getenv("KUBEBUILDER_ASSETS") == "" { + binVersion := envtestBinVersion() + cmd := exec.Command("/usr/bin/bash", "-c", fmt.Sprintf(`go install sigs.k8s.io/controller-runtime/tools/setup-envtest@latest && \ + /root/go/bin/setup-envtest use -p path %s`, binVersion)) + + cmd.Env = append(os.Environ(), "GOPATH=/root/go") + assetsPath, err := cmd.Output() + if err == nil { + os.Setenv("KUBEBUILDER_ASSETS", string(assetsPath)) + } + return err + } + + return nil +} + +// FuzzEventInfof implements a fuzzer that targets eventRecorder.Eventf(). +func FuzzEventf(data []byte) int { + doOnce.Do(func() { + if err := ensureDependencies(); err != nil { + panic(fmt.Sprintf("Failed to start the test environment manager: %v", err)) + } + }) + + ts = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + b, err := io.ReadAll(r.Body) + if err != nil { + return + } + + var payload Event + err = json.Unmarshal(b, &payload) + if err != nil { + return + } + })) + defer ts.Close() + + scheme := runtime.NewScheme() + utilruntime.Must(corev1.AddToScheme(scheme)) + + env = testenv.New( + testenv.WithScheme(scheme), + ) + + go func() { + fmt.Println("Starting the test environment") + if err := env.Start(ctx); err != nil { + panic(fmt.Sprintf("Failed to start the test environment manager: %v", err)) + } + }() + <-env.Manager.Elected() + + eventRecorder, err := NewRecorder(env, ctrl.Log, ts.URL, "test-controller") + if err != nil { + return 0 + } + eventRecorder.Client.RetryMax = 2 + //TODO: Reuse the setup above across fuzzing calls + // this will be easier once fuzzing is migrated to + // native golang fuzz. + + f := fuzz.NewConsumer(data) + obj := corev1.ConfigMap{} + err = f.GenerateStruct(&obj) + if err != nil { + return 0 + } + eventtype, err := f.GetString() + if err != nil { + return 0 + } + reason, err := f.GetString() + if err != nil { + return 0 + } + eventRecorder.Eventf(&obj, eventtype, reason, obj.Name) + + if err = env.Stop(); err != nil { + return 0 + } + + return 1 +} diff --git a/tests/fuzz/gitutil_fuzzer.go b/tests/fuzz/gitutil_fuzzer.go new file mode 100644 index 00000000..7195d092 --- /dev/null +++ b/tests/fuzz/gitutil_fuzzer.go @@ -0,0 +1,28 @@ +//go:build gofuzz +// +build gofuzz + +/* +Copyright 2021 The Flux authors + +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. +*/ +package gitutil + +import "errors" + +// FuzzLibGit2Error implements a fuzzer that targets gitutil.LibGit2Error. +func FuzzLibGit2Error(data []byte) int { + err := errors.New(string(data)) + _ = LibGit2Error(err) + return 1 +} diff --git a/tests/fuzz/oss_fuzz_build.sh b/tests/fuzz/oss_fuzz_build.sh new file mode 100755 index 00000000..c79bfb34 --- /dev/null +++ b/tests/fuzz/oss_fuzz_build.sh @@ -0,0 +1,63 @@ +#!/usr/bin/env bash + +# Copyright 2022 The Flux authors +# +# 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. + +set -euxo pipefail + +GOPATH="${GOPATH:-/root/go}" +GO_SRC="${GOPATH}/src" +PROJECT_PATH="github.com/fluxcd/pkg" + +cd "${GO_SRC}" + +# Move fuzzer to their respective directories. +# This removes dependency noises from the modules' go.mod and go.sum files. +cp "${PROJECT_PATH}/tests/fuzz/conditions_fuzzer.go" "${PROJECT_PATH}/runtime/conditions" +cp "${PROJECT_PATH}/tests/fuzz/events_fuzzer.go" "${PROJECT_PATH}/runtime/events" +cp "${PROJECT_PATH}/tests/fuzz/tls_fuzzer.go" "${PROJECT_PATH}/runtime/tls" +cp "${PROJECT_PATH}/tests/fuzz/untar_fuzzer.go" "${PROJECT_PATH}/untar" +cp "${PROJECT_PATH}/tests/fuzz/gitutil_fuzzer.go" "${PROJECT_PATH}/gitutil" + + +# compile fuzz tests for the runtime module +pushd "${PROJECT_PATH}/runtime" + +go mod tidy +compile_go_fuzzer "${PROJECT_PATH}/runtime/conditions" FuzzGetterConditions fuzz_getter_conditions +compile_go_fuzzer "${PROJECT_PATH}/runtime/conditions" FuzzConditionsMatch fuzz_conditions_match +compile_go_fuzzer "${PROJECT_PATH}/runtime/conditions" FuzzPatchApply fuzz_patch_apply +compile_go_fuzzer "${PROJECT_PATH}/runtime/conditions" FuzzConditionsUnstructured fuzz_conditions_unstructured +compile_go_fuzzer "${PROJECT_PATH}/runtime/events" FuzzEventf fuzz_eventf +compile_go_fuzzer "${PROJECT_PATH}/runtime/tls" FuzzTlsConfig fuzz_tls_config + +popd + + +# compile fuzz tests for the untar module +pushd "${PROJECT_PATH}/untar" + +go mod tidy +compile_go_fuzzer "${PROJECT_PATH}/untar" FuzzUntar fuzz_untar + +popd + + +# compile fuzz tests for the gitutil module +pushd "${PROJECT_PATH}/gitutil" + +go mod tidy +compile_go_fuzzer "${PROJECT_PATH}/gitutil" FuzzLibGit2Error fuzz_libgit2_error + +popd diff --git a/tests/fuzz/oss_fuzz_run.sh b/tests/fuzz/oss_fuzz_run.sh new file mode 100755 index 00000000..b812467f --- /dev/null +++ b/tests/fuzz/oss_fuzz_run.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash + +# Copyright 2022 The Flux authors +# +# 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. + +set -euxo pipefail + +# run each fuzzer once to ensure they are working properly +find /out -type f -name "fuzz*" -exec '{}' {} \; diff --git a/fuzz/tls_fuzzer.go b/tests/fuzz/tls_fuzzer.go similarity index 92% rename from fuzz/tls_fuzzer.go rename to tests/fuzz/tls_fuzzer.go index d0355937..f2267093 100644 --- a/fuzz/tls_fuzzer.go +++ b/tests/fuzz/tls_fuzzer.go @@ -3,10 +3,13 @@ /* Copyright 2021 The Flux authors + 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. @@ -20,8 +23,7 @@ import ( corev1 "k8s.io/api/core/v1" ) -// FuzzTlsConfig implements a fuzzer that -// targets ConfigFromSecret() +// FuzzTlsConfig implements a fuzzer that targets ConfigFromSecret(). func FuzzTlsConfig(data []byte) int { secret := &corev1.Secret{} f := fuzz.NewConsumer(data) diff --git a/tests/fuzz/untar_fuzzer.go b/tests/fuzz/untar_fuzzer.go new file mode 100644 index 00000000..a0bae71f --- /dev/null +++ b/tests/fuzz/untar_fuzzer.go @@ -0,0 +1,37 @@ +//go:build gofuzz +// +build gofuzz + +/* +Copyright 2021 The Flux authors + +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. +*/ +package untar + +import ( + "bytes" + "os" +) + +// FuzzUntar implements a fuzzer that targets untar.Untar(). +func FuzzUntar(data []byte) int { + r := bytes.NewReader(data) + tmpDir, err := os.MkdirTemp("", "dir-") + if err != nil { + return 0 + } + defer os.RemoveAll(tmpDir) + + _, _ = Untar(r, tmpDir) + return 1 +}