1
16
17 package fuzz
18
19 import (
20 "fmt"
21 "math/rand"
22 "reflect"
23 "regexp"
24 "time"
25
26 "github.com/google/gofuzz/bytesource"
27 "strings"
28 )
29
30
31 type fuzzFuncMap map[reflect.Type]reflect.Value
32
33
34 type Fuzzer struct {
35 fuzzFuncs fuzzFuncMap
36 defaultFuzzFuncs fuzzFuncMap
37 r *rand.Rand
38 nilChance float64
39 minElements int
40 maxElements int
41 maxDepth int
42 skipFieldPatterns []*regexp.Regexp
43 }
44
45
46
47 func New() *Fuzzer {
48 return NewWithSeed(time.Now().UnixNano())
49 }
50
51 func NewWithSeed(seed int64) *Fuzzer {
52 f := &Fuzzer{
53 defaultFuzzFuncs: fuzzFuncMap{
54 reflect.TypeOf(&time.Time{}): reflect.ValueOf(fuzzTime),
55 },
56
57 fuzzFuncs: fuzzFuncMap{},
58 r: rand.New(rand.NewSource(seed)),
59 nilChance: .2,
60 minElements: 1,
61 maxElements: 10,
62 maxDepth: 100,
63 }
64 return f
65 }
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91 func NewFromGoFuzz(data []byte) *Fuzzer {
92 return New().RandSource(bytesource.New(data))
93 }
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112 func (f *Fuzzer) Funcs(fuzzFuncs ...interface{}) *Fuzzer {
113 for i := range fuzzFuncs {
114 v := reflect.ValueOf(fuzzFuncs[i])
115 if v.Kind() != reflect.Func {
116 panic("Need only funcs!")
117 }
118 t := v.Type()
119 if t.NumIn() != 2 || t.NumOut() != 0 {
120 panic("Need 2 in and 0 out params!")
121 }
122 argT := t.In(0)
123 switch argT.Kind() {
124 case reflect.Ptr, reflect.Map:
125 default:
126 panic("fuzzFunc must take pointer or map type")
127 }
128 if t.In(1) != reflect.TypeOf(Continue{}) {
129 panic("fuzzFunc's second parameter must be type fuzz.Continue")
130 }
131 f.fuzzFuncs[argT] = v
132 }
133 return f
134 }
135
136
137
138 func (f *Fuzzer) RandSource(s rand.Source) *Fuzzer {
139 f.r = rand.New(s)
140 return f
141 }
142
143
144
145 func (f *Fuzzer) NilChance(p float64) *Fuzzer {
146 if p < 0 || p > 1 {
147 panic("p should be between 0 and 1, inclusive.")
148 }
149 f.nilChance = p
150 return f
151 }
152
153
154
155 func (f *Fuzzer) NumElements(atLeast, atMost int) *Fuzzer {
156 if atLeast > atMost {
157 panic("atLeast must be <= atMost")
158 }
159 if atLeast < 0 {
160 panic("atLeast must be >= 0")
161 }
162 f.minElements = atLeast
163 f.maxElements = atMost
164 return f
165 }
166
167 func (f *Fuzzer) genElementCount() int {
168 if f.minElements == f.maxElements {
169 return f.minElements
170 }
171 return f.minElements + f.r.Intn(f.maxElements-f.minElements+1)
172 }
173
174 func (f *Fuzzer) genShouldFill() bool {
175 return f.r.Float64() >= f.nilChance
176 }
177
178
179
180
181 func (f *Fuzzer) MaxDepth(d int) *Fuzzer {
182 f.maxDepth = d
183 return f
184 }
185
186
187
188 func (f *Fuzzer) SkipFieldsWithPattern(pattern *regexp.Regexp) *Fuzzer {
189 f.skipFieldPatterns = append(f.skipFieldPatterns, pattern)
190 return f
191 }
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207 func (f *Fuzzer) Fuzz(obj interface{}) {
208 v := reflect.ValueOf(obj)
209 if v.Kind() != reflect.Ptr {
210 panic("needed ptr!")
211 }
212 v = v.Elem()
213 f.fuzzWithContext(v, 0)
214 }
215
216
217
218
219
220
221
222
223 func (f *Fuzzer) FuzzNoCustom(obj interface{}) {
224 v := reflect.ValueOf(obj)
225 if v.Kind() != reflect.Ptr {
226 panic("needed ptr!")
227 }
228 v = v.Elem()
229 f.fuzzWithContext(v, flagNoCustomFuzz)
230 }
231
232 const (
233
234 flagNoCustomFuzz uint64 = 1 << iota
235 )
236
237 func (f *Fuzzer) fuzzWithContext(v reflect.Value, flags uint64) {
238 fc := &fuzzerContext{fuzzer: f}
239 fc.doFuzz(v, flags)
240 }
241
242
243
244 type fuzzerContext struct {
245 fuzzer *Fuzzer
246 curDepth int
247 }
248
249 func (fc *fuzzerContext) doFuzz(v reflect.Value, flags uint64) {
250 if fc.curDepth >= fc.fuzzer.maxDepth {
251 return
252 }
253 fc.curDepth++
254 defer func() { fc.curDepth-- }()
255
256 if !v.CanSet() {
257 return
258 }
259
260 if flags&flagNoCustomFuzz == 0 {
261
262 if v.CanAddr() && fc.tryCustom(v.Addr()) {
263 return
264 }
265 if fc.tryCustom(v) {
266 return
267 }
268 }
269
270 if fn, ok := fillFuncMap[v.Kind()]; ok {
271 fn(v, fc.fuzzer.r)
272 return
273 }
274
275 switch v.Kind() {
276 case reflect.Map:
277 if fc.fuzzer.genShouldFill() {
278 v.Set(reflect.MakeMap(v.Type()))
279 n := fc.fuzzer.genElementCount()
280 for i := 0; i < n; i++ {
281 key := reflect.New(v.Type().Key()).Elem()
282 fc.doFuzz(key, 0)
283 val := reflect.New(v.Type().Elem()).Elem()
284 fc.doFuzz(val, 0)
285 v.SetMapIndex(key, val)
286 }
287 return
288 }
289 v.Set(reflect.Zero(v.Type()))
290 case reflect.Ptr:
291 if fc.fuzzer.genShouldFill() {
292 v.Set(reflect.New(v.Type().Elem()))
293 fc.doFuzz(v.Elem(), 0)
294 return
295 }
296 v.Set(reflect.Zero(v.Type()))
297 case reflect.Slice:
298 if fc.fuzzer.genShouldFill() {
299 n := fc.fuzzer.genElementCount()
300 v.Set(reflect.MakeSlice(v.Type(), n, n))
301 for i := 0; i < n; i++ {
302 fc.doFuzz(v.Index(i), 0)
303 }
304 return
305 }
306 v.Set(reflect.Zero(v.Type()))
307 case reflect.Array:
308 if fc.fuzzer.genShouldFill() {
309 n := v.Len()
310 for i := 0; i < n; i++ {
311 fc.doFuzz(v.Index(i), 0)
312 }
313 return
314 }
315 v.Set(reflect.Zero(v.Type()))
316 case reflect.Struct:
317 for i := 0; i < v.NumField(); i++ {
318 skipField := false
319 fieldName := v.Type().Field(i).Name
320 for _, pattern := range fc.fuzzer.skipFieldPatterns {
321 if pattern.MatchString(fieldName) {
322 skipField = true
323 break
324 }
325 }
326 if !skipField {
327 fc.doFuzz(v.Field(i), 0)
328 }
329 }
330 case reflect.Chan:
331 fallthrough
332 case reflect.Func:
333 fallthrough
334 case reflect.Interface:
335 fallthrough
336 default:
337 panic(fmt.Sprintf("Can't handle %#v", v.Interface()))
338 }
339 }
340
341
342
343 func (fc *fuzzerContext) tryCustom(v reflect.Value) bool {
344
345 doCustom, ok := fc.fuzzer.fuzzFuncs[v.Type()]
346 if !ok {
347
348 if v.CanInterface() {
349 intf := v.Interface()
350 if fuzzable, ok := intf.(Interface); ok {
351 fuzzable.Fuzz(Continue{fc: fc, Rand: fc.fuzzer.r})
352 return true
353 }
354 }
355
356 doCustom, ok = fc.fuzzer.defaultFuzzFuncs[v.Type()]
357 if !ok {
358 return false
359 }
360 }
361
362 switch v.Kind() {
363 case reflect.Ptr:
364 if v.IsNil() {
365 if !v.CanSet() {
366 return false
367 }
368 v.Set(reflect.New(v.Type().Elem()))
369 }
370 case reflect.Map:
371 if v.IsNil() {
372 if !v.CanSet() {
373 return false
374 }
375 v.Set(reflect.MakeMap(v.Type()))
376 }
377 default:
378 return false
379 }
380
381 doCustom.Call([]reflect.Value{v, reflect.ValueOf(Continue{
382 fc: fc,
383 Rand: fc.fuzzer.r,
384 })})
385 return true
386 }
387
388
389
390
391 type Interface interface {
392 Fuzz(c Continue)
393 }
394
395
396
397 type Continue struct {
398 fc *fuzzerContext
399
400
401
402
403 *rand.Rand
404 }
405
406
407 func (c Continue) Fuzz(obj interface{}) {
408 v := reflect.ValueOf(obj)
409 if v.Kind() != reflect.Ptr {
410 panic("needed ptr!")
411 }
412 v = v.Elem()
413 c.fc.doFuzz(v, 0)
414 }
415
416
417
418
419
420 func (c Continue) FuzzNoCustom(obj interface{}) {
421 v := reflect.ValueOf(obj)
422 if v.Kind() != reflect.Ptr {
423 panic("needed ptr!")
424 }
425 v = v.Elem()
426 c.fc.doFuzz(v, flagNoCustomFuzz)
427 }
428
429
430
431 func (c Continue) RandString() string {
432 return randString(c.Rand)
433 }
434
435
436
437 func (c Continue) RandUint64() uint64 {
438 return randUint64(c.Rand)
439 }
440
441
442 func (c Continue) RandBool() bool {
443 return randBool(c.Rand)
444 }
445
446 func fuzzInt(v reflect.Value, r *rand.Rand) {
447 v.SetInt(int64(randUint64(r)))
448 }
449
450 func fuzzUint(v reflect.Value, r *rand.Rand) {
451 v.SetUint(randUint64(r))
452 }
453
454 func fuzzTime(t *time.Time, c Continue) {
455 var sec, nsec int64
456
457
458 sec = c.Rand.Int63n(1000 * 365 * 24 * 60 * 60)
459 c.Fuzz(&nsec)
460 *t = time.Unix(sec, nsec)
461 }
462
463 var fillFuncMap = map[reflect.Kind]func(reflect.Value, *rand.Rand){
464 reflect.Bool: func(v reflect.Value, r *rand.Rand) {
465 v.SetBool(randBool(r))
466 },
467 reflect.Int: fuzzInt,
468 reflect.Int8: fuzzInt,
469 reflect.Int16: fuzzInt,
470 reflect.Int32: fuzzInt,
471 reflect.Int64: fuzzInt,
472 reflect.Uint: fuzzUint,
473 reflect.Uint8: fuzzUint,
474 reflect.Uint16: fuzzUint,
475 reflect.Uint32: fuzzUint,
476 reflect.Uint64: fuzzUint,
477 reflect.Uintptr: fuzzUint,
478 reflect.Float32: func(v reflect.Value, r *rand.Rand) {
479 v.SetFloat(float64(r.Float32()))
480 },
481 reflect.Float64: func(v reflect.Value, r *rand.Rand) {
482 v.SetFloat(r.Float64())
483 },
484 reflect.Complex64: func(v reflect.Value, r *rand.Rand) {
485 v.SetComplex(complex128(complex(r.Float32(), r.Float32())))
486 },
487 reflect.Complex128: func(v reflect.Value, r *rand.Rand) {
488 v.SetComplex(complex(r.Float64(), r.Float64()))
489 },
490 reflect.String: func(v reflect.Value, r *rand.Rand) {
491 v.SetString(randString(r))
492 },
493 reflect.UnsafePointer: func(v reflect.Value, r *rand.Rand) {
494 panic("unimplemented")
495 },
496 }
497
498
499 func randBool(r *rand.Rand) bool {
500 return r.Int31()&(1<<30) == 0
501 }
502
503 type int63nPicker interface {
504 Int63n(int64) int64
505 }
506
507
508
509 type UnicodeRange struct {
510 First, Last rune
511 }
512
513
514
515
516 type UnicodeRanges []UnicodeRange
517
518
519
520 func (ur UnicodeRange) choose(r int63nPicker) rune {
521 count := int64(ur.Last - ur.First + 1)
522 return ur.First + rune(r.Int63n(count))
523 }
524
525
526
527
528 func (ur UnicodeRange) CustomStringFuzzFunc() func(s *string, c Continue) {
529 ur.check()
530 return func(s *string, c Continue) {
531 *s = ur.randString(c.Rand)
532 }
533 }
534
535
536
537 func (ur UnicodeRange) check() {
538 if ur.Last < ur.First {
539 panic("The last encoding must be greater than the first one.")
540 }
541 }
542
543
544
545 func (ur UnicodeRange) randString(r *rand.Rand) string {
546 n := r.Intn(20)
547 sb := strings.Builder{}
548 sb.Grow(n)
549 for i := 0; i < n; i++ {
550 sb.WriteRune(ur.choose(r))
551 }
552 return sb.String()
553 }
554
555
556
557 var defaultUnicodeRanges = UnicodeRanges{
558 {' ', '~'},
559 {'\u00a0', '\u02af'},
560 {'\u4e00', '\u9fff'},
561 }
562
563
564
565
566
567
568 func (ur UnicodeRanges) CustomStringFuzzFunc() func(s *string, c Continue) {
569
570 if len(ur) == 0 {
571 panic("UnicodeRanges is empty.")
572 }
573
574 for i := range ur {
575 ur[i].check()
576 }
577 return func(s *string, c Continue) {
578 *s = ur.randString(c.Rand)
579 }
580 }
581
582
583
584
585 func (ur UnicodeRanges) randString(r *rand.Rand) string {
586 n := r.Intn(20)
587 sb := strings.Builder{}
588 sb.Grow(n)
589 for i := 0; i < n; i++ {
590 sb.WriteRune(ur[r.Intn(len(ur))].choose(r))
591 }
592 return sb.String()
593 }
594
595
596
597 func randString(r *rand.Rand) string {
598 return defaultUnicodeRanges.randString(r)
599 }
600
601
602
603 func randUint64(r *rand.Rand) uint64 {
604 return uint64(r.Uint32())<<32 | uint64(r.Uint32())
605 }
606
View as plain text