aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/compiler/check.go
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2022-01-04 15:29:10 +0100
committerDmitry Vyukov <dvyukov@google.com>2022-01-11 16:30:08 +0100
commitbad18a53de8fa8d3d097e3d701efb72a014661cb (patch)
tree2ff6cc1aa917897c643d2e4bc5e6ce2098d55a6d /pkg/compiler/check.go
parenta19c1bce2eee5a1893b4ae9c8292b0f1b2630225 (diff)
pkg/compiler: require stricter resource constructors
Don't consider syscalls that return resources in unions/arrays as constructors. Unions and arrays are problematic because we don't have directed generation in prog.randGen.createResource() and can fail to generate a syscall that returns a particular resource (generate a wrong union option that does not contain the necessary resource). This leads to the following panics: panic: failed to create a resource ifindex with ioctl$sock_SIOCGIFCONF Require each resource to have a constructor syscall that returns the resource outside of unions/arrays.
Diffstat (limited to 'pkg/compiler/check.go')
-rw-r--r--pkg/compiler/check.go21
1 files changed, 13 insertions, 8 deletions
diff --git a/pkg/compiler/check.go b/pkg/compiler/check.go
index fe4ac7c62..ae9724dfc 100644
--- a/pkg/compiler/check.go
+++ b/pkg/compiler/check.go
@@ -632,10 +632,10 @@ func (comp *compiler) checkConstructors() {
switch n := decl.(type) {
case *ast.Call:
for _, arg := range n.Args {
- comp.checkTypeCtors(arg.Type, prog.DirIn, true, ctors, inputs, checked)
+ comp.checkTypeCtors(arg.Type, prog.DirIn, true, true, ctors, inputs, checked)
}
if n.Ret != nil {
- comp.checkTypeCtors(n.Ret, prog.DirOut, true, ctors, inputs, checked)
+ comp.checkTypeCtors(n.Ret, prog.DirOut, true, true, ctors, inputs, checked)
}
}
}
@@ -658,16 +658,19 @@ func (comp *compiler) checkConstructors() {
}
}
-func (comp *compiler) checkTypeCtors(t *ast.Type, dir prog.Dir, isArg bool,
+func (comp *compiler) checkTypeCtors(t *ast.Type, dir prog.Dir, isArg, canCreate bool,
ctors, inputs map[string]bool, checked map[structDir]bool) {
- desc := comp.getTypeDesc(t)
+ desc, args, base := comp.getArgsBase(t, isArg)
+ if base.IsOptional {
+ canCreate = false
+ }
if desc == typeResource {
// TODO(dvyukov): consider changing this to "dir == prog.DirOut".
// We have few questionable cases where resources can be created
// only by inout struct fields. These structs should be split
// into two different structs: one is in and second is out.
// But that will require attaching dir to individual fields.
- if dir != prog.DirIn {
+ if canCreate && dir != prog.DirIn {
r := comp.resources[t.Ident]
for r != nil && !ctors[r.Name.Name] {
ctors[r.Name.Name] = true
@@ -685,6 +688,9 @@ func (comp *compiler) checkTypeCtors(t *ast.Type, dir prog.Dir, isArg bool,
}
if desc == typeStruct {
s := comp.structs[t.Ident]
+ if s.IsUnion {
+ canCreate = false
+ }
name := s.Name.Name
key := structDir{name, dir}
if checked[key] {
@@ -696,17 +702,16 @@ func (comp *compiler) checkTypeCtors(t *ast.Type, dir prog.Dir, isArg bool,
if !fldHasDir {
fldDir = dir
}
- comp.checkTypeCtors(fld.Type, fldDir, false, ctors, inputs, checked)
+ comp.checkTypeCtors(fld.Type, fldDir, false, canCreate, ctors, inputs, checked)
}
return
}
if desc == typePtr {
dir = genDir(t.Args[0])
}
- _, args, _ := comp.getArgsBase(t, isArg)
for i, arg := range args {
if desc.Args[i].Type == typeArgType {
- comp.checkTypeCtors(arg, dir, desc.Args[i].IsArg, ctors, inputs, checked)
+ comp.checkTypeCtors(arg, dir, desc.Args[i].IsArg, canCreate, ctors, inputs, checked)
}
}
}