Skip to content

Commit 05f792d

Browse files
fix: xattr table index to split position into decompressed and compressed offset (#277)
* fix: xattr table index to split position into decompressed and compressed offset * chore: fix lint for unused return value
1 parent 31082f1 commit 05f792d

File tree

6 files changed

+59
-26
lines changed

6 files changed

+59
-26
lines changed

filesystem/squashfs/const_internal_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -199,12 +199,12 @@ func testGetFilesystem(f fs.File) (*FileSystem, []byte, error) {
199199
return testFs, b, nil
200200
}
201201

202-
func testGetInodeMetabytes() (inodeBytes []byte, inodesStart uint64, err error) {
202+
func testGetInodeMetabytes() (inodeBytes []byte, err error) {
203203
testFs, b, err := testGetFilesystem(nil)
204204
if err != nil {
205-
return nil, 0, err
205+
return nil, err
206206
}
207-
return b[testFs.superblock.inodeTableStart+2:], testFs.superblock.inodeTableStart, nil
207+
return b[testFs.superblock.inodeTableStart+2:], nil
208208
}
209209

210210
//nolint:deadcode // we need these references in the future

filesystem/squashfs/inode_internal_test.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ func TestInodeSize(t *testing.T) {
6969
}
7070

7171
func TestInodeHeader(t *testing.T) {
72-
b, _, err := testGetInodeMetabytes()
72+
b, err := testGetInodeMetabytes()
7373
if err != nil {
7474
t.Fatal(err)
7575
}
@@ -142,7 +142,7 @@ func TestBlockData(t *testing.T) {
142142

143143
func TestBasicDirectory(t *testing.T) {
144144
dir := testBasicDirectory
145-
b, _, err := testGetInodeMetabytes()
145+
b, err := testGetInodeMetabytes()
146146
if err != nil {
147147
t.Fatal(err)
148148
}
@@ -203,7 +203,7 @@ func TestExtendedDirectory(t *testing.T) {
203203

204204
func TestBasicFile(t *testing.T) {
205205
f := testBasicFile
206-
b, _, err := testGetInodeMetabytes()
206+
b, err := testGetInodeMetabytes()
207207
if err != nil {
208208
t.Fatal(err)
209209
}
@@ -279,7 +279,7 @@ func TestBasicFile(t *testing.T) {
279279
func TestExtendedFile(t *testing.T) {
280280
fd := testExtendedFile
281281
f := &fd
282-
b, _, err := testGetInodeMetabytes()
282+
b, err := testGetInodeMetabytes()
283283
if err != nil {
284284
t.Fatal(err)
285285
}
@@ -332,7 +332,7 @@ func TestExtendedFile(t *testing.T) {
332332

333333
func TestBasicSymlink(t *testing.T) {
334334
s := testBasicSymlink
335-
b, _, err := testGetInodeMetabytes()
335+
b, err := testGetInodeMetabytes()
336336
if err != nil {
337337
t.Fatal(err)
338338
}
@@ -430,7 +430,7 @@ func TestExtendedIPC(t *testing.T) {
430430
}
431431

432432
func TestInode(t *testing.T) {
433-
b, _, err := testGetInodeMetabytes()
433+
b, err := testGetInodeMetabytes()
434434
if err != nil {
435435
t.Fatal(err)
436436
}

filesystem/squashfs/squashfs.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -809,30 +809,32 @@ func readXattrsTable(s *superblock, file backend.File, c Compressor) (*xAttrTabl
809809
// now load the actual xAttrs data
810810
xAttrEnd := binary.LittleEndian.Uint64(b[:8])
811811
xAttrData := make([]byte, 0)
812+
offsetMap := map[uint32]uint32{0: 0}
812813
for i := xAttrStart; i < xAttrEnd; {
813814
uncompressed, size, err = fs.readMetaBlock(file, c, int64(i))
814815
if err != nil {
815816
return nil, fmt.Errorf("error reading xattr data meta block at position %d: %v", i, err)
816817
}
817818
xAttrData = append(xAttrData, uncompressed...)
818819
i += uint64(size)
820+
offsetMap[uint32(i-xAttrStart)] = uint32(len(xAttrData))
819821
}
820822

821823
// now have all of the indexes and metadata loaded
822824
// need to pass it the offset of the beginning of the id table from the beginning of the disk
823-
return parseXattrsTable(xAttrData, bIndex, s.idTableStart, c)
825+
return parseXattrsTable(xAttrData, bIndex, offsetMap, c)
824826
}
825827

826-
//nolint:unparam,unused,revive // this does not use offset or compressor yet, but only because we have not yet added support
827-
func parseXattrsTable(bUIDXattr, bIndex []byte, offset uint64, c Compressor) (*xAttrTable, error) {
828+
//nolint:unparam,unused,revive // this does not use compressor yet, but only because we have not yet added support
829+
func parseXattrsTable(bUIDXattr, bIndex []byte, offsetMap map[uint32]uint32, c Compressor) (*xAttrTable, error) {
828830
// create the ID list
829831
var (
830832
xAttrIDList []*xAttrIndex
831833
)
832834

833835
entrySize := int(xAttrIDEntrySize)
834836
for i := 0; i+entrySize <= len(bIndex); i += entrySize {
835-
entry, err := parseXAttrIndex(bIndex[i:])
837+
entry, err := parseXAttrIndex(bIndex[i:], offsetMap)
836838
if err != nil {
837839
return nil, fmt.Errorf("error parsing xAttr ID table entry in position %d: %v", i, err)
838840
}

filesystem/squashfs/squashfs_internal_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ func TestValidateBlocksize(t *testing.T) {
6868

6969
func TestParseXAttrsTable(t *testing.T) {
7070
// parseXattrsTable(bUIDXattr, bIndex []byte, offset uint64, c compressor) (*xAttrTable, error) {
71-
b, offset, err := testGetInodeMetabytes()
71+
b, err := testGetInodeMetabytes()
7272
if err != nil {
7373
t.Fatalf("error getting metadata bytes: %v", err)
7474
}
@@ -81,7 +81,7 @@ func TestParseXAttrsTable(t *testing.T) {
8181

8282
// entries in the xattr ID table are offset from beginning of disk, not from xattr table
8383
// so need offset of bUIDXattr from beginning of disk to make use of it
84-
table, err := parseXattrsTable(bUIDXattr, bIndex, offset+startUID, nil)
84+
table, err := parseXattrsTable(bUIDXattr, bIndex, map[uint32]uint32{0: 0}, nil)
8585
if err != nil {
8686
t.Fatalf("error reading xattrs table: %v", err)
8787
}

filesystem/squashfs/xattr.go

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,23 @@ type xAttrIndex struct {
1818
size uint32
1919
}
2020

21-
func parseXAttrIndex(b []byte) (*xAttrIndex, error) {
21+
func parseXAttrIndex(b []byte, offsetMap map[uint32]uint32) (*xAttrIndex, error) {
2222
if len(b) < int(xAttrIDEntrySize) {
2323
return nil, fmt.Errorf("cannot parse xAttr Index of size %d less than minimum %d", len(b), xAttrIDEntrySize)
2424
}
25-
return &xAttrIndex{
26-
pos: binary.LittleEndian.Uint64(b[0:8]),
25+
26+
offsetKey := binary.LittleEndian.Uint32(b[2:6])
27+
offset, ok := offsetMap[offsetKey]
28+
if !ok {
29+
return nil, fmt.Errorf("cannot parse xAttr Index invalid offset key %d", offsetKey)
30+
}
31+
toReturn := &xAttrIndex{
32+
pos: uint64(binary.LittleEndian.Uint16(b[0:2])) + uint64(offset),
2733
count: binary.LittleEndian.Uint32(b[8:12]),
2834
size: binary.LittleEndian.Uint32(b[12:16]),
29-
}, nil
35+
}
36+
37+
return toReturn, nil
3038
}
3139

3240
type xAttrTable struct {
@@ -39,6 +47,9 @@ func (x *xAttrTable) find(pos int) (map[string]string, error) {
3947
return nil, fmt.Errorf("position %d is greater than list size %d", pos, len(x.list))
4048
}
4149
entry := x.list[pos]
50+
if int(entry.pos) >= len(x.data) {
51+
return nil, fmt.Errorf("entry position %d is greater than list size %d", entry.pos, len(x.data))
52+
}
4253
b := x.data[entry.pos:]
4354
count := entry.count
4455
ptr := 0

filesystem/squashfs/xattr_internal_test.go

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,23 +9,43 @@ import (
99
func TestParseXAttrIndex(t *testing.T) {
1010
tests := []struct {
1111
b []byte
12+
o map[uint32]uint32
1213
x *xAttrIndex
1314
err error
1415
}{
15-
{[]byte{0x0, 0x1}, nil, fmt.Errorf("cannot parse xAttr Index of size %d less than minimum %d", 2, xAttrIDEntrySize)},
16+
{[]byte{0x0, 0x1}, map[uint32]uint32{0: 0}, nil, fmt.Errorf("cannot parse xAttr Index of size %d less than minimum %d", 2, xAttrIDEntrySize)},
1617
{[]byte{
17-
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
18-
0x8, 0x9, 0xa, 0xb,
19-
0xc, 0xd, 0xe, 0xf,
20-
0x10, 0x11, 0x12, 0x13, 0x14},
18+
0x0, 0x1, // position in decompressed
19+
0x2, 0x3, 0x4, 0x5, // offset of compressed data
20+
0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd,
21+
0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14},
22+
map[uint32]uint32{},
23+
nil, fmt.Errorf("cannot parse xAttr Index invalid offset key %d", 84148994)},
24+
{[]byte{
25+
0x0, 0x1, // position in decompressed
26+
0x2, 0x3, 0x4, 0x5, // offset of compressed data
27+
0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd,
28+
0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14},
29+
map[uint32]uint32{84148994: 5},
30+
&xAttrIndex{
31+
pos: 261,
32+
count: 0x0b0a0908,
33+
size: 0x0f0e0d0c,
34+
}, nil},
35+
{[]byte{
36+
0x0, 0x1, // position in decompressed
37+
0x2, 0x0, 0x0, 0x0, // offset of compressed data
38+
0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd,
39+
0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14},
40+
map[uint32]uint32{2: 0},
2141
&xAttrIndex{
22-
pos: 0x0706050403020100,
42+
pos: 256,
2343
count: 0x0b0a0908,
2444
size: 0x0f0e0d0c,
2545
}, nil},
2646
}
2747
for i, tt := range tests {
28-
x, err := parseXAttrIndex(tt.b)
48+
x, err := parseXAttrIndex(tt.b, tt.o)
2949
switch {
3050
case (err == nil && tt.err != nil) || (err != nil && tt.err == nil) || (err != nil && tt.err != nil && !strings.HasPrefix(err.Error(), tt.err.Error())):
3151
t.Errorf("%d: mismatched error, actual then expected", i)

0 commit comments

Comments
 (0)