From 54ba669b644f13c158fcbbde76943543eaf66e0a Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Tue, 12 Jul 2022 16:24:30 -0600 Subject: lib/btrfs: Fuzz the Node parser --- lib/binstruct/structs.go | 5 ++++ ...775199a43e0f9fd5c94bba343ce7bb6724d4ebafe311ed4 | 2 ++ ...7603487337411d9557684e849ee9457d40f8f3e5f5b2fca | 2 ++ ...ca8fa512ea6df2f483f3ffce6be73cee08059ca0bd7e8b5 | 2 ++ ...f342aeda2fd101ca74ccf3bda0faae115ac338d47f195e9 | 2 ++ lib/btrfs/types_node.go | 8 +++++ lib/btrfs/types_node_test.go | 35 ++++++++++++++++++++++ 7 files changed, 56 insertions(+) create mode 100644 lib/btrfs/testdata/fuzz/FuzzRoundTripNode/582528ddfad69eb57775199a43e0f9fd5c94bba343ce7bb6724d4ebafe311ed4 create mode 100644 lib/btrfs/testdata/fuzz/FuzzRoundTripNode/8260b6cf3bc57fc7d7603487337411d9557684e849ee9457d40f8f3e5f5b2fca create mode 100644 lib/btrfs/testdata/fuzz/FuzzRoundTripNode/9863f0d39958aa548ca8fa512ea6df2f483f3ffce6be73cee08059ca0bd7e8b5 create mode 100644 lib/btrfs/testdata/fuzz/FuzzRoundTripNode/e748e617b5b662a80f342aeda2fd101ca74ccf3bda0faae115ac338d47f195e9 create mode 100644 lib/btrfs/types_node_test.go (limited to 'lib') diff --git a/lib/binstruct/structs.go b/lib/binstruct/structs.go index 72fd5e5..9bc556c 100644 --- a/lib/binstruct/structs.go +++ b/lib/binstruct/structs.go @@ -9,6 +9,8 @@ import ( "reflect" "strconv" "strings" + + "git.lukeshu.com/btrfs-progs-ng/lib/binstruct/binutil" ) type End struct{} @@ -70,6 +72,9 @@ type structField struct { } func (sh structHandler) Unmarshal(dat []byte, dst reflect.Value) (int, error) { + if err := binutil.NeedNBytes(dat, sh.Size); err != nil { + return 0, fmt.Errorf("struct %q %w", sh.name, err) + } var n int for i, field := range sh.fields { if field.skip { diff --git a/lib/btrfs/testdata/fuzz/FuzzRoundTripNode/582528ddfad69eb57775199a43e0f9fd5c94bba343ce7bb6724d4ebafe311ed4 b/lib/btrfs/testdata/fuzz/FuzzRoundTripNode/582528ddfad69eb57775199a43e0f9fd5c94bba343ce7bb6724d4ebafe311ed4 new file mode 100644 index 0000000..a96f559 --- /dev/null +++ b/lib/btrfs/testdata/fuzz/FuzzRoundTripNode/582528ddfad69eb57775199a43e0f9fd5c94bba343ce7bb6724d4ebafe311ed4 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("0") diff --git a/lib/btrfs/testdata/fuzz/FuzzRoundTripNode/8260b6cf3bc57fc7d7603487337411d9557684e849ee9457d40f8f3e5f5b2fca b/lib/btrfs/testdata/fuzz/FuzzRoundTripNode/8260b6cf3bc57fc7d7603487337411d9557684e849ee9457d40f8f3e5f5b2fca new file mode 100644 index 0000000..d5c153f --- /dev/null +++ b/lib/btrfs/testdata/fuzz/FuzzRoundTripNode/8260b6cf3bc57fc7d7603487337411d9557684e849ee9457d40f8f3e5f5b2fca @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\x00\x00\x00\x000") diff --git a/lib/btrfs/testdata/fuzz/FuzzRoundTripNode/9863f0d39958aa548ca8fa512ea6df2f483f3ffce6be73cee08059ca0bd7e8b5 b/lib/btrfs/testdata/fuzz/FuzzRoundTripNode/9863f0d39958aa548ca8fa512ea6df2f483f3ffce6be73cee08059ca0bd7e8b5 new file mode 100644 index 0000000..6a2309e --- /dev/null +++ b/lib/btrfs/testdata/fuzz/FuzzRoundTripNode/9863f0d39958aa548ca8fa512ea6df2f483f3ffce6be73cee08059ca0bd7e8b5 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("00000000000000000000000000000000000000000000000000000000") diff --git a/lib/btrfs/testdata/fuzz/FuzzRoundTripNode/e748e617b5b662a80f342aeda2fd101ca74ccf3bda0faae115ac338d47f195e9 b/lib/btrfs/testdata/fuzz/FuzzRoundTripNode/e748e617b5b662a80f342aeda2fd101ca74ccf3bda0faae115ac338d47f195e9 new file mode 100644 index 0000000..50b960e --- /dev/null +++ b/lib/btrfs/testdata/fuzz/FuzzRoundTripNode/e748e617b5b662a80f342aeda2fd101ca74ccf3bda0faae115ac338d47f195e9 @@ -0,0 +1,2 @@ +go test fuzz v1 +[]byte("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") diff --git a/lib/btrfs/types_node.go b/lib/btrfs/types_node.go index 9f20ea9..f425460 100644 --- a/lib/btrfs/types_node.go +++ b/lib/btrfs/types_node.go @@ -128,9 +128,17 @@ func (node *Node) UnmarshalBinary(nodeBuf []byte) (int, error) { Size: uint32(len(nodeBuf)), ChecksumType: node.ChecksumType, } + if len(nodeBuf) <= binstruct.StaticSize(NodeHeader{}) { + return 0, fmt.Errorf("size must be greater than %v, but is %v", + binstruct.StaticSize(NodeHeader{}), + len(nodeBuf)) + } n, err := binstruct.Unmarshal(nodeBuf, &node.Head) if err != nil { return n, err + } else if n != binstruct.StaticSize(NodeHeader{}) { + return n, fmt.Errorf("header consumed %v bytes but expected %v", + n, binstruct.StaticSize(NodeHeader{})) } if node.Head.Level > 0 { _n, err := node.unmarshalInternal(nodeBuf[n:]) diff --git a/lib/btrfs/types_node_test.go b/lib/btrfs/types_node_test.go new file mode 100644 index 0000000..2748c38 --- /dev/null +++ b/lib/btrfs/types_node_test.go @@ -0,0 +1,35 @@ +// Copyright (C) 2022 Luke Shumaker +// +// SPDX-License-Identifier: GPL-2.0-or-later + +package btrfs_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "git.lukeshu.com/btrfs-progs-ng/lib/binstruct" + "git.lukeshu.com/btrfs-progs-ng/lib/btrfs" + "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfssum" +) + +func FuzzRoundTripNode(f *testing.F) { + f.Fuzz(func(t *testing.T, inDat []byte) { + t.Logf("dat=(%d)%q", len(inDat), inDat) + node := btrfs.Node{ + ChecksumType: btrfssum.TYPE_CRC32, + } + n, err := binstruct.Unmarshal(inDat, &node) + if err != nil { + t.Logf("err=%v", err) + //require.Equal(t, 0, n) + } else { + require.Equal(t, len(inDat), n) + + outDat, err := binstruct.Marshal(node) + require.NoError(t, err) + require.Equal(t, inDat[:], outDat) + } + }) +} -- cgit v1.2.3-2-g168b