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 error format when file larger than block size #287

Merged
merged 5 commits into from
Mar 10, 2025
Merged
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
@@ -36,7 +36,7 @@ func testGetFirstInodeHeader() *inodeHeader {
}
func testGetFirstInodeBody() inodeBody {
return extendedFile{
startBlock: 0,
blocksStart: 0,
fragmentBlockIndex: 0,
fileSize: 7,
fragmentOffset: 0,
@@ -95,7 +95,7 @@ var (

// this is for /foo/filename_0
testBasicFile = &basicFile{
startBlock: 0,
blocksStart: 0,
fragmentBlockIndex: 0,
fileSize: 0xb,
fragmentOffset: 0xc,
@@ -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,
@@ -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,
2 changes: 1 addition & 1 deletion filesystem/squashfs/file.go
Original file line number Diff line number Diff line change
@@ -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
26 changes: 15 additions & 11 deletions filesystem/squashfs/finalize.go
Original file line number Diff line number Diff line change
@@ -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
@@ -588,6 +588,7 @@ func writeDataBlocks(fileList []*finalizeFileInfo, f backend.WritableFile, ws st
}
allBlocks += blocks
allWritten += written
location += int64(written)
}
return allWritten, nil
}
@@ -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{
@@ -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
@@ -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
18 changes: 9 additions & 9 deletions filesystem/squashfs/inode.go
Original file line number Diff line number Diff line change
@@ -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
@@ -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)
@@ -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,
@@ -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,
@@ -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
@@ -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 &&
@@ -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)
@@ -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]),
4 changes: 2 additions & 2 deletions filesystem/squashfs/inode_internal_test.go
Original file line number Diff line number Diff line change
@@ -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)