diff --git a/prover/circuits/pi-interconnection/keccak/prover/maths/common/vector/vector.go b/prover/circuits/pi-interconnection/keccak/prover/maths/common/vector/vector.go index 4e96d19f511..458b3b9aef8 100644 --- a/prover/circuits/pi-interconnection/keccak/prover/maths/common/vector/vector.go +++ b/prover/circuits/pi-interconnection/keccak/prover/maths/common/vector/vector.go @@ -36,6 +36,15 @@ func ScalarMul(res, vec []field.Element, scalar field.Element) { func ScalarProd(a, b []field.Element) field.Element { // The length checks is done by gnark-crypto already a_ := fr.Vector(a) + // Workaround for gnark-crypto AVX-512 innerProdVec overread: + // The assembly reads 4 bytes past the last element of the receiver via + // VPMULUDQ.BCST at offset 28 (8-byte load from byte 28 of a 32-byte element). + // When the allocation is page-aligned this causes SIGSEGV. Ensure extra capacity. + if len(a) > 0 && cap(a) == len(a) { + padded := make(fr.Vector, len(a)+1) + copy(padded, a_) + a_ = padded[:len(a)] + } res := a_.InnerProduct(fr.Vector(b)) return res } diff --git a/prover/circuits/pi-interconnection/keccak/prover/maths/field/gen.go b/prover/circuits/pi-interconnection/keccak/prover/maths/field/gen.go index ac4983dce1f..a1a1294a589 100644 --- a/prover/circuits/pi-interconnection/keccak/prover/maths/field/gen.go +++ b/prover/circuits/pi-interconnection/keccak/prover/maths/field/gen.go @@ -16,7 +16,9 @@ func ParBatchInvert(a []Element, numCPU int) []Element { numCPU = runtime.NumCPU() } - res := make([]Element, len(a)) + // Allocate with +1 capacity to prevent gnark-crypto AVX-512 innerProdVec + // overread when the result is subsequently used in InnerProduct. + res := make([]Element, len(a), len(a)+1) parallel.Execute(len(a), func(start, stop int) { subRes := BatchInvert(a[start:stop])