Skip to content

Squashfs: fix error format when file larger than block size #287

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

Merged
merged 5 commits into from
Mar 10, 2025
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
8 changes: 4 additions & 4 deletions filesystem/squashfs/const_internal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func testGetFirstInodeHeader() *inodeHeader {
}
func testGetFirstInodeBody() inodeBody {
return extendedFile{
startBlock: 0,
blocksStart: 0,
fragmentBlockIndex: 0,
fileSize: 7,
fragmentOffset: 0,
Expand Down Expand Up @@ -95,7 +95,7 @@ var (

// this is for /foo/filename_0
testBasicFile = &basicFile{
startBlock: 0,
blocksStart: 0,
fragmentBlockIndex: 0,
fileSize: 0xb,
fragmentOffset: 0xc,
Expand Down Expand Up @@ -240,7 +240,7 @@ func GetTestFileSmall(f fs.File, c Compressor) (*File, error) {
}
testFs.compressor = c
ef := &extendedFile{
startBlock: superblockSize,
blocksStart: superblockSize,
fileSize: 7,
sparse: 0,
links: 0,
Expand Down Expand Up @@ -269,7 +269,7 @@ func GetTestFileBig(f fs.File, c Compressor) (*File, error) {
fragSize := uint64(5)
size := uint64(testFs.blocksize) + fragSize
ef := &extendedFile{
startBlock: superblockSize,
blocksStart: superblockSize,
fileSize: size,
sparse: 0,
links: 0,
Expand Down
2 changes: 1 addition & 1 deletion filesystem/squashfs/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func (fl *File) Read(b []byte) (int, error) {
// 5- read in and uncompress the necessary blocks
fs := fl.filesystem
size := fl.size() - fl.offset
location := int64(fl.startBlock)
location := int64(fl.blocksStart)
maxRead := len(b)

// if there is nothing left to read, just return EOF
Expand Down
26 changes: 15 additions & 11 deletions filesystem/squashfs/finalize.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,11 +137,11 @@ func (fs *FileSystem) Finalize(options FinalizeOptions) error {
// write file fragments
//
fragmentBlockStart := location
fragmentBlocks, fragsWritten, err := writeFragmentBlocks(fileList, f, fs.workspace, blocksize, options, fragmentBlockStart)
fragmentBlocks, _, err := writeFragmentBlocks(fileList, f, fs.workspace, blocksize, options, fragmentBlockStart)
if err != nil {
return fmt.Errorf("error writing file fragment blocks: %v", err)
}
location += fragsWritten
location += int64(len(fragmentBlocks) * blocksize)

// extract extended attributes, and save them for later; these are written at the very end
// this must be done *before* creating inodes, as inodes reference these
Expand Down Expand Up @@ -588,6 +588,7 @@ func writeDataBlocks(fileList []*finalizeFileInfo, f backend.WritableFile, ws st
}
allBlocks += blocks
allWritten += written
location += int64(written)
}
return allWritten, nil
}
Expand Down Expand Up @@ -637,9 +638,10 @@ func writeFragmentBlocks(fileList []*finalizeFileInfo, f backend.WritableFile, w
compressed: compressed,
location: location,
})
location += int64(blocksize)
// increment as all writes will be to next block block
fragmentBlockIndex++
fragmentData = fragmentData[:blocksize]
fragmentData = make([]byte, 0)
}

e.fragment = &fragmentRef{
Expand Down Expand Up @@ -1104,11 +1106,11 @@ func createInodes(fileList []*finalizeFileInfo, idtable map[uint32]uint16, optio
if e.startBlock|uint32max != uint32max || e.Size()|int64(uint32max) != int64(uint32max) || len(e.xattrs) > 0 || e.links > 0 {
// use extendedFile inode
ef := &extendedFile{
startBlock: e.startBlock,
fileSize: uint64(e.Size()),
blockSizes: e.blocks,
links: e.links,
xAttrIndex: e.xAttrIndex,
blocksStart: uint64(e.dataLocation),
fileSize: uint64(e.Size()),
blockSizes: e.blocks,
links: e.links,
xAttrIndex: e.xAttrIndex,
}
if e.fragment != nil {
ef.fragmentBlockIndex = e.fragment.block
Expand All @@ -1119,13 +1121,15 @@ func createInodes(fileList []*finalizeFileInfo, idtable map[uint32]uint16, optio
} else {
// use basicFile
bf := &basicFile{
startBlock: uint32(e.startBlock),
fileSize: uint32(e.Size()),
blockSizes: e.blocks,
blocksStart: uint32(e.dataLocation),
fileSize: uint32(e.Size()),
blockSizes: e.blocks,
}
if e.fragment != nil {
bf.fragmentBlockIndex = e.fragment.block
bf.fragmentOffset = e.fragment.offset
} else {
bf.fragmentBlockIndex = 0xffffffff
}
in = bf
inodeT = inodeBasicFile
Expand Down
18 changes: 9 additions & 9 deletions filesystem/squashfs/inode.go
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,7 @@ func parseDirectoryIndexes(b []byte, count int) ([]*directoryIndex, error) {

// basicFile
type basicFile struct {
startBlock uint32 // block count from the start of the data section where data for this file is stored
blocksStart uint32 // The offset from the start of the archive to the first data block.
fragmentBlockIndex uint32
fragmentOffset uint32
fileSize uint32
Expand All @@ -391,12 +391,12 @@ func (i basicFile) equal(o inodeBody) bool {
return false
}
}
return i.startBlock == oi.startBlock && i.fragmentOffset == oi.fragmentOffset && i.fragmentBlockIndex == oi.fragmentBlockIndex && i.fileSize == oi.fileSize
return i.blocksStart == oi.blocksStart && i.fragmentOffset == oi.fragmentOffset && i.fragmentBlockIndex == oi.fragmentBlockIndex && i.fileSize == oi.fileSize
}

func (i basicFile) toBytes() []byte {
b := make([]byte, 16+4*len(i.blockSizes))
binary.LittleEndian.PutUint32(b[0:4], i.startBlock)
binary.LittleEndian.PutUint32(b[0:4], i.blocksStart)
binary.LittleEndian.PutUint32(b[4:8], i.fragmentBlockIndex)
binary.LittleEndian.PutUint32(b[8:12], i.fragmentOffset)
binary.LittleEndian.PutUint32(b[12:16], i.fileSize)
Expand All @@ -413,7 +413,7 @@ func (i basicFile) xattrIndex() (uint32, bool) {
}
func (i basicFile) toExtended() extendedFile {
return extendedFile{
startBlock: uint64(i.startBlock),
blocksStart: uint64(i.blocksStart),
fileSize: uint64(i.fileSize),
sparse: 0,
links: 0,
Expand All @@ -433,7 +433,7 @@ func parseBasicFile(b []byte, blocksize int) (*basicFile, int, error) {
}
fileSize := binary.LittleEndian.Uint32(b[12:16])
d := &basicFile{
startBlock: binary.LittleEndian.Uint32(b[0:4]),
blocksStart: binary.LittleEndian.Uint32(b[0:4]),
fragmentBlockIndex: binary.LittleEndian.Uint32(b[4:8]),
fragmentOffset: binary.LittleEndian.Uint32(b[8:12]),
fileSize: fileSize,
Expand All @@ -455,7 +455,7 @@ func parseBasicFile(b []byte, blocksize int) (*basicFile, int, error) {

// extendedFile
type extendedFile struct {
startBlock uint64
blocksStart uint64
fileSize uint64
sparse uint64
links uint32
Expand All @@ -481,7 +481,7 @@ func (i extendedFile) equal(o inodeBody) bool {
return false
}
}
return i.startBlock == oi.startBlock &&
return i.blocksStart == oi.blocksStart &&
i.fragmentOffset == oi.fragmentOffset &&
i.fragmentBlockIndex == oi.fragmentBlockIndex &&
i.fileSize == oi.fileSize &&
Expand All @@ -492,7 +492,7 @@ func (i extendedFile) equal(o inodeBody) bool {

func (i extendedFile) toBytes() []byte {
b := make([]byte, 40+4*len(i.blockSizes))
binary.LittleEndian.PutUint64(b[0:8], i.startBlock)
binary.LittleEndian.PutUint64(b[0:8], i.blocksStart)
binary.LittleEndian.PutUint64(b[8:16], i.fileSize)
binary.LittleEndian.PutUint64(b[16:24], i.sparse)
binary.LittleEndian.PutUint32(b[24:28], i.links)
Expand Down Expand Up @@ -521,7 +521,7 @@ func parseExtendedFile(b []byte, blocksize int) (*extendedFile, int, error) {
}
fileSize := binary.LittleEndian.Uint64(b[8:16])
d := &extendedFile{
startBlock: binary.LittleEndian.Uint64(b[0:8]),
blocksStart: binary.LittleEndian.Uint64(b[0:8]),
fileSize: fileSize,
sparse: binary.LittleEndian.Uint64(b[16:24]),
links: binary.LittleEndian.Uint32(b[24:28]),
Expand Down
4 changes: 2 additions & 2 deletions filesystem/squashfs/inode_internal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -260,8 +260,8 @@ func TestBasicFile(t *testing.T) {
if ext.size() != f.size() {
t.Errorf("Mismatched sizes actual %d expected %d", ext.size(), f.size())
}
if ext.startBlock != uint64(f.startBlock) {
t.Errorf("Mismatched startBlock actual %d expected %d", ext.startBlock, f.startBlock)
if ext.blocksStart != uint64(f.blocksStart) {
t.Errorf("Mismatched startBlock actual %d expected %d", ext.blocksStart, f.blocksStart)
}
if ext.fragmentOffset != f.fragmentOffset {
t.Errorf("Mismatched fragmentOffset actual %d expected %d", ext.fragmentOffset, f.fragmentOffset)
Expand Down