From a79edf416c49f32827b12ac5e9ec9ac6ce6dc2fa Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Fri, 3 May 2019 21:11:30 +0200 Subject: [PATCH] cgo: do not allow capturing of external/exported functions Instead of assuming all declared (but not defined) functions are CGo functions, mark all pointer params of externally visible symbols 'nocapture'. This means you may not store pointers between function calls. This is already the case when calling CGo functions upstream: https://golang.org/cmd/cgo/#hdr-Passing_pointers --- compiler/compiler.go | 12 ++++++++++++ compiler/optimizer.go | 12 ------------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/compiler/compiler.go b/compiler/compiler.go index 70951c7a..b4cb5dc8 100644 --- a/compiler/compiler.go +++ b/compiler/compiler.go @@ -629,6 +629,18 @@ func (c *Compiler) parseFuncDecl(f *ir.Function) *Frame { frame.fn.LLVMFn = llvm.AddFunction(c.mod, name, fnType) } + // External/exported functions may not retain pointer values. + // https://golang.org/cmd/cgo/#hdr-Passing_pointers + if f.IsExported() { + nocaptureKind := llvm.AttributeKindID("nocapture") + nocapture := c.ctx.CreateEnumAttribute(nocaptureKind, 0) + for i, typ := range paramTypes { + if typ.TypeKind() == llvm.PointerTypeKind { + frame.fn.LLVMFn.AddAttributeAtIndex(i+1, nocapture) + } + } + } + return frame } diff --git a/compiler/optimizer.go b/compiler/optimizer.go index d412b97b..4efea247 100644 --- a/compiler/optimizer.go +++ b/compiler/optimizer.go @@ -307,18 +307,6 @@ func (c *Compiler) doesEscape(value llvm.Value) bool { return true } } else if use.IsACallInst() != nilValue { - // Call only escapes when the (pointer) parameter is not marked - // "nocapture". This flag means that the parameter does not escape - // the give function. - if use.CalledValue().IsAFunction() != nilValue { - if use.CalledValue().IsDeclaration() { - // Kind of dirty: assume external functions don't let - // pointers escape. - // TODO: introduce //go:noescape that sets the 'nocapture' - // flag on each input parameter. - continue - } - } if !c.hasFlag(use, value, "nocapture") { return true }