From 1c3c6b538214ea57193af01eac29c76a5ad53a10 Mon Sep 17 00:00:00 2001 From: Joe Tsai Date: Wed, 10 Aug 2022 17:31:44 -0700 Subject: [PATCH] util/sha256x: make Hash.Sum non-escaping (#5338) Since Hash is a concrete type, we can make it such that Sum never escapes the input. Signed-off-by: Joe Tsai --- util/sha256x/sha256.go | 11 ++++++++++- util/sha256x/sha256_test.go | 11 +++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/util/sha256x/sha256.go b/util/sha256x/sha256.go index 212e1a557..50cffb574 100644 --- a/util/sha256x/sha256.go +++ b/util/sha256x/sha256.go @@ -45,10 +45,19 @@ func (h *Hash) Sum(b []byte) []byte { h.h.Write(h.x[:h.nx]) h.nx = 0 } - return h.h.Sum(b) + + // Unfortunately hash.Hash.Sum always causes the input to escape since + // escape analysis cannot prove anything past an interface method call. + // Assuming h already escapes, we call Sum with h.x first, + // and then the copy the result to b. + sum := h.h.Sum(h.x[:0]) + return append(b, sum...) } func (h *Hash) Reset() { + if h.h == nil { + h.h = sha256.New() + } h.h.Reset() h.nx = 0 } diff --git a/util/sha256x/sha256_test.go b/util/sha256x/sha256_test.go index 226ca8281..f9f631fbc 100644 --- a/util/sha256x/sha256_test.go +++ b/util/sha256x/sha256_test.go @@ -64,6 +64,7 @@ func hashSuite(h hasher) { h.HashBytes(bytes[:(i+1)*13]) } } + func Test(t *testing.T) { c := qt.New(t) h1 := New() @@ -73,6 +74,16 @@ func Test(t *testing.T) { c.Assert(h1.Sum(nil), qt.DeepEquals, h2.Sum(nil)) } +func TestSumAllocations(t *testing.T) { + c := qt.New(t) + h := New() + n := testing.AllocsPerRun(100, func() { + var a [sha256.Size]byte + h.Sum(a[:0]) + }) + c.Assert(n, qt.Equals, 0.0) +} + func Fuzz(f *testing.F) { f.Fuzz(func(t *testing.T, seed int64) { c := qt.New(t)