From 71a59caf31ca42c3deb8967ceee0a4804d220bf4 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 9 Aug 2023 16:28:14 +0300 Subject: [PATCH] bucket: allow to allocate key on stack in Put() As per `go build -gcflags -m ./... 2>&1`: Old behaviour: ``` ./bucket.go:148:31: leaking param: key ./bucket.go:192:42: leaking param: key ./bucket.go:271:22: leaking param: key ``` Now: ``` ./bucket.go:148:31: key does not escape ./bucket.go:192:42: key does not escape ./bucket.go:271:22: key does not escape ``` Signed-off-by: Evgenii Stratonikov --- bucket.go | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/bucket.go b/bucket.go index f8741dcb6..f9f23812f 100644 --- a/bucket.go +++ b/bucket.go @@ -175,15 +175,17 @@ func (b *Bucket) CreateBucket(key []byte) (*Bucket, error) { var value = bucket.write() // Insert into node. - key = cloneBytes(key) - c.node().put(key, key, value, 0, common.BucketLeafFlag) + // Tip: Use a new variable `newKey` instead of reusing the existing `key` to prevent + // it from being marked as leaking, and accordingly cannot be allocated on stack. + newKey := cloneBytes(key) + c.node().put(newKey, newKey, value, 0, common.BucketLeafFlag) // Since subbuckets are not allowed on inline buckets, we need to // dereference the inline page, if it exists. This will cause the bucket // to be treated as a regular, non-inline bucket for the rest of the tx. b.page = nil - return b.Bucket(key), nil + return b.Bucket(newKey), nil } // CreateBucketIfNotExists creates a new bucket if it doesn't already exist and returns a reference to it. @@ -230,15 +232,17 @@ func (b *Bucket) CreateBucketIfNotExists(key []byte) (*Bucket, error) { var value = bucket.write() // Insert into node. - key = cloneBytes(key) - c.node().put(key, key, value, 0, common.BucketLeafFlag) + // Tip: Use a new variable `newKey` instead of reusing the existing `key` to prevent + // it from being marked as leaking, and accordingly cannot be allocated on stack. + newKey := cloneBytes(key) + c.node().put(newKey, newKey, value, 0, common.BucketLeafFlag) // Since subbuckets are not allowed on inline buckets, we need to // dereference the inline page, if it exists. This will cause the bucket // to be treated as a regular, non-inline bucket for the rest of the tx. b.page = nil - return b.Bucket(key), nil + return b.Bucket(newKey), nil } // DeleteBucket deletes a bucket at the given key. @@ -333,8 +337,10 @@ func (b *Bucket) Put(key []byte, value []byte) error { } // Insert into node. - key = cloneBytes(key) - c.node().put(key, key, value, 0, 0) + // Tip: Use a new variable `newKey` instead of reusing the existing `key` to prevent + // it from being marked as leaking, and accordingly cannot be allocated on stack. + newKey := cloneBytes(key) + c.node().put(newKey, newKey, value, 0, 0) return nil }