mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-04 19:17:47 +00:00
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
This commit is contained in:
committed by
Ron Evans
parent
2511aefac0
commit
a79edf416c
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user