172 lines · plain
1; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s2; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s3; RUN: opt -passes=safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s4; RUN: opt -passes=safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s5 6target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"7target triple = "x86_64-unknown-linux-gnu"8 9@.str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 110 11; no arrays / no nested arrays12; Requires no protector.13 14define void @foo(ptr %a) nounwind uwtable safestack {15entry:16 ; CHECK-LABEL: define void @foo(17 ; CHECK-NOT: __safestack_unsafe_stack_ptr18 ; CHECK: ret void19 %a.addr = alloca ptr, align 820 store ptr %a, ptr %a.addr, align 821 %0 = load ptr, ptr %a.addr, align 822 %call = call i32 (ptr, ...) @printf(ptr @.str, ptr %0)23 ret void24}25 26declare i32 @printf(ptr, ...)27 28define void @call_memset(i64 %len) safestack {29entry:30 ; CHECK-LABEL: define void @call_memset31 ; CHECK: @__safestack_unsafe_stack_ptr32 ; CHECK: ret void33 %q = alloca [10 x i8], align 134 call void @llvm.memset.p0.i64(ptr %q, i8 1, i64 %len, i1 false)35 ret void36}37 38define void @call_constant_memset() safestack {39entry:40 ; CHECK-LABEL: define void @call_constant_memset41 ; CHECK-NOT: @__safestack_unsafe_stack_ptr42 ; CHECK: ret void43 %q = alloca [10 x i8], align 144 %arraydecay = getelementptr inbounds [10 x i8], ptr %q, i32 0, i32 245 call void @llvm.memset.p0.i64(ptr %arraydecay, i8 1, i64 7, i1 false)46 ret void47}48 49define void @call_constant_overflow_memset() safestack {50entry:51 ; CHECK-LABEL: define void @call_constant_overflow_memset52 ; CHECK: @__safestack_unsafe_stack_ptr53 ; CHECK: ret void54 %q = alloca [10 x i8], align 155 %arraydecay = getelementptr inbounds [10 x i8], ptr %q, i32 0, i32 756 call void @llvm.memset.p0.i64(ptr %arraydecay, i8 1, i64 5, i1 false)57 ret void58}59 60define void @call_constant_underflow_memset() safestack {61entry:62 ; CHECK-LABEL: define void @call_constant_underflow_memset63 ; CHECK: @__safestack_unsafe_stack_ptr64 ; CHECK: ret void65 %q = alloca [10 x i8], align 166 %arraydecay = getelementptr [10 x i8], ptr %q, i32 0, i32 -167 call void @llvm.memset.p0.i64(ptr %arraydecay, i8 1, i64 3, i1 false)68 ret void69}70 71; Readnone nocapture -> safe72define void @call_readnone(i64 %len) safestack {73entry:74 ; CHECK-LABEL: define void @call_readnone75 ; CHECK-NOT: @__safestack_unsafe_stack_ptr76 ; CHECK: ret void77 %q = alloca [10 x i8], align 178 call void @readnone(ptr %q)79 ret void80}81 82; Arg0 is readnone, arg1 is not. Pass alloca ptr as arg0 -> safe83define void @call_readnone0_0(i64 %len) safestack {84entry:85 ; CHECK-LABEL: define void @call_readnone0_086 ; CHECK-NOT: @__safestack_unsafe_stack_ptr87 ; CHECK: ret void88 %q = alloca [10 x i8], align 189 call void @readnone0(ptr %q, ptr zeroinitializer)90 ret void91}92 93; Arg0 is readnone, arg1 is not. Pass alloca ptr as arg1 -> unsafe94define void @call_readnone0_1(i64 %len) safestack {95entry:96 ; CHECK-LABEL: define void @call_readnone0_197 ; CHECK: @__safestack_unsafe_stack_ptr98 ; CHECK: ret void99 %q = alloca [10 x i8], align 1100 call void @readnone0(ptr zeroinitializer, ptr %q)101 ret void102}103 104; Readonly nocapture -> unsafe105define void @call_readonly(i64 %len) safestack {106entry:107 ; CHECK-LABEL: define void @call_readonly108 ; CHECK: @__safestack_unsafe_stack_ptr109 ; CHECK: ret void110 %q = alloca [10 x i8], align 1111 call void @readonly(ptr %q)112 ret void113}114 115; Readonly nocapture -> unsafe116define void @call_arg_readonly(i64 %len) safestack {117entry:118 ; CHECK-LABEL: define void @call_arg_readonly119 ; CHECK: @__safestack_unsafe_stack_ptr120 ; CHECK: ret void121 %q = alloca [10 x i8], align 1122 call void @arg_readonly(ptr %q)123 ret void124}125 126; Readwrite nocapture -> unsafe127define void @call_readwrite(i64 %len) safestack {128entry:129 ; CHECK-LABEL: define void @call_readwrite130 ; CHECK: @__safestack_unsafe_stack_ptr131 ; CHECK: ret void132 %q = alloca [10 x i8], align 1133 call void @readwrite(ptr %q)134 ret void135}136 137; Captures the argument -> unsafe138define void @call_capture(i64 %len) safestack {139entry:140 ; CHECK-LABEL: define void @call_capture141 ; CHECK: @__safestack_unsafe_stack_ptr142 ; CHECK: ret void143 %q = alloca [10 x i8], align 1144 call void @capture(ptr %q)145 ret void146}147 148; Lifetime intrinsics are always safe.149define void @call_lifetime(ptr %p) {150 ; CHECK-LABEL: define void @call_lifetime151 ; CHECK-NOT: @__safestack_unsafe_stack_ptr152 ; CHECK: ret void153entry:154 %q = alloca [100 x i8], align 16155 call void @llvm.lifetime.start.p0(ptr %q)156 call void @llvm.lifetime.end.p0(ptr %q)157 ret void158}159 160declare void @readonly(ptr nocapture) readonly161declare void @arg_readonly(ptr readonly nocapture)162declare void @readwrite(ptr nocapture)163declare void @capture(ptr readnone) readnone164 165declare void @readnone(ptr nocapture) readnone166declare void @readnone0(ptr nocapture readnone, ptr nocapture)167 168declare void @llvm.memset.p0.i64(ptr nocapture, i8, i64, i1) nounwind argmemonly169 170declare void @llvm.lifetime.start.p0(ptr nocapture) nounwind argmemonly171declare void @llvm.lifetime.end.p0(ptr nocapture) nounwind argmemonly172