| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| ; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s | ||
| ; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s | ||
|
|
||
| @.str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1 | ||
|
|
||
| ; Address-of local taken (j = &a) | ||
| ; Requires protector. | ||
|
|
||
| define void @foo() nounwind uwtable safestack { | ||
| entry: | ||
| ; CHECK: __safestack_unsafe_stack_ptr | ||
| %retval = alloca i32, align 4 | ||
| %a = alloca i32, align 4 | ||
| %j = alloca i32*, align 8 | ||
| store i32 0, i32* %retval | ||
| %0 = load i32, i32* %a, align 4 | ||
| %add = add nsw i32 %0, 1 | ||
| store i32 %add, i32* %a, align 4 | ||
| store i32* %a, i32** %j, align 8 | ||
| ret void | ||
| } | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| ; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s | ||
| ; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s | ||
|
|
||
| @.str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1 | ||
|
|
||
| ; array of [16 x i8] | ||
|
|
||
| define void @foo(i8* %a) nounwind uwtable safestack { | ||
| entry: | ||
| ; CHECK: %[[USP:.*]] = load i8*, i8** @__safestack_unsafe_stack_ptr | ||
|
|
||
| ; CHECK: %[[USST:.*]] = getelementptr i8, i8* %[[USP]], i32 -16 | ||
|
|
||
| ; CHECK: store i8* %[[USST]], i8** @__safestack_unsafe_stack_ptr | ||
|
|
||
| ; CHECK: %[[AADDR:.*]] = alloca i8*, align 8 | ||
| %a.addr = alloca i8*, align 8 | ||
|
|
||
| ; CHECK: %[[BUFPTR:.*]] = getelementptr i8, i8* %[[USP]], i32 -16 | ||
| ; CHECK: %[[BUFPTR2:.*]] = bitcast i8* %[[BUFPTR]] to [16 x i8]* | ||
| %buf = alloca [16 x i8], align 16 | ||
|
|
||
| ; CHECK: store i8* {{.*}}, i8** %[[AADDR]], align 8 | ||
| store i8* %a, i8** %a.addr, align 8 | ||
|
|
||
| ; CHECK: %[[GEP:.*]] = getelementptr inbounds [16 x i8], [16 x i8]* %[[BUFPTR2]], i32 0, i32 0 | ||
| %gep = getelementptr inbounds [16 x i8], [16 x i8]* %buf, i32 0, i32 0 | ||
|
|
||
| ; CHECK: %[[A2:.*]] = load i8*, i8** %[[AADDR]], align 8 | ||
| %a2 = load i8*, i8** %a.addr, align 8 | ||
|
|
||
| ; CHECK: call i8* @strcpy(i8* %[[GEP]], i8* %[[A2]]) | ||
| %call = call i8* @strcpy(i8* %gep, i8* %a2) | ||
|
|
||
| ; CHECK: store i8* %[[USP]], i8** @__safestack_unsafe_stack_ptr | ||
| ret void | ||
| } | ||
|
|
||
| declare i8* @strcpy(i8*, i8*) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| ; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s | ||
| ; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s | ||
|
|
||
| ; array [4 x i8] | ||
| ; Requires protector. | ||
|
|
||
| define void @foo(i8* %a) nounwind uwtable safestack { | ||
| entry: | ||
| ; CHECK: %[[USP:.*]] = load i8*, i8** @__safestack_unsafe_stack_ptr | ||
|
|
||
| ; CHECK: %[[USST:.*]] = getelementptr i8, i8* %[[USP]], i32 -16 | ||
|
|
||
| ; CHECK: store i8* %[[USST]], i8** @__safestack_unsafe_stack_ptr | ||
|
|
||
| ; CHECK: %[[AADDR:.*]] = alloca i8*, align 8 | ||
| %a.addr = alloca i8*, align 8 | ||
|
|
||
| ; CHECK: %[[BUFPTR:.*]] = getelementptr i8, i8* %[[USP]], i32 -4 | ||
| ; CHECK: %[[BUFPTR2:.*]] = bitcast i8* %[[BUFPTR]] to [4 x i8]* | ||
| %buf = alloca [4 x i8], align 1 | ||
|
|
||
| ; CHECK: store i8* {{.*}}, i8** %[[AADDR]], align 8 | ||
| store i8* %a, i8** %a.addr, align 8 | ||
|
|
||
| ; CHECK: %[[GEP:.*]] = getelementptr inbounds [4 x i8], [4 x i8]* %[[BUFPTR2]], i32 0, i32 0 | ||
| %gep = getelementptr inbounds [4 x i8], [4 x i8]* %buf, i32 0, i32 0 | ||
|
|
||
| ; CHECK: %[[A2:.*]] = load i8*, i8** %[[AADDR]], align 8 | ||
| %a2 = load i8*, i8** %a.addr, align 8 | ||
|
|
||
| ; CHECK: call i8* @strcpy(i8* %[[GEP]], i8* %[[A2]]) | ||
| %call = call i8* @strcpy(i8* %gep, i8* %a2) | ||
|
|
||
| ; CHECK: store i8* %[[USP]], i8** @__safestack_unsafe_stack_ptr | ||
| ret void | ||
| } | ||
|
|
||
| declare i8* @strcpy(i8*, i8*) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| ; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s | ||
| ; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s | ||
|
|
||
| @.str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1 | ||
|
|
||
| ; no arrays / no nested arrays | ||
| ; Requires no protector. | ||
|
|
||
| ; CHECK-LABEL: @foo( | ||
| define void @foo(i8* %a) nounwind uwtable safestack { | ||
| entry: | ||
| ; CHECK-NOT: __safestack_unsafe_stack_ptr | ||
| %a.addr = alloca i8*, align 8 | ||
| store i8* %a, i8** %a.addr, align 8 | ||
| %0 = load i8*, i8** %a.addr, align 8 | ||
| %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i8* %0) | ||
| ret void | ||
| } | ||
|
|
||
| declare i32 @printf(i8*, ...) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| ; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s | ||
| ; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s | ||
|
|
||
| @.str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1 | ||
|
|
||
| ; PtrToInt/IntToPtr Cast | ||
| ; Requires no protector. | ||
|
|
||
| ; CHECK-LABEL: @foo( | ||
| define void @foo() nounwind uwtable safestack { | ||
| entry: | ||
| ; CHECK-NOT: __safestack_unsafe_stack_ptr | ||
| %a = alloca i32, align 4 | ||
| %0 = ptrtoint i32* %a to i64 | ||
| %1 = inttoptr i64 %0 to i32* | ||
| ret void | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| ; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s | ||
| ; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s | ||
|
|
||
| %struct.nest = type { %struct.pair, %struct.pair } | ||
| %struct.pair = type { i32, i32 } | ||
|
|
||
| @.str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1 | ||
|
|
||
| ; Nested structure, no arrays, no address-of expressions. | ||
| ; Verify that the resulting gep-of-gep does not incorrectly trigger | ||
| ; a safe stack protector. | ||
| ; safestack attribute | ||
| ; Requires no protector. | ||
| ; CHECK-LABEL: @foo( | ||
| define void @foo() nounwind uwtable safestack { | ||
| entry: | ||
| ; CHECK-NOT: __safestack_unsafe_stack_ptr | ||
| %c = alloca %struct.nest, align 4 | ||
| %b = getelementptr inbounds %struct.nest, %struct.nest* %c, i32 0, i32 1 | ||
| %_a = getelementptr inbounds %struct.pair, %struct.pair* %b, i32 0, i32 0 | ||
| %0 = load i32, i32* %_a, align 4 | ||
| %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i32 %0) | ||
| ret void | ||
| } | ||
|
|
||
| declare i32 @printf(i8*, ...) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| ; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s | ||
| ; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s | ||
|
|
||
| %class.A = type { [2 x i8] } | ||
|
|
||
| @.str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1 | ||
|
|
||
| ; [2 x i8] in a class | ||
| ; safestack attribute | ||
| ; Requires no protector. | ||
| ; CHECK-LABEL: @foo( | ||
| define signext i8 @foo() nounwind uwtable safestack { | ||
| entry: | ||
| ; CHECK-NOT: __safestack_unsafe_stack_ptr | ||
| %a = alloca %class.A, align 1 | ||
| %array = getelementptr inbounds %class.A, %class.A* %a, i32 0, i32 0 | ||
| %arrayidx = getelementptr inbounds [2 x i8], [2 x i8]* %array, i32 0, i64 0 | ||
| %0 = load i8, i8* %arrayidx, align 1 | ||
| ret i8 %0 | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| ; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s | ||
| ; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s | ||
|
|
||
| %struct.deep = type { %union.anon } | ||
| %union.anon = type { %struct.anon } | ||
| %struct.anon = type { %struct.anon.0 } | ||
| %struct.anon.0 = type { %union.anon.1 } | ||
| %union.anon.1 = type { [2 x i8] } | ||
|
|
||
| @.str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1 | ||
|
|
||
| ; [2 x i8] nested in several layers of structs and unions | ||
| ; safestack attribute | ||
| ; Requires no protector. | ||
| ; CHECK-LABEL: @foo( | ||
| define signext i8 @foo() nounwind uwtable safestack { | ||
| entry: | ||
| ; CHECK-NOT: __safestack_unsafe_stack_ptr | ||
| %x = alloca %struct.deep, align 1 | ||
| %b = getelementptr inbounds %struct.deep, %struct.deep* %x, i32 0, i32 0 | ||
| %c = bitcast %union.anon* %b to %struct.anon* | ||
| %d = getelementptr inbounds %struct.anon, %struct.anon* %c, i32 0, i32 0 | ||
| %e = getelementptr inbounds %struct.anon.0, %struct.anon.0* %d, i32 0, i32 0 | ||
| %array = bitcast %union.anon.1* %e to [2 x i8]* | ||
| %arrayidx = getelementptr inbounds [2 x i8], [2 x i8]* %array, i32 0, i64 0 | ||
| %0 = load i8, i8* %arrayidx, align 1 | ||
| ret i8 %0 | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| ; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s | ||
| ; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s | ||
|
|
||
| @.str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1 | ||
|
|
||
| ; Variable sized alloca | ||
| ; safestack attribute | ||
| ; Requires protector. | ||
| define void @foo(i32 %n) nounwind uwtable safestack { | ||
| entry: | ||
| ; CHECK: __safestack_unsafe_stack_ptr | ||
| %n.addr = alloca i32, align 4 | ||
| %a = alloca i32*, align 8 | ||
| store i32 %n, i32* %n.addr, align 4 | ||
| %0 = load i32, i32* %n.addr, align 4 | ||
| %conv = sext i32 %0 to i64 | ||
| %1 = alloca i8, i64 %conv | ||
| %2 = bitcast i8* %1 to i32* | ||
| store i32* %2, i32** %a, align 8 | ||
| ret void | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| ; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s | ||
| ; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s | ||
|
|
||
| @.str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1 | ||
|
|
||
| ; Addr-of a pointer | ||
| ; safestack attribute | ||
| ; Requires protector. | ||
| define void @foo() nounwind uwtable safestack { | ||
| entry: | ||
| ; CHECK: __safestack_unsafe_stack_ptr | ||
| %a = alloca i32*, align 8 | ||
| %b = alloca i32**, align 8 | ||
| %call = call i32* @getp() | ||
| store i32* %call, i32** %a, align 8 | ||
| store i32** %a, i32*** %b, align 8 | ||
| %0 = load i32**, i32*** %b, align 8 | ||
| call void @funcall2(i32** %0) | ||
| ret void | ||
| } | ||
|
|
||
| declare void @funcall2(i32**) | ||
| declare i32* @getp() |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| ; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s | ||
| ; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s | ||
|
|
||
| @.str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1 | ||
|
|
||
| ; Addr-of a local cast to a ptr of a different type | ||
| ; (e.g., int a; ... ; float *b = &a;) | ||
| ; safestack attribute | ||
| ; Requires protector. | ||
| define void @foo() nounwind uwtable safestack { | ||
| entry: | ||
| ; CHECK: __safestack_unsafe_stack_ptr | ||
| %a = alloca i32, align 4 | ||
| %b = alloca float*, align 8 | ||
| store i32 0, i32* %a, align 4 | ||
| %0 = bitcast i32* %a to float* | ||
| store float* %0, float** %b, align 8 | ||
| %1 = load float*, float** %b, align 8 | ||
| %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), float* %1) | ||
| ret void | ||
| } | ||
|
|
||
| declare i32 @printf(i8*, ...) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| ; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s | ||
| ; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s | ||
|
|
||
| @.str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1 | ||
|
|
||
| ; Addr-of a local cast to a ptr of a different type (optimized) | ||
| ; (e.g., int a; ... ; float *b = &a;) | ||
| ; safestack attribute | ||
| ; Requires protector. | ||
| define void @foo() nounwind uwtable safestack { | ||
| entry: | ||
| ; CHECK: __safestack_unsafe_stack_ptr | ||
| %a = alloca i32, align 4 | ||
| store i32 0, i32* %a, align 4 | ||
| %0 = bitcast i32* %a to float* | ||
| call void @funfloat(float* %0) nounwind | ||
| ret void | ||
| } | ||
|
|
||
| declare void @funfloat(float*) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| ; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s | ||
| ; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s | ||
|
|
||
| @.str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1 | ||
|
|
||
| ; Passing addr-of to function call | ||
| ; Requires protector. | ||
| define void @foo() nounwind uwtable safestack { | ||
| entry: | ||
| ; CHECK: __safestack_unsafe_stack_ptr | ||
| %b = alloca i32, align 4 | ||
| call void @funcall(i32* %b) nounwind | ||
| ret void | ||
| } | ||
|
|
||
| declare void @funcall(i32*) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| ; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s | ||
| ; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s | ||
|
|
||
| @.str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1 | ||
|
|
||
| ; Addr-of a casted pointer | ||
| ; safestack attribute | ||
| ; Requires protector. | ||
| define void @foo() nounwind uwtable safestack { | ||
| entry: | ||
| ; CHECK: __safestack_unsafe_stack_ptr | ||
| %a = alloca i32*, align 8 | ||
| %b = alloca float**, align 8 | ||
| %call = call i32* @getp() | ||
| store i32* %call, i32** %a, align 8 | ||
| %0 = bitcast i32** %a to float** | ||
| store float** %0, float*** %b, align 8 | ||
| %1 = load float**, float*** %b, align 8 | ||
| call void @funfloat2(float** %1) | ||
| ret void | ||
| } | ||
|
|
||
| declare void @funfloat2(float**) | ||
| declare i32* @getp() |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| ; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s | ||
| ; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s | ||
|
|
||
| %struct.pair = type { i32, i32 } | ||
|
|
||
| @.str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1 | ||
|
|
||
| ; Addr-of struct element, GEP followed by callinst. | ||
| ; safestack attribute | ||
| ; Requires protector. | ||
| define void @foo() nounwind uwtable safestack { | ||
| entry: | ||
| ; CHECK: __safestack_unsafe_stack_ptr | ||
| %c = alloca %struct.pair, align 4 | ||
| %y = getelementptr inbounds %struct.pair, %struct.pair* %c, i64 0, i32 1 | ||
| %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), i32* %y) nounwind | ||
| ret void | ||
| } | ||
|
|
||
| declare i32 @printf(i8*, ...) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| ; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s | ||
| ; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s | ||
|
|
||
| %struct.pair = type { i32, i32 } | ||
|
|
||
| @.str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1 | ||
|
|
||
| ; Addr-of a struct element passed into an invoke instruction. | ||
| ; (GEP followed by an invoke) | ||
| ; safestack attribute | ||
| ; Requires protector. | ||
| define i32 @foo() uwtable safestack { | ||
| entry: | ||
| ; CHECK: __safestack_unsafe_stack_ptr | ||
| %c = alloca %struct.pair, align 4 | ||
| %exn.slot = alloca i8* | ||
| %ehselector.slot = alloca i32 | ||
| %a = getelementptr inbounds %struct.pair, %struct.pair* %c, i32 0, i32 0 | ||
| store i32 0, i32* %a, align 4 | ||
| %a1 = getelementptr inbounds %struct.pair, %struct.pair* %c, i32 0, i32 0 | ||
| invoke void @_Z3exceptPi(i32* %a1) | ||
| to label %invoke.cont unwind label %lpad | ||
|
|
||
| invoke.cont: | ||
| ret i32 0 | ||
|
|
||
| lpad: | ||
| %0 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) | ||
| catch i8* null | ||
| ret i32 0 | ||
| } | ||
|
|
||
| declare void @_Z3exceptPi(i32*) | ||
| declare i32 @__gxx_personality_v0(...) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| ; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s | ||
| ; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s | ||
|
|
||
| @.str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1 | ||
|
|
||
| ; Addr-of a local, optimized into a GEP (e.g., &a - 12) | ||
| ; safestack attribute | ||
| ; Requires protector. | ||
| define void @foo() nounwind uwtable safestack { | ||
| entry: | ||
| ; CHECK: __safestack_unsafe_stack_ptr | ||
| %a = alloca i32, align 4 | ||
| %add.ptr5 = getelementptr inbounds i32, i32* %a, i64 -12 | ||
| %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), i32* %add.ptr5) nounwind | ||
| ret void | ||
| } | ||
|
|
||
| declare i32 @printf(i8*, ...) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| ; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s | ||
| ; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s | ||
|
|
||
| %struct.pair = type { i32, i32 } | ||
|
|
||
| @.str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1 | ||
|
|
||
| ; Addr-of struct element, GEP followed by ptrtoint. | ||
| ; safestack attribute | ||
| ; Requires protector. | ||
| define void @foo() nounwind uwtable safestack { | ||
| entry: | ||
| ; CHECK: __safestack_unsafe_stack_ptr | ||
| %c = alloca %struct.pair, align 4 | ||
| %b = alloca i32*, align 8 | ||
| %y = getelementptr inbounds %struct.pair, %struct.pair* %c, i32 0, i32 1 | ||
| %0 = ptrtoint i32* %y to i64 | ||
| %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i64 %0) | ||
| ret void | ||
| } | ||
|
|
||
| declare i32 @printf(i8*, ...) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| ; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s | ||
| ; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s | ||
|
|
||
| %struct.pair = type { i32, i32 } | ||
|
|
||
| @.str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1 | ||
|
|
||
| ; Addr-of struct element. (GEP followed by store). | ||
| ; safestack attribute | ||
| ; Requires protector. | ||
| define void @foo() nounwind uwtable safestack { | ||
| entry: | ||
| ; CHECK: __safestack_unsafe_stack_ptr | ||
| %c = alloca %struct.pair, align 4 | ||
| %b = alloca i32*, align 8 | ||
| %y = getelementptr inbounds %struct.pair, %struct.pair* %c, i32 0, i32 1 | ||
| store i32* %y, i32** %b, align 8 | ||
| %0 = load i32*, i32** %b, align 8 | ||
| %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i32* %0) | ||
| ret void | ||
| } | ||
|
|
||
| declare i32 @printf(i8*, ...) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| ; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s | ||
| ; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s | ||
|
|
||
| @.str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1 | ||
|
|
||
| ; Addr-of in phi instruction | ||
| ; Requires protector. | ||
| define void @foo() nounwind uwtable safestack { | ||
| entry: | ||
| ; CHECK: __safestack_unsafe_stack_ptr | ||
| %x = alloca double, align 8 | ||
| %call = call double @testi_aux() nounwind | ||
| store double %call, double* %x, align 8 | ||
| %cmp = fcmp ogt double %call, 3.140000e+00 | ||
| br i1 %cmp, label %if.then, label %if.else | ||
|
|
||
| if.then: ; preds = %entry | ||
| %call1 = call double @testi_aux() nounwind | ||
| store double %call1, double* %x, align 8 | ||
| br label %if.end4 | ||
|
|
||
| if.else: ; preds = %entry | ||
| %cmp2 = fcmp ogt double %call, 1.000000e+00 | ||
| br i1 %cmp2, label %if.then3, label %if.end4 | ||
|
|
||
| if.then3: ; preds = %if.else | ||
| br label %if.end4 | ||
|
|
||
| if.end4: ; preds = %if.else, %if.then3, %if.then | ||
| %y.0 = phi double* [ null, %if.then ], [ %x, %if.then3 ], [ null, %if.else ] | ||
| %call5 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), double* %y.0) nounwind | ||
| ret void | ||
| } | ||
|
|
||
| declare double @testi_aux() | ||
| declare i32 @printf(i8*, ...) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| ; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s | ||
| ; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s | ||
|
|
||
| @.str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1 | ||
|
|
||
| ; Addr-of in select instruction | ||
| ; safestack attribute | ||
| ; Requires protector. | ||
| define void @foo() nounwind uwtable safestack { | ||
| entry: | ||
| ; CHECK: __safestack_unsafe_stack_ptr | ||
| %x = alloca double, align 8 | ||
| %call = call double @testi_aux() nounwind | ||
| store double %call, double* %x, align 8 | ||
| %cmp2 = fcmp ogt double %call, 0.000000e+00 | ||
| %y.1 = select i1 %cmp2, double* %x, double* null | ||
| %call2 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), double* %y.1) | ||
| ret void | ||
| } | ||
|
|
||
| declare double @testi_aux() | ||
| declare i32 @printf(i8*, ...) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| ; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s | ||
| ; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s | ||
|
|
||
| %struct.vec = type { <4 x i32> } | ||
|
|
||
| @.str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1 | ||
|
|
||
| ; Addr-of a vector nested in a struct | ||
| ; safestack attribute | ||
| ; Requires protector. | ||
| define void @foo() nounwind uwtable safestack { | ||
| entry: | ||
| ; CHECK: __safestack_unsafe_stack_ptr | ||
| %c = alloca %struct.vec, align 16 | ||
| %y = getelementptr inbounds %struct.vec, %struct.vec* %c, i64 0, i32 0 | ||
| %add.ptr = getelementptr inbounds <4 x i32>, <4 x i32>* %y, i64 -12 | ||
| %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), <4 x i32>* %add.ptr) nounwind | ||
| ret void | ||
| } | ||
|
|
||
| declare i32 @printf(i8*, ...) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| ; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s | ||
| ; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s | ||
|
|
||
| @.str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1 | ||
|
|
||
| ; Addr-of a variable passed into an invoke instruction. | ||
| ; safestack attribute | ||
| ; Requires protector and stack restore after landing pad. | ||
| define i32 @foo() uwtable safestack { | ||
| entry: | ||
| ; CHECK: %[[SP:.*]] = load i8*, i8** @__safestack_unsafe_stack_ptr | ||
| ; CHECK: %[[STATICTOP:.*]] = getelementptr i8, i8* %[[SP]], i32 -16 | ||
| %a = alloca i32, align 4 | ||
| %exn.slot = alloca i8* | ||
| %ehselector.slot = alloca i32 | ||
| store i32 0, i32* %a, align 4 | ||
| invoke void @_Z3exceptPi(i32* %a) | ||
| to label %invoke.cont unwind label %lpad | ||
|
|
||
| invoke.cont: | ||
| ret i32 0 | ||
|
|
||
| lpad: | ||
| ; CHECK: landingpad | ||
| ; CHECK-NEXT: catch | ||
| %0 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) | ||
| catch i8* null | ||
| ; CHECK-NEXT: store i8* %[[STATICTOP]], i8** @__safestack_unsafe_stack_ptr | ||
| ret i32 0 | ||
| } | ||
|
|
||
| declare void @_Z3exceptPi(i32*) | ||
| declare i32 @__gxx_personality_v0(...) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| ; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s | ||
| ; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s | ||
|
|
||
| @.str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1 | ||
|
|
||
| ; no safestack attribute | ||
| ; Requires no protector. | ||
|
|
||
| ; CHECK: @foo | ||
| define void @foo(i8* %a) nounwind uwtable { | ||
| entry: | ||
| ; CHECK-NOT: __safestack_unsafe_stack_ptr | ||
| %a.addr = alloca i8*, align 8 | ||
| %buf = alloca [16 x i8], align 16 | ||
| store i8* %a, i8** %a.addr, align 8 | ||
| %arraydecay = getelementptr inbounds [16 x i8], [16 x i8]* %buf, i32 0, i32 0 | ||
| %0 = load i8*, i8** %a.addr, align 8 | ||
| %call = call i8* @strcpy(i8* %arraydecay, i8* %0) | ||
| %arraydecay1 = getelementptr inbounds [16 x i8], [16 x i8]* %buf, i32 0, i32 0 | ||
| %call2 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i8* %arraydecay1) | ||
| ret void | ||
| } | ||
|
|
||
| declare i8* @strcpy(i8*, i8*) | ||
| declare i32 @printf(i8*, ...) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| ; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s | ||
| ; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s | ||
|
|
||
| %struct.small = type { i8 } | ||
|
|
||
| @.str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1 | ||
|
|
||
| ; Address-of a structure taken in a function with a loop where | ||
| ; the alloca is an incoming value to a PHI node and a use of that PHI | ||
| ; node is also an incoming value. | ||
| ; Verify that the address-of analysis does not get stuck in infinite | ||
| ; recursion when chasing the alloca through the PHI nodes. | ||
| ; Requires protector. | ||
| define i32 @foo(i32 %arg) nounwind uwtable safestack { | ||
| bb: | ||
| ; CHECK: __safestack_unsafe_stack_ptr | ||
| %tmp = alloca %struct.small*, align 8 | ||
| %tmp1 = call i32 (...) @dummy(%struct.small** %tmp) nounwind | ||
| %tmp2 = load %struct.small*, %struct.small** %tmp, align 8 | ||
| %tmp3 = ptrtoint %struct.small* %tmp2 to i64 | ||
| %tmp4 = trunc i64 %tmp3 to i32 | ||
| %tmp5 = icmp sgt i32 %tmp4, 0 | ||
| br i1 %tmp5, label %bb6, label %bb21 | ||
|
|
||
| bb6: ; preds = %bb17, %bb | ||
| %tmp7 = phi %struct.small* [ %tmp19, %bb17 ], [ %tmp2, %bb ] | ||
| %tmp8 = phi i64 [ %tmp20, %bb17 ], [ 1, %bb ] | ||
| %tmp9 = phi i32 [ %tmp14, %bb17 ], [ %tmp1, %bb ] | ||
| %tmp10 = getelementptr inbounds %struct.small, %struct.small* %tmp7, i64 0, i32 0 | ||
| %tmp11 = load i8, i8* %tmp10, align 1 | ||
| %tmp12 = icmp eq i8 %tmp11, 1 | ||
| %tmp13 = add nsw i32 %tmp9, 8 | ||
| %tmp14 = select i1 %tmp12, i32 %tmp13, i32 %tmp9 | ||
| %tmp15 = trunc i64 %tmp8 to i32 | ||
| %tmp16 = icmp eq i32 %tmp15, %tmp4 | ||
| br i1 %tmp16, label %bb21, label %bb17 | ||
|
|
||
| bb17: ; preds = %bb6 | ||
| %tmp18 = getelementptr inbounds %struct.small*, %struct.small** %tmp, i64 %tmp8 | ||
| %tmp19 = load %struct.small*, %struct.small** %tmp18, align 8 | ||
| %tmp20 = add i64 %tmp8, 1 | ||
| br label %bb6 | ||
|
|
||
| bb21: ; preds = %bb6, %bb | ||
| %tmp22 = phi i32 [ %tmp1, %bb ], [ %tmp14, %bb6 ] | ||
| %tmp23 = call i32 (...) @dummy(i32 %tmp22) nounwind | ||
| ret i32 undef | ||
| } | ||
|
|
||
| declare i32 @dummy(...) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| ; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s | ||
| ; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s | ||
|
|
||
| %struct.__jmp_buf_tag = type { [8 x i64], i32, %struct.__sigset_t } | ||
| %struct.__sigset_t = type { [16 x i64] } | ||
|
|
||
| @.str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1 | ||
| @buf = internal global [1 x %struct.__jmp_buf_tag] zeroinitializer, align 16 | ||
|
|
||
| ; setjmp/longjmp test. | ||
| ; Requires protector. | ||
| define i32 @foo() nounwind uwtable safestack { | ||
| entry: | ||
| ; CHECK: %[[SP:.*]] = load i8*, i8** @__safestack_unsafe_stack_ptr | ||
| ; CHECK: %[[STATICTOP:.*]] = getelementptr i8, i8* %[[SP]], i32 -16 | ||
| %retval = alloca i32, align 4 | ||
| %x = alloca i32, align 4 | ||
| store i32 0, i32* %retval | ||
| store i32 42, i32* %x, align 4 | ||
| %call = call i32 @_setjmp(%struct.__jmp_buf_tag* getelementptr inbounds ([1 x %struct.__jmp_buf_tag], [1 x %struct.__jmp_buf_tag]* @buf, i32 0, i32 0)) returns_twice | ||
| ; CHECK: setjmp | ||
| ; CHECK-NEXT: store i8* %[[STATICTOP]], i8** @__safestack_unsafe_stack_ptr | ||
| %tobool = icmp ne i32 %call, 0 | ||
| br i1 %tobool, label %if.else, label %if.then | ||
| if.then: ; preds = %entry | ||
| call void @funcall(i32* %x) | ||
| br label %if.end | ||
| if.else: ; preds = %entry | ||
| call i32 (...) @dummy() | ||
| br label %if.end | ||
| if.end: ; preds = %if.else, %if.then | ||
| ret i32 0 | ||
| } | ||
|
|
||
| declare i32 @_setjmp(%struct.__jmp_buf_tag*) | ||
| declare void @funcall(i32*) | ||
| declare i32 @dummy(...) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| ; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s | ||
| ; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s | ||
|
|
||
| %struct.__jmp_buf_tag = type { [8 x i64], i32, %struct.__sigset_t } | ||
| %struct.__sigset_t = type { [16 x i64] } | ||
|
|
||
| @.str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1 | ||
| @buf = internal global [1 x %struct.__jmp_buf_tag] zeroinitializer, align 16 | ||
|
|
||
| ; setjmp/longjmp test with dynamically sized array. | ||
| ; Requires protector. | ||
| ; CHECK: @foo(i32 %[[ARG:.*]]) | ||
| define i32 @foo(i32 %size) nounwind uwtable safestack { | ||
| entry: | ||
| ; CHECK: %[[DYNPTR:.*]] = alloca i8* | ||
| ; CHECK-NEXT: %[[SP:.*]] = load i8*, i8** @__safestack_unsafe_stack_ptr | ||
| ; CHECK-NEXT: store i8* %[[SP]], i8** %[[DYNPTR]] | ||
|
|
||
| ; CHECK-NEXT: %[[ZEXT:.*]] = zext i32 %[[ARG]] to i64 | ||
| ; CHECK-NEXT: %[[MUL:.*]] = mul i64 %[[ZEXT]], 4 | ||
| ; CHECK-NEXT: %[[SP2:.*]] = load i8*, i8** @__safestack_unsafe_stack_ptr | ||
| ; CHECK-NEXT: %[[PTRTOINT:.*]] = ptrtoint i8* %[[SP2]] to i64 | ||
| ; CHECK-NEXT: %[[SUB:.*]] = sub i64 %[[PTRTOINT]], %[[MUL]] | ||
| ; CHECK-NEXT: %[[AND:.*]] = and i64 %[[SUB]], -16 | ||
| ; CHECK-NEXT: %[[INTTOPTR:.*]] = inttoptr i64 %[[AND]] to i8* | ||
| ; CHECK-NEXT: store i8* %[[INTTOPTR]], i8** @__safestack_unsafe_stack_ptr | ||
| ; CHECK-NEXT: store i8* %[[INTTOPTR]], i8** %unsafe_stack_dynamic_ptr | ||
| ; CHECK-NEXT: %[[ALLOCA:.*]] = inttoptr i64 %[[SUB]] to i32* | ||
| %a = alloca i32, i32 %size | ||
|
|
||
| ; CHECK: setjmp | ||
| ; CHECK-NEXT: %[[LOAD:.*]] = load i8*, i8** %[[DYNPTR]] | ||
| ; CHECK-NEXT: store i8* %[[LOAD]], i8** @__safestack_unsafe_stack_ptr | ||
| %call = call i32 @_setjmp(%struct.__jmp_buf_tag* getelementptr inbounds ([1 x %struct.__jmp_buf_tag], [1 x %struct.__jmp_buf_tag]* @buf, i32 0, i32 0)) returns_twice | ||
|
|
||
| ; CHECK: call void @funcall(i32* %[[ALLOCA]]) | ||
| call void @funcall(i32* %a) | ||
| ret i32 0 | ||
| } | ||
|
|
||
| declare i32 @_setjmp(%struct.__jmp_buf_tag*) | ||
| declare void @funcall(i32*) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| ; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s | ||
| ; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s | ||
|
|
||
| %struct.foo = type { [16 x i8] } | ||
|
|
||
| @.str = private unnamed_addr constant [4 x i8] c"%s\0A\00", align 1 | ||
|
|
||
| ; struct { [16 x i8] } | ||
|
|
||
| define void @foo(i8* %a) nounwind uwtable safestack { | ||
| entry: | ||
| ; CHECK: %[[USP:.*]] = load i8*, i8** @__safestack_unsafe_stack_ptr | ||
|
|
||
| ; CHECK: %[[USST:.*]] = getelementptr i8, i8* %[[USP]], i32 -16 | ||
|
|
||
| ; CHECK: store i8* %[[USST]], i8** @__safestack_unsafe_stack_ptr | ||
|
|
||
| ; CHECK: %[[AADDR:.*]] = alloca i8*, align 8 | ||
| %a.addr = alloca i8*, align 8 | ||
|
|
||
| ; CHECK: %[[BUFPTR:.*]] = getelementptr i8, i8* %[[USP]], i32 -16 | ||
| ; CHECK: %[[BUFPTR2:.*]] = bitcast i8* %[[BUFPTR]] to %struct.foo* | ||
| %buf = alloca %struct.foo, align 1 | ||
|
|
||
| ; CHECK: store i8* {{.*}}, i8** %[[AADDR]], align 8 | ||
| store i8* %a, i8** %a.addr, align 8 | ||
|
|
||
| ; CHECK: %[[GEP:.*]] = getelementptr inbounds %struct.foo, %struct.foo* %[[BUFPTR2]], i32 0, i32 0, i32 0 | ||
| %gep = getelementptr inbounds %struct.foo, %struct.foo* %buf, i32 0, i32 0, i32 0 | ||
|
|
||
| ; CHECK: %[[A:.*]] = load i8*, i8** %[[AADDR]], align 8 | ||
| %a2 = load i8*, i8** %a.addr, align 8 | ||
|
|
||
| ; CHECK: call i8* @strcpy(i8* %[[GEP]], i8* %[[A]]) | ||
| %call = call i8* @strcpy(i8* %gep, i8* %a2) | ||
|
|
||
| ; CHECK: store i8* %[[USP]], i8** @__safestack_unsafe_stack_ptr | ||
| ret void | ||
| } | ||
|
|
||
| declare i8* @strcpy(i8*, i8*) |