[chore] - correctly handle input shorter than 512 bytes (#2077)

* correctly handle input shorter than 512 bytes

* add tests

* reorder tests

* add another test case

* update test

* address comment
This commit is contained in:
ahrav
2023-10-31 16:42:42 -07:00
committed by GitHub
parent 89b6315e19
commit 95e0090bc2
3 changed files with 80 additions and 3 deletions
+3 -1
View File
@@ -414,9 +414,11 @@ func (a *Archive) handleNestedFileMIME(ctx logContext.Context, tempEnv tempEnv,
// determineMimeType reads from the provided reader to detect the MIME type.
// It returns the detected MIME type and a new reader that includes the read portion.
func determineMimeType(reader io.Reader) (mimeType, io.Reader, error) {
// A buffer of 512 bytes is used since many file formats store their magic numbers within the first 512 bytes.
// If fewer bytes are read, MIME type detection may still succeed.
buffer := make([]byte, 512)
n, err := reader.Read(buffer)
if err != nil {
if err != nil && !errors.Is(err, io.EOF) {
return "", nil, fmt.Errorf("unable to read file for MIME type detection: %w", err)
}
+76 -1
View File
@@ -11,8 +11,9 @@ import (
"testing"
"time"
diskbufferreader "github.com/trufflesecurity/disk-buffer-reader"
"github.com/h2non/filetype"
"github.com/stretchr/testify/assert"
diskbufferreader "github.com/trufflesecurity/disk-buffer-reader"
logContext "github.com/trufflesecurity/trufflehog/v3/pkg/context"
"github.com/trufflesecurity/trufflehog/v3/pkg/sources"
@@ -271,3 +272,77 @@ func TestNestedDirArchive(t *testing.T) {
}
assert.Equal(t, want, count)
}
func TestDetermineMimeType(t *testing.T) {
filetype.AddMatcher(filetype.NewType("txt", "text/plain"), func(buf []byte) bool {
return strings.HasPrefix(string(buf), "text:")
})
pngBytes := []byte("\x89PNG\r\n\x1a\n")
jpegBytes := []byte{0xFF, 0xD8, 0xFF}
textBytes := []byte("text: This is a plain text")
rpmBytes := []byte("\xed\xab\xee\xdb")
tests := []struct {
name string
input io.Reader
expected mimeType
shouldFail bool
}{
{
name: "PNG file",
input: bytes.NewReader(pngBytes),
expected: mimeType("image/png"),
shouldFail: false,
},
{
name: "JPEG file",
input: bytes.NewReader(jpegBytes),
expected: mimeType("image/jpeg"),
shouldFail: false,
},
{
name: "Text file",
input: bytes.NewReader(textBytes),
expected: mimeType("text/plain"),
shouldFail: false,
},
{
name: "RPM file",
input: bytes.NewReader(rpmBytes),
expected: rpmMimeType,
shouldFail: false,
},
{
name: "Truncated JPEG file",
input: io.LimitReader(bytes.NewReader(jpegBytes), 2),
expected: mimeType("unknown"),
shouldFail: true,
},
{
name: "Empty reader",
input: bytes.NewReader([]byte{}),
shouldFail: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
originalData, _ := io.ReadAll(io.TeeReader(tt.input, &bytes.Buffer{}))
tt.input = bytes.NewReader(originalData) // Reset the reader
mime, reader, err := determineMimeType(tt.input)
if err != nil && !tt.shouldFail {
t.Fatalf("unexpected error: %v", err)
}
if !tt.shouldFail {
assert.Equal(t, tt.expected, mime)
}
// Ensure the reader still contains all the original data.
data, _ := io.ReadAll(reader)
assert.Equal(t, originalData, data)
})
}
}
+1 -1
View File
@@ -7,8 +7,8 @@ import (
"testing"
"testing/iotest"
diskbufferreader "github.com/trufflesecurity/disk-buffer-reader"
"github.com/stretchr/testify/assert"
diskbufferreader "github.com/trufflesecurity/disk-buffer-reader"
"github.com/trufflesecurity/trufflehog/v3/pkg/context"
)