mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-12 15:03:41 +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:
Vendored
+18
-2
@@ -5,6 +5,7 @@ target triple = "wasm32-unknown-unknown-wasm"
|
||||
|
||||
@runtime.stackChainStart = external global %runtime.stackChainObject*
|
||||
@someGlobal = global i8 3
|
||||
@ptrGlobal = global i8** null
|
||||
|
||||
declare void @runtime.trackPointer(i8* nocapture readonly)
|
||||
|
||||
@@ -20,8 +21,6 @@ define i8* @needsStackSlots() {
|
||||
; so tracking it is not really necessary.
|
||||
%ptr = call i8* @runtime.alloc(i32 4, i8* null)
|
||||
call void @runtime.trackPointer(i8* %ptr)
|
||||
; Restoring the stack pointer can happen at this position, before the return.
|
||||
; This avoids issues with tail calls.
|
||||
call void @someArbitraryFunction()
|
||||
%val = load i8, i8* @someGlobal
|
||||
ret i8* %ptr
|
||||
@@ -103,3 +102,20 @@ define void @testGEPBitcast() {
|
||||
define void @someArbitraryFunction() {
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @earlyPopRegression() {
|
||||
%x.alloc = call i8* @runtime.alloc(i32 4, i8* null)
|
||||
call void @runtime.trackPointer(i8* %x.alloc)
|
||||
%x = bitcast i8* %x.alloc to i8**
|
||||
; At this point the pass used to pop the stack chain, resulting in a potential use-after-free during allocAndSave.
|
||||
musttail call void @allocAndSave(i8** %x)
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @allocAndSave(i8** %x) {
|
||||
%y = call i8* @runtime.alloc(i32 4, i8* null)
|
||||
call void @runtime.trackPointer(i8* %y)
|
||||
store i8* %y, i8** %x
|
||||
store i8** %x, i8*** @ptrGlobal
|
||||
ret void
|
||||
}
|
||||
Reference in New Issue
Block a user