aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/compiler
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2024-05-03 07:13:00 +0200
committerDmitry Vyukov <dvyukov@google.com>2024-05-03 08:23:29 +0000
commit2ca36995aaecbfcd2268b19cf3445fdf64bb508e (patch)
tree8b4a125e7f593a6c70b754d954f0f3d0b89dc67b /pkg/compiler
parent375d4445a31b220afd91f42a7aa1b610d689a897 (diff)
prog: fix panic during squashing
Netbsd syzbot instance crashes trying to squash a pointer. Pointers must not be squashed. This happens because of recursive ucontext_t type that contains a pointer to itself. When we assign SquashableElem recursive struct types may not be fully generated yet, and ForeachArgType won't observe all types. Assign SquashableElem after all types are fully generated.
Diffstat (limited to 'pkg/compiler')
-rw-r--r--pkg/compiler/compiler_test.go30
-rw-r--r--pkg/compiler/gen.go8
-rw-r--r--pkg/compiler/types.go7
3 files changed, 41 insertions, 4 deletions
diff --git a/pkg/compiler/compiler_test.go b/pkg/compiler/compiler_test.go
index 0a2396b5b..51bbbdf65 100644
--- a/pkg/compiler/compiler_test.go
+++ b/pkg/compiler/compiler_test.go
@@ -355,3 +355,33 @@ foo$2(a ptr[in, string[str1]], b ptr[in, string[str2]])
}
}
}
+
+func TestSquashablePtr(t *testing.T) {
+ t.Parallel()
+ // recursive must not be marked as squashable b/c it contains a pointer.
+ const input = `
+foo(a ptr[in, recursive])
+
+recursive {
+ f0 ptr[in, recursive, opt]
+ f1 int32
+ f2 array[int8]
+}
+`
+ eh := func(pos ast.Pos, msg string) {
+ t.Errorf("%v: %v", pos, msg)
+ }
+ desc := ast.Parse([]byte(input), "input", eh)
+ if desc == nil {
+ t.Fatal("failed to parse")
+ }
+ p := Compile(desc, map[string]uint64{"SYS_foo": 1}, targets.List[targets.TestOS][targets.TestArch64], eh)
+ if p == nil {
+ t.Fatal("failed to compile")
+ }
+ for _, typ := range p.Types {
+ if ptr, ok := typ.(*prog.PtrType); ok && ptr.SquashableElem {
+ t.Fatal("got squashable ptr")
+ }
+ }
+}
diff --git a/pkg/compiler/gen.go b/pkg/compiler/gen.go
index f91e2502c..1fcf8dcac 100644
--- a/pkg/compiler/gen.go
+++ b/pkg/compiler/gen.go
@@ -103,6 +103,14 @@ func (comp *compiler) genSyscalls() []*prog.Syscall {
calls = append(calls, comp.genSyscall(n, callArgSizes[n.CallName]))
}
}
+ // We assign SquashableElem here rather than during pointer type generation
+ // because during pointer generation recursive struct types may not be fully
+ // generated yet, thus ForeachArgType won't observe all types.
+ prog.ForeachTypePost(calls, func(typ prog.Type, ctx *prog.TypeCtx) {
+ if ptr, ok := typ.(*prog.PtrType); ok {
+ ptr.SquashableElem = isSquashableElem(ptr.Elem, ptr.ElemDir)
+ }
+ })
sort.Slice(calls, func(i, j int) bool {
return calls[i].Name < calls[j].Name
})
diff --git a/pkg/compiler/types.go b/pkg/compiler/types.go
index 70a0bd565..906af199c 100644
--- a/pkg/compiler/types.go
+++ b/pkg/compiler/types.go
@@ -213,10 +213,9 @@ var typePtr = &typeDesc{
elem := comp.genType(args[1], 0)
elemDir := genDir(args[0])
return &prog.PtrType{
- TypeCommon: base.TypeCommon,
- Elem: elem,
- ElemDir: elemDir,
- SquashableElem: isSquashableElem(elem, elemDir),
+ TypeCommon: base.TypeCommon,
+ Elem: elem,
+ ElemDir: elemDir,
}
},
}