mirror of
https://github.com/golang/go
synced 2024-11-12 06:40:22 -07:00
crypto/sha1: fix AVX2 variant on AMD64
AVX2 variant reads next blocks while calculating current block. Avoid reading past the end of data, by switching back to original, for last blocks. Fixes #15617. Change-Id: I04fa2d83f1b47995117c77b4a3d403a7dff594d4 Reviewed-on: https://go-review.googlesource.com/23138 Reviewed-by: Keith Randall <khr@golang.org> Run-TryBot: Ilya Tocar <ilya.tocar@intel.com> TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
parent
8a1dc32447
commit
805eaeef33
28
src/crypto/sha1/issue15617_test.go
Normal file
28
src/crypto/sha1/issue15617_test.go
Normal file
@ -0,0 +1,28 @@
|
||||
// +build amd64
|
||||
// +build linux darwin
|
||||
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package sha1_test
|
||||
|
||||
import (
|
||||
"crypto/sha1"
|
||||
"syscall"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestOutOfBoundsRead(t *testing.T) {
|
||||
const pageSize = 4 << 10
|
||||
data, err := syscall.Mmap(0, 0, 2*pageSize, syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_ANON|syscall.MAP_PRIVATE)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err := syscall.Mprotect(data[pageSize:], syscall.PROT_NONE); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
for i := 0; i < pageSize; i++ {
|
||||
sha1.Sum(data[pageSize-i : pageSize])
|
||||
}
|
||||
}
|
@ -94,13 +94,15 @@ func TestBlockSize(t *testing.T) {
|
||||
|
||||
// Tests that blockGeneric (pure Go) and block (in assembly for some architectures) match.
|
||||
func TestBlockGeneric(t *testing.T) {
|
||||
gen, asm := New().(*digest), New().(*digest)
|
||||
buf := make([]byte, BlockSize*20) // arbitrary factor
|
||||
rand.Read(buf)
|
||||
blockGeneric(gen, buf)
|
||||
block(asm, buf)
|
||||
if *gen != *asm {
|
||||
t.Error("block and blockGeneric resulted in different states")
|
||||
for i := 1; i < 30; i++ { // arbitrary factor
|
||||
gen, asm := New().(*digest), New().(*digest)
|
||||
buf := make([]byte, BlockSize*i)
|
||||
rand.Read(buf)
|
||||
blockGeneric(gen, buf)
|
||||
block(asm, buf)
|
||||
if *gen != *asm {
|
||||
t.Errorf("For %#v block and blockGeneric resulted in different states", buf)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,13 +12,22 @@ func blockAVX2(dig *digest, p []byte)
|
||||
func blockAMD64(dig *digest, p []byte)
|
||||
func checkAVX2() bool
|
||||
|
||||
// TODO(TocarIP): fix AVX2 crash (golang.org/issue/15617) and
|
||||
// then re-enable this:
|
||||
var hasAVX2 = false // checkAVX2()
|
||||
var hasAVX2 = checkAVX2()
|
||||
|
||||
func block(dig *digest, p []byte) {
|
||||
if hasAVX2 && len(p) >= 256 {
|
||||
blockAVX2(dig, p)
|
||||
// blockAVX2 calculates sha1 for 2 block per iteration
|
||||
// it also interleaves precalculation for next block.
|
||||
// So it may read up-to 192 bytes past end of p
|
||||
// We may add checks inside blockAVX2, but this will
|
||||
// just turn it into a copy of blockAMD64,
|
||||
// so call it directly, instead.
|
||||
safeLen := len(p) - 128
|
||||
if safeLen%128 != 0 {
|
||||
safeLen -= 64
|
||||
}
|
||||
blockAVX2(dig, p[:safeLen])
|
||||
blockAMD64(dig, p[safeLen:])
|
||||
} else {
|
||||
blockAMD64(dig, p)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user