Skip to content

Commit 43cadcf

Browse files
committed
fuzzers: split bls fuzzing into 8 different units
1 parent 8b4d214 commit 43cadcf

File tree

2 files changed

+71
-26
lines changed

2 files changed

+71
-26
lines changed

oss-fuzz.sh

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,16 @@ compile_fuzzer tests/fuzzers/rlp Fuzz fuzzRlp
5151
compile_fuzzer tests/fuzzers/trie Fuzz fuzzTrie
5252
compile_fuzzer tests/fuzzers/stacktrie Fuzz fuzzStackTrie
5353

54+
compile_fuzzer tests/fuzzers/bls12381 FuzzG1Add fuzzG1Add
55+
compile_fuzzer tests/fuzzers/bls12381 FuzzG1Mul fuzzG1Mul
56+
compile_fuzzer tests/fuzzers/bls12381 FuzzG1MultiExp fuzzG1MultiExp
57+
compile_fuzzer tests/fuzzers/bls12381 FuzzG2Add fuzzG2Add
58+
compile_fuzzer tests/fuzzers/bls12381 FuzzG2Mul fuzzG2Mul
59+
compile_fuzzer tests/fuzzers/bls12381 FuzzG2MultiExp fuzzG2MultiExp
60+
compile_fuzzer tests/fuzzers/bls12381 FuzzPairing fuzzPairing
61+
compile_fuzzer tests/fuzzers/bls12381 FuzzMapG1 fuzzMapG1
62+
compile_fuzzer tests/fuzzers/bls12381 FuzzMapG2 fuzzMapG2
63+
5464
# This doesn't work very well @TODO
5565
#compile_fuzzertests/fuzzers/abi Fuzz fuzzAbi
5666

tests/fuzzers/bls12381/bls_fuzzer.go

Lines changed: 61 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -24,42 +24,77 @@ import (
2424
"github.com/ethereum/go-ethereum/core/vm"
2525
)
2626

27-
// The function must return
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
2874
// 1 if the fuzzer should increase priority of the
2975
// given input during subsequent fuzzing (for example, the input is lexically
3076
// correct and was parsed successfully);
3177
// -1 if the input must not be added to corpus even if gives new coverage; and
3278
// 0 otherwise
3379
// other values are reserved for future use.
34-
func Fuzz(data []byte) int {
35-
36-
// The bls ones are at 10 - 18
37-
var precompiles = []vm.PrecompiledContract{
38-
vm.PrecompiledContractsYoloV2[common.BytesToAddress([]byte{10})],
39-
vm.PrecompiledContractsYoloV2[common.BytesToAddress([]byte{11})],
40-
vm.PrecompiledContractsYoloV2[common.BytesToAddress([]byte{12})],
41-
vm.PrecompiledContractsYoloV2[common.BytesToAddress([]byte{13})],
42-
vm.PrecompiledContractsYoloV2[common.BytesToAddress([]byte{14})],
43-
vm.PrecompiledContractsYoloV2[common.BytesToAddress([]byte{15})],
44-
vm.PrecompiledContractsYoloV2[common.BytesToAddress([]byte{16})],
45-
vm.PrecompiledContractsYoloV2[common.BytesToAddress([]byte{17})],
46-
vm.PrecompiledContractsYoloV2[common.BytesToAddress([]byte{18})],
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
4790
}
48-
4991
cpy := make([]byte, len(data))
5092
copy(cpy, data)
51-
var useful = false
52-
for i, precompile := range precompiles {
53-
precompile.RequiredGas(cpy)
54-
if _, err := precompile.Run(cpy); err == nil {
55-
useful = true
56-
}
57-
if !bytes.Equal(cpy, data) {
58-
panic(fmt.Sprintf("input data modified, precompile %d: %x %x", i, data, cpy))
59-
}
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))
6096
}
61-
if !useful {
62-
// Input not great
97+
if err != nil {
6398
return 0
6499
}
65100
return 1

0 commit comments

Comments
 (0)