Skip to content

Commit ce425cd

Browse files
committed
fuzzers: fuzzers for keystore, rlp, trie, whisper (cred to @guidovranken)
1 parent 23c8c74 commit ce425cd

File tree

9 files changed

+425
-0
lines changed

9 files changed

+425
-0
lines changed

fuzzbuzz.yaml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# bmt keystore rlp trie whisperv6
2+
3+
base: ubuntu:16.04
4+
targets:
5+
- name: rlp
6+
language: go
7+
version: "1.11"
8+
corpus: ./fuzzers/rlp/corpus
9+
harness:
10+
function: Fuzz
11+
package: github.com/ethereum/go-ethereum/fuzzers/rlp
12+
checkout: github.com/ethereum/go-ethereum/
13+
- name: keystore
14+
language: go
15+
version: "1.11"
16+
corpus: ./fuzzers/keystore/corpus
17+
harness:
18+
function: Fuzz
19+
package: github.com/ethereum/go-ethereum/fuzzers/keystore
20+
checkout: github.com/ethereum/go-ethereum/
21+
- name: trie
22+
language: go
23+
version: "1.11"
24+
corpus: ./fuzzers/trie/corpus
25+
harness:
26+
function: Fuzz
27+
package: github.com/ethereum/go-ethereum/fuzzers/trie
28+
checkout: github.com/ethereum/go-ethereum/
29+
- name: whisperv6
30+
language: go
31+
version: "1.11"
32+
corpus: ./fuzzers/whisperv6/corpus
33+
harness:
34+
function: Fuzz
35+
package: github.com/ethereum/go-ethereum/fuzzers/whisperv6
36+
checkout: github.com/ethereum/go-ethereum/
37+
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ns��,��

fuzzers/keystore/keystore-fuzz.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package keystore
2+
3+
import (
4+
"os"
5+
6+
"github.com/ethereum/go-ethereum/accounts/keystore"
7+
)
8+
9+
func Fuzz(input []byte) int {
10+
11+
ks := keystore.NewKeyStore("/tmp/ks", keystore.LightScryptN, keystore.LightScryptP)
12+
13+
a, err := ks.NewAccount(string(input))
14+
if err != nil {
15+
panic(err)
16+
}
17+
if err := ks.Unlock(a, string(input)); err != nil {
18+
panic(err)
19+
}
20+
os.Remove(a.URL.Path)
21+
return 0
22+
}

fuzzers/rlp/corpus/r.bin

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ˀ����������

fuzzers/rlp/rlp_fuzzer.go

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
package rlp
2+
3+
import (
4+
"bytes"
5+
"fmt"
6+
7+
"github.com/ethereum/go-ethereum/core/types"
8+
"github.com/ethereum/go-ethereum/rlp"
9+
)
10+
11+
func decodeEncode(input []byte, val interface{}, i int) {
12+
if err := rlp.DecodeBytes(input, val); err == nil {
13+
output, err := rlp.EncodeToBytes(val)
14+
if err != nil {
15+
panic(err)
16+
}
17+
if !bytes.Equal(input, output) {
18+
panic(fmt.Sprintf("case %d: encode-decode is not equal, \ninput : %x\noutput: %x", i, input, output))
19+
}
20+
}
21+
}
22+
23+
func Fuzz(input []byte) int {
24+
25+
var i int
26+
{
27+
if len(input) > 0 {
28+
rlp.Split(input)
29+
}
30+
}
31+
{
32+
if len(input) > 0 {
33+
if elems, _, err := rlp.SplitList(input); err == nil {
34+
rlp.CountValues(elems)
35+
}
36+
}
37+
}
38+
39+
{
40+
rlp.NewStream(bytes.NewReader(input), 0).Decode(new(interface{}))
41+
}
42+
43+
{
44+
decodeEncode(input, new(interface{}), i)
45+
i++
46+
}
47+
{
48+
var v struct {
49+
Int uint
50+
String string
51+
Bytes []byte
52+
}
53+
decodeEncode(input, &v, i)
54+
i++
55+
}
56+
57+
{
58+
type Types struct {
59+
Bool bool
60+
Raw rlp.RawValue
61+
Slice []*Types
62+
Iface []interface{}
63+
}
64+
var v Types
65+
decodeEncode(input, &v, i)
66+
i++
67+
}
68+
{
69+
type AllTypes struct {
70+
Int uint
71+
String string
72+
Bytes []byte
73+
Bool bool
74+
Raw rlp.RawValue
75+
Slice []*AllTypes
76+
Array [3]*AllTypes
77+
Iface []interface{}
78+
}
79+
var v AllTypes
80+
decodeEncode(input, &v, i)
81+
i++
82+
}
83+
{
84+
decodeEncode(input, [10]byte{}, i)
85+
i++
86+
}
87+
{
88+
var v struct {
89+
Byte [10]byte
90+
Rool [10]bool
91+
}
92+
decodeEncode(input, &v, i)
93+
i++
94+
}
95+
{
96+
var h types.Header
97+
decodeEncode(input, &h, i)
98+
i++
99+
var b types.Block
100+
decodeEncode(input, &b, i)
101+
i++
102+
var t types.Transaction
103+
decodeEncode(input, &t, i)
104+
i++
105+
var txs types.Transactions
106+
decodeEncode(input, &txs, i)
107+
i++
108+
var rs types.Receipts
109+
decodeEncode(input, &rs, i)
110+
i++
111+
}
112+
113+
return 0
114+
}

