mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-19 21:31:37 +00:00
crypto, tests: update fuzzers to native go fuzzing (#28352)
This commit is contained in:
parent
8f57d6caea
commit
f7b6ad67a7
9 changed files with 315 additions and 147 deletions
|
|
@ -1,59 +0,0 @@
|
|||
// Only enable fuzzer on platforms with AVX enabled
|
||||
//go:build go1.7 && amd64 && !gccgo && !appengine
|
||||
// +build go1.7,amd64,!gccgo,!appengine
|
||||
|
||||
package blake2b
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
)
|
||||
|
||||
func Fuzz(data []byte) int {
|
||||
// Make sure the data confirms to the input model
|
||||
if len(data) != 211 {
|
||||
return 0
|
||||
}
|
||||
// Parse everything and call all the implementations
|
||||
var (
|
||||
rounds = binary.BigEndian.Uint16(data[0:2])
|
||||
|
||||
h [8]uint64
|
||||
m [16]uint64
|
||||
t [2]uint64
|
||||
f uint64
|
||||
)
|
||||
for i := 0; i < 8; i++ {
|
||||
offset := 2 + i*8
|
||||
h[i] = binary.LittleEndian.Uint64(data[offset : offset+8])
|
||||
}
|
||||
for i := 0; i < 16; i++ {
|
||||
offset := 66 + i*8
|
||||
m[i] = binary.LittleEndian.Uint64(data[offset : offset+8])
|
||||
}
|
||||
t[0] = binary.LittleEndian.Uint64(data[194:202])
|
||||
t[1] = binary.LittleEndian.Uint64(data[202:210])
|
||||
|
||||
if data[210]%2 == 1 { // Avoid spinning the fuzzer to hit 0/1
|
||||
f = 0xFFFFFFFFFFFFFFFF
|
||||
}
|
||||
// Run the blake2b compression on all instruction sets and cross reference
|
||||
want := h
|
||||
fGeneric(&want, &m, t[0], t[1], f, uint64(rounds))
|
||||
|
||||
have := h
|
||||
fSSE4(&have, &m, t[0], t[1], f, uint64(rounds))
|
||||
if have != want {
|
||||
panic("SSE4 mismatches generic algo")
|
||||
}
|
||||
have = h
|
||||
fAVX(&have, &m, t[0], t[1], f, uint64(rounds))
|
||||
if have != want {
|
||||
panic("AVX mismatches generic algo")
|
||||
}
|
||||
have = h
|
||||
fAVX2(&have, &m, t[0], t[1], f, uint64(rounds))
|
||||
if have != want {
|
||||
panic("AVX2 mismatches generic algo")
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
package blake2b
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
|
@ -57,3 +58,60 @@ var testVectorsF = []testVector{
|
|||
},
|
||||
},
|
||||
}
|
||||
|
||||
func Fuzz(f *testing.F) {
|
||||
f.Fuzz(func(t *testing.T, data []byte) {
|
||||
fuzz(data)
|
||||
})
|
||||
}
|
||||
|
||||
func fuzz(data []byte) {
|
||||
// Make sure the data confirms to the input model
|
||||
if len(data) != 211 {
|
||||
return
|
||||
}
|
||||
// Parse everything and call all the implementations
|
||||
var (
|
||||
rounds = binary.BigEndian.Uint16(data[0:2])
|
||||
|
||||
h [8]uint64
|
||||
m [16]uint64
|
||||
t [2]uint64
|
||||
f uint64
|
||||
)
|
||||
|
||||
for i := 0; i < 8; i++ {
|
||||
offset := 2 + i*8
|
||||
h[i] = binary.LittleEndian.Uint64(data[offset : offset+8])
|
||||
}
|
||||
for i := 0; i < 16; i++ {
|
||||
offset := 66 + i*8
|
||||
m[i] = binary.LittleEndian.Uint64(data[offset : offset+8])
|
||||
}
|
||||
t[0] = binary.LittleEndian.Uint64(data[194:202])
|
||||
t[1] = binary.LittleEndian.Uint64(data[202:210])
|
||||
|
||||
if data[210]%2 == 1 { // Avoid spinning the fuzzer to hit 0/1
|
||||
f = 0xFFFFFFFFFFFFFFFF
|
||||
}
|
||||
|
||||
// Run the blake2b compression on all instruction sets and cross reference
|
||||
want := h
|
||||
fGeneric(&want, &m, t[0], t[1], f, uint64(rounds))
|
||||
|
||||
have := h
|
||||
fSSE4(&have, &m, t[0], t[1], f, uint64(rounds))
|
||||
if have != want {
|
||||
panic("SSE4 mismatches generic algo")
|
||||
}
|
||||
have = h
|
||||
fAVX(&have, &m, t[0], t[1], f, uint64(rounds))
|
||||
if have != want {
|
||||
panic("AVX mismatches generic algo")
|
||||
}
|
||||
have = h
|
||||
fAVX2(&have, &m, t[0], t[1], f, uint64(rounds))
|
||||
if have != want {
|
||||
panic("AVX2 mismatches generic algo")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2017 The go-ethereum Authors
|
||||
// Copyright 2023 The go-ethereum Authors
|
||||
// This file is part of the go-ethereum library.
|
||||
//
|
||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||
|
|
@ -18,41 +18,51 @@ package bitutil
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain/common/bitutil"
|
||||
)
|
||||
|
||||
// Fuzz implements a go-fuzz fuzzer method to test various encoding method
|
||||
// invocations.
|
||||
func Fuzz(data []byte) int {
|
||||
if len(data) == 0 {
|
||||
return 0
|
||||
}
|
||||
if data[0]%2 == 0 {
|
||||
return fuzzEncode(data[1:])
|
||||
}
|
||||
return fuzzDecode(data[1:])
|
||||
func FuzzEncoder(f *testing.F) {
|
||||
f.Fuzz(func(t *testing.T, data []byte) {
|
||||
fuzzEncode(data)
|
||||
})
|
||||
}
|
||||
func FuzzDecoder(f *testing.F) {
|
||||
f.Fuzz(func(t *testing.T, data []byte) {
|
||||
fuzzDecode(data)
|
||||
})
|
||||
}
|
||||
|
||||
// fuzzEncode implements a go-fuzz fuzzer method to test the bitset encoding and
|
||||
// decoding algorithm.
|
||||
func fuzzEncode(data []byte) int {
|
||||
func fuzzEncode(data []byte) {
|
||||
proc, _ := bitutil.DecompressBytes(bitutil.CompressBytes(data), len(data))
|
||||
if !bytes.Equal(data, proc) {
|
||||
panic("content mismatch")
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
||||
// fuzzDecode implements a go-fuzz fuzzer method to test the bit decoding and
|
||||
// reencoding algorithm.
|
||||
func fuzzDecode(data []byte) int {
|
||||
func fuzzDecode(data []byte) {
|
||||
blob, err := bitutil.DecompressBytes(data, 1024)
|
||||
if err != nil {
|
||||
return 0
|
||||
return
|
||||
}
|
||||
if comp := bitutil.CompressBytes(blob); !bytes.Equal(comp, data) {
|
||||
// re-compress it (it's OK if the re-compressed differs from the
|
||||
// original - the first input may not have been compressed at all)
|
||||
comp := bitutil.CompressBytes(blob)
|
||||
if len(comp) > len(blob) {
|
||||
// After compression, it must be smaller or equal
|
||||
panic("bad compression")
|
||||
}
|
||||
// But decompressing it once again should work
|
||||
decomp, err := bitutil.DecompressBytes(data, 1024)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if !bytes.Equal(decomp, blob) {
|
||||
panic("content mismatch")
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
|
@ -61,8 +61,8 @@ func getG2Points(input io.Reader) (*cloudflare.G2, *google.G2, *bn254.G2Affine)
|
|||
return xc, xg, xs
|
||||
}
|
||||
|
||||
// FuzzAdd fuzzez bn256 addition between the Google and Cloudflare libraries.
|
||||
func FuzzAdd(data []byte) int {
|
||||
// fuzzAdd fuzzez bn256 addition between the Google and Cloudflare libraries.
|
||||
func fuzzAdd(data []byte) int {
|
||||
input := bytes.NewReader(data)
|
||||
xc, xg, xs := getG1Points(input)
|
||||
if xc == nil {
|
||||
|
|
@ -94,9 +94,9 @@ func FuzzAdd(data []byte) int {
|
|||
return 1
|
||||
}
|
||||
|
||||
// FuzzMul fuzzez bn256 scalar multiplication between the Google and Cloudflare
|
||||
// fuzzMul fuzzez bn256 scalar multiplication between the Google and Cloudflare
|
||||
// libraries.
|
||||
func FuzzMul(data []byte) int {
|
||||
func fuzzMul(data []byte) int {
|
||||
input := bytes.NewReader(data)
|
||||
pc, pg, ps := getG1Points(input)
|
||||
if pc == nil {
|
||||
|
|
@ -136,7 +136,7 @@ func FuzzMul(data []byte) int {
|
|||
return 1
|
||||
}
|
||||
|
||||
func FuzzPair(data []byte) int {
|
||||
func fuzzPair(data []byte) int {
|
||||
input := bytes.NewReader(data)
|
||||
pc, pg, ps := getG1Points(input)
|
||||
if pc == nil {
|
||||
|
|
|
|||
143
tests/fuzzers/rlp/rlp_fuzzer.go
Normal file
143
tests/fuzzers/rlp/rlp_fuzzer.go
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
// Copyright 2019 The go-ethereum Authors
|
||||
// This file is part of the go-ethereum library.
|
||||
//
|
||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package rlp
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||
"github.com/XinFinOrg/XDPoSChain/rlp"
|
||||
"github.com/holiman/uint256"
|
||||
)
|
||||
|
||||
func decodeEncode(input []byte, val interface{}, i int) {
|
||||
if err := rlp.DecodeBytes(input, val); err == nil {
|
||||
output, err := rlp.EncodeToBytes(val)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if !bytes.Equal(input, output) {
|
||||
panic(fmt.Sprintf("case %d: encode-decode is not equal, \ninput : %x\noutput: %x", i, input, output))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func fuzz(input []byte) int {
|
||||
if len(input) == 0 {
|
||||
return 0
|
||||
}
|
||||
if len(input) > 500*1024 {
|
||||
return 0
|
||||
}
|
||||
|
||||
var i int
|
||||
{
|
||||
rlp.Split(input)
|
||||
}
|
||||
{
|
||||
if elems, _, err := rlp.SplitList(input); err == nil {
|
||||
rlp.CountValues(elems)
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
rlp.NewStream(bytes.NewReader(input), 0).Decode(new(interface{}))
|
||||
}
|
||||
|
||||
{
|
||||
decodeEncode(input, new(interface{}), i)
|
||||
i++
|
||||
}
|
||||
{
|
||||
var v struct {
|
||||
Int uint
|
||||
String string
|
||||
Bytes []byte
|
||||
}
|
||||
decodeEncode(input, &v, i)
|
||||
i++
|
||||
}
|
||||
|
||||
{
|
||||
type Types struct {
|
||||
Bool bool
|
||||
Raw rlp.RawValue
|
||||
Slice []*Types
|
||||
Iface []interface{}
|
||||
}
|
||||
var v Types
|
||||
decodeEncode(input, &v, i)
|
||||
i++
|
||||
}
|
||||
{
|
||||
type AllTypes struct {
|
||||
Int uint
|
||||
String string
|
||||
Bytes []byte
|
||||
Bool bool
|
||||
Raw rlp.RawValue
|
||||
Slice []*AllTypes
|
||||
Array [3]*AllTypes
|
||||
Iface []interface{}
|
||||
}
|
||||
var v AllTypes
|
||||
decodeEncode(input, &v, i)
|
||||
i++
|
||||
}
|
||||
{
|
||||
decodeEncode(input, [10]byte{}, i)
|
||||
i++
|
||||
}
|
||||
{
|
||||
var v struct {
|
||||
Byte [10]byte
|
||||
Rool [10]bool
|
||||
}
|
||||
decodeEncode(input, &v, i)
|
||||
i++
|
||||
}
|
||||
{
|
||||
var h types.Header
|
||||
decodeEncode(input, &h, i)
|
||||
i++
|
||||
var b types.Block
|
||||
decodeEncode(input, &b, i)
|
||||
i++
|
||||
var t types.Transaction
|
||||
decodeEncode(input, &t, i)
|
||||
i++
|
||||
var txs types.Transactions
|
||||
decodeEncode(input, &txs, i)
|
||||
i++
|
||||
var rs types.Receipts
|
||||
decodeEncode(input, &rs, i)
|
||||
}
|
||||
{
|
||||
i++
|
||||
var v struct {
|
||||
AnIntPtr *big.Int
|
||||
AnInt big.Int
|
||||
AnU256Ptr *uint256.Int
|
||||
AnU256 uint256.Int
|
||||
NotAnU256 [4]uint64
|
||||
}
|
||||
decodeEncode(input, &v, i)
|
||||
}
|
||||
return 1
|
||||
}
|
||||
25
tests/fuzzers/rlp/rlp_test.go
Normal file
25
tests/fuzzers/rlp/rlp_test.go
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
// Copyright 2023 The go-ethereum Authors
|
||||
// This file is part of the go-ethereum library.
|
||||
//
|
||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package rlp
|
||||
|
||||
import "testing"
|
||||
|
||||
func Fuzz(f *testing.F) {
|
||||
f.Fuzz(func(t *testing.T, data []byte) {
|
||||
fuzz(data)
|
||||
})
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2017 The go-ethereum Authors
|
||||
// Copyright 2023 The go-ethereum Authors
|
||||
// This file is part of the go-ethereum library.
|
||||
//
|
||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||
|
|
@ -17,20 +17,15 @@
|
|||
package runtime
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain/core/vm/runtime"
|
||||
)
|
||||
|
||||
// Fuzz is the basic entry point for the go-fuzz tool
|
||||
//
|
||||
// This returns 1 for valid parsable/runable code, 0
|
||||
// for invalid opcode.
|
||||
func Fuzz(input []byte) int {
|
||||
_, _, err := runtime.Execute(input, input, &runtime.Config{
|
||||
GasLimit: 12000000,
|
||||
func Fuzz(f *testing.F) {
|
||||
f.Fuzz(func(t *testing.T, code, input []byte) {
|
||||
runtime.Execute(code, input, &runtime.Config{
|
||||
GasLimit: 12000000,
|
||||
})
|
||||
})
|
||||
// invalid opcode
|
||||
if err != nil && len(err.Error()) > 6 && err.Error()[:7] == "invalid" {
|
||||
return 0
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
// Copyright 2021 The go-ethereum Authors
|
||||
// This file is part of the go-ethereum library.
|
||||
//
|
||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// build +gofuzz
|
||||
|
||||
package secp256k1
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain/crypto/secp256k1"
|
||||
"github.com/btcsuite/btcd/btcec/v2"
|
||||
fuzz "github.com/google/gofuzz"
|
||||
)
|
||||
|
||||
func Fuzz(input []byte) int {
|
||||
var (
|
||||
fuzzer = fuzz.NewFromGoFuzz(input)
|
||||
curveA = secp256k1.S256()
|
||||
curveB = btcec.S256()
|
||||
dataP1 []byte
|
||||
dataP2 []byte
|
||||
)
|
||||
// first point
|
||||
fuzzer.Fuzz(&dataP1)
|
||||
x1, y1 := curveB.ScalarBaseMult(dataP1)
|
||||
// second point
|
||||
fuzzer.Fuzz(&dataP2)
|
||||
x2, y2 := curveB.ScalarBaseMult(dataP2)
|
||||
resAX, resAY := curveA.Add(x1, y1, x2, y2)
|
||||
resBX, resBY := curveB.Add(x1, y1, x2, y2)
|
||||
if resAX.Cmp(resBX) != 0 || resAY.Cmp(resBY) != 0 {
|
||||
fmt.Printf("%s %s %s %s\n", x1, y1, x2, y2)
|
||||
panic(fmt.Sprintf("Addition failed: geth: %s %s btcd: %s %s", resAX, resAY, resBX, resBY))
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
|
@ -1,8 +1,54 @@
|
|||
// Copyright 2021 The go-ethereum Authors
|
||||
// This file is part of the go-ethereum library.
|
||||
//
|
||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package secp256k1
|
||||
|
||||
import "testing"
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain/crypto/secp256k1"
|
||||
"github.com/btcsuite/btcd/btcec/v2"
|
||||
)
|
||||
|
||||
func TestFuzzer(t *testing.T) {
|
||||
test := "00000000N0000000/R00000000000000000U0000S0000000mkhP000000000000000U"
|
||||
Fuzz([]byte(test))
|
||||
a, b := "00000000N0000000/R0000000000000000", "0U0000S0000000mkhP000000000000000U"
|
||||
fuzz([]byte(a), []byte(b))
|
||||
}
|
||||
|
||||
func Fuzz(f *testing.F) {
|
||||
f.Fuzz(func(t *testing.T, a, b []byte) {
|
||||
fuzz(a, b)
|
||||
})
|
||||
}
|
||||
|
||||
func fuzz(dataP1, dataP2 []byte) int {
|
||||
var (
|
||||
curveA = secp256k1.S256()
|
||||
curveB = btcec.S256()
|
||||
)
|
||||
// first point
|
||||
x1, y1 := curveB.ScalarBaseMult(dataP1)
|
||||
// second points
|
||||
x2, y2 := curveB.ScalarBaseMult(dataP2)
|
||||
resAX, resAY := curveA.Add(x1, y1, x2, y2)
|
||||
resBX, resBY := curveB.Add(x1, y1, x2, y2)
|
||||
if resAX.Cmp(resBX) != 0 || resAY.Cmp(resBY) != 0 {
|
||||
fmt.Printf("%s %s %s %s\n", x1, y1, x2, y2)
|
||||
panic(fmt.Sprintf("Addition failed: geth: %s %s btcd: %s %s", resAX, resAY, resBX, resBY))
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue