Skip to content

Commit a9d4fff

Browse files
authored
trie: move fuzzers into native packages ethereum#28467 (#1239)
1 parent 4b4980d commit a9d4fff

File tree

1 file changed

+49
-16
lines changed

1 file changed

+49
-16
lines changed

trie/trie_test.go

Lines changed: 49 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"errors"
2424
"fmt"
2525
"hash"
26+
"io"
2627
"math/big"
2728
"math/rand"
2829
"reflect"
@@ -292,8 +293,9 @@ func TestRandomCases(t *testing.T) {
292293
{op: 1, key: common.Hex2Bytes("980c393656413a15c8da01978ed9f89feb80b502f58f2d640e3a2f5f7a99a7018f1b573befd92053ac6f78fca4a87268"), value: common.Hex2Bytes("")}, // step 24
293294
{op: 1, key: common.Hex2Bytes("fd"), value: common.Hex2Bytes("")}, // step 25
294295
}
295-
runRandTest(rt)
296-
296+
if err := runRandTest(rt); err != nil {
297+
t.Fatal(err)
298+
}
297299
}
298300

299301
// randTest performs random trie operations.
@@ -319,36 +321,53 @@ const (
319321
)
320322

321323
func (randTest) Generate(r *rand.Rand, size int) reflect.Value {
324+
var finishedFn = func() bool {
325+
size--
326+
return size > 0
327+
}
328+
return reflect.ValueOf(generateSteps(finishedFn, r))
329+
}
330+
331+
func generateSteps(finished func() bool, r io.Reader) randTest {
322332
var allKeys [][]byte
333+
var one = []byte{0}
323334
genKey := func() []byte {
324-
if len(allKeys) < 2 || r.Intn(100) < 10 {
335+
r.Read(one)
336+
if len(allKeys) < 2 || one[0]%100 > 90 {
325337
// new key
326-
key := make([]byte, r.Intn(50))
338+
size := one[0] % 50
339+
key := make([]byte, size)
327340
r.Read(key)
328341
allKeys = append(allKeys, key)
329342
return key
330343
}
331344
// use existing key
332-
return allKeys[r.Intn(len(allKeys))]
345+
idx := int(one[0]) % len(allKeys)
346+
return allKeys[idx]
333347
}
334-
335348
var steps randTest
336-
for i := 0; i < size; i++ {
337-
step := randTestStep{op: r.Intn(opMax)}
349+
for !finished() {
350+
r.Read(one)
351+
step := randTestStep{op: int(one[0]) % opMax}
338352
switch step.op {
339353
case opUpdate:
340354
step.key = genKey()
341355
step.value = make([]byte, 8)
342-
binary.BigEndian.PutUint64(step.value, uint64(i))
356+
binary.BigEndian.PutUint64(step.value, uint64(len(steps)))
343357
case opGet, opDelete:
344358
step.key = genKey()
345359
}
346360
steps = append(steps, step)
347361
}
348-
return reflect.ValueOf(steps)
362+
return steps
349363
}
350364

351-
func runRandTest(rt randTest) bool {
365+
// runRandTestBool coerces error to boolean, for use in quick.Check
366+
func runRandTestBool(rt randTest) bool {
367+
return runRandTest(rt) == nil
368+
}
369+
370+
func runRandTest(rt randTest) error {
352371
triedb := NewDatabase(memorydb.New())
353372

354373
tr, _ := New(common.Hash{}, triedb)
@@ -378,12 +397,12 @@ func runRandTest(rt randTest) bool {
378397
hash, err := tr.Commit(nil)
379398
if err != nil {
380399
rt[i].err = err
381-
return false
400+
return err
382401
}
383402
newtr, err := New(hash, triedb)
384403
if err != nil {
385404
rt[i].err = err
386-
return false
405+
return err
387406
}
388407
tr = newtr
389408
case opItercheckhash:
@@ -398,14 +417,14 @@ func runRandTest(rt randTest) bool {
398417
}
399418
// Abort the test on error.
400419
if rt[i].err != nil {
401-
return false
420+
return rt[i].err
402421
}
403422
}
404-
return true
423+
return nil
405424
}
406425

407426
func TestRandom(t *testing.T) {
408-
if err := quick.Check(runRandTest, nil); err != nil {
427+
if err := quick.Check(runRandTestBool, nil); err != nil {
409428
if cerr, ok := err.(*quick.CheckError); ok {
410429
t.Fatalf("random test iteration %d failed: %s", cerr.Count, spew.Sdump(cerr.In))
411430
}
@@ -841,3 +860,17 @@ func TestDecodeNode(t *testing.T) {
841860
decodeNode(hash, elems)
842861
}
843862
}
863+
864+
func FuzzTrie(f *testing.F) {
865+
f.Fuzz(func(t *testing.T, data []byte) {
866+
var steps = 500
867+
var input = bytes.NewReader(data)
868+
var finishedFn = func() bool {
869+
steps--
870+
return steps < 0 || input.Len() == 0
871+
}
872+
if err := runRandTest(generateSteps(finishedFn, input)); err != nil {
873+
t.Fatal(err)
874+
}
875+
})
876+
}

0 commit comments

Comments
 (0)