Skip to content

Commit

Permalink
Fuzzing: Initial commit
Browse files Browse the repository at this point in the history
Signed-off-by: AdamKorcz <adam@adalogics.com>
  • Loading branch information
AdamKorcz committed Sep 30, 2021
1 parent 7ec4e61 commit 60d07e7
Show file tree
Hide file tree
Showing 5 changed files with 609 additions and 100 deletions.
61 changes: 0 additions & 61 deletions controllers/git_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,79 +4,18 @@ import (
"context"
"io/ioutil"
"os"
"path/filepath"
"testing"
"time"

"github.com/go-git/go-billy/v5/memfs"
gogit "github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/object"
"github.com/go-git/go-git/v5/storage/memory"
"github.com/go-logr/logr"

"github.com/fluxcd/pkg/gittestserver"
"github.com/fluxcd/source-controller/pkg/git"
)

func populateRepoFromFixture(repo *gogit.Repository, fixture string) error {
working, err := repo.Worktree()
if err != nil {
return err
}
fs := working.Filesystem

if err = filepath.Walk(fixture, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if info.IsDir() {
return fs.MkdirAll(fs.Join(path[len(fixture):]), info.Mode())
}
// copy symlinks as-is, so I can test what happens with broken symlinks
if info.Mode()&os.ModeSymlink > 0 {
target, err := os.Readlink(path)
if err != nil {
return err
}
return fs.Symlink(target, path[len(fixture):])
}

fileBytes, err := ioutil.ReadFile(path)
if err != nil {
return err
}

ff, err := fs.Create(path[len(fixture):])
if err != nil {
return err
}
defer ff.Close()

_, err = ff.Write(fileBytes)
return err
}); err != nil {
return err
}

_, err = working.Add(".")
if err != nil {
return err
}

if _, err = working.Commit("Initial revision from "+fixture, &gogit.CommitOptions{
Author: &object.Signature{
Name: "Testbot",
Email: "test@example.com",
When: time.Now(),
},
}); err != nil {
return err
}

return nil
}

