summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@lukeshu.com>2023-05-06 21:22:31 -0600
committerLuke Shumaker <lukeshu@lukeshu.com>2023-05-06 21:22:31 -0600
commit140966a9dde8fbd804dd2596da49920e24470d22 (patch)
tree5addaf7a63ad310584514790bcdd9f87f111a2d7
parenteffd6957051b0bdb685cbe5eb1e876d50a54ad39 (diff)
btrfstree: Fix an issue with .Padding pointing to a buffer it doesn't own
-rw-r--r--lib/btrfs/btrfstree/types_node.go51
1 files changed, 27 insertions, 24 deletions
diff --git a/lib/btrfs/btrfstree/types_node.go b/lib/btrfs/btrfstree/types_node.go
index e29431f..a90ac86 100644
--- a/lib/btrfs/btrfstree/types_node.go
+++ b/lib/btrfs/btrfstree/types_node.go
@@ -267,7 +267,8 @@ func (node *Node) unmarshalInterior(bodyBuf []byte) (int, error) {
return n, fmt.Errorf("item %v: %w", i, err)
}
}
- node.Padding = bodyBuf[n:]
+ node.Padding = bytePool.Get(len(bodyBuf[n:]))
+ copy(node.Padding, bodyBuf[n:])
return len(bodyBuf), nil
}
@@ -306,23 +307,6 @@ type ItemHeader struct {
binstruct.End `bin:"off=0x19"`
}
-var itemPool containers.SlicePool[Item]
-
-// RawFree is for low-level use by caches; don't use .RawFree, use
-// ReleaseNode.
-func (node *Node) RawFree() {
- if node == nil {
- return
- }
- for i := range node.BodyLeaf {
- node.BodyLeaf[i].Body.Free()
- node.BodyLeaf[i] = Item{}
- }
- itemPool.Put(node.BodyLeaf)
- *node = Node{}
- nodePool.Put(node)
-}
-
func (node *Node) unmarshalLeaf(bodyBuf []byte) (int, error) {
head := 0
tail := len(bodyBuf)
@@ -360,7 +344,8 @@ func (node *Node) unmarshalLeaf(bodyBuf []byte) (int, error) {
}
}
- node.Padding = bodyBuf[head:tail]
+ node.Padding = bytePool.Get(len(bodyBuf[head:tail]))
+ copy(node.Padding, bodyBuf[head:tail])
return len(bodyBuf), nil
}
@@ -434,12 +419,30 @@ type IOError struct {
func (e *IOError) Error() string { return "i/o error: " + e.Err.Error() }
func (e *IOError) Unwrap() error { return e.Err }
-var bytePool containers.SlicePool[byte]
+var (
+ bytePool containers.SlicePool[byte]
+ itemPool containers.SlicePool[Item]
+ nodePool = typedsync.Pool[*Node]{
+ New: func() *Node {
+ return new(Node)
+ },
+ }
+)
-var nodePool = typedsync.Pool[*Node]{
- New: func() *Node {
- return new(Node)
- },
+// RawFree is for low-level use by caches; don't use .RawFree, use
+// ReleaseNode.
+func (node *Node) RawFree() {
+ if node == nil {
+ return
+ }
+ for i := range node.BodyLeaf {
+ node.BodyLeaf[i].Body.Free()
+ node.BodyLeaf[i] = Item{}
+ }
+ itemPool.Put(node.BodyLeaf)
+ bytePool.Put(node.Padding)
+ *node = Node{}
+ nodePool.Put(node)
}
// ReadNode reads a node from the given file.