From ad9ac6d07ce1819260c2b7f090fd4fe742c80d9f Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Sun, 10 Jul 2022 23:49:07 -0600 Subject: Fuzz btrfsitem, and by consequence improve binstruct errors --- lib/btrfs/btrfsitem/item_dir.go | 50 ++++++++++++++--------------------------- 1 file changed, 17 insertions(+), 33 deletions(-) (limited to 'lib/btrfs/btrfsitem/item_dir.go') diff --git a/lib/btrfs/btrfsitem/item_dir.go b/lib/btrfs/btrfsitem/item_dir.go index 859cd14..2fb2d41 100644 --- a/lib/btrfs/btrfsitem/item_dir.go +++ b/lib/btrfs/btrfsitem/item_dir.go @@ -9,47 +9,21 @@ import ( "hash/crc32" "git.lukeshu.com/btrfs-progs-ng/lib/binstruct" + "git.lukeshu.com/btrfs-progs-ng/lib/binstruct/binutil" "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/internal" ) -// key.objectid = inode of directory containing this entry -// key.offset = -// for DIR_ITEM and XATTR_ITEM = NameHash(name) -// for DIR_INDEX = index id in the directory (starting at 2, because "." and "..") -type DirEntries []DirEntry // DIR_ITEM=84 DIR_INDEX=96 XATTR_ITEM=24 +const MaxNameLen = 255 func NameHash(dat []byte) uint64 { return uint64(^crc32.Update(1, crc32.MakeTable(crc32.Castagnoli), dat)) } -func (o *DirEntries) UnmarshalBinary(dat []byte) (int, error) { - *o = nil - n := 0 - for n < len(dat) { - var ref DirEntry - _n, err := binstruct.Unmarshal(dat, &ref) - n += _n - if err != nil { - return n, err - } - *o = append(*o, ref) - } - return n, nil -} - -func (o DirEntries) MarshalBinary() ([]byte, error) { - var ret []byte - for _, ref := range o { - bs, err := binstruct.Marshal(ref) - ret = append(ret, bs...) - if err != nil { - return ret, err - } - } - return ret, nil -} - -type DirEntry struct { +// key.objectid = inode of directory containing this entry +// key.offset = +// for DIR_ITEM and XATTR_ITEM = NameHash(name) +// for DIR_INDEX = index id in the directory (starting at 2, because "." and "..") +type DirEntry struct { // DIR_ITEM=84 DIR_INDEX=96 XATTR_ITEM=24 Location internal.Key `bin:"off=0x0, siz=0x11"` TransID int64 `bin:"off=0x11, siz=8"` DataLen uint16 `bin:"off=0x19, siz=2"` // [ignored-when-writing] @@ -61,10 +35,20 @@ type DirEntry struct { } func (o *DirEntry) UnmarshalBinary(dat []byte) (int, error) { + if err := binutil.NeedNBytes(dat, 0x1e); err != nil { + return 0, err + } n, err := binstruct.UnmarshalWithoutInterface(dat, o) if err != nil { return n, err } + if o.NameLen > MaxNameLen { + return 0, fmt.Errorf("maximum name len is %v, but .NameLen=%v", + MaxNameLen, o.NameLen) + } + if err := binutil.NeedNBytes(dat, 0x1e+int(o.DataLen)+int(o.NameLen)); err != nil { + return 0, err + } o.Data = dat[n : n+int(o.DataLen)] n += int(o.DataLen) o.Name = dat[n : n+int(o.NameLen)] -- cgit v1.2.3-2-g168b