github.com/google/syzkaller@v0.0.0-20240517125934-c0f1611a36d6/prog/mutation.go (about)

     1  // Copyright 2015 syzkaller project authors. All rights reserved.
     2  // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
     3  
     4  package prog
     5  
     6  import (
     7  	"encoding/binary"
     8  	"fmt"
     9  	"math"
    10  	"math/rand"
    11  	"sort"
    12  
    13  	"github.com/google/syzkaller/pkg/image"
    14  )
    15  
    16  // Maximum length of generated binary blobs inserted into the program.
    17  const maxBlobLen = uint64(100 << 10)
    18  
    19  // Mutate program p.
    20  //
    21  // p:           The program to mutate.
    22  // rs:          Random source.
    23  // ncalls:      The allowed maximum calls in mutated program.
    24  // ct:          ChoiceTable for syscalls.
    25  // noMutate:    Set of IDs of syscalls which should not be mutated.
    26  // corpus:      The entire corpus, including original program p.
    27  func (p *Prog) Mutate(rs rand.Source, ncalls int, ct *ChoiceTable, noMutate map[int]bool, corpus []*Prog) {
    28  	p.MutateWithOpts(rs, ncalls, ct, noMutate, corpus, DefaultMutateOpts)
    29  }
    30  
    31  var DefaultMutateOpts = MutateOpts{
    32  	ExpectedIterations: 5,
    33  	MutateArgCount:     3,
    34  
    35  	SquashWeight:     50,
    36  	SpliceWeight:     200,
    37  	InsertWeight:     100,
    38  	MutateArgWeight:  100,
    39  	RemoveCallWeight: 10,
    40  }
    41  
    42  type MutateOpts struct {
    43  	ExpectedIterations int
    44  	MutateArgCount     int
    45  	SquashWeight       int
    46  	SpliceWeight       int
    47  	InsertWeight       int
    48  	MutateArgWeight    int
    49  	RemoveCallWeight   int
    50  }
    51  
    52  func (o MutateOpts) weight() int {
    53  	return o.SquashWeight + o.SpliceWeight + o.InsertWeight + o.MutateArgWeight + o.RemoveCallWeight
    54  }
    55  
    56  func (p *Prog) MutateWithOpts(rs rand.Source, ncalls int, ct *ChoiceTable, noMutate map[int]bool,
    57  	corpus []*Prog, opts MutateOpts) {
    58  	if p.isUnsafe {
    59  		panic("mutation of unsafe programs is not supposed to be done")
    60  	}
    61  	totalWeight := opts.weight()
    62  	r := newRand(p.Target, rs)
    63  	if ncalls < len(p.Calls) {
    64  		ncalls = len(p.Calls)
    65  	}
    66  	ctx := &mutator{
    67  		p:        p,
    68  		r:        r,
    69  		ncalls:   ncalls,
    70  		ct:       ct,
    71  		noMutate: noMutate,
    72  		corpus:   corpus,
    73  		opts:     opts,
    74  	}
    75  	for stop, ok := false, false; !stop; stop = ok && len(p.Calls) != 0 && r.oneOf(opts.ExpectedIterations) {
    76  		val := r.Intn(totalWeight)
    77  		val -= opts.SquashWeight
    78  		if val < 0 {
    79  			// Not all calls have anything squashable,
    80  			// so this has lower priority in reality.
    81  			ok = ctx.squashAny()
    82  			continue
    83  		}
    84  		val -= opts.SpliceWeight
    85  		if val < 0 {
    86  			ok = ctx.splice()
    87  			continue
    88  		}
    89  		val -= opts.InsertWeight
    90  		if val < 0 {
    91  			ok = ctx.insertCall()
    92  			continue
    93  		}
    94  		val -= opts.MutateArgWeight
    95  		if val < 0 {
    96  			ok = ctx.mutateArg()
    97  			continue
    98  		}
    99  		ok = ctx.removeCall()
   100  	}
   101  	p.sanitizeFix()
   102  	p.debugValidate()
   103  	if got := len(p.Calls); got < 1 || got > ncalls {
   104  		panic(fmt.Sprintf("bad number of calls after mutation: %v, want [1, %v]", got, ncalls))
   105  	}
   106  }
   107  
   108  // Internal state required for performing mutations -- currently this matches
   109  // the arguments passed to Mutate().
   110  type mutator struct {
   111  	p        *Prog        // The program to mutate.
   112  	r        *randGen     // The randGen instance.
   113  	ncalls   int          // The allowed maximum calls in mutated program.
   114  	ct       *ChoiceTable // ChoiceTable for syscalls.
   115  	noMutate map[int]bool // Set of IDs of syscalls which should not be mutated.
   116  	corpus   []*Prog      // The entire corpus, including original program p.
   117  	opts     MutateOpts
   118  }
   119  
   120  // This function selects a random other program p0 out of the corpus, and
   121  // mutates ctx.p as follows: preserve ctx.p's Calls up to a random index i
   122  // (exclusive) concatenated with p0's calls from index i (inclusive).
   123  func (ctx *mutator) splice() bool {
   124  	p, r := ctx.p, ctx.r
   125  	if len(ctx.corpus) == 0 || len(p.Calls) == 0 || len(p.Calls) >= ctx.ncalls {
   126  		return false
   127  	}
   128  	p0 := ctx.corpus[r.Intn(len(ctx.corpus))]
   129  	p0c := p0.Clone()
   130  	idx := r.Intn(len(p.Calls))
   131  	p.Calls = append(p.Calls[:idx], append(p0c.Calls, p.Calls[idx:]...)...)
   132  	for i := len(p.Calls) - 1; i >= ctx.ncalls; i-- {
   133  		p.RemoveCall(i)
   134  	}
   135  	return true
   136  }
   137  
   138  // Picks a random complex pointer and squashes its arguments into an ANY.
   139  // Subsequently, if the ANY contains blobs, mutates a random blob.
   140  func (ctx *mutator) squashAny() bool {
   141  	p, r := ctx.p, ctx.r
   142  	complexPtrs := p.complexPtrs()
   143  	if len(complexPtrs) == 0 {
   144  		return false
   145  	}
   146  	ptr := complexPtrs[r.Intn(len(complexPtrs))]
   147  	if ctx.noMutate[ptr.call.Meta.ID] {
   148  		return false
   149  	}
   150  	if !p.Target.isAnyPtr(ptr.arg.Type()) {
   151  		p.Target.squashPtr(ptr.arg)
   152  	}
   153  	var blobs []*DataArg
   154  	var bases []*PointerArg
   155  	ForeachSubArg(ptr.arg, func(arg Arg, ctx *ArgCtx) {
   156  		if data, ok := arg.(*DataArg); ok && arg.Dir() != DirOut {
   157  			blobs = append(blobs, data)
   158  			bases = append(bases, ctx.Base)
   159  		}
   160  	})
   161  	if len(blobs) == 0 {
   162  		return false
   163  	}
   164  	// Note: we need to call analyze before we mutate the blob.
   165  	// After mutation the blob can grow out of bounds of the data area
   166  	// and analyze will crash with out-of-bounds access while marking existing allocations.
   167  	s := analyze(ctx.ct, ctx.corpus, p, ptr.call)
   168  	// TODO(dvyukov): we probably want special mutation for ANY.
   169  	// E.g. merging adjacent ANYBLOBs (we don't create them,
   170  	// but they can appear in future); or replacing ANYRES
   171  	// with a blob (and merging it with adjacent blobs).
   172  	idx := r.Intn(len(blobs))
   173  	arg := blobs[idx]
   174  	base := bases[idx]
   175  	baseSize := base.Res.Size()
   176  	arg.data = mutateData(r, arg.Data(), 0, maxBlobLen)
   177  	// Update base pointer if size has increased.
   178  	if baseSize < base.Res.Size() {
   179  		newArg := r.allocAddr(s, base.Type(), base.Dir(), base.Res.Size(), base.Res)
   180  		*base = *newArg
   181  	}
   182  	return true
   183  }
   184  
   185  // Inserts a new call at a randomly chosen point (with bias towards the end of
   186  // existing program). Does not insert a call if program already has ncalls.
   187  func (ctx *mutator) insertCall() bool {
   188  	p, r := ctx.p, ctx.r
   189  	if len(p.Calls) >= ctx.ncalls {
   190  		return false
   191  	}
   192  	idx := r.biasedRand(len(p.Calls)+1, 5)
   193  	var c *Call
   194  	if idx < len(p.Calls) {
   195  		c = p.Calls[idx]
   196  	}
   197  	s := analyze(ctx.ct, ctx.corpus, p, c)
   198  	calls := r.generateCall(s, p, idx)
   199  	p.insertBefore(c, calls)
   200  	for len(p.Calls) > ctx.ncalls {
   201  		p.RemoveCall(idx)
   202  	}
   203  	return true
   204  }
   205  
   206  // Removes a random call from program.
   207  func (ctx *mutator) removeCall() bool {
   208  	p, r := ctx.p, ctx.r
   209  	if len(p.Calls) == 0 {
   210  		return false
   211  	}
   212  	idx := r.Intn(len(p.Calls))
   213  	p.RemoveCall(idx)
   214  	return true
   215  }
   216  
   217  // Mutate an argument of a random call.
   218  func (ctx *mutator) mutateArg() bool {
   219  	p, r := ctx.p, ctx.r
   220  	if len(p.Calls) == 0 {
   221  		return false
   222  	}
   223  
   224  	idx := chooseCall(p, r)
   225  	if idx < 0 {
   226  		return false
   227  	}
   228  	c := p.Calls[idx]
   229  	if ctx.noMutate[c.Meta.ID] {
   230  		return false
   231  	}
   232  	updateSizes := true
   233  	for stop, ok := false, false; !stop; stop = ok && r.oneOf(ctx.opts.MutateArgCount) {
   234  		ok = true
   235  		ma := &mutationArgs{target: p.Target}
   236  		ForeachArg(c, ma.collectArg)
   237  		if len(ma.args) == 0 {
   238  			return false
   239  		}
   240  		s := analyze(ctx.ct, ctx.corpus, p, c)
   241  		arg, argCtx := ma.chooseArg(r.Rand)
   242  		calls, ok1 := p.Target.mutateArg(r, s, arg, argCtx, &updateSizes)
   243  		if !ok1 {
   244  			ok = false
   245  			continue
   246  		}
   247  		moreCalls, fieldsPatched := r.patchConditionalFields(c, s)
   248  		calls = append(calls, moreCalls...)
   249  		p.insertBefore(c, calls)
   250  		idx += len(calls)
   251  		for len(p.Calls) > ctx.ncalls {
   252  			idx--
   253  			p.RemoveCall(idx)
   254  		}
   255  		if idx < 0 || idx >= len(p.Calls) || p.Calls[idx] != c {
   256  			panic(fmt.Sprintf("wrong call index: idx=%v calls=%v p.Calls=%v ncalls=%v",
   257  				idx, len(calls), len(p.Calls), ctx.ncalls))
   258  		}
   259  		if updateSizes || fieldsPatched {
   260  			p.Target.assignSizesCall(c)
   261  		}
   262  	}
   263  	return true
   264  }
   265  
   266  // Select a call based on the complexity of the arguments.
   267  func chooseCall(p *Prog, r *randGen) int {
   268  	var prioSum float64
   269  	var callPriorities []float64
   270  	for _, c := range p.Calls {
   271  		var totalPrio float64
   272  		ForeachArg(c, func(arg Arg, ctx *ArgCtx) {
   273  			prio, stopRecursion := arg.Type().getMutationPrio(p.Target, arg, false)
   274  			totalPrio += prio
   275  			ctx.Stop = stopRecursion
   276  		})
   277  		prioSum += totalPrio
   278  		callPriorities = append(callPriorities, prioSum)
   279  	}
   280  	if prioSum == 0 {
   281  		return -1 // All calls are without arguments.
   282  	}
   283  	return sort.SearchFloat64s(callPriorities, prioSum*r.Float64())
   284  }
   285  
   286  func (target *Target) mutateArg(r *randGen, s *state, arg Arg, ctx ArgCtx, updateSizes *bool) ([]*Call, bool) {
   287  	var baseSize uint64
   288  	if ctx.Base != nil {
   289  		baseSize = ctx.Base.Res.Size()
   290  	}
   291  	calls, retry, preserve := arg.Type().mutate(r, s, arg, ctx)
   292  	if retry {
   293  		return nil, false
   294  	}
   295  	if preserve {
   296  		*updateSizes = false
   297  	}
   298  	// Update base pointer if size has increased.
   299  	if base := ctx.Base; base != nil && baseSize < base.Res.Size() {
   300  		newArg := r.allocAddr(s, base.Type(), base.Dir(), base.Res.Size(), base.Res)
   301  		replaceArg(base, newArg)
   302  	}
   303  	return calls, true
   304  }
   305  
   306  func regenerate(r *randGen, s *state, arg Arg) (calls []*Call, retry, preserve bool) {
   307  	var newArg Arg
   308  	newArg, calls = r.generateArg(s, arg.Type(), arg.Dir())
   309  	replaceArg(arg, newArg)
   310  	return
   311  }
   312  
   313  func mutateInt(r *randGen, a *ConstArg, t *IntType) uint64 {
   314  	switch {
   315  	case r.nOutOf(1, 3):
   316  		return a.Val + (uint64(r.Intn(4)) + 1)
   317  	case r.nOutOf(1, 2):
   318  		return a.Val - (uint64(r.Intn(4)) + 1)
   319  	default:
   320  		return a.Val ^ (1 << uint64(r.Intn(int(t.TypeBitSize()))))
   321  	}
   322  }
   323  
   324  func mutateAlignedInt(r *randGen, a *ConstArg, t *IntType) uint64 {
   325  	rangeEnd := t.RangeEnd
   326  	if t.RangeBegin == 0 && int64(rangeEnd) == -1 {
   327  		// Special [0:-1] range for all possible values.
   328  		rangeEnd = uint64(1<<t.TypeBitSize() - 1)
   329  	}
   330  	index := (a.Val - t.RangeBegin) / t.Align
   331  	misalignment := (a.Val - t.RangeBegin) % t.Align
   332  	switch {
   333  	case r.nOutOf(1, 3):
   334  		index += uint64(r.Intn(4)) + 1
   335  	case r.nOutOf(1, 2):
   336  		index -= uint64(r.Intn(4)) + 1
   337  	default:
   338  		index ^= 1 << uint64(r.Intn(int(t.TypeBitSize())))
   339  	}
   340  	lastIndex := (rangeEnd - t.RangeBegin) / t.Align
   341  	index %= lastIndex + 1
   342  	return t.RangeBegin + index*t.Align + misalignment
   343  }
   344  
   345  func (t *IntType) mutate(r *randGen, s *state, arg Arg, ctx ArgCtx) (calls []*Call, retry, preserve bool) {
   346  	if r.bin() {
   347  		return regenerate(r, s, arg)
   348  	}
   349  	a := arg.(*ConstArg)
   350  	if t.Align == 0 {
   351  		a.Val = mutateInt(r, a, t)
   352  	} else {
   353  		a.Val = mutateAlignedInt(r, a, t)
   354  	}
   355  	a.Val = truncateToBitSize(a.Val, t.TypeBitSize())
   356  	return
   357  }
   358  
   359  func (t *FlagsType) mutate(r *randGen, s *state, arg Arg, ctx ArgCtx) (calls []*Call, retry, preserve bool) {
   360  	a := arg.(*ConstArg)
   361  	for oldVal := a.Val; oldVal == a.Val; {
   362  		a.Val = r.flags(t.Vals, t.BitMask, a.Val)
   363  	}
   364  	return
   365  }
   366  
   367  func (t *LenType) mutate(r *randGen, s *state, arg Arg, ctx ArgCtx) (calls []*Call, retry, preserve bool) {
   368  	if !r.mutateSize(arg.(*ConstArg), *ctx.Parent, ctx.Fields) {
   369  		retry = true
   370  		return
   371  	}
   372  	preserve = true
   373  	return
   374  }
   375  
   376  func (t *ResourceType) mutate(r *randGen, s *state, arg Arg, ctx ArgCtx) (calls []*Call, retry, preserve bool) {
   377  	return regenerate(r, s, arg)
   378  }
   379  
   380  func (t *VmaType) mutate(r *randGen, s *state, arg Arg, ctx ArgCtx) (calls []*Call, retry, preserve bool) {
   381  	return regenerate(r, s, arg)
   382  }
   383  
   384  func (t *ProcType) mutate(r *randGen, s *state, arg Arg, ctx ArgCtx) (calls []*Call, retry, preserve bool) {
   385  	return regenerate(r, s, arg)
   386  }
   387  
   388  func (t *BufferType) mutate(r *randGen, s *state, arg Arg, ctx ArgCtx) (calls []*Call, retry, preserve bool) {
   389  	minLen, maxLen := uint64(0), maxBlobLen
   390  	if t.Kind == BufferBlobRange {
   391  		minLen, maxLen = t.RangeBegin, t.RangeEnd
   392  	}
   393  	a := arg.(*DataArg)
   394  	if a.Dir() == DirOut {
   395  		if t.Kind == BufferFilename && r.oneOf(100) {
   396  			a.size = uint64(r.randFilenameLength())
   397  		} else {
   398  			mutateBufferSize(r, a, minLen, maxLen)
   399  		}
   400  		return
   401  	}
   402  	switch t.Kind {
   403  	case BufferBlobRand, BufferBlobRange:
   404  		data := append([]byte{}, a.Data()...)
   405  		a.data = mutateData(r, data, minLen, maxLen)
   406  	case BufferString:
   407  		if len(t.Values) != 0 {
   408  			a.data = r.randString(s, t)
   409  		} else {
   410  			if t.TypeSize != 0 {
   411  				minLen, maxLen = t.TypeSize, t.TypeSize
   412  			}
   413  			data := append([]byte{}, a.Data()...)
   414  			a.data = mutateData(r, data, minLen, maxLen)
   415  		}
   416  	case BufferFilename:
   417  		a.data = []byte(r.filename(s, t))
   418  	case BufferGlob:
   419  		if len(t.Values) != 0 {
   420  			a.data = r.randString(s, t)
   421  		} else {
   422  			a.data = []byte(r.filename(s, t))
   423  		}
   424  	case BufferText:
   425  		data := append([]byte{}, a.Data()...)
   426  		a.data = r.mutateText(t.Text, data)
   427  	case BufferCompressed:
   428  		a.data, retry = r.mutateImage(a.Data())
   429  	default:
   430  		panic("unknown buffer kind")
   431  	}
   432  	return
   433  }
   434  
   435  func (r *randGen) mutateImage(compressed []byte) (data []byte, retry bool) {
   436  	data, dtor := image.MustDecompress(compressed)
   437  	defer dtor()
   438  	if len(data) == 0 {
   439  		return compressed, true // Do not mutate empty data.
   440  	}
   441  	hm := MakeGenericHeatmap(data, r.Rand)
   442  	for i := hm.NumMutations(); i > 0; i-- {
   443  		index := hm.ChooseLocation()
   444  		width := 1 << uint(r.Intn(4))
   445  		if index+width > len(data) {
   446  			width = 1
   447  		}
   448  		storeInt(data[index:], r.randInt(uint64(width*8)), width)
   449  	}
   450  	return image.Compress(data), false
   451  }
   452  
   453  func mutateBufferSize(r *randGen, arg *DataArg, minLen, maxLen uint64) {
   454  	for oldSize := arg.Size(); oldSize == arg.Size(); {
   455  		arg.size += uint64(r.Intn(33)) - 16
   456  		// Cast to int64 to prevent underflows.
   457  		if int64(arg.size) < int64(minLen) {
   458  			arg.size = minLen
   459  		}
   460  		if arg.size > maxLen {
   461  			arg.size = maxLen
   462  		}
   463  	}
   464  }
   465  
   466  func (t *ArrayType) mutate(r *randGen, s *state, arg Arg, ctx ArgCtx) (calls []*Call, retry, preserve bool) {
   467  	a := arg.(*GroupArg)
   468  	if len(a.Inner) > 1 && r.oneOf(5) {
   469  		// Swap array elements.
   470  		for r.nOutOf(2, 3) {
   471  			i, j := r.Intn(len(a.Inner)), r.Intn(len(a.Inner))
   472  			a.Inner[i], a.Inner[j] = a.Inner[j], a.Inner[i]
   473  		}
   474  	}
   475  	count := uint64(0)
   476  	switch t.Kind {
   477  	case ArrayRandLen:
   478  		if r.bin() {
   479  			for count = uint64(len(a.Inner)); r.bin(); {
   480  				count++
   481  			}
   482  		} else {
   483  			for count == uint64(len(a.Inner)) {
   484  				count = r.randArrayLen()
   485  			}
   486  		}
   487  	case ArrayRangeLen:
   488  		if t.RangeBegin == t.RangeEnd {
   489  			panic("trying to mutate fixed length array")
   490  		}
   491  		for count == uint64(len(a.Inner)) {
   492  			count = r.randRange(t.RangeBegin, t.RangeEnd)
   493  		}
   494  	}
   495  	if count > uint64(len(a.Inner)) {
   496  		for count > uint64(len(a.Inner)) {
   497  			newArg, newCalls := r.generateArg(s, t.Elem, a.Dir())
   498  			a.Inner = append(a.Inner, newArg)
   499  			calls = append(calls, newCalls...)
   500  			for _, c := range newCalls {
   501  				s.analyze(c)
   502  			}
   503  		}
   504  	} else if count < uint64(len(a.Inner)) {
   505  		for _, arg := range a.Inner[count:] {
   506  			removeArg(arg)
   507  		}
   508  		a.Inner = a.Inner[:count]
   509  	}
   510  	return
   511  }
   512  
   513  func (t *PtrType) mutate(r *randGen, s *state, arg Arg, ctx ArgCtx) (calls []*Call, retry, preserve bool) {
   514  	a := arg.(*PointerArg)
   515  	if r.oneOf(1000) {
   516  		removeArg(a.Res)
   517  		index := r.rand(len(r.target.SpecialPointers))
   518  		newArg := MakeSpecialPointerArg(t, a.Dir(), index)
   519  		replaceArg(arg, newArg)
   520  		return
   521  	}
   522  	newArg := r.allocAddr(s, t, a.Dir(), a.Res.Size(), a.Res)
   523  	replaceArg(arg, newArg)
   524  	return
   525  }
   526  
   527  func (t *StructType) mutate(r *randGen, s *state, arg Arg, ctx ArgCtx) (calls []*Call, retry, preserve bool) {
   528  	gen := r.target.SpecialTypes[t.Name()]
   529  	if gen == nil {
   530  		panic("bad arg returned by mutationArgs: StructType")
   531  	}
   532  	var newArg Arg
   533  	newArg, calls = gen(&Gen{r, s}, t, arg.Dir(), arg)
   534  	a := arg.(*GroupArg)
   535  	for i, f := range newArg.(*GroupArg).Inner {
   536  		replaceArg(a.Inner[i], f)
   537  	}
   538  	return
   539  }
   540  
   541  func (t *UnionType) mutate(r *randGen, s *state, arg Arg, ctx ArgCtx) (calls []*Call, retry, preserve bool) {
   542  	if gen := r.target.SpecialTypes[t.Name()]; gen != nil {
   543  		var newArg Arg
   544  		newArg, calls = gen(&Gen{r, s}, t, arg.Dir(), arg)
   545  		replaceArg(arg, newArg)
   546  		return
   547  	}
   548  	a := arg.(*UnionArg)
   549  	index := r.Intn(len(t.Fields) - 1)
   550  	if index >= a.Index {
   551  		index++
   552  	}
   553  	optType, optDir := t.Fields[index].Type, t.Fields[index].Dir(a.Dir())
   554  	var newOpt Arg
   555  	newOpt, calls = r.generateArg(s, optType, optDir)
   556  	replaceArg(arg, MakeUnionArg(t, a.Dir(), newOpt, index))
   557  	return
   558  }
   559  
   560  func (t *CsumType) mutate(r *randGen, s *state, arg Arg, ctx ArgCtx) (calls []*Call, retry, preserve bool) {
   561  	panic("CsumType can't be mutated")
   562  }
   563  
   564  func (t *ConstType) mutate(r *randGen, s *state, arg Arg, ctx ArgCtx) (calls []*Call, retry, preserve bool) {
   565  	panic("ConstType can't be mutated")
   566  }
   567  
   568  type mutationArgs struct {
   569  	target        *Target
   570  	ignoreSpecial bool
   571  	prioSum       float64
   572  	args          []mutationArg
   573  	argsBuffer    [16]mutationArg
   574  }
   575  
   576  type mutationArg struct {
   577  	arg      Arg
   578  	ctx      ArgCtx
   579  	priority float64
   580  }
   581  
   582  const (
   583  	maxPriority = float64(10)
   584  	minPriority = float64(1)
   585  	dontMutate  = float64(0)
   586  )
   587  
   588  func (ma *mutationArgs) collectArg(arg Arg, ctx *ArgCtx) {
   589  	ignoreSpecial := ma.ignoreSpecial
   590  	ma.ignoreSpecial = false
   591  
   592  	typ := arg.Type()
   593  	prio, stopRecursion := typ.getMutationPrio(ma.target, arg, ignoreSpecial)
   594  	ctx.Stop = stopRecursion
   595  
   596  	if prio == dontMutate {
   597  		return
   598  	}
   599  
   600  	_, isArrayTyp := typ.(*ArrayType)
   601  	_, isBufferTyp := typ.(*BufferType)
   602  	if !isBufferTyp && !isArrayTyp && arg.Dir() == DirOut || !typ.Varlen() && typ.Size() == 0 {
   603  		return
   604  	}
   605  
   606  	if len(ma.args) == 0 {
   607  		ma.args = ma.argsBuffer[:0]
   608  	}
   609  	ma.prioSum += prio
   610  	ma.args = append(ma.args, mutationArg{arg, *ctx, ma.prioSum})
   611  }
   612  
   613  func (ma *mutationArgs) chooseArg(r *rand.Rand) (Arg, ArgCtx) {
   614  	goal := ma.prioSum * r.Float64()
   615  	chosenIdx := sort.Search(len(ma.args), func(i int) bool { return ma.args[i].priority >= goal })
   616  	arg := ma.args[chosenIdx]
   617  	return arg.arg, arg.ctx
   618  }
   619  
   620  // TODO: find a way to estimate optimal priority values.
   621  // Assign a priority for each type. The boolean is the reference type and it has
   622  // the minimum priority, since it has only two possible values.
   623  func (t *IntType) getMutationPrio(target *Target, arg Arg, ignoreSpecial bool) (prio float64, stopRecursion bool) {
   624  	// For a integer without a range of values, the priority is based on
   625  	// the number of bits occupied by the underlying type.
   626  	plainPrio := math.Log2(float64(t.TypeBitSize())) + 0.1*maxPriority
   627  	if t.Kind != IntRange {
   628  		return plainPrio, false
   629  	}
   630  
   631  	size := t.RangeEnd - t.RangeBegin + 1
   632  	if t.Align != 0 {
   633  		if t.RangeBegin == 0 && int64(t.RangeEnd) == -1 {
   634  			// Special [0:-1] range for all possible values.
   635  			size = (1<<t.TypeBitSize()-1)/t.Align + 1
   636  		} else {
   637  			size = (t.RangeEnd-t.RangeBegin)/t.Align + 1
   638  		}
   639  	}
   640  	switch {
   641  	case size <= 15:
   642  		// For a small range, we assume that it is effectively
   643  		// similar with FlagsType and we need to try all possible values.
   644  		prio = rangeSizePrio(size)
   645  	case size <= 256:
   646  		// We consider that a relevant range has at most 256
   647  		// values (the number of values that can be represented on a byte).
   648  		prio = maxPriority
   649  	default:
   650  		// Ranges larger than 256 are equivalent with a plain integer.
   651  		prio = plainPrio
   652  	}
   653  	return prio, false
   654  }
   655  
   656  func (t *StructType) getMutationPrio(target *Target, arg Arg, ignoreSpecial bool) (prio float64, stopRecursion bool) {
   657  	if target.SpecialTypes[t.Name()] == nil || ignoreSpecial {
   658  		return dontMutate, false
   659  	}
   660  	return maxPriority, true
   661  }
   662  
   663  func (t *UnionType) getMutationPrio(target *Target, arg Arg, ignoreSpecial bool) (prio float64, stopRecursion bool) {
   664  	if target.SpecialTypes[t.Name()] == nil && len(t.Fields) == 1 || ignoreSpecial {
   665  		return dontMutate, false
   666  	}
   667  	// For a non-special type union with more than one option
   668  	// we mutate the union itself and also the value of the current option.
   669  	if target.SpecialTypes[t.Name()] == nil {
   670  		return maxPriority, false
   671  	}
   672  	return maxPriority, true
   673  }
   674  
   675  func (t *FlagsType) getMutationPrio(target *Target, arg Arg, ignoreSpecial bool) (prio float64, stopRecursion bool) {
   676  	prio = rangeSizePrio(uint64(len(t.Vals)))
   677  	if t.BitMask {
   678  		// We want a higher priority because the mutation will include
   679  		// more possible operations (bitwise operations).
   680  		prio += 0.1 * maxPriority
   681  	}
   682  	return prio, false
   683  }
   684  
   685  // Assigns a priority based on the range size.
   686  func rangeSizePrio(size uint64) (prio float64) {
   687  	switch size {
   688  	case 0:
   689  		prio = dontMutate
   690  	case 1:
   691  		prio = minPriority
   692  	default:
   693  		// Priority proportional with the number of values. After a threshold, the priority is constant.
   694  		// The threshold is 15 because most of the calls have <= 15 possible values for a flag.
   695  		prio = math.Min(float64(size)/3+0.4*maxPriority, 0.9*maxPriority)
   696  	}
   697  	return prio
   698  }
   699  
   700  func (t *PtrType) getMutationPrio(target *Target, arg Arg, ignoreSpecial bool) (prio float64, stopRecursion bool) {
   701  	if arg.(*PointerArg).IsSpecial() {
   702  		// TODO: we ought to mutate this, but we don't have code for this yet.
   703  		return dontMutate, false
   704  	}
   705  	return 0.3 * maxPriority, false
   706  }
   707  
   708  func (t *ConstType) getMutationPrio(target *Target, arg Arg, ignoreSpecial bool) (prio float64, stopRecursion bool) {
   709  	return dontMutate, false
   710  }
   711  
   712  func (t *CsumType) getMutationPrio(target *Target, arg Arg, ignoreSpecial bool) (prio float64, stopRecursion bool) {
   713  	return dontMutate, false
   714  }
   715  
   716  func (t *ProcType) getMutationPrio(target *Target, arg Arg, ignoreSpecial bool) (prio float64, stopRecursion bool) {
   717  	return 0.5 * maxPriority, false
   718  }
   719  
   720  func (t *ResourceType) getMutationPrio(target *Target, arg Arg, ignoreSpecial bool) (prio float64, stopRecursion bool) {
   721  	return 0.5 * maxPriority, false
   722  }
   723  
   724  func (t *VmaType) getMutationPrio(target *Target, arg Arg, ignoreSpecial bool) (prio float64, stopRecursion bool) {
   725  	return 0.5 * maxPriority, false
   726  }
   727  
   728  func (t *LenType) getMutationPrio(target *Target, arg Arg, ignoreSpecial bool) (prio float64, stopRecursion bool) {
   729  	// Mutating LenType only produces "incorrect" results according to descriptions.
   730  	return 0.1 * maxPriority, false
   731  }
   732  
   733  func (t *BufferType) getMutationPrio(target *Target, arg Arg, ignoreSpecial bool) (prio float64, stopRecursion bool) {
   734  	if arg.Dir() == DirOut && !t.Varlen() {
   735  		return dontMutate, false
   736  	}
   737  	if t.Kind == BufferString && len(t.Values) == 1 {
   738  		// These are effectively consts (and frequently file names).
   739  		return dontMutate, false
   740  	}
   741  	if t.Kind == BufferCompressed {
   742  		// Prioritise mutation of compressed buffers, e.g. disk images (`compressed_image`).
   743  		return maxPriority, false
   744  	}
   745  	return 0.8 * maxPriority, false
   746  }
   747  
   748  func (t *ArrayType) getMutationPrio(target *Target, arg Arg, ignoreSpecial bool) (prio float64, stopRecursion bool) {
   749  	if t.Kind == ArrayRangeLen && t.RangeBegin == t.RangeEnd {
   750  		return dontMutate, false
   751  	}
   752  	return maxPriority, false
   753  }
   754  
   755  func mutateData(r *randGen, data []byte, minLen, maxLen uint64) []byte {
   756  	for stop := false; !stop; stop = stop && r.oneOf(3) {
   757  		f := mutateDataFuncs[r.Intn(len(mutateDataFuncs))]
   758  		data, stop = f(r, data, minLen, maxLen)
   759  	}
   760  	return data
   761  }
   762  
   763  // The maximum delta for integer mutations.
   764  const maxDelta = 35
   765  
   766  var mutateDataFuncs = [...]func(r *randGen, data []byte, minLen, maxLen uint64) ([]byte, bool){
   767  	// TODO(dvyukov): duplicate part of data.
   768  	// Flip bit in byte.
   769  	func(r *randGen, data []byte, minLen, maxLen uint64) ([]byte, bool) {
   770  		if len(data) == 0 {
   771  			return data, false
   772  		}
   773  		byt := r.Intn(len(data))
   774  		bit := r.Intn(8)
   775  		data[byt] ^= 1 << uint(bit)
   776  		return data, true
   777  	},
   778  	// Insert random bytes.
   779  	func(r *randGen, data []byte, minLen, maxLen uint64) ([]byte, bool) {
   780  		if len(data) == 0 || uint64(len(data)) >= maxLen {
   781  			return data, false
   782  		}
   783  		n := r.Intn(16) + 1
   784  		if r := int(maxLen) - len(data); n > r {
   785  			n = r
   786  		}
   787  		pos := r.Intn(len(data))
   788  		for i := 0; i < n; i++ {
   789  			data = append(data, 0)
   790  		}
   791  		copy(data[pos+n:], data[pos:])
   792  		for i := 0; i < n; i++ {
   793  			data[pos+i] = byte(r.Int31())
   794  		}
   795  		if uint64(len(data)) > maxLen || r.bin() {
   796  			data = data[:len(data)-n] // preserve original length
   797  		}
   798  		return data, true
   799  	},
   800  	// Remove bytes.
   801  	func(r *randGen, data []byte, minLen, maxLen uint64) ([]byte, bool) {
   802  		if len(data) == 0 {
   803  			return data, false
   804  		}
   805  		n := r.Intn(16) + 1
   806  		if n > len(data) {
   807  			n = len(data)
   808  		}
   809  		pos := 0
   810  		if n < len(data) {
   811  			pos = r.Intn(len(data) - n)
   812  		}
   813  		copy(data[pos:], data[pos+n:])
   814  		data = data[:len(data)-n]
   815  		if uint64(len(data)) < minLen || r.bin() {
   816  			for i := 0; i < n; i++ {
   817  				data = append(data, 0) // preserve original length
   818  			}
   819  		}
   820  		return data, true
   821  	},
   822  	// Append a bunch of bytes.
   823  	func(r *randGen, data []byte, minLen, maxLen uint64) ([]byte, bool) {
   824  		if uint64(len(data)) >= maxLen {
   825  			return data, false
   826  		}
   827  		const max = 256
   828  		n := max - r.biasedRand(max, 10)
   829  		if r := int(maxLen) - len(data); n > r {
   830  			n = r
   831  		}
   832  		for i := 0; i < n; i++ {
   833  			data = append(data, byte(r.rand(256)))
   834  		}
   835  		return data, true
   836  	},
   837  	// Replace int8/int16/int32/int64 with a random value.
   838  	func(r *randGen, data []byte, minLen, maxLen uint64) ([]byte, bool) {
   839  		width := 1 << uint(r.Intn(4))
   840  		if len(data) < width {
   841  			return data, false
   842  		}
   843  		i := r.Intn(len(data) - width + 1)
   844  		storeInt(data[i:], r.Uint64(), width)
   845  		return data, true
   846  	},
   847  	// Add/subtract from an int8/int16/int32/int64.
   848  	func(r *randGen, data []byte, minLen, maxLen uint64) ([]byte, bool) {
   849  		width := 1 << uint(r.Intn(4))
   850  		if len(data) < width {
   851  			return data, false
   852  		}
   853  		i := r.Intn(len(data) - width + 1)
   854  		v := loadInt(data[i:], width)
   855  		delta := r.rand(2*maxDelta+1) - maxDelta
   856  		if delta == 0 {
   857  			delta = 1
   858  		}
   859  		if r.oneOf(10) {
   860  			v = swapInt(v, width)
   861  			v += delta
   862  			v = swapInt(v, width)
   863  		} else {
   864  			v += delta
   865  		}
   866  		storeInt(data[i:], v, width)
   867  		return data, true
   868  	},
   869  	// Set int8/int16/int32/int64 to an interesting value.
   870  	func(r *randGen, data []byte, minLen, maxLen uint64) ([]byte, bool) {
   871  		width := 1 << uint(r.Intn(4))
   872  		if len(data) < width {
   873  			return data, false
   874  		}
   875  		i := r.Intn(len(data) - width + 1)
   876  		value := r.randInt64()
   877  		if r.oneOf(10) {
   878  			value = swap64(value)
   879  		}
   880  		storeInt(data[i:], value, width)
   881  		return data, true
   882  	},
   883  }
   884  
   885  func swap16(v uint16) uint16 {
   886  	v0 := byte(v >> 0)
   887  	v1 := byte(v >> 8)
   888  	v = 0
   889  	v |= uint16(v1) << 0
   890  	v |= uint16(v0) << 8
   891  	return v
   892  }
   893  
   894  func swap32(v uint32) uint32 {
   895  	v0 := byte(v >> 0)
   896  	v1 := byte(v >> 8)
   897  	v2 := byte(v >> 16)
   898  	v3 := byte(v >> 24)
   899  	v = 0
   900  	v |= uint32(v3) << 0
   901  	v |= uint32(v2) << 8
   902  	v |= uint32(v1) << 16
   903  	v |= uint32(v0) << 24
   904  	return v
   905  }
   906  
   907  func swap64(v uint64) uint64 {
   908  	v0 := byte(v >> 0)
   909  	v1 := byte(v >> 8)
   910  	v2 := byte(v >> 16)
   911  	v3 := byte(v >> 24)
   912  	v4 := byte(v >> 32)
   913  	v5 := byte(v >> 40)
   914  	v6 := byte(v >> 48)
   915  	v7 := byte(v >> 56)
   916  	v = 0
   917  	v |= uint64(v7) << 0
   918  	v |= uint64(v6) << 8
   919  	v |= uint64(v5) << 16
   920  	v |= uint64(v4) << 24
   921  	v |= uint64(v3) << 32
   922  	v |= uint64(v2) << 40
   923  	v |= uint64(v1) << 48
   924  	v |= uint64(v0) << 56
   925  	return v
   926  }
   927  
   928  func swapInt(v uint64, size int) uint64 {
   929  	switch size {
   930  	case 1:
   931  		return v
   932  	case 2:
   933  		return uint64(swap16(uint16(v)))
   934  	case 4:
   935  		return uint64(swap32(uint32(v)))
   936  	case 8:
   937  		return swap64(v)
   938  	default:
   939  		panic(fmt.Sprintf("swapInt: bad size %v", size))
   940  	}
   941  }
   942  
   943  func loadInt(data []byte, size int) uint64 {
   944  	switch size {
   945  	case 1:
   946  		return uint64(data[0])
   947  	case 2:
   948  		return uint64(binary.LittleEndian.Uint16(data))
   949  	case 4:
   950  		return uint64(binary.LittleEndian.Uint32(data))
   951  	case 8:
   952  		return binary.LittleEndian.Uint64(data)
   953  	default:
   954  		panic(fmt.Sprintf("loadInt: bad size %v", size))
   955  	}
   956  }
   957  
   958  func storeInt(data []byte, v uint64, size int) {
   959  	switch size {
   960  	case 1:
   961  		data[0] = uint8(v)
   962  	case 2:
   963  		binary.LittleEndian.PutUint16(data, uint16(v))
   964  	case 4:
   965  		binary.LittleEndian.PutUint32(data, uint32(v))
   966  	case 8:
   967  		binary.LittleEndian.PutUint64(data, v)
   968  	default:
   969  		panic(fmt.Sprintf("storeInt: bad size %v", size))
   970  	}
   971  }