Skip to content

Commit 6104ab6

Browse files
tests/fuzzers/bls1381: add bls fuzzer (ethereum#21796)
* added bls fuzzer * crypto/bls12381: revert bls-changes, fixup fuzzer tests * fuzzers: split bls fuzzing into 8 different units * fuzzers/bls: remove (now stale) corpus * crypto/bls12381: added blsfuzz corpus * fuzzers/bls12381: fix the bls corpus * fuzzers: fix oss-fuzz script * tests/fuzzers: fixups on bls corpus * test/fuzzers: remove leftover corpus Co-authored-by: Marius van der Wijden <m.vanderwijden@live.de>
1 parent bddf5aa commit 6104ab6

12 files changed

+128
-1
lines changed

crypto/bls12381/fp_test.go

+9
Original file line numberDiff line numberDiff line change
@@ -1393,6 +1393,15 @@ func BenchmarkMultiplication(t *testing.B) {
13931393
}
13941394
}
13951395

1396+
func BenchmarkInverse(t *testing.B) {
1397+
a, _ := new(fe).rand(rand.Reader)
1398+
b, _ := new(fe).rand(rand.Reader)
1399+
t.ResetTimer()
1400+
for i := 0; i < t.N; i++ {
1401+
inverse(a, b)
1402+
}
1403+
}
1404+
13961405
func padBytes(in []byte, size int) []byte {
13971406
out := make([]byte, size)
13981407
if len(in) > size {

oss-fuzz.sh

+18-1
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,20 @@ function compile_fuzzer {
3030
path=$SRC/go-ethereum/$1
3131
func=$2
3232
fuzzer=$3
33-
echo "Building $fuzzer"
33+
corpusfile="${path}/testdata/${fuzzer}_seed_corpus.zip"
34+
echo "Building $fuzzer (expecting corpus at $corpusfile)"
3435
(cd $path && \
3536
go-fuzz -func $func -o $WORK/$fuzzer.a . && \
3637
echo "First stage built OK" && \
3738
$CXX $CXXFLAGS $LIB_FUZZING_ENGINE $WORK/$fuzzer.a -o $OUT/$fuzzer && \
3839
echo "Second stage built ok" )
3940

41+
## Check if there exists a seed corpus file
42+
if [ -f $corpusfile ]
43+
then
44+
cp $corpusfile $OUT/
45+
echo "Found seed corpus: $corpusfile"
46+
fi
4047
}
4148

4249
compile_fuzzer common/bitutil Fuzz fuzzBitutilCompress
@@ -51,6 +58,16 @@ compile_fuzzer tests/fuzzers/rlp Fuzz fuzzRlp
5158
compile_fuzzer tests/fuzzers/trie Fuzz fuzzTrie
5259
compile_fuzzer tests/fuzzers/stacktrie Fuzz fuzzStackTrie
5360

61+
compile_fuzzer tests/fuzzers/bls12381 FuzzG1Add fuzz_g1_add
62+
compile_fuzzer tests/fuzzers/bls12381 FuzzG1Mul fuzz_g1_mul
63+
compile_fuzzer tests/fuzzers/bls12381 FuzzG1MultiExp fuzz_g1_multiexp
64+
compile_fuzzer tests/fuzzers/bls12381 FuzzG2Add fuzz_g2_add
65+
compile_fuzzer tests/fuzzers/bls12381 FuzzG2Mul fuzz_g2_mul
66+
compile_fuzzer tests/fuzzers/bls12381 FuzzG2MultiExp fuzz_g2_multiexp
67+
compile_fuzzer tests/fuzzers/bls12381 FuzzPairing fuzz_pairing
68+
compile_fuzzer tests/fuzzers/bls12381 FuzzMapG1 fuzz_map_g1
69+
compile_fuzzer tests/fuzzers/bls12381 FuzzMapG2 fuzz_map_g2
70+
5471
# This doesn't work very well @TODO
5572
#compile_fuzzertests/fuzzers/abi Fuzz fuzzAbi
5673

tests/fuzzers/bls12381/bls_fuzzer.go

+101
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
// Copyright 2020 The go-ethereum Authors
2+
// This file is part of the go-ethereum library.
3+
//
4+
// The go-ethereum library is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU Lesser General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
//
9+
// The go-ethereum library is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU Lesser General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU Lesser General Public License
15+
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
16+
17+
package bls
18+
19+
import (
20+
"bytes"
21+
"fmt"
22+
23+
"github.com/ethereum/go-ethereum/common"
24+
"github.com/ethereum/go-ethereum/core/vm"
25+
)
26+
27+
const (
28+
blsG1Add = byte(10)
29+
blsG1Mul = byte(11)
30+
blsG1MultiExp = byte(12)
31+
blsG2Add = byte(13)
32+
blsG2Mul = byte(14)
33+
blsG2MultiExp = byte(15)
34+
blsPairing = byte(16)
35+
blsMapG1 = byte(17)
36+
blsMapG2 = byte(18)
37+
)
38+
39+
func FuzzG1Add(data []byte) int { return fuzz(blsG1Add, data) }
40+
func FuzzG1Mul(data []byte) int { return fuzz(blsG1Mul, data) }
41+
func FuzzG1MultiExp(data []byte) int { return fuzz(blsG1MultiExp, data) }
42+
func FuzzG2Add(data []byte) int { return fuzz(blsG2Add, data) }
43+
func FuzzG2Mul(data []byte) int { return fuzz(blsG2Mul, data) }
44+
func FuzzG2MultiExp(data []byte) int { return fuzz(blsG2MultiExp, data) }
45+
func FuzzPairing(data []byte) int { return fuzz(blsPairing, data) }
46+
func FuzzMapG1(data []byte) int { return fuzz(blsMapG1, data) }
47+
func FuzzMapG2(data []byte) int { return fuzz(blsMapG2, data) }
48+
49+
func checkInput(id byte, inputLen int) bool {
50+
switch id {
51+
case blsG1Add:
52+
return inputLen == 256
53+
case blsG1Mul:
54+
return inputLen == 160
55+
case blsG1MultiExp:
56+
return inputLen%160 == 0
57+
case blsG2Add:
58+
return inputLen == 512
59+
case blsG2Mul:
60+
return inputLen == 288
61+
case blsG2MultiExp:
62+
return inputLen%288 == 0
63+
case blsPairing:
64+
return inputLen%384 == 0
65+
case blsMapG1:
66+
return inputLen == 64
67+
case blsMapG2:
68+
return inputLen == 128
69+
}
70+
panic("programmer error")
71+
}
72+
73+
// The fuzzer functions must return
74+
// 1 if the fuzzer should increase priority of the
75+
// given input during subsequent fuzzing (for example, the input is lexically
76+
// correct and was parsed successfully);
77+
// -1 if the input must not be added to corpus even if gives new coverage; and
78+
// 0 otherwise
79+
// other values are reserved for future use.
80+
func fuzz(id byte, data []byte) int {
81+
// Even on bad input, it should not crash, so we still test the gas calc
82+
precompile := vm.PrecompiledContractsYoloV2[common.BytesToAddress([]byte{id})]
83+
gas := precompile.RequiredGas(data)
84+
if !checkInput(id, len(data)) {
85+
return 0
86+
}
87+
// If the gas cost is too large (25M), bail out
88+
if gas > 25*1000*1000 {
89+
return 0
90+
}
91+
cpy := make([]byte, len(data))
92+
copy(cpy, data)
93+
_, err := precompile.Run(cpy)
94+
if !bytes.Equal(cpy, data) {
95+
panic(fmt.Sprintf("input data modified, precompile %d: %x %x", id, data, cpy))
96+
}
97+
if err != nil {
98+
return 0
99+
}
100+
return 1
101+
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

0 commit comments

Comments
 (0)