1*cee313d2SEric Christopher; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s 2*cee313d2SEric Christopher; RUN: opt -safe-stack -S -mtriple=i386-pc-contiki-unknown < %s -o - | FileCheck -check-prefix=SINGLE-THREAD %s 3*cee313d2SEric Christopher; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s 4*cee313d2SEric Christopher 5*cee313d2SEric Christopher; array [4 x i8] 6*cee313d2SEric Christopher; Requires protector. 7*cee313d2SEric Christopher 8*cee313d2SEric Christopher; CHECK: @__safestack_unsafe_stack_ptr = external thread_local(initialexec) global i8* 9*cee313d2SEric Christopher; SINGLE-THREAD: @__safestack_unsafe_stack_ptr = external global i8* 10*cee313d2SEric Christopher 11*cee313d2SEric Christopherdefine void @foo(i8* %a) nounwind uwtable safestack { 12*cee313d2SEric Christopherentry: 13*cee313d2SEric Christopher ; CHECK: %[[USP:.*]] = load i8*, i8** @__safestack_unsafe_stack_ptr 14*cee313d2SEric Christopher 15*cee313d2SEric Christopher ; CHECK: %[[USST:.*]] = getelementptr i8, i8* %[[USP]], i32 -16 16*cee313d2SEric Christopher 17*cee313d2SEric Christopher ; CHECK: store i8* %[[USST]], i8** @__safestack_unsafe_stack_ptr 18*cee313d2SEric Christopher 19*cee313d2SEric Christopher %a.addr = alloca i8*, align 8 20*cee313d2SEric Christopher %buf = alloca [4 x i8], align 1 21*cee313d2SEric Christopher 22*cee313d2SEric Christopher ; CHECK: %[[AADDR:.*]] = alloca i8*, align 8 23*cee313d2SEric Christopher ; CHECK: store i8* {{.*}}, i8** %[[AADDR]], align 8 24*cee313d2SEric Christopher store i8* %a, i8** %a.addr, align 8 25*cee313d2SEric Christopher 26*cee313d2SEric Christopher ; CHECK: %[[BUFPTR:.*]] = getelementptr i8, i8* %[[USP]], i32 -4 27*cee313d2SEric Christopher ; CHECK: %[[BUFPTR2:.*]] = bitcast i8* %[[BUFPTR]] to [4 x i8]* 28*cee313d2SEric Christopher ; CHECK: %[[GEP:.*]] = getelementptr inbounds [4 x i8], [4 x i8]* %[[BUFPTR2]], i32 0, i32 0 29*cee313d2SEric Christopher %gep = getelementptr inbounds [4 x i8], [4 x i8]* %buf, i32 0, i32 0 30*cee313d2SEric Christopher 31*cee313d2SEric Christopher ; CHECK: %[[A2:.*]] = load i8*, i8** %[[AADDR]], align 8 32*cee313d2SEric Christopher %a2 = load i8*, i8** %a.addr, align 8 33*cee313d2SEric Christopher 34*cee313d2SEric Christopher ; CHECK: call i8* @strcpy(i8* %[[GEP]], i8* %[[A2]]) 35*cee313d2SEric Christopher %call = call i8* @strcpy(i8* %gep, i8* %a2) 36*cee313d2SEric Christopher 37*cee313d2SEric Christopher ; CHECK: store i8* %[[USP]], i8** @__safestack_unsafe_stack_ptr 38*cee313d2SEric Christopher ret void 39*cee313d2SEric Christopher} 40*cee313d2SEric Christopher 41*cee313d2SEric Christopher; Load from an array at a fixed offset, no overflow. 42*cee313d2SEric Christopherdefine i8 @StaticArrayFixedSafe() nounwind uwtable safestack { 43*cee313d2SEric Christopherentry: 44*cee313d2SEric Christopher ; CHECK-LABEL: define i8 @StaticArrayFixedSafe( 45*cee313d2SEric Christopher ; CHECK-NOT: __safestack_unsafe_stack_ptr 46*cee313d2SEric Christopher ; CHECK: ret i8 47*cee313d2SEric Christopher %buf = alloca i8, i32 4, align 1 48*cee313d2SEric Christopher %gep = getelementptr inbounds i8, i8* %buf, i32 2 49*cee313d2SEric Christopher %x = load i8, i8* %gep, align 1 50*cee313d2SEric Christopher ret i8 %x 51*cee313d2SEric Christopher} 52*cee313d2SEric Christopher 53*cee313d2SEric Christopher; Load from an array at a fixed offset with overflow. 54*cee313d2SEric Christopherdefine i8 @StaticArrayFixedUnsafe() nounwind uwtable safestack { 55*cee313d2SEric Christopherentry: 56*cee313d2SEric Christopher ; CHECK-LABEL: define i8 @StaticArrayFixedUnsafe( 57*cee313d2SEric Christopher ; CHECK: __safestack_unsafe_stack_ptr 58*cee313d2SEric Christopher ; CHECK: ret i8 59*cee313d2SEric Christopher %buf = alloca i8, i32 4, align 1 60*cee313d2SEric Christopher %gep = getelementptr inbounds i8, i8* %buf, i32 5 61*cee313d2SEric Christopher %x = load i8, i8* %gep, align 1 62*cee313d2SEric Christopher ret i8 %x 63*cee313d2SEric Christopher} 64*cee313d2SEric Christopher 65*cee313d2SEric Christopher; Load from an array at an unknown offset. 66*cee313d2SEric Christopherdefine i8 @StaticArrayVariableUnsafe(i32 %ofs) nounwind uwtable safestack { 67*cee313d2SEric Christopherentry: 68*cee313d2SEric Christopher ; CHECK-LABEL: define i8 @StaticArrayVariableUnsafe( 69*cee313d2SEric Christopher ; CHECK: __safestack_unsafe_stack_ptr 70*cee313d2SEric Christopher ; CHECK: ret i8 71*cee313d2SEric Christopher %buf = alloca i8, i32 4, align 1 72*cee313d2SEric Christopher %gep = getelementptr inbounds i8, i8* %buf, i32 %ofs 73*cee313d2SEric Christopher %x = load i8, i8* %gep, align 1 74*cee313d2SEric Christopher ret i8 %x 75*cee313d2SEric Christopher} 76*cee313d2SEric Christopher 77*cee313d2SEric Christopher; Load from an array of an unknown size. 78*cee313d2SEric Christopherdefine i8 @DynamicArrayUnsafe(i32 %sz) nounwind uwtable safestack { 79*cee313d2SEric Christopherentry: 80*cee313d2SEric Christopher ; CHECK-LABEL: define i8 @DynamicArrayUnsafe( 81*cee313d2SEric Christopher ; CHECK: __safestack_unsafe_stack_ptr 82*cee313d2SEric Christopher ; CHECK: ret i8 83*cee313d2SEric Christopher %buf = alloca i8, i32 %sz, align 1 84*cee313d2SEric Christopher %gep = getelementptr inbounds i8, i8* %buf, i32 2 85*cee313d2SEric Christopher %x = load i8, i8* %gep, align 1 86*cee313d2SEric Christopher ret i8 %x 87*cee313d2SEric Christopher} 88*cee313d2SEric Christopher 89*cee313d2SEric Christopherdeclare i8* @strcpy(i8*, i8*) 90