From bad18a53de8fa8d3d097e3d701efb72a014661cb Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Tue, 4 Jan 2022 15:29:10 +0100 Subject: 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. --- pkg/compiler/check.go | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) (limited to 'pkg/compiler/check.go') 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) } } } -- cgit mrf-deployment