diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2020-05-03 16:53:36 +0200 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2020-05-05 14:01:52 +0200 |
| commit | 1905d7c090a13a8b94e5d19a5388104f2d7693fd (patch) | |
| tree | 35a501ee366d2d41b46da91af19a01485f9bae66 /prog | |
| parent | 3dda7e67688077f3c6f91450d18dc14c776d3872 (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.go | 99 | ||||
| -rw-r--r-- | prog/decl_test.go | 3 | ||||
| -rw-r--r-- | prog/rand.go | 2 | ||||
| -rw-r--r-- | prog/size.go | 2 | ||||
| -rw-r--r-- | prog/target.go | 19 |
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 { |
