mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-07-26 06:38:42 +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
|
||||
}
|
||||
+37
-2
@@ -5,6 +5,7 @@ target triple = "wasm32-unknown-unknown-wasm"
|
||||
|
||||
@runtime.stackChainStart = internal global %runtime.stackChainObject* null
|
||||
@someGlobal = global i8 3
|
||||
@ptrGlobal = global i8** null
|
||||
|
||||
declare void @runtime.trackPointer(i8* nocapture readonly)
|
||||
|
||||
@@ -25,9 +26,9 @@ define i8* @needsStackSlots() {
|
||||
%ptr = call i8* @runtime.alloc(i32 4, i8* null)
|
||||
%4 = getelementptr { %runtime.stackChainObject*, i32, i8* }, { %runtime.stackChainObject*, i32, i8* }* %gc.stackobject, i32 0, i32 2
|
||||
store i8* %ptr, i8** %4, align 4
|
||||
store %runtime.stackChainObject* %1, %runtime.stackChainObject** @runtime.stackChainStart, align 4
|
||||
call void @someArbitraryFunction()
|
||||
%val = load i8, i8* @someGlobal, align 1
|
||||
store %runtime.stackChainObject* %1, %runtime.stackChainObject** @runtime.stackChainStart, align 4
|
||||
ret i8* %ptr
|
||||
}
|
||||
|
||||
@@ -75,8 +76,8 @@ define i8* @fibNext(i8* %x, i8* %y) {
|
||||
%out.alloc = call i8* @runtime.alloc(i32 1, i8* null)
|
||||
%4 = getelementptr { %runtime.stackChainObject*, i32, i8* }, { %runtime.stackChainObject*, i32, i8* }* %gc.stackobject, i32 0, i32 2
|
||||
store i8* %out.alloc, i8** %4, align 4
|
||||
store %runtime.stackChainObject* %1, %runtime.stackChainObject** @runtime.stackChainStart, align 4
|
||||
store i8 %out.val, i8* %out.alloc, align 1
|
||||
store %runtime.stackChainObject* %1, %runtime.stackChainObject** @runtime.stackChainStart, align 4
|
||||
ret i8* %out.alloc
|
||||
}
|
||||
|
||||
@@ -141,3 +142,37 @@ define void @testGEPBitcast() {
|
||||
define void @someArbitraryFunction() {
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @earlyPopRegression() {
|
||||
%gc.stackobject = alloca { %runtime.stackChainObject*, i32, i8* }, align 8
|
||||
store { %runtime.stackChainObject*, i32, i8* } { %runtime.stackChainObject* null, i32 1, i8* null }, { %runtime.stackChainObject*, i32, i8* }* %gc.stackobject, align 4
|
||||
%1 = load %runtime.stackChainObject*, %runtime.stackChainObject** @runtime.stackChainStart, align 4
|
||||
%2 = getelementptr { %runtime.stackChainObject*, i32, i8* }, { %runtime.stackChainObject*, i32, i8* }* %gc.stackobject, i32 0, i32 0
|
||||
store %runtime.stackChainObject* %1, %runtime.stackChainObject** %2, align 4
|
||||
%3 = bitcast { %runtime.stackChainObject*, i32, i8* }* %gc.stackobject to %runtime.stackChainObject*
|
||||
store %runtime.stackChainObject* %3, %runtime.stackChainObject** @runtime.stackChainStart, align 4
|
||||
%x.alloc = call i8* @runtime.alloc(i32 4, i8* null)
|
||||
%4 = getelementptr { %runtime.stackChainObject*, i32, i8* }, { %runtime.stackChainObject*, i32, i8* }* %gc.stackobject, i32 0, i32 2
|
||||
store i8* %x.alloc, i8** %4, align 4
|
||||
%x = bitcast i8* %x.alloc to i8**
|
||||
call void @allocAndSave(i8** %x)
|
||||
store %runtime.stackChainObject* %1, %runtime.stackChainObject** @runtime.stackChainStart, align 4
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @allocAndSave(i8** %x) {
|
||||
%gc.stackobject = alloca { %runtime.stackChainObject*, i32, i8* }, align 8
|
||||
store { %runtime.stackChainObject*, i32, i8* } { %runtime.stackChainObject* null, i32 1, i8* null }, { %runtime.stackChainObject*, i32, i8* }* %gc.stackobject, align 4
|
||||
%1 = load %runtime.stackChainObject*, %runtime.stackChainObject** @runtime.stackChainStart, align 4
|
||||
%2 = getelementptr { %runtime.stackChainObject*, i32, i8* }, { %runtime.stackChainObject*, i32, i8* }* %gc.stackobject, i32 0, i32 0
|
||||
store %runtime.stackChainObject* %1, %runtime.stackChainObject** %2, align 4
|
||||
%3 = bitcast { %runtime.stackChainObject*, i32, i8* }* %gc.stackobject to %runtime.stackChainObject*
|
||||
store %runtime.stackChainObject* %3, %runtime.stackChainObject** @runtime.stackChainStart, align 4
|
||||
%y = call i8* @runtime.alloc(i32 4, i8* null)
|
||||
%4 = getelementptr { %runtime.stackChainObject*, i32, i8* }, { %runtime.stackChainObject*, i32, i8* }* %gc.stackobject, i32 0, i32 2
|
||||
store i8* %y, i8** %4, align 4
|
||||
store i8* %y, i8** %x, align 4
|
||||
store i8** %x, i8*** @ptrGlobal, align 4
|
||||
store %runtime.stackChainObject* %1, %runtime.stackChainObject** @runtime.stackChainStart, align 4
|
||||
ret void
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user