blob: da0a5f93800d85215614c1f34b3d344df2e42cde [file] [log] [blame]
Matteo Scandoloa4285862020-12-01 18:10:10 -08001/*
2Copyright 2014 Google Inc. All rights reserved.
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17package fuzz
18
19import (
20 "fmt"
21 "math/rand"
22 "reflect"
23 "regexp"
24 "time"
25)
26
27// fuzzFuncMap is a map from a type to a fuzzFunc that handles that type.
28type fuzzFuncMap map[reflect.Type]reflect.Value
29
30// Fuzzer knows how to fill any object with random fields.
31type Fuzzer struct {
32 fuzzFuncs fuzzFuncMap
33 defaultFuzzFuncs fuzzFuncMap
34 r *rand.Rand
35 nilChance float64
36 minElements int
37 maxElements int
38 maxDepth int
39 skipFieldPatterns []*regexp.Regexp
40}
41
42// New returns a new Fuzzer. Customize your Fuzzer further by calling Funcs,
43// RandSource, NilChance, or NumElements in any order.
44func New() *Fuzzer {
45 return NewWithSeed(time.Now().UnixNano())
46}
47
48func NewWithSeed(seed int64) *Fuzzer {
49 f := &Fuzzer{
50 defaultFuzzFuncs: fuzzFuncMap{
51 reflect.TypeOf(&time.Time{}): reflect.ValueOf(fuzzTime),
52 },
53
54 fuzzFuncs: fuzzFuncMap{},
55 r: rand.New(rand.NewSource(seed)),
56 nilChance: .2,
57 minElements: 1,
58 maxElements: 10,
59 maxDepth: 100,
60 }
61 return f
62}
63
64// Funcs adds each entry in fuzzFuncs as a custom fuzzing function.
65//
66// Each entry in fuzzFuncs must be a function taking two parameters.
67// The first parameter must be a pointer or map. It is the variable that
68// function will fill with random data. The second parameter must be a
69// fuzz.Continue, which will provide a source of randomness and a way
70// to automatically continue fuzzing smaller pieces of the first parameter.
71//
72// These functions are called sensibly, e.g., if you wanted custom string
73// fuzzing, the function `func(s *string, c fuzz.Continue)` would get
74// called and passed the address of strings. Maps and pointers will always
75// be made/new'd for you, ignoring the NilChange option. For slices, it
76// doesn't make much sense to pre-create them--Fuzzer doesn't know how
77// long you want your slice--so take a pointer to a slice, and make it
78// yourself. (If you don't want your map/pointer type pre-made, take a
79// pointer to it, and make it yourself.) See the examples for a range of
80// custom functions.
81func (f *Fuzzer) Funcs(fuzzFuncs ...interface{}) *Fuzzer {
82 for i := range fuzzFuncs {
83 v := reflect.ValueOf(fuzzFuncs[i])
84 if v.Kind() != reflect.Func {
85 panic("Need only funcs!")
86 }
87 t := v.Type()
88 if t.NumIn() != 2 || t.NumOut() != 0 {
89 panic("Need 2 in and 0 out params!")
90 }
91 argT := t.In(0)
92 switch argT.Kind() {
93 case reflect.Ptr, reflect.Map:
94 default:
95 panic("fuzzFunc must take pointer or map type")
96 }
97 if t.In(1) != reflect.TypeOf(Continue{}) {
98 panic("fuzzFunc's second parameter must be type fuzz.Continue")
99 }
100 f.fuzzFuncs[argT] = v
101 }
102 return f
103}
104
105// RandSource causes f to get values from the given source of randomness.
106// Use if you want deterministic fuzzing.
107func (f *Fuzzer) RandSource(s rand.Source) *Fuzzer {
108 f.r = rand.New(s)
109 return f
110}
111
112// NilChance sets the probability of creating a nil pointer, map, or slice to
113// 'p'. 'p' should be between 0 (no nils) and 1 (all nils), inclusive.
114func (f *Fuzzer) NilChance(p float64) *Fuzzer {
115 if p < 0 || p > 1 {
116 panic("p should be between 0 and 1, inclusive.")
117 }
118 f.nilChance = p
119 return f
120}
121
122// NumElements sets the minimum and maximum number of elements that will be
123// added to a non-nil map or slice.
124func (f *Fuzzer) NumElements(atLeast, atMost int) *Fuzzer {
125 if atLeast > atMost {
126 panic("atLeast must be <= atMost")
127 }
128 if atLeast < 0 {
129 panic("atLeast must be >= 0")
130 }
131 f.minElements = atLeast
132 f.maxElements = atMost
133 return f
134}
135
136func (f *Fuzzer) genElementCount() int {
137 if f.minElements == f.maxElements {
138 return f.minElements
139 }
140 return f.minElements + f.r.Intn(f.maxElements-f.minElements+1)
141}
142
143func (f *Fuzzer) genShouldFill() bool {
144 return f.r.Float64() > f.nilChance
145}
146
147// MaxDepth sets the maximum number of recursive fuzz calls that will be made
148// before stopping. This includes struct members, pointers, and map and slice
149// elements.
150func (f *Fuzzer) MaxDepth(d int) *Fuzzer {
151 f.maxDepth = d
152 return f
153}
154
155// Skip fields which match the supplied pattern. Call this multiple times if needed
156// This is useful to skip XXX_ fields generated by protobuf
157func (f *Fuzzer) SkipFieldsWithPattern(pattern *regexp.Regexp) *Fuzzer {
158 f.skipFieldPatterns = append(f.skipFieldPatterns, pattern)
159 return f
160}
161
162// Fuzz recursively fills all of obj's fields with something random. First
163// this tries to find a custom fuzz function (see Funcs). If there is no
164// custom function this tests whether the object implements fuzz.Interface and,
165// if so, calls Fuzz on it to fuzz itself. If that fails, this will see if
166// there is a default fuzz function provided by this package. If all of that
167// fails, this will generate random values for all primitive fields and then
168// recurse for all non-primitives.
169//
170// This is safe for cyclic or tree-like structs, up to a limit. Use the
171// MaxDepth method to adjust how deep you need it to recurse.
172//
173// obj must be a pointer. Only exported (public) fields can be set (thanks,
174// golang :/ ) Intended for tests, so will panic on bad input or unimplemented
175// fields.
176func (f *Fuzzer) Fuzz(obj interface{}) {
177 v := reflect.ValueOf(obj)
178 if v.Kind() != reflect.Ptr {
179 panic("needed ptr!")
180 }
181 v = v.Elem()
182 f.fuzzWithContext(v, 0)
183}
184
185// FuzzNoCustom is just like Fuzz, except that any custom fuzz function for
186// obj's type will not be called and obj will not be tested for fuzz.Interface
187// conformance. This applies only to obj and not other instances of obj's
188// type.
189// Not safe for cyclic or tree-like structs!
190// obj must be a pointer. Only exported (public) fields can be set (thanks, golang :/ )
191// Intended for tests, so will panic on bad input or unimplemented fields.
192func (f *Fuzzer) FuzzNoCustom(obj interface{}) {
193 v := reflect.ValueOf(obj)
194 if v.Kind() != reflect.Ptr {
195 panic("needed ptr!")
196 }
197 v = v.Elem()
198 f.fuzzWithContext(v, flagNoCustomFuzz)
199}
200
201const (
202 // Do not try to find a custom fuzz function. Does not apply recursively.
203 flagNoCustomFuzz uint64 = 1 << iota
204)
205
206func (f *Fuzzer) fuzzWithContext(v reflect.Value, flags uint64) {
207 fc := &fuzzerContext{fuzzer: f}
208 fc.doFuzz(v, flags)
209}
210
211// fuzzerContext carries context about a single fuzzing run, which lets Fuzzer
212// be thread-safe.
213type fuzzerContext struct {
214 fuzzer *Fuzzer
215 curDepth int
216}
217
218func (fc *fuzzerContext) doFuzz(v reflect.Value, flags uint64) {
219 if fc.curDepth >= fc.fuzzer.maxDepth {
220 return
221 }
222 fc.curDepth++
223 defer func() { fc.curDepth-- }()
224
225 if !v.CanSet() {
226 return
227 }
228
229 if flags&flagNoCustomFuzz == 0 {
230 // Check for both pointer and non-pointer custom functions.
231 if v.CanAddr() && fc.tryCustom(v.Addr()) {
232 return
233 }
234 if fc.tryCustom(v) {
235 return
236 }
237 }
238
239 if fn, ok := fillFuncMap[v.Kind()]; ok {
240 fn(v, fc.fuzzer.r)
241 return
242 }
243 switch v.Kind() {
244 case reflect.Map:
245 if fc.fuzzer.genShouldFill() {
246 v.Set(reflect.MakeMap(v.Type()))
247 n := fc.fuzzer.genElementCount()
248 for i := 0; i < n; i++ {
249 key := reflect.New(v.Type().Key()).Elem()
250 fc.doFuzz(key, 0)
251 val := reflect.New(v.Type().Elem()).Elem()
252 fc.doFuzz(val, 0)
253 v.SetMapIndex(key, val)
254 }
255 return
256 }
257 v.Set(reflect.Zero(v.Type()))
258 case reflect.Ptr:
259 if fc.fuzzer.genShouldFill() {
260 v.Set(reflect.New(v.Type().Elem()))
261 fc.doFuzz(v.Elem(), 0)
262 return
263 }
264 v.Set(reflect.Zero(v.Type()))
265 case reflect.Slice:
266 if fc.fuzzer.genShouldFill() {
267 n := fc.fuzzer.genElementCount()
268 v.Set(reflect.MakeSlice(v.Type(), n, n))
269 for i := 0; i < n; i++ {
270 fc.doFuzz(v.Index(i), 0)
271 }
272 return
273 }
274 v.Set(reflect.Zero(v.Type()))
275 case reflect.Array:
276 if fc.fuzzer.genShouldFill() {
277 n := v.Len()
278 for i := 0; i < n; i++ {
279 fc.doFuzz(v.Index(i), 0)
280 }
281 return
282 }
283 v.Set(reflect.Zero(v.Type()))
284 case reflect.Struct:
285 for i := 0; i < v.NumField(); i++ {
286 skipField := false
287 fieldName := v.Type().Field(i).Name
288 for _, pattern := range fc.fuzzer.skipFieldPatterns {
289 if pattern.MatchString(fieldName) {
290 skipField = true
291 break
292 }
293 }
294 if !skipField {
295 fc.doFuzz(v.Field(i), 0)
296 }
297 }
298 case reflect.Chan:
299 fallthrough
300 case reflect.Func:
301 fallthrough
302 case reflect.Interface:
303 fallthrough
304 default:
305 panic(fmt.Sprintf("Can't handle %#v", v.Interface()))
306 }
307}
308
309// tryCustom searches for custom handlers, and returns true iff it finds a match
310// and successfully randomizes v.
311func (fc *fuzzerContext) tryCustom(v reflect.Value) bool {
312 // First: see if we have a fuzz function for it.
313 doCustom, ok := fc.fuzzer.fuzzFuncs[v.Type()]
314 if !ok {
315 // Second: see if it can fuzz itself.
316 if v.CanInterface() {
317 intf := v.Interface()
318 if fuzzable, ok := intf.(Interface); ok {
319 fuzzable.Fuzz(Continue{fc: fc, Rand: fc.fuzzer.r})
320 return true
321 }
322 }
323 // Finally: see if there is a default fuzz function.
324 doCustom, ok = fc.fuzzer.defaultFuzzFuncs[v.Type()]
325 if !ok {
326 return false
327 }
328 }
329
330 switch v.Kind() {
331 case reflect.Ptr:
332 if v.IsNil() {
333 if !v.CanSet() {
334 return false
335 }
336 v.Set(reflect.New(v.Type().Elem()))
337 }
338 case reflect.Map:
339 if v.IsNil() {
340 if !v.CanSet() {
341 return false
342 }
343 v.Set(reflect.MakeMap(v.Type()))
344 }
345 default:
346 return false
347 }
348
349 doCustom.Call([]reflect.Value{v, reflect.ValueOf(Continue{
350 fc: fc,
351 Rand: fc.fuzzer.r,
352 })})
353 return true
354}
355
356// Interface represents an object that knows how to fuzz itself. Any time we
357// find a type that implements this interface we will delegate the act of
358// fuzzing itself.
359type Interface interface {
360 Fuzz(c Continue)
361}
362
363// Continue can be passed to custom fuzzing functions to allow them to use
364// the correct source of randomness and to continue fuzzing their members.
365type Continue struct {
366 fc *fuzzerContext
367
368 // For convenience, Continue implements rand.Rand via embedding.
369 // Use this for generating any randomness if you want your fuzzing
370 // to be repeatable for a given seed.
371 *rand.Rand
372}
373
374// Fuzz continues fuzzing obj. obj must be a pointer.
375func (c Continue) Fuzz(obj interface{}) {
376 v := reflect.ValueOf(obj)
377 if v.Kind() != reflect.Ptr {
378 panic("needed ptr!")
379 }
380 v = v.Elem()
381 c.fc.doFuzz(v, 0)
382}
383
384// FuzzNoCustom continues fuzzing obj, except that any custom fuzz function for
385// obj's type will not be called and obj will not be tested for fuzz.Interface
386// conformance. This applies only to obj and not other instances of obj's
387// type.
388func (c Continue) FuzzNoCustom(obj interface{}) {
389 v := reflect.ValueOf(obj)
390 if v.Kind() != reflect.Ptr {
391 panic("needed ptr!")
392 }
393 v = v.Elem()
394 c.fc.doFuzz(v, flagNoCustomFuzz)
395}
396
397// RandString makes a random string up to 20 characters long. The returned string
398// may include a variety of (valid) UTF-8 encodings.
399func (c Continue) RandString() string {
400 return randString(c.Rand)
401}
402
403// RandUint64 makes random 64 bit numbers.
404// Weirdly, rand doesn't have a function that gives you 64 random bits.
405func (c Continue) RandUint64() uint64 {
406 return randUint64(c.Rand)
407}
408
409// RandBool returns true or false randomly.
410func (c Continue) RandBool() bool {
411 return randBool(c.Rand)
412}
413
414func fuzzInt(v reflect.Value, r *rand.Rand) {
415 v.SetInt(int64(randUint64(r)))
416}
417
418func fuzzUint(v reflect.Value, r *rand.Rand) {
419 v.SetUint(randUint64(r))
420}
421
422func fuzzTime(t *time.Time, c Continue) {
423 var sec, nsec int64
424 // Allow for about 1000 years of random time values, which keeps things
425 // like JSON parsing reasonably happy.
426 sec = c.Rand.Int63n(1000 * 365 * 24 * 60 * 60)
427 c.Fuzz(&nsec)
428 *t = time.Unix(sec, nsec)
429}
430
431var fillFuncMap = map[reflect.Kind]func(reflect.Value, *rand.Rand){
432 reflect.Bool: func(v reflect.Value, r *rand.Rand) {
433 v.SetBool(randBool(r))
434 },
435 reflect.Int: fuzzInt,
436 reflect.Int8: fuzzInt,
437 reflect.Int16: fuzzInt,
438 reflect.Int32: fuzzInt,
439 reflect.Int64: fuzzInt,
440 reflect.Uint: fuzzUint,
441 reflect.Uint8: fuzzUint,
442 reflect.Uint16: fuzzUint,
443 reflect.Uint32: fuzzUint,
444 reflect.Uint64: fuzzUint,
445 reflect.Uintptr: fuzzUint,
446 reflect.Float32: func(v reflect.Value, r *rand.Rand) {
447 v.SetFloat(float64(r.Float32()))
448 },
449 reflect.Float64: func(v reflect.Value, r *rand.Rand) {
450 v.SetFloat(r.Float64())
451 },
452 reflect.Complex64: func(v reflect.Value, r *rand.Rand) {
453 panic("unimplemented")
454 },
455 reflect.Complex128: func(v reflect.Value, r *rand.Rand) {
456 panic("unimplemented")
457 },
458 reflect.String: func(v reflect.Value, r *rand.Rand) {
459 v.SetString(randString(r))
460 },
461 reflect.UnsafePointer: func(v reflect.Value, r *rand.Rand) {
462 panic("unimplemented")
463 },
464}
465
466// randBool returns true or false randomly.
467func randBool(r *rand.Rand) bool {
468 if r.Int()&1 == 1 {
469 return true
470 }
471 return false
472}
473
474type charRange struct {
475 first, last rune
476}
477
478// choose returns a random unicode character from the given range, using the
479// given randomness source.
480func (r *charRange) choose(rand *rand.Rand) rune {
481 count := int64(r.last - r.first)
482 return r.first + rune(rand.Int63n(count))
483}
484
485var unicodeRanges = []charRange{
486 {' ', '~'}, // ASCII characters
487 {'\u00a0', '\u02af'}, // Multi-byte encoded characters
488 {'\u4e00', '\u9fff'}, // Common CJK (even longer encodings)
489}
490
491// randString makes a random string up to 20 characters long. The returned string
492// may include a variety of (valid) UTF-8 encodings.
493func randString(r *rand.Rand) string {
494 n := r.Intn(20)
495 runes := make([]rune, n)
496 for i := range runes {
497 runes[i] = unicodeRanges[r.Intn(len(unicodeRanges))].choose(r)
498 }
499 return string(runes)
500}
501
502// randUint64 makes random 64 bit numbers.
503// Weirdly, rand doesn't have a function that gives you 64 random bits.
504func randUint64(r *rand.Rand) uint64 {
505 return uint64(r.Uint32())<<32 | uint64(r.Uint32())
506}