func TestRepoForFixture(t *testing.T) {
repo, err := gogit.Init(memory.NewStorage(), memfs.New())
if err != nil {
Expand Down
127 changes: 127 additions & 0 deletions controllers/test_utils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
/*
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 controllers

import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"time"

"github.com/fluxcd/pkg/gittestserver"
"github.com/go-git/go-billy/v5/memfs"
"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/config"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/object"
"github.com/go-git/go-git/v5/storage/memory"
)

// Initialise a git server with a repo including the files in dir.
func initGitRepo(gitServer *gittestserver.GitServer, fixture, branch, repositoryPath string) error {
fs := memfs.New()
repo, err := git.Init(memory.NewStorage(), fs)
if err != nil {
return err
}

err = populateRepoFromFixture(repo, fixture)
if err != nil {
return err
}

working, err := repo.Worktree()
if err != nil {
return err
}
if err = working.Checkout(&git.CheckoutOptions{
Branch: plumbing.NewBranchReferenceName(branch),
Create: true,
}); err != nil {
return err
}

remote, err := repo.CreateRemote(&config.RemoteConfig{
Name: "origin",
URLs: []string{gitServer.HTTPAddressWithCredentials() + repositoryPath},
})
if err != nil {
return err
}

return remote.Push(&git.PushOptions{
RefSpecs: []config.RefSpec{
config.RefSpec(fmt.Sprintf("refs/heads/%s:refs/heads/%s", branch, branch)),
},
})
}

func populateRepoFromFixture(repo *git.Repository, fixture string) error {
working, err := repo.Worktree()
if err != nil {
return err
}
fs := working.Filesystem

if err = filepath.Walk(fixture, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if info.IsDir() {
return fs.MkdirAll(fs.Join(path[len(fixture):]), info.Mode())
}
// copy symlinks as-is, so I can test what happens with broken symlinks
if info.Mode()&os.ModeSymlink > 0 {
target, err := os.Readlink(path)
if err != nil {
return err
}
return fs.Symlink(target, path[len(fixture):])
}

fileBytes, err := ioutil.ReadFile(path)
if err != nil {
return err
}

ff, err := fs.Create(path[len(fixture):])
if err != nil {
return err
}
defer ff.Close()

_, err = ff.Write(fileBytes)
return err
}); err != nil {
return err
}

_, err = working.Add(".")
if err != nil {
return err
}

if _, err = working.Commit("Initial revision from "+fixture, &git.CommitOptions{
Author: &object.Signature{
Name: "Testbot",
Email: "test@example.com",
When: time.Now(),
},
}); err != nil {
return err
}

return nil
}
39 changes: 0 additions & 39 deletions controllers/update_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1116,45 +1116,6 @@ func commitInRepo(repoURL, branch, msg string, changeFiles func(path string)) {
Expect(repo.Push(&git.PushOptions{RemoteName: "origin"})).To(Succeed())
}

// Initialise a git server with a repo including the files in dir.
func initGitRepo(gitServer *gittestserver.GitServer, fixture, branch, repositoryPath string) error {
fs := memfs.New()
repo, err := git.Init(memory.NewStorage(), fs)
if err != nil {
return err
}

err = populateRepoFromFixture(repo, fixture)
if err != nil {
return err
}

working, err := repo.Worktree()
if err != nil {
return err
}
if err = working.Checkout(&git.CheckoutOptions{
Branch: plumbing.NewBranchReferenceName(branch),
Create: true,
}); err != nil {
return err
}

remote, err := repo.CreateRemote(&config.RemoteConfig{
Name: "origin",
URLs: []string{gitServer.HTTPAddressWithCredentials() + repositoryPath},
})
if err != nil {
return err
}

return remote.Push(&git.PushOptions{
RefSpecs: []config.RefSpec{
config.RefSpec(fmt.Sprintf("refs/heads/%s:refs/heads/%s", branch, branch)),
},
})
}

func checkoutBranch(repo *git.Repository, branch string) error {
working, err := repo.Worktree()
if err != nil {
Expand Down
95 changes: 95 additions & 0 deletions fuzz/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
FROM golang:1.16-buster as builder

# Up-to-date libgit2 dependencies are only available in sid (unstable).
# The libgit2 dependencies must be listed here to be able to build on ARM64.
RUN echo "deb http://deb.debian.org/debian unstable main" >> /etc/apt/sources.list \
&& echo "deb-src http://deb.debian.org/debian unstable main" >> /etc/apt/sources.list
RUN set -eux; \
apt-get update \
&& apt-get install -y vim clang cmake libgit2-dev/unstable \
zlib1g-dev/unstable libssh2-1-dev/unstable libpcre3-dev/unstable \
&& apt-get clean \
&& apt-get autoremove --purge -y \
&& rm -rf /var/lib/apt/lists/*

RUN mkdir /static_a_files
ARG LIBGIT2_VER=1.1.0
RUN curl -L https://github.com/libgit2/libgit2/releases/download/v$LIBGIT2_VER/libgit2-$LIBGIT2_VER.tar.gz -o /tmp/libgit2.tar.gz \
&& cd /tmp \
&& tar -xvf /tmp/libgit2.tar.gz \
&& cd libgit2-1.1.0 \
&& mkdir build && cd build \
&& cmake .. -DBUILD_SHARED_LIBS=OFF \
&& make \
&& mv libgit2.a /static_a_files/

# Build openssl
ARG OPENSSL_VERSION=1.1.1g
ARG OPENSSL_HASH=ddb04774f1e32f0c49751e21b67216ac87852ceb056b75209af2443400636d46
RUN set -ex \
&& curl -s -O https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz \
&& echo "${OPENSSL_HASH} openssl-${OPENSSL_VERSION}.tar.gz" | sha256sum -c \
&& tar -xzf openssl-${OPENSSL_VERSION}.tar.gz \
&& cd openssl-${OPENSSL_VERSION} \
&& ./Configure linux-x86_64 no-shared --static \
&& make \
&& mv libcrypto.a /static_a_files/ \
&& mv libssl.a /static_a_files/

# Build libssh2
RUN git clone https://github.com/libssh2/libssh2 \
&& cd libssh2 \
&& mkdir build \
&& cd build \
&& cmake .. -DBUILD_SHARED_LIBS=OFF \
&& make \
&& mv ./src/libssh2.a /static_a_files/

RUN git clone --depth=1 --branch=fuzz1 https://github.com/AdamKorcz/image-automation-controller /image-automation-controller
WORKDIR /image-automation-controller

RUN cd / \
&& go get -u github.com/dvyukov/go-fuzz/go-fuzz@latest github.com/dvyukov/go-fuzz/go-fuzz-build@latest \
&& go install sigs.k8s.io/controller-runtime/tools/setup-envtest@latest
RUN go get github.com/AdaLogics/go-fuzz-headers

RUN cd / \
&& git clone https://github.com/fluxcd/source-controller \
&& cd source-controller/config/crd/bases \
&& mkdir /image-automation-controller/controllers/testdata/crds \
&& cp ./* /image-automation-controller/controllers/testdata/crds/


RUN cd / \
&& git clone https://github.com/fluxcd/image-reflector-controller \
&& cd image-reflector-controller/config/crd/bases \
&& cp ./* /image-automation-controller/controllers/testdata/crds/

RUN mv ./fuzz/fuzz.go ./controllers/
RUN cd /image-automation-controller/controllers/ \
&& go mod tidy
RUN go mod download github.com/dvyukov/go-fuzz

RUN mkdir /fuzzers
RUN cd controllers \
&& go-fuzz-build -libfuzzer -func=FuzzReconciler \
&& clang -o /fuzzers/FuzzReconciler reflect-fuzz.a \
/static_a_files/libgit2.a \
/static_a_files/libssh2.a \
/static_a_files/libssl.a \
/static_a_files/libcrypto.a \
-lpcre -lz \
-fsanitize=fuzzer
RUN cd controllers \
&& go-fuzz-build -libfuzzer -func=FuzzUpdateWithSetters \
&& clang -o /fuzzers/FuzzUpdateWithSetters reflect-fuzz.a \
/static_a_files/libgit2.a \
/static_a_files/libssh2.a \
/static_a_files/libssl.a \
/static_a_files/libcrypto.a \
-lpcre -lz \
-fsanitize=fuzzer

# Run fuzzer from /image-automation-controller/controllers
#RUN cd controllers && /fuzzers/FuzzUpdateWithSetters
#RUN cd controllers && /fuzzers/FuzzReconciler
Loading

0 comments on commit 60d07e7

Please sign in to comment.