internal/repository: Fix LoadBlob + fuzz test

When given a buf that is big enough for a compressed blob but not its
decompressed contents, the copy at the end of LoadBlob would skip the
last part of the contents.

Fixes #3783.
This commit is contained in:
greatroar 2022-06-06 16:26:38 +02:00
parent b7c990871f
commit c9557b2822
4 changed files with 50 additions and 1 deletions

2
.gitattributes vendored Normal file
View file

@ -0,0 +1,2 @@
# Workaround for https://github.com/golang/go/issues/52268.
**/testdata/fuzz/*/* eol=lf

View file

@ -0,0 +1,43 @@
//go:build go1.18
// +build go1.18
package repository
import (
"context"
"testing"
"github.com/restic/restic/internal/backend/mem"
"github.com/restic/restic/internal/restic"
)
// Test saving a blob and loading it again, with varying buffer sizes.
// Also a regression test for #3783.
func FuzzSaveLoadBlob(f *testing.F) {
f.Fuzz(func(t *testing.T, blob []byte, buflen uint) {
if buflen > 64<<20 {
// Don't allocate enormous buffers. We're not testing the allocator.
t.Skip()
}
id := restic.Hash(blob)
repo, _ := TestRepositoryWithBackend(t, mem.New(), 2)
_, _, err := repo.SaveBlob(context.TODO(), restic.DataBlob, blob, id, false)
if err != nil {
t.Fatal(err)
}
err = repo.Flush(context.TODO())
if err != nil {
t.Fatal(err)
}
buf, err := repo.LoadBlob(context.TODO(), restic.DataBlob, id, make([]byte, buflen))
if err != nil {
t.Fatal(err)
}
if restic.Hash(buf) != id {
t.Fatal("mismatch")
}
})
}

View file

@ -303,8 +303,9 @@ func (r *Repository) LoadBlob(ctx context.Context, t restic.BlobType, id restic.
return plaintext, nil
}
// move decrypted data to the start of the buffer
buf = buf[:len(plaintext)]
copy(buf, plaintext)
return buf[:len(plaintext)], nil
return buf, nil
}
if lastError != nil {

View file

@ -0,0 +1,3 @@
go test fuzz v1
[]byte("\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6")
uint(109)