Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

squashfs: fix directory listings #195

Merged
merged 1 commit into from
Dec 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions filesystem/squashfs/const_internal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
const (
Squashfsfile = "./testdata/file.sqs"
SquashfsUncompressedfile = "./testdata/file_uncompressed.sqs"
SquashfsfileListing = "./testdata/list.txt"
)

// first header
Expand Down
9 changes: 4 additions & 5 deletions filesystem/squashfs/directory.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,16 +54,15 @@ type directoryEntryGroup struct {

// parse raw bytes of a directory to get the contents
func parseDirectory(b []byte) (*directory, error) {
// must have at least one header
if _, err := parseDirectoryHeader(b); err != nil {
return nil, fmt.Errorf("could not parse directory header: %v", err)
}
entries := make([]*directoryEntryRaw, 0)
for pos := 0; pos+dirHeaderSize < len(b); {
for pos := 0; pos+dirHeaderSize <= len(b); {
directoryHeader, err := parseDirectoryHeader(b[pos:])
if err != nil {
return nil, fmt.Errorf("could not parse directory header: %v", err)
}
if directoryHeader.count == 0 {
return nil, fmt.Errorf("corrupted directory, must have at least one entry")
}
if directoryHeader.count > maxDirEntries {
return nil, fmt.Errorf("corrupted directory, had %d entries instead of max %d", directoryHeader.count, maxDirEntries)
}
Expand Down
6 changes: 5 additions & 1 deletion filesystem/squashfs/directory_internal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ var (
testDirectory = &directory{
entries: testDirectoryEntries,
}
testDirectoryTableWithNoEntries = []byte{
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
}
)

func TestParseDirectoryHeader(t *testing.T) {
Expand Down Expand Up @@ -115,7 +118,8 @@ func TestParseDirectory(t *testing.T) {
err error
}{
{testDirectoryTable, testDirectory, nil},
{testDirectoryTable[:10], nil, fmt.Errorf("could not parse directory header: header was 10 bytes, less than minimum 12")},
{testDirectoryTable[:10], &directory{}, nil},
{testDirectoryTableWithNoEntries, nil, fmt.Errorf("corrupted directory, must have at least one entry")},
}
for i, tt := range tests {
dir, err := parseDirectory(tt.b)
Expand Down
66 changes: 66 additions & 0 deletions filesystem/squashfs/squashfs_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package squashfs_test

import (
"bufio"
"fmt"
"io"
"os"
Expand Down Expand Up @@ -294,6 +295,71 @@ func TestSquashfsRead(t *testing.T) {
}
}

// Check the directory listing is correct
func TestSquashfsCheckListing(t *testing.T) {
// read the directory listing in
var listing = map[string]struct{}{}
flist, err := os.Open(squashfs.SquashfsfileListing)
if err != nil {
t.Fatal(err)
}
defer flist.Close()
scanner := bufio.NewScanner(flist)
for scanner.Scan() {
line := scanner.Text()
line = strings.TrimPrefix(line, ".")
if line == "/" {
continue
}
listing[line] = struct{}{}
}
if err := scanner.Err(); err != nil {
t.Fatal(err)
}

// Open the squash file
f, err := os.Open(squashfs.Squashfsfile)
if err != nil {
t.Fatal(err)
}
defer f.Close()
fi, err := f.Stat()
if err != nil {
t.Fatal(err)
}
// create the filesystem
fs, err := squashfs.Read(f, fi.Size(), 0, 0)
if err != nil {
t.Fatal(err)
}

var list func(dir string)
list = func(dir string) {
fis, err := fs.ReadDir(dir)
if err != nil {
t.Fatal(err)
}
for _, fi := range fis {
p := path.Join(dir, fi.Name())
if _, found := listing[p]; found {
delete(listing, p)
} else {
t.Errorf("Found unexpected path %q in listing", p)
}
if fi.IsDir() {
list(p)
}
}
}

list("/")

// listing should be empty now
for p := range listing {
t.Errorf("Didn't find %q in listing", p)
}
}

func TestSquashfsCreate(t *testing.T) {
tests := []struct {
blocksize int64
Expand Down
3 changes: 3 additions & 0 deletions filesystem/squashfs/testdata/buildtestsqs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,7 @@ mksquashfs . /data/file.sqs

# uncompressed version
mksquashfs . /data/file_uncompressed.sqs -noI -noD -noF

# create listing to check
find . > /data/list.txt
EOF
Loading
Loading