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:
Nia Waldvogel
2022-06-03 12:41:36 -04:00
committed by Ayke
parent 906757603d
commit 2c93a4085c
3 changed files with 65 additions and 34 deletions
+10 -30
View File
@@ -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)
}
}