2017-01-24 12:58:59 +00:00
|
|
|
// Copyright 2017 syzkaller project authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
package prog
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2018-01-24 10:35:22 +00:00
|
|
|
"strings"
|
2017-01-24 12:58:59 +00:00
|
|
|
)
|
|
|
|
|
2017-11-29 08:47:55 +00:00
|
|
|
func (target *Target) generateSize(arg Arg, lenType *LenType) uint64 {
|
2017-01-24 12:58:59 +00:00
|
|
|
if arg == nil {
|
|
|
|
// Arg is an optional pointer, set size to 0.
|
2017-11-29 08:47:55 +00:00
|
|
|
return 0
|
2017-01-24 12:58:59 +00:00
|
|
|
}
|
|
|
|
|
2017-12-31 13:58:00 +00:00
|
|
|
bitSize := lenType.BitSize
|
|
|
|
if bitSize == 0 {
|
|
|
|
bitSize = 8
|
2017-11-29 08:47:55 +00:00
|
|
|
}
|
2017-07-11 14:49:08 +00:00
|
|
|
switch arg.Type().(type) {
|
2017-09-05 08:46:34 +00:00
|
|
|
case *VmaType:
|
2017-07-11 14:49:08 +00:00
|
|
|
a := arg.(*PointerArg)
|
2018-02-19 18:35:04 +00:00
|
|
|
return a.VmaSize * 8 / bitSize
|
2017-09-05 08:46:34 +00:00
|
|
|
case *ArrayType:
|
2017-07-11 14:49:08 +00:00
|
|
|
a := arg.(*GroupArg)
|
2017-12-31 13:58:00 +00:00
|
|
|
if lenType.BitSize != 0 {
|
|
|
|
return a.Size() * 8 / bitSize
|
2017-01-24 12:58:59 +00:00
|
|
|
} else {
|
2017-11-29 08:47:55 +00:00
|
|
|
return uint64(len(a.Inner))
|
2017-01-24 12:58:59 +00:00
|
|
|
}
|
|
|
|
default:
|
2017-12-31 13:58:00 +00:00
|
|
|
return arg.Size() * 8 / bitSize
|
2017-01-24 12:58:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-14 17:25:01 +00:00
|
|
|
func (target *Target) assignSizes(args []Arg, parentsMap map[Arg]Arg) {
|
2017-07-11 14:49:08 +00:00
|
|
|
// Create a map from field names to args.
|
|
|
|
argsMap := make(map[string]Arg)
|
2017-01-24 12:58:59 +00:00
|
|
|
for _, arg := range args {
|
2017-09-05 08:46:34 +00:00
|
|
|
if IsPad(arg.Type()) {
|
2017-01-24 12:58:59 +00:00
|
|
|
continue
|
|
|
|
}
|
2017-07-11 14:49:08 +00:00
|
|
|
argsMap[arg.Type().FieldName()] = arg
|
2017-01-24 12:58:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Fill in size arguments.
|
|
|
|
for _, arg := range args {
|
2017-07-11 14:49:08 +00:00
|
|
|
if arg = InnerArg(arg); arg == nil {
|
2017-01-24 12:58:59 +00:00
|
|
|
continue // Pointer to optional len field, no need to fill in value.
|
|
|
|
}
|
2017-09-05 08:46:34 +00:00
|
|
|
if typ, ok := arg.Type().(*LenType); ok {
|
2017-07-11 14:49:08 +00:00
|
|
|
a := arg.(*ConstArg)
|
|
|
|
|
2017-01-24 12:58:59 +00:00
|
|
|
buf, ok := argsMap[typ.Buf]
|
|
|
|
if ok {
|
2017-11-29 08:47:55 +00:00
|
|
|
a.Val = target.generateSize(InnerArg(buf), typ)
|
2017-01-24 12:58:59 +00:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
if typ.Buf == "parent" {
|
2017-07-11 14:49:08 +00:00
|
|
|
a.Val = parentsMap[arg].Size()
|
2017-12-31 13:58:00 +00:00
|
|
|
if typ.BitSize != 0 {
|
|
|
|
a.Val = a.Val * 8 / typ.BitSize
|
2017-01-24 12:58:59 +00:00
|
|
|
}
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
sizeAssigned := false
|
|
|
|
for parent := parentsMap[arg]; parent != nil; parent = parentsMap[parent] {
|
2018-01-24 10:35:22 +00:00
|
|
|
parentName := parent.Type().Name()
|
|
|
|
if pos := strings.IndexByte(parentName, '['); pos != -1 {
|
|
|
|
// For template parents, strip arguments.
|
|
|
|
parentName = parentName[:pos]
|
|
|
|
}
|
|
|
|
if typ.Buf == parentName {
|
2017-07-11 14:49:08 +00:00
|
|
|
a.Val = parent.Size()
|
2017-12-31 13:58:00 +00:00
|
|
|
if typ.BitSize != 0 {
|
|
|
|
a.Val = a.Val * 8 / typ.BitSize
|
2017-01-24 12:58:59 +00:00
|
|
|
}
|
|
|
|
sizeAssigned = true
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if sizeAssigned {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
panic(fmt.Sprintf("len field '%v' references non existent field '%v', argsMap: %+v",
|
|
|
|
typ.FieldName(), typ.Buf, argsMap))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-14 17:25:01 +00:00
|
|
|
func (target *Target) assignSizesArray(args []Arg) {
|
2017-07-11 14:49:08 +00:00
|
|
|
parentsMap := make(map[Arg]Arg)
|
2018-02-18 12:49:48 +00:00
|
|
|
for _, arg := range args {
|
|
|
|
ForeachSubArg(arg, func(arg Arg, _ *ArgCtx) {
|
|
|
|
if _, ok := arg.Type().(*StructType); ok {
|
|
|
|
for _, field := range arg.(*GroupArg).Inner {
|
|
|
|
parentsMap[InnerArg(field)] = arg
|
|
|
|
}
|
2017-01-24 12:58:59 +00:00
|
|
|
}
|
2018-02-18 12:49:48 +00:00
|
|
|
})
|
|
|
|
}
|
2017-09-14 17:25:01 +00:00
|
|
|
target.assignSizes(args, parentsMap)
|
2018-02-18 12:49:48 +00:00
|
|
|
for _, arg := range args {
|
|
|
|
ForeachSubArg(arg, func(arg Arg, _ *ArgCtx) {
|
|
|
|
if _, ok := arg.Type().(*StructType); ok {
|
|
|
|
target.assignSizes(arg.(*GroupArg).Inner, parentsMap)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
2017-01-24 12:58:59 +00:00
|
|
|
}
|
|
|
|
|
2017-09-14 17:25:01 +00:00
|
|
|
func (target *Target) assignSizesCall(c *Call) {
|
|
|
|
target.assignSizesArray(c.Args)
|
2017-01-24 12:58:59 +00:00
|
|
|
}
|
2017-11-27 07:59:37 +00:00
|
|
|
|
|
|
|
func (r *randGen) mutateSize(arg *ConstArg, parent []Arg) bool {
|
|
|
|
typ := arg.Type().(*LenType)
|
2017-12-31 13:58:00 +00:00
|
|
|
elemSize := typ.BitSize / 8
|
2017-11-27 07:59:37 +00:00
|
|
|
if elemSize == 0 {
|
|
|
|
elemSize = 1
|
|
|
|
for _, field := range parent {
|
|
|
|
if typ.Buf != field.Type().FieldName() {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
if inner := InnerArg(field); inner != nil {
|
|
|
|
switch targetType := inner.Type().(type) {
|
|
|
|
case *VmaType:
|
|
|
|
return false
|
|
|
|
case *ArrayType:
|
2018-02-17 15:51:52 +00:00
|
|
|
if targetType.Type.Varlen() {
|
|
|
|
return false
|
|
|
|
}
|
2017-11-27 07:59:37 +00:00
|
|
|
elemSize = targetType.Type.Size()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if r.oneOf(100) {
|
|
|
|
arg.Val = r.rand64()
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
if r.bin() {
|
|
|
|
// Small adjustment to trigger missed size checks.
|
|
|
|
if arg.Val != 0 && r.bin() {
|
|
|
|
arg.Val = r.randRangeInt(0, arg.Val-1)
|
|
|
|
} else {
|
|
|
|
arg.Val = r.randRangeInt(arg.Val+1, arg.Val+1000)
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
// Try to provoke int overflows.
|
|
|
|
max := ^uint64(0)
|
|
|
|
if r.oneOf(3) {
|
|
|
|
max = 1<<32 - 1
|
|
|
|
if r.oneOf(2) {
|
|
|
|
max = 1<<16 - 1
|
|
|
|
if r.oneOf(2) {
|
|
|
|
max = 1<<8 - 1
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
n := max / elemSize
|
|
|
|
delta := uint64(1000 - r.biasedRand(1000, 10))
|
|
|
|
if elemSize == 1 || r.oneOf(10) {
|
|
|
|
n -= delta
|
|
|
|
} else {
|
|
|
|
n += delta
|
|
|
|
}
|
|
|
|
arg.Val = n
|
|
|
|
return true
|
|
|
|
}
|