aboutsummaryrefslogtreecommitdiffstats
path: root/tools/syz-check
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2019-12-22 11:19:49 +0100
committerDmitry Vyukov <dvyukov@google.com>2019-12-22 11:19:49 +0100
commitc5907f7c7aa255d8c270c7f05e682d2ef6041553 (patch)
tree55a827fcd4d33c27d5f2b99523ff414f55100558 /tools/syz-check
parent1461be9d82541ed8a2562169fe8719e1cdeeff2b (diff)
tools/syz-check: check templates
Also rename some netfilter types to eliminate massive amounts of template warnings. Update #590
Diffstat (limited to 'tools/syz-check')
-rw-r--r--tools/syz-check/check.go38
1 files changed, 28 insertions, 10 deletions
diff --git a/tools/syz-check/check.go b/tools/syz-check/check.go
index 30fe326d9..effcb273d 100644
--- a/tools/syz-check/check.go
+++ b/tools/syz-check/check.go
@@ -22,6 +22,7 @@ import (
"runtime"
"runtime/pprof"
"sort"
+ "strings"
"github.com/google/syzkaller/pkg/ast"
"github.com/google/syzkaller/pkg/compiler"
@@ -116,7 +117,12 @@ func writeWarnings(OS, arch string, warnings []Warn) error {
return w1.msg < w2.msg
})
buf := new(bytes.Buffer)
+ prev := ""
for _, warn := range warns {
+ if warn.msg == prev {
+ continue // deduplicate warnings in templates
+ }
+ prev = warn.msg
fmt.Fprintf(buf, "%v\n", warn.msg)
}
warnFile := filepath.Join("sys", OS, file+".warn")
@@ -140,16 +146,16 @@ func checkImpl(structs map[string]*dwarf.StructType, structDescs []*prog.KeyedSt
if typ.Varlen() {
continue
}
- astStruct := locs[typ.Name()]
- if astStruct == nil {
- // TODO: that's a template. Handle templates.
- continue
- }
if checked[typ.Name()] {
continue
}
checked[typ.Name()] = true
- warns, err := checkStruct(typ, astStruct, structs[typ.Name()])
+ name := templateName(typ.Name())
+ astStruct := locs[name]
+ if astStruct == nil {
+ continue
+ }
+ warns, err := checkStruct(typ, astStruct, structs[name])
if err != nil {
return nil, err
}
@@ -158,17 +164,25 @@ func checkImpl(structs map[string]*dwarf.StructType, structDescs []*prog.KeyedSt
return warnings, nil
}
+func templateName(name string) string {
+ if pos := strings.IndexByte(name, '['); pos != -1 {
+ name = name[:pos]
+ }
+ return name
+}
+
func checkStruct(typ *prog.StructDesc, astStruct *ast.Struct, str *dwarf.StructType) ([]Warn, error) {
var warnings []Warn
warn := func(pos ast.Pos, msg string, args ...interface{}) {
warnings = append(warnings, Warn{pos, fmt.Sprintf(msg, args...)})
}
+ name := templateName(typ.Name())
if str == nil {
- warn(astStruct.Pos, "struct %v: no corresponding struct in kernel", typ.Name())
+ warn(astStruct.Pos, "struct %v: no corresponding struct in kernel", name)
return warnings, nil
}
if typ.Size() != uint64(str.ByteSize) {
- warn(astStruct.Pos, "struct %v: bad size: syz=%v kernel=%v", typ.Name(), typ.Size(), str.ByteSize)
+ warn(astStruct.Pos, "struct %v: bad size: syz=%v kernel=%v", name, typ.Size(), str.ByteSize)
}
// TODO: handle unions, currently we should report some false errors.
if str.Kind == "union" {
@@ -198,7 +212,7 @@ func checkStruct(typ *prog.StructDesc, astStruct *ast.Struct, str *dwarf.StructT
if ai < len(str.Field) {
fld := str.Field[ai]
pos := astStruct.Fields[ai].Pos
- desc := fmt.Sprintf("field %v.%v", typ.Name(), field.FieldName())
+ desc := fmt.Sprintf("field %v.%v", name, field.FieldName())
if field.FieldName() != fld.Name {
desc += "/" + fld.Name
}
@@ -231,7 +245,7 @@ func checkStruct(typ *prog.StructDesc, astStruct *ast.Struct, str *dwarf.StructT
offset += field.Size()
}
if ai != len(str.Field) {
- warn(astStruct.Pos, "struct %v: bad number of fields: syz=%v kernel=%v", typ.Name(), ai, len(str.Field))
+ warn(astStruct.Pos, "struct %v: bad number of fields: syz=%v kernel=%v", name, ai, len(str.Field))
}
return warnings, nil
}
@@ -261,6 +275,10 @@ func parseDescriptions(OS, arch string) ([]*prog.KeyedStruct, map[string]*ast.St
switch n := decl.(type) {
case *ast.Struct:
locs[n.Name.Name] = n
+ case *ast.TypeDef:
+ if n.Struct != nil {
+ locs[n.Name.Name] = n.Struct
+ }
}
}
return prg.StructDescs, locs, warnings, nil