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)