1; RUN: opt < %s -msan-check-access-address=0 -S -passes=msan 2>&1 | FileCheck \ 2; RUN: %s "--check-prefixes=CHECK,INLINE" 3; RUN: opt < %s -msan -msan-check-access-address=0 -S | FileCheck %s --check-prefixes=CHECK,INLINE 4; RUN: opt < %s -msan-check-access-address=0 -msan-poison-stack-with-call=1 -S \ 5; RUN: -passes=msan 2>&1 | FileCheck %s "--check-prefixes=CHECK,CALL" 6; RUN: opt < %s -msan -msan-check-access-address=0 -msan-poison-stack-with-call=1 -S | FileCheck %s --check-prefixes=CHECK,CALL 7; RUN: opt < %s -msan-check-access-address=0 -msan-track-origins=1 -S \ 8; RUN: -passes=msan 2>&1 | FileCheck %s "--check-prefixes=CHECK,ORIGIN" 9; RUN: opt < %s -msan -msan-check-access-address=0 -msan-track-origins=1 -S | FileCheck %s --check-prefixes=CHECK,ORIGIN 10; RUN: opt < %s -msan-check-access-address=0 -msan-track-origins=2 -S \ 11; RUN: -passes=msan 2>&1 | FileCheck %s "--check-prefixes=CHECK,ORIGIN" 12; RUN: opt < %s -msan -msan-check-access-address=0 -msan-track-origins=2 -S | FileCheck %s --check-prefixes=CHECK,ORIGIN 13; RUN: opt < %s -S -passes="msan<kernel>" 2>&1 | FileCheck %s \ 14; RUN: "--check-prefixes=CHECK,KMSAN" 15; RUN: opt < %s -msan-kernel=1 -S -passes=msan 2>&1 | FileCheck %s \ 16; RUN: "--check-prefixes=CHECK,KMSAN" 17; RUN: opt < %s -msan -msan-kernel=1 -S | FileCheck %s --check-prefixes=CHECK,KMSAN 18 19target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" 20target triple = "x86_64-unknown-linux-gnu" 21 22define void @static() sanitize_memory { 23entry: 24 %x = alloca i32, align 4 25 ret void 26} 27 28; CHECK-LABEL: define void @static( 29; INLINE: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 4, i1 false) 30; CALL: call void @__msan_poison_stack(i8* {{.*}}, i64 4) 31; ORIGIN: call void @__msan_set_alloca_origin4(i8* {{.*}}, i64 4, 32; KMSAN: call void @__msan_poison_alloca(i8* {{.*}}, i64 4, 33; CHECK: ret void 34 35 36define void @dynamic() sanitize_memory { 37entry: 38 br label %l 39l: 40 %x = alloca i32, align 4 41 ret void 42} 43 44; CHECK-LABEL: define void @dynamic( 45; INLINE: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 4, i1 false) 46; CALL: call void @__msan_poison_stack(i8* {{.*}}, i64 4) 47; ORIGIN: call void @__msan_set_alloca_origin4(i8* {{.*}}, i64 4, 48; KMSAN: call void @__msan_poison_alloca(i8* {{.*}}, i64 4, 49; CHECK: ret void 50 51define void @array() sanitize_memory { 52entry: 53 %x = alloca i32, i64 5, align 4 54 ret void 55} 56 57; CHECK-LABEL: define void @array( 58; INLINE: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 20, i1 false) 59; CALL: call void @__msan_poison_stack(i8* {{.*}}, i64 20) 60; ORIGIN: call void @__msan_set_alloca_origin4(i8* {{.*}}, i64 20, 61; KMSAN: call void @__msan_poison_alloca(i8* {{.*}}, i64 20, 62; CHECK: ret void 63 64define void @array_non_const(i64 %cnt) sanitize_memory { 65entry: 66 %x = alloca i32, i64 %cnt, align 4 67 ret void 68} 69 70; CHECK-LABEL: define void @array_non_const( 71; CHECK: %[[A:.*]] = mul i64 4, %cnt 72; INLINE: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 %[[A]], i1 false) 73; CALL: call void @__msan_poison_stack(i8* {{.*}}, i64 %[[A]]) 74; ORIGIN: call void @__msan_set_alloca_origin4(i8* {{.*}}, i64 %[[A]], 75; KMSAN: call void @__msan_poison_alloca(i8* {{.*}}, i64 %[[A]], 76; CHECK: ret void 77 78; Check that the local is unpoisoned in the absence of sanitize_memory 79define void @unpoison_local() { 80entry: 81 %x = alloca i32, i64 5, align 4 82 ret void 83} 84 85; CHECK-LABEL: define void @unpoison_local( 86; INLINE: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 0, i64 20, i1 false) 87; CALL: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 0, i64 20, i1 false) 88; ORIGIN-NOT: call void @__msan_set_alloca_origin4(i8* {{.*}}, i64 20, 89; KMSAN: call void @__msan_unpoison_alloca(i8* {{.*}}, i64 20) 90; CHECK: ret void 91 92; Check that every llvm.lifetime.start() causes poisoning of locals. 93define void @lifetime_start() sanitize_memory { 94entry: 95 %x = alloca i32, align 4 96 %c = bitcast i32* %x to i8* 97 br label %another_bb 98 99another_bb: 100 call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %c) 101 store i32 7, i32* %x 102 call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %c) 103 call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %c) 104 store i32 8, i32* %x 105 call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %c) 106 ret void 107} 108 109; CHECK-LABEL: define void @lifetime_start( 110; CHECK-LABEL: entry: 111; CHECK: %x = alloca i32 112; CHECK-LABEL: another_bb: 113 114; CHECK: call void @llvm.lifetime.start 115; INLINE: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 4, i1 false) 116; CALL: call void @__msan_poison_stack(i8* {{.*}}, i64 4) 117; ORIGIN: call void @__msan_set_alloca_origin4(i8* {{.*}}, i64 4, 118; KMSAN: call void @__msan_poison_alloca(i8* {{.*}}, i64 4, 119 120; CHECK: call void @llvm.lifetime.start 121; INLINE: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 4, i1 false) 122; CALL: call void @__msan_poison_stack(i8* {{.*}}, i64 4) 123; ORIGIN: call void @__msan_set_alloca_origin4(i8* {{.*}}, i64 4, 124; KMSAN: call void @__msan_poison_alloca(i8* {{.*}}, i64 4, 125; CHECK: ret void 126 127; Make sure variable-length arrays are handled correctly. 128define void @lifetime_start_var(i64 %cnt) sanitize_memory { 129entry: 130 %x = alloca i32, i64 %cnt, align 4 131 %c = bitcast i32* %x to i8* 132 call void @llvm.lifetime.start.p0i8(i64 -1, i8* nonnull %c) 133 call void @llvm.lifetime.end.p0i8(i64 -1, i8* nonnull %c) 134 ret void 135} 136 137; CHECK-LABEL: define void @lifetime_start_var( 138; CHECK-LABEL: entry: 139; CHECK: %x = alloca i32, i64 %cnt 140; CHECK: call void @llvm.lifetime.start 141; CHECK: %[[A:.*]] = mul i64 4, %cnt 142; INLINE: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 %[[A]], i1 false) 143; CALL: call void @__msan_poison_stack(i8* {{.*}}, i64 %[[A]]) 144; ORIGIN: call void @__msan_set_alloca_origin4(i8* {{.*}}, i64 %[[A]], 145; KMSAN: call void @__msan_poison_alloca(i8* {{.*}}, i64 %[[A]], 146; CHECK: call void @llvm.lifetime.end 147; CHECK: ret void 148 149 150; If we can't trace one of the lifetime markers to a single alloca, fall back 151; to poisoning allocas at the beginning of the function. 152; Each alloca must be poisoned only once. 153define void @lifetime_no_alloca(i8 %v) sanitize_memory { 154entry: 155 %x = alloca i32, align 4 156 %y = alloca i32, align 4 157 %z = alloca i32, align 4 158 %cx = bitcast i32* %x to i8* 159 %cy = bitcast i32* %y to i8* 160 %cz = bitcast i32* %z to i8* 161 %tobool = icmp eq i8 %v, 0 162 %xy = select i1 %tobool, i32* %x, i32* %y 163 %cxcy = select i1 %tobool, i8* %cx, i8* %cy 164 br label %another_bb 165 166another_bb: 167 call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %cz) 168 store i32 7, i32* %z 169 call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %cz) 170 call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %cz) 171 store i32 7, i32* %z 172 call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %cz) 173 call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %cxcy) 174 store i32 8, i32* %xy 175 call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %cxcy) 176 ret void 177} 178 179; CHECK-LABEL: define void @lifetime_no_alloca( 180; CHECK-LABEL: entry: 181; CHECK: %x = alloca i32 182; INLINE: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 4, i1 false) 183; CALL: call void @__msan_poison_stack(i8* {{.*}}, i64 4) 184; ORIGIN: call void @__msan_set_alloca_origin4(i8* {{.*}}, i64 4, 185; KMSAN: call void @__msan_poison_alloca(i8* {{.*}}, i64 4, 186; CHECK: %y = alloca i32 187; INLINE: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 4, i1 false) 188; CALL: call void @__msan_poison_stack(i8* {{.*}}, i64 4) 189; ORIGIN: call void @__msan_set_alloca_origin4(i8* {{.*}}, i64 4, 190; KMSAN: call void @__msan_poison_alloca(i8* {{.*}}, i64 4, 191; CHECK: %z = alloca i32 192; INLINE: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 4, i1 false) 193; CALL: call void @__msan_poison_stack(i8* {{.*}}, i64 4) 194; ORIGIN: call void @__msan_set_alloca_origin4(i8* {{.*}}, i64 4, 195; KMSAN: call void @__msan_poison_alloca(i8* {{.*}}, i64 4, 196 197; There're two lifetime intrinsics for %z, but we must instrument it only once. 198; INLINE-NOT: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 4, i1 false) 199; CALL-NOT: call void @__msan_poison_stack(i8* {{.*}}, i64 4) 200; ORIGIN-NOT: call void @__msan_set_alloca_origin4(i8* {{.*}}, i64 4, 201; KMSAN-NOT: call void @__msan_poison_alloca(i8* {{.*}}, i64 4, 202; CHECK-LABEL: another_bb: 203 204; CHECK: call void @llvm.lifetime.start 205; INLINE-NOT: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 4, i1 false) 206; CALL-NOT: call void @__msan_poison_stack(i8* {{.*}}, i64 4) 207; ORIGIN-NOT: call void @__msan_set_alloca_origin4(i8* {{.*}}, i64 4, 208; KMSAN-NOT: call void @__msan_poison_alloca(i8* {{.*}}, i64 4, 209; CHECK: call void @llvm.lifetime.end 210; CHECK: call void @llvm.lifetime.start 211; INLINE-NOT: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 4, i1 false) 212; CALL-NOT: call void @__msan_poison_stack(i8* {{.*}}, i64 4) 213; ORIGIN-NOT: call void @__msan_set_alloca_origin4(i8* {{.*}}, i64 4, 214; KMSAN-NOT: call void @__msan_poison_alloca(i8* {{.*}}, i64 4, 215; CHECK: call void @llvm.lifetime.end 216 217 218 219declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) 220declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) 221