Home | History | Annotate | Download | only in prog
      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 	"fmt"
      8 	"math/rand"
      9 	"unsafe"
     10 )
     11 
     12 const maxBlobLen = uint64(100 << 10)
     13 
     14 func (p *Prog) Mutate(rs rand.Source, ncalls int, ct *ChoiceTable, corpus []*Prog) {
     15 	r := newRand(p.Target, rs)
     16 	ctx := &mutator{
     17 		p:      p,
     18 		r:      r,
     19 		ncalls: ncalls,
     20 		ct:     ct,
     21 		corpus: corpus,
     22 	}
     23 	for stop, ok := false, false; !stop; stop = ok && r.oneOf(3) {
     24 		switch {
     25 		case r.oneOf(5):
     26 			// Not all calls have anything squashable,
     27 			// so this has lower priority in reality.
     28 			ok = ctx.squashAny()
     29 		case r.nOutOf(1, 100):
     30 			ok = ctx.splice()
     31 		case r.nOutOf(20, 31):
     32 			ok = ctx.insertCall()
     33 		case r.nOutOf(10, 11):
     34 			ok = ctx.mutateArg()
     35 		default:
     36 			ok = ctx.removeCall()
     37 		}
     38 	}
     39 	for _, c := range p.Calls {
     40 		p.Target.SanitizeCall(c)
     41 	}
     42 	p.debugValidate()
     43 }
     44 
     45 type mutator struct {
     46 	p      *Prog
     47 	r      *randGen
     48 	ncalls int
     49 	ct     *ChoiceTable
     50 	corpus []*Prog
     51 }
     52 
     53 func (ctx *mutator) splice() bool {
     54 	p, r := ctx.p, ctx.r
     55 	if len(ctx.corpus) == 0 || len(p.Calls) == 0 {
     56 		return false
     57 	}
     58 	p0 := ctx.corpus[r.Intn(len(ctx.corpus))]
     59 	p0c := p0.Clone()
     60 	idx := r.Intn(len(p.Calls))
     61 	p.Calls = append(p.Calls[:idx], append(p0c.Calls, p.Calls[idx:]...)...)
     62 	for i := len(p.Calls) - 1; i >= ctx.ncalls; i-- {
     63 		p.removeCall(i)
     64 	}
     65 	return true
     66 }
     67 
     68 func (ctx *mutator) squashAny() bool {
     69 	p, r := ctx.p, ctx.r
     70 	complexPtrs := p.complexPtrs()
     71 	if len(complexPtrs) == 0 {
     72 		return false
     73 	}
     74 	ptr := complexPtrs[r.Intn(len(complexPtrs))]
     75 	if !p.Target.isAnyPtr(ptr.Type()) {
     76 		p.Target.squashPtr(ptr, true)
     77 	}
     78 	var blobs []*DataArg
     79 	var bases []*PointerArg
     80 	ForeachSubArg(ptr, func(arg Arg, ctx *ArgCtx) {
     81 		if data, ok := arg.(*DataArg); ok && arg.Type().Dir() != DirOut {
     82 			blobs = append(blobs, data)
     83 			bases = append(bases, ctx.Base)
     84 		}
     85 	})
     86 	if len(blobs) == 0 {
     87 		return false
     88 	}
     89 	// TODO(dvyukov): we probably want special mutation for ANY.
     90 	// E.g. merging adjacent ANYBLOBs (we don't create them,
     91 	// but they can appear in future); or replacing ANYRES
     92 	// with a blob (and merging it with adjacent blobs).
     93 	idx := r.Intn(len(blobs))
     94 	arg := blobs[idx]
     95 	base := bases[idx]
     96 	baseSize := base.Res.Size()
     97 	arg.data = mutateData(r, arg.Data(), 0, maxBlobLen)
     98 	// Update base pointer if size has increased.
     99 	if baseSize < base.Res.Size() {
    100 		s := analyze(ctx.ct, p, p.Calls[0])
    101 		newArg := r.allocAddr(s, base.Type(), base.Res.Size(), base.Res)
    102 		*base = *newArg
    103 	}
    104 	return true
    105 }
    106 
    107 func (ctx *mutator) insertCall() bool {
    108 	p, r := ctx.p, ctx.r
    109 	if len(p.Calls) >= ctx.ncalls {
    110 		return false
    111 	}
    112 	idx := r.biasedRand(len(p.Calls)+1, 5)
    113 	var c *Call
    114 	if idx < len(p.Calls) {
    115 		c = p.Calls[idx]
    116 	}
    117 	s := analyze(ctx.ct, p, c)
    118 	calls := r.generateCall(s, p)
    119 	p.insertBefore(c, calls)
    120 	return true
    121 }
    122 
    123 func (ctx *mutator) removeCall() bool {
    124 	p, r := ctx.p, ctx.r
    125 	if len(p.Calls) == 0 {
    126 		return false
    127 	}
    128 	idx := r.Intn(len(p.Calls))
    129 	p.removeCall(idx)
    130 	return true
    131 }
    132 
    133 func (ctx *mutator) mutateArg() bool {
    134 	p, r := ctx.p, ctx.r
    135 	if len(p.Calls) == 0 {
    136 		return false
    137 	}
    138 	c := p.Calls[r.Intn(len(p.Calls))]
    139 	if len(c.Args) == 0 {
    140 		return false
    141 	}
    142 	s := analyze(ctx.ct, p, c)
    143 	updateSizes := true
    144 	for stop, ok := false, false; !stop; stop = ok && r.oneOf(3) {
    145 		ok = true
    146 		ma := &mutationArgs{target: p.Target}
    147 		ForeachArg(c, ma.collectArg)
    148 		if len(ma.args) == 0 {
    149 			return false
    150 		}
    151 		idx := r.Intn(len(ma.args))
    152 		arg, ctx := ma.args[idx], ma.ctxes[idx]
    153 		calls, ok1 := p.Target.mutateArg(r, s, arg, ctx, &updateSizes)
    154 		if !ok1 {
    155 			ok = false
    156 			continue
    157 		}
    158 		p.insertBefore(c, calls)
    159 		if updateSizes {
    160 			p.Target.assignSizesCall(c)
    161 		}
    162 		p.Target.SanitizeCall(c)
    163 	}
    164 	return true
    165 }
    166 
    167 func (target *Target) mutateArg(r *randGen, s *state, arg Arg, ctx ArgCtx, updateSizes *bool) ([]*Call, bool) {
    168 	var baseSize uint64
    169 	if ctx.Base != nil {
    170 		baseSize = ctx.Base.Res.Size()
    171 	}
    172 	calls, retry, preserve := arg.Type().mutate(r, s, arg, ctx)
    173 	if retry {
    174 		return nil, false
    175 	}
    176 	if preserve {
    177 		*updateSizes = false
    178 	}
    179 	// Update base pointer if size has increased.
    180 	if base := ctx.Base; base != nil && baseSize < base.Res.Size() {
    181 		newArg := r.allocAddr(s, base.Type(), base.Res.Size(), base.Res)
    182 		replaceArg(base, newArg)
    183 	}
    184 	for _, c := range calls {
    185 		target.SanitizeCall(c)
    186 	}
    187 	return calls, true
    188 }
    189 
    190 func regenerate(r *randGen, s *state, arg Arg) (calls []*Call, retry, preserve bool) {
    191 	var newArg Arg
    192 	newArg, calls = r.generateArg(s, arg.Type())
    193 	replaceArg(arg, newArg)
    194 	return
    195 }
    196 
    197 func mutateInt(r *randGen, s *state, arg Arg) (calls []*Call, retry, preserve bool) {
    198 	if r.bin() {
    199 		return regenerate(r, s, arg)
    200 	}
    201 	a := arg.(*ConstArg)
    202 	switch {
    203 	case r.nOutOf(1, 3):
    204 		a.Val += uint64(r.Intn(4)) + 1
    205 	case r.nOutOf(1, 2):
    206 		a.Val -= uint64(r.Intn(4)) + 1
    207 	default:
    208 		a.Val ^= 1 << uint64(r.Intn(64))
    209 	}
    210 	return
    211 }
    212 
    213 func (t *IntType) mutate(r *randGen, s *state, arg Arg, ctx ArgCtx) (calls []*Call, retry, preserve bool) {
    214 	return mutateInt(r, s, arg)
    215 }
    216 
    217 func (t *FlagsType) mutate(r *randGen, s *state, arg Arg, ctx ArgCtx) (calls []*Call, retry, preserve bool) {
    218 	return mutateInt(r, s, arg)
    219 }
    220 
    221 func (t *LenType) mutate(r *randGen, s *state, arg Arg, ctx ArgCtx) (calls []*Call, retry, preserve bool) {
    222 	if !r.mutateSize(arg.(*ConstArg), *ctx.Parent) {
    223 		retry = true
    224 		return
    225 	}
    226 	preserve = true
    227 	return
    228 }
    229 
    230 func (t *ResourceType) mutate(r *randGen, s *state, arg Arg, ctx ArgCtx) (calls []*Call, retry, preserve bool) {
    231 	return regenerate(r, s, arg)
    232 }
    233 
    234 func (t *VmaType) mutate(r *randGen, s *state, arg Arg, ctx ArgCtx) (calls []*Call, retry, preserve bool) {
    235 	return regenerate(r, s, arg)
    236 }
    237 
    238 func (t *ProcType) mutate(r *randGen, s *state, arg Arg, ctx ArgCtx) (calls []*Call, retry, preserve bool) {
    239 	return regenerate(r, s, arg)
    240 }
    241 
    242 func (t *BufferType) mutate(r *randGen, s *state, arg Arg, ctx ArgCtx) (calls []*Call, retry, preserve bool) {
    243 	a := arg.(*DataArg)
    244 	switch t.Kind {
    245 	case BufferBlobRand, BufferBlobRange:
    246 		data := append([]byte{}, a.Data()...)
    247 		minLen, maxLen := uint64(0), maxBlobLen
    248 		if t.Kind == BufferBlobRange {
    249 			minLen, maxLen = t.RangeBegin, t.RangeEnd
    250 		}
    251 		a.data = mutateData(r, data, minLen, maxLen)
    252 	case BufferString:
    253 		data := append([]byte{}, a.Data()...)
    254 		if r.bin() {
    255 			minLen, maxLen := uint64(0), maxBlobLen
    256 			if t.TypeSize != 0 {
    257 				minLen, maxLen = t.TypeSize, t.TypeSize
    258 			}
    259 			a.data = mutateData(r, data, minLen, maxLen)
    260 		} else {
    261 			a.data = r.randString(s, t)
    262 		}
    263 	case BufferFilename:
    264 		a.data = []byte(r.filename(s, t))
    265 	case BufferText:
    266 		data := append([]byte{}, a.Data()...)
    267 		a.data = r.mutateText(t.Text, data)
    268 	default:
    269 		panic("unknown buffer kind")
    270 	}
    271 	return
    272 }
    273 
    274 func (t *ArrayType) mutate(r *randGen, s *state, arg Arg, ctx ArgCtx) (calls []*Call, retry, preserve bool) {
    275 	// TODO: swap elements of the array
    276 	a := arg.(*GroupArg)
    277 	count := uint64(0)
    278 	switch t.Kind {
    279 	case ArrayRandLen:
    280 		for count == uint64(len(a.Inner)) {
    281 			count = r.randArrayLen()
    282 		}
    283 	case ArrayRangeLen:
    284 		if t.RangeBegin == t.RangeEnd {
    285 			panic("trying to mutate fixed length array")
    286 		}
    287 		for count == uint64(len(a.Inner)) {
    288 			count = r.randRange(t.RangeBegin, t.RangeEnd)
    289 		}
    290 	}
    291 	if count > uint64(len(a.Inner)) {
    292 		for count > uint64(len(a.Inner)) {
    293 			newArg, newCalls := r.generateArg(s, t.Type)
    294 			a.Inner = append(a.Inner, newArg)
    295 			calls = append(calls, newCalls...)
    296 			for _, c := range newCalls {
    297 				s.analyze(c)
    298 			}
    299 		}
    300 	} else if count < uint64(len(a.Inner)) {
    301 		for _, arg := range a.Inner[count:] {
    302 			removeArg(arg)
    303 		}
    304 		a.Inner = a.Inner[:count]
    305 	}
    306 	return
    307 }
    308 
    309 func (t *PtrType) mutate(r *randGen, s *state, arg Arg, ctx ArgCtx) (calls []*Call, retry, preserve bool) {
    310 	a := arg.(*PointerArg)
    311 	newArg := r.allocAddr(s, t, a.Res.Size(), a.Res)
    312 	replaceArg(arg, newArg)
    313 	return
    314 }
    315 
    316 func (t *StructType) mutate(r *randGen, s *state, arg Arg, ctx ArgCtx) (calls []*Call, retry, preserve bool) {
    317 	gen := r.target.SpecialTypes[t.Name()]
    318 	if gen == nil {
    319 		panic("bad arg returned by mutationArgs: StructType")
    320 	}
    321 	var newArg Arg
    322 	newArg, calls = gen(&Gen{r, s}, t, arg)
    323 	a := arg.(*GroupArg)
    324 	for i, f := range newArg.(*GroupArg).Inner {
    325 		replaceArg(a.Inner[i], f)
    326 	}
    327 	return
    328 }
    329 
    330 func (t *UnionType) mutate(r *randGen, s *state, arg Arg, ctx ArgCtx) (calls []*Call, retry, preserve bool) {
    331 	if gen := r.target.SpecialTypes[t.Name()]; gen != nil {
    332 		var newArg Arg
    333 		newArg, calls = gen(&Gen{r, s}, t, arg)
    334 		replaceArg(arg, newArg)
    335 	} else {
    336 		a := arg.(*UnionArg)
    337 		current := -1
    338 		for i, option := range t.Fields {
    339 			if a.Option.Type().FieldName() == option.FieldName() {
    340 				current = i
    341 				break
    342 			}
    343 		}
    344 		if current == -1 {
    345 			panic("can't find current option in union")
    346 		}
    347 		newIdx := r.Intn(len(t.Fields) - 1)
    348 		if newIdx >= current {
    349 			newIdx++
    350 		}
    351 		optType := t.Fields[newIdx]
    352 		removeArg(a.Option)
    353 		var newOpt Arg
    354 		newOpt, calls = r.generateArg(s, optType)
    355 		replaceArg(arg, MakeUnionArg(t, newOpt))
    356 	}
    357 	return
    358 }
    359 
    360 func (t *CsumType) mutate(r *randGen, s *state, arg Arg, ctx ArgCtx) (calls []*Call, retry, preserve bool) {
    361 	panic("CsumType can't be mutated")
    362 }
    363 
    364 func (t *ConstType) mutate(r *randGen, s *state, arg Arg, ctx ArgCtx) (calls []*Call, retry, preserve bool) {
    365 	panic("ConstType can't be mutated")
    366 }
    367 
    368 type mutationArgs struct {
    369 	target        *Target
    370 	args          []Arg
    371 	ctxes         []ArgCtx
    372 	ignoreSpecial bool
    373 }
    374 
    375 func (ma *mutationArgs) collectArg(arg Arg, ctx *ArgCtx) {
    376 	ignoreSpecial := ma.ignoreSpecial
    377 	ma.ignoreSpecial = false
    378 	switch typ := arg.Type().(type) {
    379 	case *StructType:
    380 		if ma.target.SpecialTypes[typ.Name()] == nil || ignoreSpecial {
    381 			return // For structs only individual fields are updated.
    382 		}
    383 		// These special structs are mutated as a whole.
    384 		ctx.Stop = true
    385 	case *UnionType:
    386 		if ma.target.SpecialTypes[typ.Name()] == nil && len(typ.Fields) == 1 || ignoreSpecial {
    387 			return
    388 		}
    389 		ctx.Stop = true
    390 	case *ArrayType:
    391 		// Don't mutate fixed-size arrays.
    392 		if typ.Kind == ArrayRangeLen && typ.RangeBegin == typ.RangeEnd {
    393 			return
    394 		}
    395 	case *CsumType:
    396 		return // Checksum is updated when the checksummed data changes.
    397 	case *ConstType:
    398 		return // Well, this is const.
    399 	case *BufferType:
    400 		if typ.Kind == BufferString && len(typ.Values) == 1 {
    401 			return // string const
    402 		}
    403 	case *PtrType:
    404 		if arg.(*PointerArg).IsNull() {
    405 			// TODO: we ought to mutate this, but we don't have code for this yet.
    406 			return
    407 		}
    408 	}
    409 	typ := arg.Type()
    410 	if typ == nil || typ.Dir() == DirOut || !typ.Varlen() && typ.Size() == 0 {
    411 		return
    412 	}
    413 	ma.args = append(ma.args, arg)
    414 	ma.ctxes = append(ma.ctxes, *ctx)
    415 }
    416 
    417 func mutateData(r *randGen, data []byte, minLen, maxLen uint64) []byte {
    418 	for stop := false; !stop; stop = stop && r.oneOf(3) {
    419 		f := mutateDataFuncs[r.Intn(len(mutateDataFuncs))]
    420 		data, stop = f(r, data, minLen, maxLen)
    421 	}
    422 	return data
    423 }
    424 
    425 const maxInc = 35
    426 
    427 var mutateDataFuncs = [...]func(r *randGen, data []byte, minLen, maxLen uint64) ([]byte, bool){
    428 	// TODO(dvyukov): duplicate part of data.
    429 	// Flip bit in byte.
    430 	func(r *randGen, data []byte, minLen, maxLen uint64) ([]byte, bool) {
    431 		if len(data) == 0 {
    432 			return data, false
    433 		}
    434 		byt := r.Intn(len(data))
    435 		bit := r.Intn(8)
    436 		data[byt] ^= 1 << uint(bit)
    437 		return data, true
    438 	},
    439 	// Insert random bytes.
    440 	func(r *randGen, data []byte, minLen, maxLen uint64) ([]byte, bool) {
    441 		if len(data) == 0 {
    442 			return data, false
    443 		}
    444 		n := r.Intn(16) + 1
    445 		if r := int(maxLen) - len(data); n > r {
    446 			n = r
    447 		}
    448 		pos := r.Intn(len(data))
    449 		for i := 0; i < n; i++ {
    450 			data = append(data, 0)
    451 		}
    452 		copy(data[pos+n:], data[pos:])
    453 		for i := 0; i < n; i++ {
    454 			data[pos+i] = byte(r.Int31())
    455 		}
    456 		if uint64(len(data)) > maxLen || r.bin() {
    457 			data = data[:len(data)-n] // preserve original length
    458 		}
    459 		return data, true
    460 	},
    461 	// Remove bytes.
    462 	func(r *randGen, data []byte, minLen, maxLen uint64) ([]byte, bool) {
    463 		if len(data) == 0 {
    464 			return data, false
    465 		}
    466 		n := r.Intn(16) + 1
    467 		if n > len(data) {
    468 			n = len(data)
    469 		}
    470 		pos := 0
    471 		if n < len(data) {
    472 			pos = r.Intn(len(data) - n)
    473 		}
    474 		copy(data[pos:], data[pos+n:])
    475 		data = data[:len(data)-n]
    476 		if uint64(len(data)) < minLen || r.bin() {
    477 			for i := 0; i < n; i++ {
    478 				data = append(data, 0) // preserve original length
    479 			}
    480 		}
    481 		return data, true
    482 	},
    483 	// Append a bunch of bytes.
    484 	func(r *randGen, data []byte, minLen, maxLen uint64) ([]byte, bool) {
    485 		if uint64(len(data)) >= maxLen {
    486 			return data, false
    487 		}
    488 		const max = 256
    489 		n := max - r.biasedRand(max, 10)
    490 		if r := int(maxLen) - len(data); n > r {
    491 			n = r
    492 		}
    493 		for i := 0; i < n; i++ {
    494 			data = append(data, byte(r.rand(256)))
    495 		}
    496 		return data, true
    497 	},
    498 	// Replace int8/int16/int32/int64 with a random value.
    499 	func(r *randGen, data []byte, minLen, maxLen uint64) ([]byte, bool) {
    500 		width := 1 << uint(r.Intn(4))
    501 		if len(data) < width {
    502 			return data, false
    503 		}
    504 		i := r.Intn(len(data) - width + 1)
    505 		storeInt(data[i:], r.Uint64(), width)
    506 		return data, true
    507 	},
    508 	// Add/subtract from an int8/int16/int32/int64.
    509 	func(r *randGen, data []byte, minLen, maxLen uint64) ([]byte, bool) {
    510 		width := 1 << uint(r.Intn(4))
    511 		if len(data) < width {
    512 			return data, false
    513 		}
    514 		i := r.Intn(len(data) - width + 1)
    515 		v := loadInt(data[i:], width)
    516 		delta := r.rand(2*maxInc+1) - maxInc
    517 		if delta == 0 {
    518 			delta = 1
    519 		}
    520 		if r.oneOf(10) {
    521 			v = swapInt(v, width)
    522 			v += delta
    523 			v = swapInt(v, width)
    524 		} else {
    525 			v += delta
    526 		}
    527 		storeInt(data[i:], v, width)
    528 		return data, true
    529 	},
    530 	// Set int8/int16/int32/int64 to an interesting value.
    531 	func(r *randGen, data []byte, minLen, maxLen uint64) ([]byte, bool) {
    532 		width := 1 << uint(r.Intn(4))
    533 		if len(data) < width {
    534 			return data, false
    535 		}
    536 		i := r.Intn(len(data) - width + 1)
    537 		value := r.randInt()
    538 		if r.oneOf(10) {
    539 			value = swap64(value)
    540 		}
    541 		storeInt(data[i:], value, width)
    542 		return data, true
    543 	},
    544 }
    545 
    546 func swap16(v uint16) uint16 {
    547 	v0 := byte(v >> 0)
    548 	v1 := byte(v >> 8)
    549 	v = 0
    550 	v |= uint16(v1) << 0
    551 	v |= uint16(v0) << 8
    552 	return v
    553 }
    554 
    555 func swap32(v uint32) uint32 {
    556 	v0 := byte(v >> 0)
    557 	v1 := byte(v >> 8)
    558 	v2 := byte(v >> 16)
    559 	v3 := byte(v >> 24)
    560 	v = 0
    561 	v |= uint32(v3) << 0
    562 	v |= uint32(v2) << 8
    563 	v |= uint32(v1) << 16
    564 	v |= uint32(v0) << 24
    565 	return v
    566 }
    567 
    568 func swap64(v uint64) uint64 {
    569 	v0 := byte(v >> 0)
    570 	v1 := byte(v >> 8)
    571 	v2 := byte(v >> 16)
    572 	v3 := byte(v >> 24)
    573 	v4 := byte(v >> 32)
    574 	v5 := byte(v >> 40)
    575 	v6 := byte(v >> 48)
    576 	v7 := byte(v >> 56)
    577 	v = 0
    578 	v |= uint64(v7) << 0
    579 	v |= uint64(v6) << 8
    580 	v |= uint64(v5) << 16
    581 	v |= uint64(v4) << 24
    582 	v |= uint64(v3) << 32
    583 	v |= uint64(v2) << 40
    584 	v |= uint64(v1) << 48
    585 	v |= uint64(v0) << 56
    586 	return v
    587 }
    588 
    589 func swapInt(v uint64, size int) uint64 {
    590 	switch size {
    591 	case 1:
    592 		return v
    593 	case 2:
    594 		return uint64(swap16(uint16(v)))
    595 	case 4:
    596 		return uint64(swap32(uint32(v)))
    597 	case 8:
    598 		return swap64(v)
    599 	default:
    600 		panic(fmt.Sprintf("swapInt: bad size %v", size))
    601 	}
    602 }
    603 
    604 func loadInt(data []byte, size int) uint64 {
    605 	p := unsafe.Pointer(&data[0])
    606 	switch size {
    607 	case 1:
    608 		return uint64(*(*uint8)(p))
    609 	case 2:
    610 		return uint64(*(*uint16)(p))
    611 	case 4:
    612 		return uint64(*(*uint32)(p))
    613 	case 8:
    614 		return *(*uint64)(p)
    615 	default:
    616 		panic(fmt.Sprintf("loadInt: bad size %v", size))
    617 	}
    618 }
    619 
    620 func storeInt(data []byte, v uint64, size int) {
    621 	p := unsafe.Pointer(&data[0])
    622 	switch size {
    623 	case 1:
    624 		*(*uint8)(p) = uint8(v)
    625 	case 2:
    626 		*(*uint16)(p) = uint16(v)
    627 	case 4:
    628 		*(*uint32)(p) = uint32(v)
    629 	case 8:
    630 		*(*uint64)(p) = v
    631 	default:
    632 		panic(fmt.Sprintf("storeInt: bad size %v", size))
    633 	}
    634 }
    635