fuzzers/trie/corpus/data

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
asdlfkjasf23oiejfasdfadkfqlkjfasdlkfjalwk4jfalsdkfjawlefkjsadlfkjasldkfjwalefkjasdlfkjM

fuzzers/trie/trie-fuzzer.go

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
package trie
2+
3+
import (
4+
"bytes"
5+
"encoding/binary"
6+
"fmt"
7+
8+
"github.com/ethereum/go-ethereum/common"
9+
"github.com/ethereum/go-ethereum/ethdb/memorydb"
10+
"github.com/ethereum/go-ethereum/trie"
11+
)
12+
13+
// randTest performs random trie operations.
14+
// Instances of this test are created by Generate.
15+
type randTest []randTestStep
16+
17+
type randTestStep struct {
18+
op int
19+
key []byte // for opUpdate, opDelete, opGet
20+
value []byte // for opUpdate
21+
err error // for debugging
22+
}
23+
24+
type proofDb struct{}
25+
26+
func (proofDb) Put(key []byte, value []byte) error {
27+
return nil
28+
}
29+
30+
func (proofDb) Delete(key []byte) error {
31+
return nil
32+
}
33+
34+
const (
35+
opUpdate = iota
36+
opDelete
37+
opGet
38+
opCommit
39+
opHash
40+
opReset
41+
opItercheckhash
42+
opProve
43+
opMax // boundary value, not an actual op
44+
)
45+
46+
type dataSource struct {
47+
input []byte
48+
reader *bytes.Reader
49+
}
50+
51+
func newDataSource(input []byte) *dataSource {
52+
return &dataSource{
53+
input, bytes.NewReader(input),
54+
}
55+
}
56+
func (ds *dataSource) ReadByte() byte {
57+
if b, err := ds.reader.ReadByte(); err != nil {
58+
return 0
59+
} else {
60+
return b
61+
}
62+
}
63+
func (ds *dataSource) Read(buf []byte) (int, error) {
64+
return ds.reader.Read(buf)
65+
}
66+
func (ds *dataSource) Ended() bool {
67+
return ds.reader.Len() == 0
68+
}
69+
70+
func Generate(input []byte) randTest {
71+
72+
var allKeys [][]byte
73+
r := newDataSource(input)
74+
genKey := func() []byte {
75+
76+
if len(allKeys) < 2 || r.ReadByte() < 0x0f {
77+
// new key
78+
key := make([]byte, r.ReadByte()%50)
79+
r.Read(key)
80+
allKeys = append(allKeys, key)
81+
return key
82+
}
83+
// use existing key
84+
return allKeys[int(r.ReadByte())%len(allKeys)]
85+
}
86+
87+
var steps randTest
88+
89+
for i := 0; !r.Ended(); i++ {
90+
91+
step := randTestStep{op: int(r.ReadByte()) % opMax}
92+
switch step.op {
93+
case opUpdate:
94+
step.key = genKey()
95+
step.value = make([]byte, 8)
96+
binary.BigEndian.PutUint64(step.value, uint64(i))
97+
case opGet, opDelete, opProve:
98+
step.key = genKey()
99+
}
100+
steps = append(steps, step)
101+
if len(steps) > 500 {
102+
break
103+
}
104+
}
105+
106+
return steps
107+
}
108+
109+
func Fuzz(input []byte) int {
110+
program := Generate(input)
111+
if len(program) == 0 {
112+
return -1
113+
}
114+
if err := runRandTest(program); err != nil {
115+
panic(err)
116+
}
117+
return 0
118+
}
119+
120+
func runRandTest(rt randTest) error {
121+
122+
triedb := trie.NewDatabase(memorydb.New())
123+
124+
tr, _ := trie.New(common.Hash{}, triedb)
125+
values := make(map[string]string) // tracks content of the trie
126+
127+
for i, step := range rt {
128+
switch step.op {
129+
case opUpdate:
130+
tr.Update(step.key, step.value)
131+
values[string(step.key)] = string(step.value)
132+
case opDelete:
133+
tr.Delete(step.key)
134+
delete(values, string(step.key))
135+
case opGet:
136+
v := tr.Get(step.key)
137+
want := values[string(step.key)]
138+
if string(v) != want {
139+
rt[i].err = fmt.Errorf("mismatch for key 0x%x, got 0x%x want 0x%x", step.key, v, want)
140+
}
141+
case opCommit:
142+
_, rt[i].err = tr.Commit(nil)
143+
case opHash:
144+
tr.Hash()
145+
case opReset:
146+
hash, err := tr.Commit(nil)
147+
if err != nil {
148+
return err
149+
}
150+
newtr, err := trie.New(hash, triedb)
151+
if err != nil {
152+
return err
153+
}
154+
tr = newtr
155+
case opItercheckhash:
156+
checktr, _ := trie.New(common.Hash{}, triedb)
157+
it := trie.NewIterator(tr.NodeIterator(nil))
158+
for it.Next() {
159+
checktr.Update(it.Key, it.Value)
160+
}
161+
if tr.Hash() != checktr.Hash() {
162+
return fmt.Errorf("hash mismatch in opItercheckhash")
163+
}
164+
case opProve:
165+
rt[i].err = tr.Prove(step.key, 0, proofDb{})
166+
}
167+
// Abort the test on error.
168+
if rt[i].err != nil {
169+
return rt[i].err
170+
}
171+
}
172+
return nil
173+
}
61 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)