aboutsummaryrefslogtreecommitdiffstats
path: root/prog
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2020-05-03 16:53:36 +0200
committerDmitry Vyukov <dvyukov@google.com>2020-05-05 14:01:52 +0200
commit1905d7c090a13a8b94e5d19a5388104f2d7693fd (patch)
tree35a501ee366d2d41b46da91af19a01485f9bae66 /prog
parent3dda7e67688077f3c6f91450d18dc14c776d3872 (diff)
prog: refactor ANY to not fabricate new types
Currently ANY implementation fabricates new types dynamically. This is something we don't do anywhere else, generally types come from compiler and all are static. Dynamic types will conflict with use of Ref in Arg optimization. Move ANY types creation into compiler. Update #1580
Diffstat (limited to 'prog')
-rw-r--r--prog/any.go99
-rw-r--r--prog/decl_test.go3
-rw-r--r--prog/rand.go2
-rw-r--r--prog/size.go2
-rw-r--r--prog/target.go19
5 files changed, 34 insertions, 91 deletions
diff --git a/prog/any.go b/prog/any.go
index ce3736a4b..7bf38b6be 100644
--- a/prog/any.go
+++ b/prog/any.go
@@ -21,88 +21,29 @@ type anyTypes struct {
resoct *ResourceType
}
-// This generates type descriptions for:
-//
-// resource ANYRES16[int16]: 0xffffffffffffffff, 0
-// resource ANYRES32[int32]: 0xffffffffffffffff, 0
-// resource ANYRES64[int64]: 0xffffffffffffffff, 0
-// ANY [
-// bin array[int8]
-// res16 ANYRES16
-// res32 ANYRES32
-// res64 ANYRES64
-// resdec fmt[dec, ANYRES64]
-// reshex fmt[hex, ANYRES64]
-// resoct fmt[oct, ANYRES64]
-// ] [varlen]
-func initAnyTypes(target *Target) {
- target.any.union = &UnionType{
- TypeCommon: TypeCommon{
- TypeName: "ANYUNION",
- IsVarlen: true,
- },
- }
- target.any.array = &ArrayType{
- TypeCommon: TypeCommon{
- TypeName: "ANYARRAY",
- IsVarlen: true,
- },
- Elem: target.any.union,
- }
- target.any.ptrPtr = &PtrType{
- TypeCommon: TypeCommon{
- TypeName: "ANYPTR",
- TypeSize: target.PtrSize,
- IsOptional: true,
- },
- Elem: target.any.array,
- ElemDir: DirIn,
- }
- target.any.ptr64 = &PtrType{
- TypeCommon: TypeCommon{
- TypeName: "ANYPTR64",
- TypeSize: 8,
- IsOptional: true,
- },
- Elem: target.any.array,
- ElemDir: DirIn,
- }
- target.any.blob = &BufferType{
- TypeCommon: TypeCommon{
- TypeName: "ANYBLOB",
- IsVarlen: true,
- },
- }
- createResource := func(name, base string, bf BinaryFormat, size uint64) *ResourceType {
- return &ResourceType{
- TypeCommon: TypeCommon{
- TypeName: name,
- TypeSize: size,
- IsOptional: true,
- },
- ArgFormat: bf,
- Desc: &ResourceDesc{
- Name: name,
- Kind: []string{name},
- Values: []uint64{^uint64(0), 0},
- },
+func (target *Target) initAnyTypes() {
+ var anyPtrs *UnionType
+ for _, typ := range target.types {
+ if typ.Name() == "ANYPTRS" {
+ anyPtrs = typ.(*UnionType)
+ break
}
}
- target.any.res16 = createResource("ANYRES16", "int16", FormatNative, 2)
- target.any.res32 = createResource("ANYRES32", "int32", FormatNative, 4)
- target.any.res64 = createResource("ANYRES64", "int64", FormatNative, 8)
- target.any.resdec = createResource("ANYRESDEC", "int64", FormatStrDec, 20)
- target.any.reshex = createResource("ANYRESHEX", "int64", FormatStrHex, 18)
- target.any.resoct = createResource("ANYRESOCT", "int64", FormatStrOct, 23)
- target.any.union.Fields = []Field{
- {Name: "ANYBLOB", Type: target.any.blob},
- {Name: "ANYRES16", Type: target.any.res16},
- {Name: "ANYRES32", Type: target.any.res32},
- {Name: "ANYRES64", Type: target.any.res64},
- {Name: "ANYRESDEC", Type: target.any.resdec},
- {Name: "ANYRESHEX", Type: target.any.reshex},
- {Name: "ANYRESOCT", Type: target.any.resoct},
+ if anyPtrs == nil {
+ panic("no builtin ANYPTRS type")
}
+ // These types are generated by builtin descriptions in pkg/compiler/types.go.
+ target.any.ptrPtr = anyPtrs.Fields[0].Type.(*PtrType)
+ target.any.ptr64 = anyPtrs.Fields[1].Type.(*PtrType)
+ target.any.array = target.any.ptrPtr.Elem.(*ArrayType)
+ target.any.union = target.any.array.Elem.(*UnionType)
+ target.any.blob = target.any.union.Fields[0].Type.(*BufferType)
+ target.any.res16 = target.any.union.Fields[1].Type.(*ResourceType)
+ target.any.res32 = target.any.union.Fields[2].Type.(*ResourceType)
+ target.any.res64 = target.any.union.Fields[3].Type.(*ResourceType)
+ target.any.resdec = target.any.union.Fields[4].Type.(*ResourceType)
+ target.any.reshex = target.any.union.Fields[5].Type.(*ResourceType)
+ target.any.resoct = target.any.union.Fields[6].Type.(*ResourceType)
}
func (target *Target) getAnyPtrType(size uint64) *PtrType {
diff --git a/prog/decl_test.go b/prog/decl_test.go
index f999ae589..5f1795ec6 100644
--- a/prog/decl_test.go
+++ b/prog/decl_test.go
@@ -13,9 +13,8 @@ func TestResourceCtors(t *testing.T) {
t.Skip("too slow")
}
testEachTarget(t, func(t *testing.T, target *Target) {
- expectFail := false
for _, res := range target.Resources {
- if len(target.calcResourceCtors(res, true)) == 0 != expectFail {
+ if len(target.calcResourceCtors(res, true)) == 0 && !strings.HasPrefix(res.Name, "ANY") {
t.Errorf("resource %v can't be created", res.Name)
}
}
diff --git a/prog/rand.go b/prog/rand.go
index 150f4b266..18c86d77a 100644
--- a/prog/rand.go
+++ b/prog/rand.go
@@ -568,7 +568,7 @@ func (target *Target) GenerateAllSyzProg(rs rand.Source) *Prog {
s := newState(target, target.DefaultChoiceTable(), nil)
handled := make(map[string]bool)
for _, meta := range target.Syscalls {
- if !strings.HasPrefix(meta.CallName, "syz_") || handled[meta.CallName] {
+ if !strings.HasPrefix(meta.CallName, "syz_") || handled[meta.CallName] || meta.Attrs.Disabled {
continue
}
handled[meta.CallName] = true
diff --git a/prog/size.go b/prog/size.go
index 61d382723..6eccec50f 100644
--- a/prog/size.go
+++ b/prog/size.go
@@ -55,7 +55,7 @@ func (target *Target) assignSize(dst *ConstArg, pos Arg, path []string, args []A
offset += buf.Size()
continue
}
- if typ := buf.Type().Name(); typ == target.any.ptrPtr.Name() || typ == target.any.ptr64.Name() {
+ if typ := buf.Type(); typ == target.any.ptrPtr || typ == target.any.ptr64 {
// If path points into squashed argument, we don't have the target argument.
// In such case we simply leave size argument as is. It can't happen during generation,
// only during mutation and mutation can set size to random values, so it should be fine.
diff --git a/prog/target.go b/prog/target.go
index af03dc47f..630fb7cbf 100644
--- a/prog/target.go
+++ b/prog/target.go
@@ -23,7 +23,6 @@ type Target struct {
Syscalls []*Syscall
Resources []*ResourceDesc
Consts []ConstValue
- Types []Type
// MakeDataMmap creates calls that mmaps target data memory range.
MakeDataMmap func() []*Call
@@ -57,10 +56,12 @@ type Target struct {
SpecialPointers []uint64
// Filled by prog package:
+ SyscallMap map[string]*Syscall
+ ConstMap map[string]uint64
+
init sync.Once
initArch func(target *Target)
- SyscallMap map[string]*Syscall
- ConstMap map[string]uint64
+ types []Type
resourceMap map[string]*ResourceDesc
// Maps resource name to a list of calls that can create the resource.
resourceCtors map[string][]*Syscall
@@ -75,12 +76,13 @@ const maxSpecialPointers = 16
var targets = make(map[string]*Target)
-func RegisterTarget(target *Target, initArch func(target *Target)) {
+func RegisterTarget(target *Target, types []Type, initArch func(target *Target)) {
key := target.OS + "/" + target.Arch
if targets[key] != nil {
panic(fmt.Sprintf("duplicate target %v", key))
}
target.initArch = initArch
+ target.types = types
targets[key] = target
}
@@ -122,7 +124,6 @@ func (target *Target) lazyInit() {
target.AnnotateCall = func(c ExecCall) string { return "" }
target.initTarget()
target.initArch(target)
- target.ConstMap = nil // currently used only by initArch
// Give these 2 known addresses fixed positions and prepend target-specific ones at the end.
target.SpecialPointers = append([]uint64{
0x0000000000000000, // NULL pointer (keep this first because code uses special index=0 as NULL)
@@ -132,6 +133,9 @@ func (target *Target) lazyInit() {
if len(target.SpecialPointers) > maxSpecialPointers {
panic("too many special pointers")
}
+ // These are used only during lazyInit.
+ target.ConstMap = nil
+ target.types = nil
}
func (target *Target) initTarget() {
@@ -140,8 +144,8 @@ func (target *Target) initTarget() {
target.ConstMap[c.Name] = c.Value
}
- target.resourceMap = restoreLinks(target.Syscalls, target.Resources, target.Types)
- target.Types = nil
+ target.resourceMap = restoreLinks(target.Syscalls, target.Resources, target.types)
+ target.initAnyTypes()
target.SyscallMap = make(map[string]*Syscall)
for i, c := range target.Syscalls {
@@ -156,7 +160,6 @@ func (target *Target) initTarget() {
for _, res := range target.Resources {
target.resourceCtors[res.Name] = target.calcResourceCtors(res, false)
}
- initAnyTypes(target)
}
func (target *Target) GetConst(name string) uint64 {