mirror of
https://github.com/anchore/syft.git
synced 2026-11-01 23:16:30 +01:00
fix: propagate non-EOF errors out of safeCopy (#4807)
Signed-off-by: SAY-5 <SAY-5@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
package file
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// errReader returns a deterministic non-EOF error after emitting some
|
||||
// bytes, mimicking what compress/flate does when it hits a corrupt
|
||||
// stream mid-entry.
|
||||
type errReader struct {
|
||||
data []byte
|
||||
err error
|
||||
off int
|
||||
}
|
||||
|
||||
func (r *errReader) Read(p []byte) (int, error) {
|
||||
if r.off >= len(r.data) {
|
||||
return 0, r.err
|
||||
}
|
||||
n := copy(p, r.data[r.off:])
|
||||
r.off += n
|
||||
return n, nil
|
||||
}
|
||||
|
||||
func TestSafeCopy(t *testing.T) {
|
||||
t.Run("clean copy returns nil", func(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
if err := safeCopy(&buf, strings.NewReader("hello")); err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if got := buf.String(); got != "hello" {
|
||||
t.Fatalf("unexpected buffer contents: %q", got)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("propagates decompression error", func(t *testing.T) {
|
||||
// #4806: safeCopy used to drop non-EOF errors, so the caller
|
||||
// would persist a partial buffer as a successful extract and
|
||||
// downstream catalogers silently read empty manifests.
|
||||
sentinel := errors.New("flate: corrupt input before offset 42")
|
||||
var buf bytes.Buffer
|
||||
err := safeCopy(&buf, &errReader{data: []byte("partial"), err: sentinel})
|
||||
if err == nil {
|
||||
t.Fatalf("expected error to be returned, got nil")
|
||||
}
|
||||
if !errors.Is(err, sentinel) {
|
||||
t.Fatalf("error does not wrap sentinel: %v", err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("EOF is not treated as an error", func(t *testing.T) {
|
||||
// The old code had a dead io.EOF branch that labelled clean
|
||||
// reads as decompression bombs; keep the happy path clean.
|
||||
var buf bytes.Buffer
|
||||
err := safeCopy(&buf, io.LimitReader(strings.NewReader("abc"), 3))
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error on clean copy: %v", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user