mirror of
https://github.com/project-zot/zot.git
synced 2024-12-16 21:56:37 -05:00
Add fuzz tests for storage_fs (#601)
This commit uses native go fuzzing to fuzz test implementations of storage in storage_fs. moved fuzzing testdata for storage_fs in separate repo added make target and script for importing fuzz data and running all fuzz tests Signed-off-by: Alex Stan <alexandrustan96@yahoo.ro>
This commit is contained in:
parent
b5f27c5b50
commit
16e9822c7f
6 changed files with 870 additions and 12 deletions
11
Makefile
11
Makefile
|
@ -283,3 +283,14 @@ bats-metrics: binary check-skopeo $(BATS)
|
||||||
bats-metrics-verbose: EXTENSIONS=metrics
|
bats-metrics-verbose: EXTENSIONS=metrics
|
||||||
bats-metrics-verbose: binary check-skopeo $(BATS)
|
bats-metrics-verbose: binary check-skopeo $(BATS)
|
||||||
$(BATS) --trace -p --verbose-run --print-output-on-failure --show-output-of-passing-tests test/blackbox/metrics.bats
|
$(BATS) --trace -p --verbose-run --print-output-on-failure --show-output-of-passing-tests test/blackbox/metrics.bats
|
||||||
|
|
||||||
|
.PHONY: fuzz-all
|
||||||
|
fuzz-all: fuzztime=${1}
|
||||||
|
fuzz-all:
|
||||||
|
rm -rf test-data; \
|
||||||
|
rm -rf pkg/storage/testdata; \
|
||||||
|
git clone https://github.com/project-zot/test-data.git; \
|
||||||
|
mv test-data/storage pkg/storage/testdata; \
|
||||||
|
rm -rf test-data; \
|
||||||
|
bash test/scripts/fuzzAll.sh ${fuzztime}; \
|
||||||
|
rm -rf pkg/storage/testdata; \
|
||||||
|
|
13
README_fuzz.md
Normal file
13
README_fuzz.md
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
# Fuzzing in Zot
|
||||||
|
|
||||||
|
This project makes use of native Go 1.18 fuzzing. An in-depth tutorial for fuzzing in Go can be found [here](https://go.dev/doc/fuzz/).
|
||||||
|
As language specifies, fuzz tests are included among unit-tests, inside the the same `*_test.go files`, in the packages they intend to fuzz. See [fuzzing for local storage](pkg/storage/local_test.go)
|
||||||
|
|
||||||
|
Zot doesn't store the test data for fuzzing in the same repo, nor it is added before fuzzing with `(*testing.F).Add` . Instead, it is stored in a separate repo called [test-data](https://github.com/project-zot/test-data).
|
||||||
|
|
||||||
|
To start fuzzing locally, one can use the Make target [fuzz-all](Makefile) .
|
||||||
|
**The default runtime for each fuzz test is 10s**, which can be overriden with the **fuzztime** variable
|
||||||
|
```
|
||||||
|
make fuzz-all fuzztime=20
|
||||||
|
```
|
||||||
|
By running this target, testdata for fuzzing gets downloaded from the previously mentioned repo and the fuzzing begins for every fuzz function that is found.
|
|
@ -7,13 +7,16 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"io/fs"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
"unicode/utf8"
|
||||||
|
|
||||||
apexlog "github.com/apex/log"
|
apexlog "github.com/apex/log"
|
||||||
guuid "github.com/gofrs/uuid"
|
guuid "github.com/gofrs/uuid"
|
||||||
|
@ -186,6 +189,13 @@ func (is *ImageStoreLocal) Unlock(lockStart *time.Time) {
|
||||||
|
|
||||||
func (is *ImageStoreLocal) initRepo(name string) error {
|
func (is *ImageStoreLocal) initRepo(name string) error {
|
||||||
repoDir := path.Join(is.rootDir, name)
|
repoDir := path.Join(is.rootDir, name)
|
||||||
|
|
||||||
|
if !utf8.ValidString(name) {
|
||||||
|
is.log.Error().Msg("input is not valid UTF-8")
|
||||||
|
|
||||||
|
return zerr.ErrInvalidRepositoryName
|
||||||
|
}
|
||||||
|
|
||||||
// create "blobs" subdir
|
// create "blobs" subdir
|
||||||
err := ensureDir(path.Join(repoDir, "blobs"), is.log)
|
err := ensureDir(path.Join(repoDir, "blobs"), is.log)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -850,6 +860,7 @@ func (is *ImageStoreLocal) NewBlobUpload(repo string) (string, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", zerr.ErrRepoNotFound
|
return "", zerr.ErrRepoNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
|
|
||||||
return uid, nil
|
return uid, nil
|
||||||
|
@ -859,6 +870,12 @@ func (is *ImageStoreLocal) NewBlobUpload(repo string) (string, error) {
|
||||||
func (is *ImageStoreLocal) GetBlobUpload(repo, uuid string) (int64, error) {
|
func (is *ImageStoreLocal) GetBlobUpload(repo, uuid string) (int64, error) {
|
||||||
blobUploadPath := is.BlobUploadPath(repo, uuid)
|
blobUploadPath := is.BlobUploadPath(repo, uuid)
|
||||||
|
|
||||||
|
if !utf8.ValidString(blobUploadPath) {
|
||||||
|
is.log.Error().Msg("input is not valid UTF-8")
|
||||||
|
|
||||||
|
return -1, zerr.ErrInvalidRepositoryName
|
||||||
|
}
|
||||||
|
|
||||||
binfo, err := os.Stat(blobUploadPath)
|
binfo, err := os.Stat(blobUploadPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
|
@ -1673,12 +1690,23 @@ func ifOlderThan(imgStore *ImageStoreLocal, repo string, delay time.Duration) ca
|
||||||
}
|
}
|
||||||
|
|
||||||
func DirExists(d string) bool {
|
func DirExists(d string) bool {
|
||||||
fi, err := os.Stat(d)
|
if !utf8.ValidString(d) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
fileInfo, err := os.Stat(d)
|
||||||
|
if err != nil {
|
||||||
|
if e, ok := err.(*fs.PathError); ok && errors.Is(e.Err, syscall.ENAMETOOLONG) || //nolint: errorlint
|
||||||
|
errors.Is(e.Err, syscall.EINVAL) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil && os.IsNotExist(err) {
|
if err != nil && os.IsNotExist(err) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if !fi.IsDir() {
|
if !fileInfo.IsDir() {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,22 +5,26 @@ import (
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
_ "crypto/sha256"
|
_ "crypto/sha256"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"io/fs"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"math/big"
|
"math/big"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
|
"syscall"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
godigest "github.com/opencontainers/go-digest"
|
godigest "github.com/opencontainers/go-digest"
|
||||||
|
imeta "github.com/opencontainers/image-spec/specs-go"
|
||||||
ispec "github.com/opencontainers/image-spec/specs-go/v1"
|
ispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
artifactspec "github.com/oras-project/artifacts-spec/specs-go/v1"
|
artifactspec "github.com/oras-project/artifacts-spec/specs-go/v1"
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
. "github.com/smartystreets/goconvey/convey"
|
. "github.com/smartystreets/goconvey/convey"
|
||||||
"zotregistry.io/zot/errors"
|
zerr "zotregistry.io/zot/errors"
|
||||||
"zotregistry.io/zot/pkg/extensions/monitoring"
|
"zotregistry.io/zot/pkg/extensions/monitoring"
|
||||||
"zotregistry.io/zot/pkg/log"
|
"zotregistry.io/zot/pkg/log"
|
||||||
"zotregistry.io/zot/pkg/storage"
|
"zotregistry.io/zot/pkg/storage"
|
||||||
|
@ -40,10 +44,8 @@ func TestStorageFSAPIs(t *testing.T) {
|
||||||
true, log, metrics, nil)
|
true, log, metrics, nil)
|
||||||
|
|
||||||
Convey("Repo layout", t, func(c C) {
|
Convey("Repo layout", t, func(c C) {
|
||||||
repoName := "test"
|
|
||||||
|
|
||||||
Convey("Bad image manifest", func() {
|
Convey("Bad image manifest", func() {
|
||||||
upload, err := imgStore.NewBlobUpload("test")
|
upload, err := imgStore.NewBlobUpload(repoName)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(upload, ShouldNotBeEmpty)
|
So(upload, ShouldNotBeEmpty)
|
||||||
|
|
||||||
|
@ -56,17 +58,17 @@ func TestStorageFSAPIs(t *testing.T) {
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(blob, ShouldEqual, buflen)
|
So(blob, ShouldEqual, buflen)
|
||||||
|
|
||||||
err = imgStore.FinishBlobUpload("test", upload, buf, digest.String())
|
err = imgStore.FinishBlobUpload(repoName, upload, buf, digest.String())
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
annotationsMap := make(map[string]string)
|
annotationsMap := make(map[string]string)
|
||||||
annotationsMap[ispec.AnnotationRefName] = tag
|
annotationsMap[ispec.AnnotationRefName] = tag
|
||||||
|
|
||||||
cblob, cdigest := test.GetRandomImageConfig()
|
cblob, cdigest := test.GetRandomImageConfig()
|
||||||
_, clen, err := imgStore.FullBlobUpload("test", bytes.NewReader(cblob), cdigest.String())
|
_, clen, err := imgStore.FullBlobUpload(repoName, bytes.NewReader(cblob), cdigest.String())
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(clen, ShouldEqual, len(cblob))
|
So(clen, ShouldEqual, len(cblob))
|
||||||
hasBlob, _, err := imgStore.CheckBlob("test", cdigest.String())
|
hasBlob, _, err := imgStore.CheckBlob(repoName, cdigest.String())
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(hasBlob, ShouldEqual, true)
|
So(hasBlob, ShouldEqual, true)
|
||||||
|
|
||||||
|
@ -195,7 +197,6 @@ func TestGetReferrers(t *testing.T) {
|
||||||
Size: int64(buflen),
|
Size: int64(buflen),
|
||||||
}
|
}
|
||||||
artifactManifest.Blobs = []artifactspec.Descriptor{}
|
artifactManifest.Blobs = []artifactspec.Descriptor{}
|
||||||
|
|
||||||
manBuf, err := json.Marshal(artifactManifest)
|
manBuf, err := json.Marshal(artifactManifest)
|
||||||
manBufLen := len(manBuf)
|
manBufLen := len(manBuf)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
@ -214,6 +215,711 @@ func TestGetReferrers(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func FuzzNewBlobUpload(f *testing.F) {
|
||||||
|
f.Fuzz(func(t *testing.T, data string) {
|
||||||
|
dir := t.TempDir()
|
||||||
|
defer os.RemoveAll(dir)
|
||||||
|
t.Logf("Input argument is %s", data)
|
||||||
|
log := log.Logger{Logger: zerolog.New(os.Stdout)}
|
||||||
|
metrics := monitoring.NewMetricsServer(false, log)
|
||||||
|
imgStore := storage.NewImageStore(dir, true, storage.DefaultGCDelay, true, true, log, metrics, nil)
|
||||||
|
|
||||||
|
_, err := imgStore.NewBlobUpload(data)
|
||||||
|
if err != nil {
|
||||||
|
if isKnownErr(err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func FuzzPutBlobChunk(f *testing.F) {
|
||||||
|
f.Fuzz(func(t *testing.T, data string) {
|
||||||
|
dir := t.TempDir()
|
||||||
|
defer os.RemoveAll(dir)
|
||||||
|
t.Logf("Input argument is %s", data)
|
||||||
|
log := log.Logger{Logger: zerolog.New(os.Stdout)}
|
||||||
|
metrics := monitoring.NewMetricsServer(false, log)
|
||||||
|
imgStore := storage.NewImageStore(dir, true, storage.DefaultGCDelay, true, true, log, metrics, nil)
|
||||||
|
|
||||||
|
repoName := data
|
||||||
|
uuid, err := imgStore.NewBlobUpload(repoName)
|
||||||
|
if err != nil {
|
||||||
|
if isKnownErr(err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := bytes.NewBuffer([]byte(data))
|
||||||
|
buflen := buf.Len()
|
||||||
|
_, err = imgStore.PutBlobChunk(repoName, uuid, 0, int64(buflen), buf)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func FuzzPutBlobChunkStreamed(f *testing.F) {
|
||||||
|
f.Fuzz(func(t *testing.T, data string) {
|
||||||
|
dir := t.TempDir()
|
||||||
|
defer os.RemoveAll(dir)
|
||||||
|
t.Logf("Input argument is %s", data)
|
||||||
|
log := log.Logger{Logger: zerolog.New(os.Stdout)}
|
||||||
|
metrics := monitoring.NewMetricsServer(false, log)
|
||||||
|
imgStore := storage.NewImageStore(dir, true, storage.DefaultGCDelay, true, true, log, metrics, nil)
|
||||||
|
|
||||||
|
repoName := data
|
||||||
|
|
||||||
|
uuid, err := imgStore.NewBlobUpload(repoName)
|
||||||
|
if err != nil {
|
||||||
|
if isKnownErr(err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := bytes.NewBuffer([]byte(data))
|
||||||
|
_, err = imgStore.PutBlobChunkStreamed(repoName, uuid, buf)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func FuzzGetBlobUpload(f *testing.F) {
|
||||||
|
f.Fuzz(func(t *testing.T, data1 string, data2 string) {
|
||||||
|
dir := t.TempDir()
|
||||||
|
defer os.RemoveAll(dir)
|
||||||
|
log := log.Logger{Logger: zerolog.New(os.Stdout)}
|
||||||
|
metrics := monitoring.NewMetricsServer(false, log)
|
||||||
|
imgStore := storage.NewImageStore(dir, true, storage.DefaultGCDelay, true, true, log, metrics, nil)
|
||||||
|
|
||||||
|
_, err := imgStore.GetBlobUpload(data1, data2)
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, zerr.ErrUploadNotFound) || isKnownErr(err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func FuzzTestPutGetImageManifest(f *testing.F) {
|
||||||
|
f.Fuzz(func(t *testing.T, data []byte) {
|
||||||
|
log := &log.Logger{Logger: zerolog.New(os.Stdout)}
|
||||||
|
metrics := monitoring.NewMetricsServer(false, *log)
|
||||||
|
|
||||||
|
dir := t.TempDir()
|
||||||
|
defer os.RemoveAll(dir)
|
||||||
|
|
||||||
|
imgStore := storage.NewImageStore(dir, true, storage.DefaultGCDelay, true, true, *log, metrics, nil)
|
||||||
|
|
||||||
|
cblob, cdigest := test.GetRandomImageConfig()
|
||||||
|
|
||||||
|
ldigest, lblob, err := newRandomBlobForFuzz(data)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("error occurred while generating random blob, %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, _, err = imgStore.FullBlobUpload(repoName, bytes.NewReader(cblob), cdigest.String())
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
_, _, err = imgStore.FullBlobUpload(repoName, bytes.NewReader(lblob), ldigest.String())
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
manifest, err := NewRandomImgManifest(data, cdigest, ldigest, cblob, lblob)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
manifestBuf, err := json.Marshal(manifest)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Error %v occurred while marshaling manifest", err)
|
||||||
|
}
|
||||||
|
mdigest := godigest.FromBytes(manifestBuf)
|
||||||
|
_, err = imgStore.PutImageManifest(repoName, mdigest.String(), ispec.MediaTypeImageManifest, manifestBuf)
|
||||||
|
if err != nil && errors.Is(err, zerr.ErrBadManifest) {
|
||||||
|
t.Errorf("the error that occurred is %v \n", err)
|
||||||
|
}
|
||||||
|
_, _, _, err = imgStore.GetImageManifest(repoName, mdigest.String())
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("the error that occurred is %v \n", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func FuzzTestPutDeleteImageManifest(f *testing.F) {
|
||||||
|
f.Fuzz(func(t *testing.T, data []byte) {
|
||||||
|
log := &log.Logger{Logger: zerolog.New(os.Stdout)}
|
||||||
|
metrics := monitoring.NewMetricsServer(false, *log)
|
||||||
|
|
||||||
|
dir := t.TempDir()
|
||||||
|
defer os.RemoveAll(dir)
|
||||||
|
|
||||||
|
imgStore := storage.NewImageStore(dir, true, storage.DefaultGCDelay, true, true, *log, metrics, nil)
|
||||||
|
|
||||||
|
cblob, cdigest := test.GetRandomImageConfig()
|
||||||
|
|
||||||
|
ldigest, lblob, err := newRandomBlobForFuzz(data)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("error occurred while generating random blob, %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, _, err = imgStore.FullBlobUpload(repoName, bytes.NewReader(cblob), cdigest.String())
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, _, err = imgStore.FullBlobUpload(repoName, bytes.NewReader(lblob), ldigest.String())
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
manifest, err := NewRandomImgManifest(data, cdigest, ldigest, cblob, lblob)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
manifestBuf, err := json.Marshal(manifest)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Error %v occurred while marshaling manifest", err)
|
||||||
|
}
|
||||||
|
mdigest := godigest.FromBytes(manifestBuf)
|
||||||
|
_, err = imgStore.PutImageManifest(repoName, mdigest.String(), ispec.MediaTypeImageManifest, manifestBuf)
|
||||||
|
if err != nil && errors.Is(err, zerr.ErrBadManifest) {
|
||||||
|
t.Errorf("the error that occurred is %v \n", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = imgStore.DeleteImageManifest(repoName, mdigest.String())
|
||||||
|
if err != nil {
|
||||||
|
if isKnownErr(err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t.Errorf("the error that occurred is %v \n", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// no integration with PutImageManifest, just throw fuzz data.
|
||||||
|
func FuzzTestDeleteImageManifest(f *testing.F) {
|
||||||
|
f.Fuzz(func(t *testing.T, data []byte) {
|
||||||
|
log := &log.Logger{Logger: zerolog.New(os.Stdout)}
|
||||||
|
metrics := monitoring.NewMetricsServer(false, *log)
|
||||||
|
|
||||||
|
dir := t.TempDir()
|
||||||
|
defer os.RemoveAll(dir)
|
||||||
|
|
||||||
|
imgStore := storage.NewImageStore(dir, true, storage.DefaultGCDelay, true, true, *log, metrics, nil)
|
||||||
|
|
||||||
|
digest, _, err := newRandomBlobForFuzz(data)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = imgStore.DeleteImageManifest(string(data), digest.String())
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, zerr.ErrRepoNotFound) || isKnownErr(err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func FuzzDirExists(f *testing.F) {
|
||||||
|
f.Fuzz(func(t *testing.T, data string) { //nolint: unusedparams
|
||||||
|
_ = storage.DirExists(data)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func FuzzInitRepo(f *testing.F) {
|
||||||
|
f.Fuzz(func(t *testing.T, data string) {
|
||||||
|
log := &log.Logger{Logger: zerolog.New(os.Stdout)}
|
||||||
|
metrics := monitoring.NewMetricsServer(false, *log)
|
||||||
|
|
||||||
|
dir := t.TempDir()
|
||||||
|
defer os.RemoveAll(dir)
|
||||||
|
|
||||||
|
imgStore := storage.NewImageStore(dir, true, storage.DefaultGCDelay, true, true, *log, metrics, nil)
|
||||||
|
err := imgStore.InitRepo(data)
|
||||||
|
if err != nil {
|
||||||
|
if isKnownErr(err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func FuzzInitValidateRepo(f *testing.F) {
|
||||||
|
f.Fuzz(func(t *testing.T, data string) {
|
||||||
|
log := &log.Logger{Logger: zerolog.New(os.Stdout)}
|
||||||
|
metrics := monitoring.NewMetricsServer(false, *log)
|
||||||
|
|
||||||
|
dir := t.TempDir()
|
||||||
|
defer os.RemoveAll(dir)
|
||||||
|
|
||||||
|
imgStore := storage.NewImageStore(dir, true, storage.DefaultGCDelay, true, true, *log, metrics, nil)
|
||||||
|
err := imgStore.InitRepo(data)
|
||||||
|
if err != nil {
|
||||||
|
if isKnownErr(err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
_, err = imgStore.ValidateRepo(data)
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, zerr.ErrRepoNotFound) || errors.Is(err, zerr.ErrRepoBadVersion) || isKnownErr(err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func FuzzGetImageTags(f *testing.F) {
|
||||||
|
f.Fuzz(func(t *testing.T, data string) {
|
||||||
|
log := &log.Logger{Logger: zerolog.New(os.Stdout)}
|
||||||
|
metrics := monitoring.NewMetricsServer(false, *log)
|
||||||
|
|
||||||
|
dir := t.TempDir()
|
||||||
|
defer os.RemoveAll(dir)
|
||||||
|
|
||||||
|
imgStore := storage.NewImageStore(dir, true, storage.DefaultGCDelay, true, true, *log, metrics, nil)
|
||||||
|
_, err := imgStore.GetImageTags(data)
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, zerr.ErrRepoNotFound) || isKnownErr(err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func FuzzBlobUploadPath(f *testing.F) {
|
||||||
|
f.Fuzz(func(t *testing.T, repo, uuid string) {
|
||||||
|
log := &log.Logger{Logger: zerolog.New(os.Stdout)}
|
||||||
|
metrics := monitoring.NewMetricsServer(false, *log)
|
||||||
|
|
||||||
|
dir := t.TempDir()
|
||||||
|
defer os.RemoveAll(dir)
|
||||||
|
|
||||||
|
imgStore := storage.NewImageStore(dir, true, storage.DefaultGCDelay, true, true, *log, metrics, nil)
|
||||||
|
|
||||||
|
_ = imgStore.BlobUploadPath(repo, uuid)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func FuzzBlobUploadInfo(f *testing.F) {
|
||||||
|
f.Fuzz(func(t *testing.T, data string, uuid string) {
|
||||||
|
log := &log.Logger{Logger: zerolog.New(os.Stdout)}
|
||||||
|
metrics := monitoring.NewMetricsServer(false, *log)
|
||||||
|
|
||||||
|
dir := t.TempDir()
|
||||||
|
defer os.RemoveAll(dir)
|
||||||
|
|
||||||
|
imgStore := storage.NewImageStore(dir, true, storage.DefaultGCDelay, true, true, *log, metrics, nil)
|
||||||
|
repo := data
|
||||||
|
|
||||||
|
_, err := imgStore.BlobUploadInfo(repo, uuid)
|
||||||
|
if err != nil {
|
||||||
|
if isKnownErr(err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func FuzzTestGetImageManifest(f *testing.F) {
|
||||||
|
f.Fuzz(func(t *testing.T, data string) {
|
||||||
|
dir := t.TempDir()
|
||||||
|
defer os.RemoveAll(dir)
|
||||||
|
|
||||||
|
log := log.Logger{Logger: zerolog.New(os.Stdout)}
|
||||||
|
metrics := monitoring.NewMetricsServer(false, log)
|
||||||
|
imgStore := storage.NewImageStore(dir, true, storage.DefaultGCDelay, true, true, log, metrics, nil)
|
||||||
|
|
||||||
|
repoName := data
|
||||||
|
|
||||||
|
digest := godigest.FromBytes([]byte(data))
|
||||||
|
|
||||||
|
_, _, _, err := imgStore.GetImageManifest(repoName, digest.String())
|
||||||
|
if err != nil {
|
||||||
|
if isKnownErr(err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func FuzzFinishBlobUpload(f *testing.F) {
|
||||||
|
f.Fuzz(func(t *testing.T, data string) {
|
||||||
|
dir := t.TempDir()
|
||||||
|
defer os.RemoveAll(dir)
|
||||||
|
|
||||||
|
log := log.Logger{Logger: zerolog.New(os.Stdout)}
|
||||||
|
metrics := monitoring.NewMetricsServer(false, log)
|
||||||
|
imgStore := storage.NewImageStore(dir, true, storage.DefaultGCDelay, true, true, log, metrics, nil)
|
||||||
|
|
||||||
|
repoName := data
|
||||||
|
|
||||||
|
upload, err := imgStore.NewBlobUpload(repoName)
|
||||||
|
if err != nil {
|
||||||
|
if isKnownErr(err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
content := []byte(data)
|
||||||
|
buf := bytes.NewBuffer(content)
|
||||||
|
buflen := buf.Len()
|
||||||
|
digest := godigest.FromBytes(content)
|
||||||
|
|
||||||
|
_, err = imgStore.PutBlobChunk(repoName, upload, 0, int64(buflen), buf)
|
||||||
|
if err != nil {
|
||||||
|
if isKnownErr(err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = imgStore.FinishBlobUpload(repoName, upload, buf, digest.String())
|
||||||
|
if err != nil {
|
||||||
|
if isKnownErr(err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func FuzzFullBlobUpload(f *testing.F) {
|
||||||
|
f.Fuzz(func(t *testing.T, data []byte) {
|
||||||
|
log := &log.Logger{Logger: zerolog.New(os.Stdout)}
|
||||||
|
metrics := monitoring.NewMetricsServer(false, *log)
|
||||||
|
repoName := "test"
|
||||||
|
|
||||||
|
dir := t.TempDir()
|
||||||
|
defer os.RemoveAll(dir)
|
||||||
|
|
||||||
|
imgStore := storage.NewImageStore(dir, true, storage.DefaultGCDelay, true, true, *log, metrics, nil)
|
||||||
|
|
||||||
|
ldigest, lblob, err := newRandomBlobForFuzz(data)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("error occurred while generating random blob, %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, _, err = imgStore.FullBlobUpload(repoName, bytes.NewReader(lblob), ldigest.String())
|
||||||
|
if err != nil {
|
||||||
|
if isKnownErr(err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func FuzzDedupeBlob(f *testing.F) {
|
||||||
|
f.Fuzz(func(t *testing.T, data string) {
|
||||||
|
log := &log.Logger{Logger: zerolog.New(os.Stdout)}
|
||||||
|
metrics := monitoring.NewMetricsServer(false, *log)
|
||||||
|
|
||||||
|
dir := t.TempDir()
|
||||||
|
defer os.RemoveAll(dir)
|
||||||
|
|
||||||
|
imgStore := storage.NewImageStore(dir, true, storage.DefaultGCDelay, true, true, *log, metrics, nil)
|
||||||
|
|
||||||
|
blobDigest := godigest.FromString(data)
|
||||||
|
|
||||||
|
// replacement for .uploads folder, usually retrieved from BlobUploadPath
|
||||||
|
src := path.Join(imgStore.RootDir(), "src")
|
||||||
|
blob := bytes.NewReader([]byte(data))
|
||||||
|
|
||||||
|
_, _, err := imgStore.FullBlobUpload("repoName", blob, blobDigest.String())
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
dst := imgStore.BlobPath("repoName", blobDigest)
|
||||||
|
|
||||||
|
err = os.MkdirAll(src, 0o755)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = imgStore.DedupeBlob(src, blobDigest, dst)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func FuzzDeleteBlobUpload(f *testing.F) {
|
||||||
|
f.Fuzz(func(t *testing.T, data string) {
|
||||||
|
log := &log.Logger{Logger: zerolog.New(os.Stdout)}
|
||||||
|
metrics := monitoring.NewMetricsServer(false, *log)
|
||||||
|
repoName := data
|
||||||
|
|
||||||
|
dir := t.TempDir()
|
||||||
|
defer os.RemoveAll(dir)
|
||||||
|
|
||||||
|
imgStore := storage.NewImageStore(dir, true, storage.DefaultGCDelay, true, true, *log, metrics, nil)
|
||||||
|
|
||||||
|
uuid, err := imgStore.NewBlobUpload(repoName)
|
||||||
|
if err != nil {
|
||||||
|
if isKnownErr(err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = imgStore.DeleteBlobUpload(repoName, uuid)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func FuzzBlobPath(f *testing.F) {
|
||||||
|
f.Fuzz(func(t *testing.T, data string) {
|
||||||
|
log := &log.Logger{Logger: zerolog.New(os.Stdout)}
|
||||||
|
metrics := monitoring.NewMetricsServer(false, *log)
|
||||||
|
repoName := data
|
||||||
|
|
||||||
|
dir := t.TempDir()
|
||||||
|
defer os.RemoveAll(dir)
|
||||||
|
|
||||||
|
imgStore := storage.NewImageStore(dir, true, storage.DefaultGCDelay, true, true, *log, metrics, nil)
|
||||||
|
digest := godigest.FromString(data)
|
||||||
|
|
||||||
|
_ = imgStore.BlobPath(repoName, digest)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func FuzzCheckBlob(f *testing.F) {
|
||||||
|
f.Fuzz(func(t *testing.T, data string) {
|
||||||
|
log := &log.Logger{Logger: zerolog.New(os.Stdout)}
|
||||||
|
metrics := monitoring.NewMetricsServer(false, *log)
|
||||||
|
repoName := data
|
||||||
|
|
||||||
|
dir := t.TempDir()
|
||||||
|
defer os.RemoveAll(dir)
|
||||||
|
|
||||||
|
imgStore := storage.NewImageStore(dir, true, storage.DefaultGCDelay, true, true, *log, metrics, nil)
|
||||||
|
digest := godigest.FromString(data)
|
||||||
|
|
||||||
|
_, _, err := imgStore.FullBlobUpload(repoName, bytes.NewReader([]byte(data)), digest.String())
|
||||||
|
if err != nil {
|
||||||
|
if isKnownErr(err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
_, _, err = imgStore.CheckBlob(repoName, digest.String())
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func FuzzGetBlob(f *testing.F) {
|
||||||
|
f.Fuzz(func(t *testing.T, data string) {
|
||||||
|
log := &log.Logger{Logger: zerolog.New(os.Stdout)}
|
||||||
|
metrics := monitoring.NewMetricsServer(false, *log)
|
||||||
|
repoName := data
|
||||||
|
|
||||||
|
dir := t.TempDir()
|
||||||
|
defer os.RemoveAll(dir)
|
||||||
|
|
||||||
|
imgStore := storage.NewImageStore(dir, true, storage.DefaultGCDelay, true, true, *log, metrics, nil)
|
||||||
|
digest := godigest.FromString(data)
|
||||||
|
|
||||||
|
_, _, err := imgStore.FullBlobUpload(repoName, bytes.NewReader([]byte(data)), digest.String())
|
||||||
|
if err != nil {
|
||||||
|
if isKnownErr(err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, _, err = imgStore.GetBlob(repoName, digest.String(), "application/vnd.oci.image.layer.v1.tar+gzip")
|
||||||
|
if err != nil {
|
||||||
|
if isKnownErr(err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func FuzzDeleteBlob(f *testing.F) {
|
||||||
|
f.Fuzz(func(t *testing.T, data string) {
|
||||||
|
log := &log.Logger{Logger: zerolog.New(os.Stdout)}
|
||||||
|
metrics := monitoring.NewMetricsServer(false, *log)
|
||||||
|
repoName := data
|
||||||
|
|
||||||
|
dir := t.TempDir()
|
||||||
|
defer os.RemoveAll(dir)
|
||||||
|
|
||||||
|
imgStore := storage.NewImageStore(dir, true, storage.DefaultGCDelay, true, true, *log, metrics, nil)
|
||||||
|
digest := godigest.FromString(data)
|
||||||
|
|
||||||
|
_, _, err := imgStore.FullBlobUpload(repoName, bytes.NewReader([]byte(data)), digest.String())
|
||||||
|
if err != nil {
|
||||||
|
if isKnownErr(err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = imgStore.DeleteBlob(repoName, digest.String())
|
||||||
|
if err != nil {
|
||||||
|
if isKnownErr(err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func FuzzGetIndexContent(f *testing.F) {
|
||||||
|
f.Fuzz(func(t *testing.T, data string) {
|
||||||
|
log := &log.Logger{Logger: zerolog.New(os.Stdout)}
|
||||||
|
metrics := monitoring.NewMetricsServer(false, *log)
|
||||||
|
repoName := data
|
||||||
|
|
||||||
|
dir := t.TempDir()
|
||||||
|
defer os.RemoveAll(dir)
|
||||||
|
|
||||||
|
imgStore := storage.NewImageStore(dir, true, storage.DefaultGCDelay, true, true, *log, metrics, nil)
|
||||||
|
digest := godigest.FromString(data)
|
||||||
|
|
||||||
|
_, _, err := imgStore.FullBlobUpload(repoName, bytes.NewReader([]byte(data)), digest.String())
|
||||||
|
if err != nil {
|
||||||
|
if isKnownErr(err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = imgStore.GetIndexContent(repoName)
|
||||||
|
if err != nil {
|
||||||
|
if isKnownErr(err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func FuzzGetBlobContent(f *testing.F) {
|
||||||
|
f.Fuzz(func(t *testing.T, data string) {
|
||||||
|
log := &log.Logger{Logger: zerolog.New(os.Stdout)}
|
||||||
|
metrics := monitoring.NewMetricsServer(false, *log)
|
||||||
|
repoName := data
|
||||||
|
|
||||||
|
dir := t.TempDir()
|
||||||
|
defer os.RemoveAll(dir)
|
||||||
|
|
||||||
|
imgStore := storage.NewImageStore(dir, true, storage.DefaultGCDelay, true, true, *log, metrics, nil)
|
||||||
|
digest := godigest.FromString(data)
|
||||||
|
|
||||||
|
_, _, err := imgStore.FullBlobUpload(repoName, bytes.NewReader([]byte(data)), digest.String())
|
||||||
|
if err != nil {
|
||||||
|
if isKnownErr(err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = imgStore.GetBlobContent(repoName, digest.String())
|
||||||
|
if err != nil {
|
||||||
|
if isKnownErr(err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func FuzzGetReferrers(f *testing.F) {
|
||||||
|
f.Fuzz(func(t *testing.T, data string) {
|
||||||
|
log := &log.Logger{Logger: zerolog.New(os.Stdout)}
|
||||||
|
metrics := monitoring.NewMetricsServer(false, *log)
|
||||||
|
|
||||||
|
dir := t.TempDir()
|
||||||
|
defer os.RemoveAll(dir)
|
||||||
|
|
||||||
|
imgStore := storage.NewImageStore(dir, true, storage.DefaultGCDelay, true, true, *log, metrics, nil)
|
||||||
|
|
||||||
|
err := test.CopyFiles("../../test/data/zot-test", path.Join(dir, "zot-test"))
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
digest := godigest.FromBytes([]byte(data))
|
||||||
|
buf := bytes.NewBuffer([]byte(data))
|
||||||
|
buflen := buf.Len()
|
||||||
|
err = ioutil.WriteFile(path.Join(imgStore.RootDir(), //nolint: gosec
|
||||||
|
"zot-test", "blobs", digest.Algorithm().String(), digest.Encoded()),
|
||||||
|
buf.Bytes(), 0o644)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
_, _, err = imgStore.FullBlobUpload("zot-test", buf, digest.String())
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
artifactManifest := artifactspec.Manifest{}
|
||||||
|
artifactManifest.ArtifactType = data
|
||||||
|
artifactManifest.Subject = artifactspec.Descriptor{
|
||||||
|
MediaType: ispec.MediaTypeImageManifest,
|
||||||
|
Digest: digest,
|
||||||
|
Size: int64(buflen),
|
||||||
|
}
|
||||||
|
artifactManifest.Blobs = []artifactspec.Descriptor{}
|
||||||
|
|
||||||
|
manBuf, err := json.Marshal(artifactManifest)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
manDigest := godigest.FromBytes(manBuf)
|
||||||
|
_, err = imgStore.PutImageManifest("zot-test", manDigest.Encoded(), artifactspec.MediaTypeArtifactManifest, manBuf)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
_, err = imgStore.GetReferrers("zot-test", digest.String(), data)
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, zerr.ErrManifestNotFound) || isKnownErr(err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func FuzzRunGCRepo(f *testing.F) {
|
||||||
|
f.Fuzz(func(t *testing.T, data string) {
|
||||||
|
log := &log.Logger{Logger: zerolog.New(os.Stdout)}
|
||||||
|
metrics := monitoring.NewMetricsServer(false, *log)
|
||||||
|
dir := t.TempDir()
|
||||||
|
defer os.RemoveAll(dir)
|
||||||
|
|
||||||
|
imgStore := storage.NewImageStore(dir, true, storage.DefaultGCDelay, true, true, *log, metrics, nil)
|
||||||
|
|
||||||
|
imgStore.RunGCRepo(data)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func TestDedupeLinks(t *testing.T) {
|
func TestDedupeLinks(t *testing.T) {
|
||||||
dir := t.TempDir()
|
dir := t.TempDir()
|
||||||
|
|
||||||
|
@ -416,6 +1122,10 @@ func TestNegativeCases(t *testing.T) {
|
||||||
|
|
||||||
err = imgStore.InitRepo("test-dir")
|
err = imgStore.InitRepo("test-dir")
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
|
|
||||||
|
// Init repo should fail if repo is invalid UTF-8
|
||||||
|
err = imgStore.InitRepo("hi \255")
|
||||||
|
So(err, ShouldNotBeNil)
|
||||||
})
|
})
|
||||||
|
|
||||||
Convey("Invalid validate repo", t, func(c C) {
|
Convey("Invalid validate repo", t, func(c C) {
|
||||||
|
@ -438,7 +1148,7 @@ func TestNegativeCases(t *testing.T) {
|
||||||
}
|
}
|
||||||
_, err = imgStore.ValidateRepo("invalid-test")
|
_, err = imgStore.ValidateRepo("invalid-test")
|
||||||
So(err, ShouldNotBeNil)
|
So(err, ShouldNotBeNil)
|
||||||
So(err, ShouldEqual, errors.ErrRepoNotFound)
|
So(err, ShouldEqual, zerr.ErrRepoNotFound)
|
||||||
|
|
||||||
err = os.Chmod(path.Join(dir, "invalid-test"), 0o755) // remove all perms
|
err = os.Chmod(path.Join(dir, "invalid-test"), 0o755) // remove all perms
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -483,7 +1193,7 @@ func TestNegativeCases(t *testing.T) {
|
||||||
|
|
||||||
isValid, err = imgStore.ValidateRepo("invalid-test")
|
isValid, err = imgStore.ValidateRepo("invalid-test")
|
||||||
So(err, ShouldNotBeNil)
|
So(err, ShouldNotBeNil)
|
||||||
So(err, ShouldEqual, errors.ErrRepoBadVersion)
|
So(err, ShouldEqual, zerr.ErrRepoBadVersion)
|
||||||
So(isValid, ShouldEqual, false)
|
So(isValid, ShouldEqual, false)
|
||||||
|
|
||||||
files, err := ioutil.ReadDir(path.Join(dir, "test"))
|
files, err := ioutil.ReadDir(path.Join(dir, "test"))
|
||||||
|
@ -676,6 +1386,27 @@ func TestNegativeCases(t *testing.T) {
|
||||||
ok := storage.DirExists(filePath)
|
ok := storage.DirExists(filePath)
|
||||||
So(ok, ShouldBeFalse)
|
So(ok, ShouldBeFalse)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
Convey("DirExists call with invalid UTF-8 as argument", t, func(c C) {
|
||||||
|
dir := t.TempDir()
|
||||||
|
|
||||||
|
filePath := path.Join(dir, "hi \255")
|
||||||
|
ok := storage.DirExists(filePath)
|
||||||
|
So(ok, ShouldBeFalse)
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("DirExists call with name too long as argument", t, func(c C) {
|
||||||
|
var builder strings.Builder
|
||||||
|
for i := 0; i < 1025; i++ {
|
||||||
|
_, err := builder.WriteString("0")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
path := builder.String()
|
||||||
|
ok := storage.DirExists(path)
|
||||||
|
So(ok, ShouldBeFalse)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHardLink(t *testing.T) {
|
func TestHardLink(t *testing.T) {
|
||||||
|
@ -1311,3 +2042,56 @@ func TestPutBlobChunkStreamed(t *testing.T) {
|
||||||
So(err, ShouldNotBeNil)
|
So(err, ShouldNotBeNil)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewRandomImgManifest(data []byte, cdigest, ldigest godigest.Digest, cblob, lblob []byte) (*ispec.Manifest, error) {
|
||||||
|
annotationsMap := make(map[string]string)
|
||||||
|
|
||||||
|
key := string(data)
|
||||||
|
val := string(data)
|
||||||
|
annotationsMap[key] = val
|
||||||
|
|
||||||
|
schemaVersion := 2
|
||||||
|
|
||||||
|
manifest := ispec.Manifest{
|
||||||
|
MediaType: "application/vnd.oci.image.manifest.v1+json",
|
||||||
|
Config: ispec.Descriptor{
|
||||||
|
MediaType: "application/vnd.oci.image.config.v1+json",
|
||||||
|
Digest: cdigest,
|
||||||
|
Size: int64(len(cblob)),
|
||||||
|
},
|
||||||
|
Layers: []ispec.Descriptor{
|
||||||
|
{
|
||||||
|
MediaType: "application/vnd.oci.image.layer.v1.tar",
|
||||||
|
Digest: ldigest,
|
||||||
|
Size: int64(len(lblob)),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Annotations: annotationsMap,
|
||||||
|
Versioned: imeta.Versioned{
|
||||||
|
SchemaVersion: schemaVersion,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return &manifest, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func newRandomBlobForFuzz(data []byte) (godigest.Digest, []byte, error) {
|
||||||
|
return godigest.FromBytes(data), data, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func isKnownErr(err error) bool {
|
||||||
|
if errors.Is(err, zerr.ErrInvalidRepositoryName) || errors.Is(err, zerr.ErrManifestNotFound) ||
|
||||||
|
errors.Is(err, zerr.ErrRepoNotFound) ||
|
||||||
|
errors.Is(err, zerr.ErrBadManifest) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if err, ok := err.(*fs.PathError); ok && errors.Is(err.Err, syscall.EACCES) || //nolint: errorlint
|
||||||
|
errors.Is(err.Err, syscall.ENAMETOOLONG) ||
|
||||||
|
errors.Is(err.Err, syscall.EINVAL) ||
|
||||||
|
errors.Is(err.Err, syscall.ENOENT) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
|
@ -191,6 +191,10 @@ func TestStorageAPIs(t *testing.T) {
|
||||||
So(err, ShouldNotBeNil)
|
So(err, ShouldNotBeNil)
|
||||||
So(bupload, ShouldEqual, -1)
|
So(bupload, ShouldEqual, -1)
|
||||||
|
|
||||||
|
bupload, err = imgStore.GetBlobUpload("hi", " \255")
|
||||||
|
So(err, ShouldNotBeNil)
|
||||||
|
So(bupload, ShouldEqual, -1)
|
||||||
|
|
||||||
bupload, err = imgStore.GetBlobUpload("test", upload)
|
bupload, err = imgStore.GetBlobUpload("test", upload)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(bupload, ShouldBeGreaterThanOrEqualTo, 0)
|
So(bupload, ShouldBeGreaterThanOrEqualTo, 0)
|
||||||
|
|
18
test/scripts/fuzzAll.sh
Normal file
18
test/scripts/fuzzAll.sh
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
fuzzTime=${1:-10}
|
||||||
|
|
||||||
|
files=$(grep -r --include='**_test.go' --files-with-matches 'func Fuzz' .)
|
||||||
|
|
||||||
|
for file in ${files}
|
||||||
|
do
|
||||||
|
funcs=$(grep -oP 'func \K(Fuzz\w*)' $file)
|
||||||
|
for func in ${funcs}
|
||||||
|
do
|
||||||
|
echo "Fuzzing $func in $file"
|
||||||
|
parentDir=$(dirname $file)
|
||||||
|
go test $parentDir -run=$func -fuzz=$func$ -fuzztime=${fuzzTime}s -tags sync,metrics,search,scrub,ui_base,containers_image_openpgp | grep -oP -x '^(?:(?!\blevel\b).)*$'
|
||||||
|
done
|
||||||
|
done
|
Loading…
Reference in a new issue