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