mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-10 22:13:39 +00:00
transform (MakeGCStackSlots): do not move the stack chain pop earlier
Previously, the MakeGCStackSlots pass would attempt to pop the stack chain before a tail call. This resulted in use-after-free bugs when the tail call allocated memory and used a value allocated by its caller. Instead of trying to move the stack chain pop, remove the tail flag from the call.
This commit is contained in:
+10
-30
@@ -271,37 +271,17 @@ func MakeGCStackSlots(mod llvm.Module) bool {
|
||||
// Make sure this stack object is popped from the linked list of stack
|
||||
// objects at return.
|
||||
for _, ret := range returns {
|
||||
inst := ret
|
||||
// Try to do the popping of the stack object earlier, by inserting
|
||||
// it not right before the return instruction but moving the insert
|
||||
// position up.
|
||||
// This is necessary so that the GC stack slot pass doesn't
|
||||
// interfere with tail calls (in particular, musttail calls).
|
||||
for {
|
||||
prevInst := llvm.PrevInstruction(inst)
|
||||
if prevInst == parent {
|
||||
break
|
||||
}
|
||||
if _, ok := pointerStores[prevInst]; ok {
|
||||
// Pop the stack object after the last store instruction.
|
||||
// This can probably be made more efficient: storing to the
|
||||
// stack chain object and then immediately popping isn't
|
||||
// useful.
|
||||
break
|
||||
}
|
||||
if prevInst.IsNil() {
|
||||
// Start of basic block. Pop the stack object here.
|
||||
break
|
||||
}
|
||||
if !prevInst.IsAPHINode().IsNil() {
|
||||
// Do not insert before a PHI node. PHI nodes must be
|
||||
// grouped at the beginning of a basic block before any
|
||||
// other instruction.
|
||||
break
|
||||
}
|
||||
inst = prevInst
|
||||
// Check for any tail calls at this return.
|
||||
prev := llvm.PrevInstruction(ret)
|
||||
if !prev.IsNil() && !prev.IsABitCastInst().IsNil() {
|
||||
// A bitcast can appear before a tail call, so skip backwards more.
|
||||
prev = llvm.PrevInstruction(prev)
|
||||
}
|
||||
builder.SetInsertPointBefore(inst)
|
||||
if !prev.IsNil() && !prev.IsACallInst().IsNil() {
|
||||
// This is no longer a tail call.
|
||||
prev.SetTailCall(false)
|
||||
}
|
||||
builder.SetInsertPointBefore(ret)
|
||||
builder.CreateStore(parent, stackChainStart)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user