1 // RUN: %clang_cc1 -no-enable-noundef-analysis -std=c++11 -Wno-error=return-type -fsanitize=signed-integer-overflow,integer-divide-by-zero,float-divide-by-zero,shift-base,shift-exponent,unreachable,return,vla-bound,alignment,null,vptr,object-size,float-cast-overflow,bool,enum,array-bounds,function -fsanitize-recover=signed-integer-overflow,integer-divide-by-zero,float-divide-by-zero,shift-base,shift-exponent,vla-bound,alignment,null,vptr,object-size,float-cast-overflow,bool,enum,array-bounds,function -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECK-FUNCSAN 2 // RUN: %clang_cc1 -no-enable-noundef-analysis -std=c++11 -Wno-error=return-type -fsanitize=vptr,address -fsanitize-recover=vptr,address -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=CHECK-ASAN 3 // RUN: %clang_cc1 -no-enable-noundef-analysis -std=c++11 -Wno-error=return-type -fsanitize=vptr -fsanitize-recover=vptr -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=DOWNCAST-NULL 4 // RUN: %clang_cc1 -no-enable-noundef-analysis -std=c++11 -Wno-error=return-type -fsanitize=function -emit-llvm %s -o - -triple x86_64-linux-gnux32 | FileCheck %s --check-prefix=CHECK-FUNCSAN 5 // RUN: %clang_cc1 -no-enable-noundef-analysis -std=c++11 -Wno-error=return-type -fsanitize=function -emit-llvm %s -o - -triple i386-linux-gnu | FileCheck %s --check-prefix=CHECK-FUNCSAN 6 7 struct S { 8 double d; 9 int a, b; 10 virtual int f(); 11 }; 12 13 // Check that type descriptor global is not modified by ASan. 14 // CHECK-ASAN: [[TYPE_DESCR:@[0-9]+]] = private unnamed_addr constant { i16, i16, [4 x i8] } { i16 -1, i16 0, [4 x i8] c"'S'\00" } 15 16 // Check that type mismatch handler is not modified by ASan. 17 // CHECK-ASAN: private unnamed_addr global { { ptr, i32, i32 }, ptr, ptr, i8 } { {{.*}}, ptr [[TYPE_DESCR]], {{.*}} } 18 19 struct T : S {}; 20 21 // CHECK-LABEL: @_Z17reference_binding 22 void reference_binding(int *p, S *q) { 23 // C++ core issue 453: If an lvalue to which a reference is directly bound 24 // designates neither an existing object or function of an appropriate type, 25 // nor a region of storage of suitable size and alignment to contain an object 26 // of the reference's type, the behavior is undefined. 27 28 // CHECK: icmp ne {{.*}}, null 29 30 // CHECK: %[[SIZE:.*]] = call i64 @llvm.objectsize.i64 31 // CHECK-NEXT: icmp uge i64 %[[SIZE]], 4 32 33 // CHECK: %[[PTRINT:.*]] = ptrtoint 34 // CHECK-NEXT: %[[MISALIGN:.*]] = and i64 %[[PTRINT]], 3 35 // CHECK-NEXT: icmp eq i64 %[[MISALIGN]], 0 36 int &r = *p; 37 38 // A reference is not required to refer to an object within its lifetime. 39 // CHECK-NOT: __ubsan_handle_dynamic_type_cache_miss 40 S &r2 = *q; 41 } 42 43 // CHECK-LABEL: @_Z13member_access 44 // CHECK-ASAN-LABEL: @_Z13member_access 45 void member_access(S *p) { 46 // (1a) Check 'p' is appropriately sized and aligned for member access. 47 48 // CHECK: icmp ne {{.*}}, null 49 50 // CHECK: %[[SIZE:.*]] = call i64 @llvm.objectsize.i64 51 // CHECK-NEXT: icmp uge i64 %[[SIZE]], 24 52 53 // CHECK: %[[PTRINT:.*]] = ptrtoint 54 // CHECK-NEXT: %[[MISALIGN:.*]] = and i64 %[[PTRINT]], 7 55 // CHECK-NEXT: icmp eq i64 %[[MISALIGN]], 0 56 57 // (1b) Check that 'p' actually points to an 'S'. 58 59 // CHECK: %[[VTABLE:.*]] = load ptr, ptr %0 60 // CHECK: %[[VPTR:.*]] = ptrtoint ptr %[[VTABLE]] to i64 61 // hash_16_bytes: 62 // 63 // If this number changes, it indicates that either the mangled name of ::S 64 // has changed, or that LLVM's hashing function has changed. The latter case 65 // is OK if the hashing function is still stable. 66 // 67 // The two hash values are for 64- and 32-bit Clang binaries, respectively. 68 // FIXME: We should produce a 64-bit value either way. 69 // 70 // CHECK-NEXT: mul i64 %[[VPTR]], -4658895280553007687, !nosanitize 71 // CHECK-NEXT: lshr i64 {{.*}}, 31 72 // CHECK-NEXT: xor i64 %[[#]], %[[#]] 73 // CHECK-NEXT: %[[HASH:.*]] = xor i64 4589795628539611399, %[[#]], !nosanitize 74 // 75 // Check the hash against the table: 76 // 77 // CHECK-NEXT: %[[IDX:.*]] = and i64 %{{.*}}, 127 78 // CHECK-NEXT: getelementptr inbounds [128 x i64], ptr @__ubsan_vptr_type_cache, i32 0, i64 %[[IDX]] 79 // CHECK-NEXT: %[[CACHEVAL:.*]] = load i64, ptr 80 // CHECK-NEXT: icmp eq i64 %[[CACHEVAL]], %[[HASH]] 81 // CHECK-NEXT: br i1 82 83 // CHECK: call void @__ubsan_handle_dynamic_type_cache_miss({{.*}}, i64 %{{.*}}, i64 %[[HASH]]) 84 // CHECK-NOT: unreachable 85 // CHECK: {{.*}}: 86 87 // (2) Check 'p->b' is appropriately sized and aligned for a load. 88 89 // FIXME: Suppress this in the trivial case of a member access, because we 90 // know we've just checked the member access expression itself. 91 92 // CHECK: %[[SIZE:.*]] = call i64 @llvm.objectsize.i64 93 // CHECK-NEXT: icmp uge i64 %[[SIZE]], 4 94 95 // CHECK: %[[PTRINT:.*]] = ptrtoint 96 // CHECK-NEXT: %[[MISALIGN:.*]] = and i64 %[[PTRINT]], 3 97 // CHECK-NEXT: icmp eq i64 %[[MISALIGN]], 0 98 int k = p->b; 99 100 // (3a) Check 'p' is appropriately sized and aligned for member function call. 101 102 // CHECK: icmp ne {{.*}}, null 103 104 // CHECK: %[[SIZE:.*]] = call i64 @llvm.objectsize.i64 105 // CHECK-NEXT: icmp uge i64 %[[SIZE]], 24 106 107 // CHECK: %[[PTRINT:.*]] = ptrtoint 108 // CHECK-NEXT: %[[MISALIGN:.*]] = and i64 %[[PTRINT]], 7 109 // CHECK-NEXT: icmp eq i64 %[[MISALIGN]], 0 110 111 // (3b) Check that 'p' actually points to an 'S' 112 113 // CHECK: [[VTABLE2:%.*]] = load ptr, ptr 114 // CHECK: ptrtoint ptr [[VTABLE2]] to i64 115 // CHECK-NEXT: mul i64 %[[#]], -4658895280553007687, !nosanitize 116 // [...] 117 // CHECK: getelementptr inbounds [128 x i64], ptr @__ubsan_vptr_type_cache, i32 0, i64 % 118 // CHECK: br i1 119 // CHECK: call void @__ubsan_handle_dynamic_type_cache_miss({{.*}}, i64 %{{.*}}, i64 %{{.*}}) 120 // CHECK-NOT: unreachable 121 // CHECK: {{.*}}: 122 123 k = p->f(); 124 } 125 126 // CHECK-LABEL: @_Z12lsh_overflow 127 int lsh_overflow(int a, int b) { 128 // CHECK: %[[RHS_inbounds:.*]] = icmp ule i32 %[[RHS:.*]], 31 129 // CHECK-NEXT: br i1 %[[RHS_inbounds]], label %[[CHECK_BB:.*]], label %[[CONT_BB:.*]], 130 131 // CHECK: [[CHECK_BB]]: 132 // CHECK-NEXT: %[[SHIFTED_OUT_WIDTH:.*]] = sub nuw nsw i32 31, %[[RHS]] 133 // CHECK-NEXT: %[[SHIFTED_OUT:.*]] = lshr i32 %[[LHS:.*]], %[[SHIFTED_OUT_WIDTH]] 134 135 // This is present for C++11 but not for C: C++ core issue 1457 allows a '1' 136 // to be shifted into the sign bit, but not out of it. 137 // CHECK-NEXT: %[[SHIFTED_OUT_NOT_SIGN:.*]] = lshr i32 %[[SHIFTED_OUT]], 1 138 139 // CHECK-NEXT: %[[NO_OVERFLOW:.*]] = icmp eq i32 %[[SHIFTED_OUT_NOT_SIGN]], 0 140 // CHECK-NEXT: br label %[[CONT_BB]] 141 142 // CHECK: [[CONT_BB]]: 143 // CHECK-NEXT: %[[VALID_BASE:.*]] = phi i1 [ true, {{.*}} ], [ %[[NO_OVERFLOW]], %[[CHECK_BB]] ] 144 // CHECK-NEXT: %[[VALID:.*]] = and i1 %[[RHS_inbounds]], %[[VALID_BASE]] 145 // CHECK-NEXT: br i1 %[[VALID]] 146 147 // CHECK: call void @__ubsan_handle_shift_out_of_bounds 148 // CHECK-NOT: call void @__ubsan_handle_shift_out_of_bounds 149 150 // CHECK: %[[RET:.*]] = shl i32 %[[LHS]], %[[RHS]] 151 // CHECK-NEXT: ret i32 %[[RET]] 152 return a << b; 153 } 154 155 // CHECK-LABEL: @_Z9no_return 156 int no_return() { 157 // CHECK: call void @__ubsan_handle_missing_return(ptr @{{.*}}) [[NR_NUW:#[0-9]+]] 158 // CHECK-NEXT: unreachable 159 } 160 161 // CHECK-LABEL: @_Z9sour_bool 162 bool sour_bool(bool *p) { 163 // CHECK: %[[OK:.*]] = icmp ule i8 {{.*}}, 1 164 // CHECK: br i1 %[[OK]] 165 // CHECK: call void @__ubsan_handle_load_invalid_value(ptr @{{.*}}, i64 {{.*}}) 166 return *p; 167 } 168 169 enum E1 { e1a = 0, e1b = 127 } e1; 170 enum E2 { e2a = -1, e2b = 64 } e2; 171 enum E3 { e3a = (1u << 31) - 1 } e3; 172 173 // CHECK-LABEL: @_Z14bad_enum_value 174 int bad_enum_value() { 175 // CHECK: %[[E1:.*]] = icmp ule i32 {{.*}}, 127 176 // CHECK: br i1 %[[E1]] 177 // CHECK: call void @__ubsan_handle_load_invalid_value( 178 int a = e1; 179 180 // CHECK: %[[E2HI:.*]] = icmp sle i32 {{.*}}, 127 181 // CHECK: %[[E2LO:.*]] = icmp sge i32 {{.*}}, -128 182 // CHECK: %[[E2:.*]] = and i1 %[[E2HI]], %[[E2LO]] 183 // CHECK: br i1 %[[E2]] 184 // CHECK: call void @__ubsan_handle_load_invalid_value( 185 int b = e2; 186 187 // CHECK: %[[E3:.*]] = icmp ule i32 {{.*}}, 2147483647 188 // CHECK: br i1 %[[E3]] 189 // CHECK: call void @__ubsan_handle_load_invalid_value( 190 int c = e3; 191 return a + b + c; 192 } 193 194 // CHECK-LABEL: @_Z20bad_downcast_pointer 195 // DOWNCAST-NULL-LABEL: @_Z20bad_downcast_pointer 196 void bad_downcast_pointer(S *p) { 197 // CHECK: %[[NONNULL:.*]] = icmp ne {{.*}}, null 198 // CHECK: br i1 %[[NONNULL]], 199 200 // A null pointer access is guarded without -fsanitize=null. 201 // DOWNCAST-NULL: %[[NONNULL:.*]] = icmp ne {{.*}}, null 202 // DOWNCAST-NULL: br i1 %[[NONNULL]], 203 204 // CHECK: %[[SIZE:.*]] = call i64 @llvm.objectsize.i64.p0( 205 // CHECK: %[[E1:.*]] = icmp uge i64 %[[SIZE]], 24 206 // CHECK: %[[MISALIGN:.*]] = and i64 %{{.*}}, 7 207 // CHECK: %[[E2:.*]] = icmp eq i64 %[[MISALIGN]], 0 208 // CHECK: %[[E12:.*]] = and i1 %[[E1]], %[[E2]] 209 // CHECK: br i1 %[[E12]], 210 211 // CHECK: call void @__ubsan_handle_type_mismatch 212 // CHECK: br label 213 214 // CHECK: br i1 %{{.*}}, 215 216 // CHECK: call void @__ubsan_handle_dynamic_type_cache_miss 217 // CHECK: br label 218 (void) static_cast<T*>(p); 219 } 220 221 // CHECK-LABEL: @_Z22bad_downcast_reference 222 void bad_downcast_reference(S &p) { 223 // CHECK: %[[E1:.*]] = icmp ne {{.*}}, null 224 // CHECK-NOT: br i1 225 226 // CHECK: %[[SIZE:.*]] = call i64 @llvm.objectsize.i64.p0( 227 // CHECK: %[[E2:.*]] = icmp uge i64 %[[SIZE]], 24 228 229 // CHECK: %[[MISALIGN:.*]] = and i64 %{{.*}}, 7 230 // CHECK: %[[E3:.*]] = icmp eq i64 %[[MISALIGN]], 0 231 232 // CHECK: %[[E12:.*]] = and i1 %[[E1]], %[[E2]] 233 // CHECK: %[[E123:.*]] = and i1 %[[E12]], %[[E3]] 234 // CHECK: br i1 %[[E123]], 235 236 // CHECK: call void @__ubsan_handle_type_mismatch 237 // CHECK: br label 238 239 // CHECK: br i1 %{{.*}}, 240 241 // CHECK: call void @__ubsan_handle_dynamic_type_cache_miss 242 // CHECK: br label 243 (void) static_cast<T&>(p); 244 } 245 246 // CHECK-LABEL: @_Z11array_index 247 int array_index(const int (&a)[4], int n) { 248 // CHECK: %[[K1_OK:.*]] = icmp ult i64 %{{.*}}, 4 249 // CHECK: br i1 %[[K1_OK]] 250 // CHECK: call void @__ubsan_handle_out_of_bounds( 251 int k1 = a[n]; 252 253 // CHECK: %[[R1_OK:.*]] = icmp ule i64 %{{.*}}, 4 254 // CHECK: br i1 %[[R1_OK]] 255 // CHECK: call void @__ubsan_handle_out_of_bounds( 256 const int *r1 = &a[n]; 257 258 // CHECK: %[[K2_OK:.*]] = icmp ult i64 %{{.*}}, 8 259 // CHECK: br i1 %[[K2_OK]] 260 // CHECK: call void @__ubsan_handle_out_of_bounds( 261 int k2 = ((const int(&)[8])a)[n]; 262 263 // CHECK: %[[K3_OK:.*]] = icmp ult i64 %{{.*}}, 4 264 // CHECK: br i1 %[[K3_OK]] 265 // CHECK: call void @__ubsan_handle_out_of_bounds( 266 int k3 = n[a]; 267 268 return k1 + *r1 + k2; 269 } 270 271 // CHECK-LABEL: @_Z17multi_array_index 272 int multi_array_index(int n, int m) { 273 int arr[4][6]; 274 275 // CHECK: %[[IDX1_OK:.*]] = icmp ult i64 %{{.*}}, 4 276 // CHECK: br i1 %[[IDX1_OK]] 277 // CHECK: call void @__ubsan_handle_out_of_bounds( 278 279 // CHECK: %[[IDX2_OK:.*]] = icmp ult i64 %{{.*}}, 6 280 // CHECK: br i1 %[[IDX2_OK]] 281 // CHECK: call void @__ubsan_handle_out_of_bounds( 282 return arr[n][m]; 283 } 284 285 // CHECK-LABEL: @_Z11array_arith 286 int array_arith(const int (&a)[4], int n) { 287 // CHECK: %[[K1_OK:.*]] = icmp ule i64 %{{.*}}, 4 288 // CHECK: br i1 %[[K1_OK]] 289 // CHECK: call void @__ubsan_handle_out_of_bounds( 290 const int *k1 = a + n; 291 292 // CHECK: %[[K2_OK:.*]] = icmp ule i64 %{{.*}}, 8 293 // CHECK: br i1 %[[K2_OK]] 294 // CHECK: call void @__ubsan_handle_out_of_bounds( 295 const int *k2 = (const int(&)[8])a + n; 296 297 return *k1 + *k2; 298 } 299 300 struct ArrayMembers { 301 int a1[5]; 302 int a2[1]; 303 }; 304 // CHECK-LABEL: @_Z18struct_array_index 305 int struct_array_index(ArrayMembers *p, int n) { 306 // CHECK: %[[IDX_OK:.*]] = icmp ult i64 %{{.*}}, 5 307 // CHECK: br i1 %[[IDX_OK]] 308 // CHECK: call void @__ubsan_handle_out_of_bounds( 309 return p->a1[n]; 310 } 311 312 // CHECK-LABEL: @_Z16flex_array_index 313 int flex_array_index(ArrayMembers *p, int n) { 314 // CHECK-NOT: call void @__ubsan_handle_out_of_bounds( 315 return p->a2[n]; 316 } 317 318 extern int incomplete[]; 319 // CHECK-LABEL: @_Z22incomplete_array_index 320 int incomplete_array_index(int n) { 321 // CHECK-NOT: call void @__ubsan_handle_out_of_bounds( 322 return incomplete[n]; 323 } 324 325 typedef __attribute__((ext_vector_type(4))) int V4I; 326 // CHECK-LABEL: @_Z12vector_index 327 int vector_index(V4I v, int n) { 328 // CHECK: %[[IDX_OK:.*]] = icmp ult i64 %{{.*}}, 4 329 // CHECK: br i1 %[[IDX_OK]] 330 // CHECK: call void @__ubsan_handle_out_of_bounds( 331 return v[n]; 332 } 333 334 // CHECK-LABEL: @_Z12string_index 335 char string_index(int n) { 336 // CHECK: %[[IDX_OK:.*]] = icmp ult i64 %{{.*}}, 6 337 // CHECK: br i1 %[[IDX_OK]] 338 // CHECK: call void @__ubsan_handle_out_of_bounds( 339 return "Hello"[n]; 340 } 341 342 class A // align=4 343 { 344 int a1, a2, a3; 345 }; 346 347 class B // align=8 348 { 349 long b1, b2; 350 }; 351 352 class C : public A, public B // align=16 353 { 354 alignas(16) int c1; 355 }; 356 357 // Make sure we check the alignment of the pointer after subtracting any 358 // offset. The pointer before subtraction doesn't need to be aligned for 359 // the destination type. 360 361 // CHECK-LABEL: define{{.*}} void @_Z16downcast_pointerP1B(ptr %b) 362 void downcast_pointer(B *b) { 363 (void) static_cast<C*>(b); 364 // Alignment check from EmitTypeCheck(TCK_DowncastPointer, ...) 365 // CHECK: [[SUB:%[.a-z0-9]*]] = getelementptr inbounds i8, ptr {{.*}}, i64 -16 366 // null check goes here 367 // CHECK: [[FROM_PHI:%.+]] = phi ptr [ [[SUB]], {{.*}} ], {{.*}} 368 // Objectsize check goes here 369 // CHECK: [[C_INT:%.+]] = ptrtoint ptr [[FROM_PHI]] to i64 370 // CHECK-NEXT: [[MASKED:%.+]] = and i64 [[C_INT]], 15 371 // CHECK-NEXT: [[TEST:%.+]] = icmp eq i64 [[MASKED]], 0 372 // AND the alignment test with the objectsize test. 373 // CHECK-NEXT: [[AND:%.+]] = and i1 {{.*}}, [[TEST]] 374 // CHECK-NEXT: br i1 [[AND]] 375 } 376 377 // CHECK-LABEL: define{{.*}} void @_Z18downcast_referenceR1B(ptr nonnull align {{[0-9]+}} dereferenceable({{[0-9]+}}) %b) 378 void downcast_reference(B &b) { 379 (void) static_cast<C&>(b); 380 // Alignment check from EmitTypeCheck(TCK_DowncastReference, ...) 381 // CHECK: [[SUB:%[.a-z0-9]*]] = getelementptr inbounds i8, ptr {{.*}}, i64 -16 382 // Objectsize check goes here 383 // CHECK: [[C_INT:%.+]] = ptrtoint ptr [[SUB]] to i64 384 // CHECK-NEXT: [[MASKED:%.+]] = and i64 [[C_INT]], 15 385 // CHECK-NEXT: [[TEST:%.+]] = icmp eq i64 [[MASKED]], 0 386 // AND the alignment test with the objectsize test. 387 // CHECK: [[AND:%.+]] = and i1 {{.*}}, [[TEST]] 388 // CHECK-NEXT: br i1 [[AND]] 389 } 390 391 // CHECK-FUNCSAN: @_Z22indirect_function_callPFviE({{.*}} !func_sanitize ![[FUNCSAN:.*]] { 392 void indirect_function_call(void (*p)(int)) { 393 // CHECK: [[PTR:%.+]] = load ptr, ptr 394 395 // Signature check 396 // CHECK-NEXT: [[SIGPTR:%.+]] = getelementptr <{ i32, i32 }>, ptr [[PTR]], i32 -1, i32 0 397 // CHECK-NEXT: [[SIG:%.+]] = load i32, ptr [[SIGPTR]] 398 // CHECK-NEXT: [[SIGCMP:%.+]] = icmp eq i32 [[SIG]], -1056584962 399 // CHECK-NEXT: br i1 [[SIGCMP]] 400 401 // CalleeTypeHash check 402 // CHECK: [[CalleeTypeHashPtr:%.+]] = getelementptr <{ i32, i32 }>, ptr [[PTR]], i32 -1, i32 1 403 // CHECK-NEXT: [[CalleeTypeHash:%.+]] = load i32, ptr [[CalleeTypeHashPtr]] 404 // CHECK-NEXT: [[CalleeTypeHashMatch:%.+]] = icmp eq i32 [[CalleeTypeHash]], -1988405058 405 // CHECK-NEXT: br i1 [[CalleeTypeHashMatch]] 406 407 p(42); 408 } 409 410 namespace VBaseObjectSize { 411 // Note: C is laid out such that offsetof(C, B) + sizeof(B) extends outside 412 // the C object. 413 struct alignas(16) A { void *a1, *a2; }; 414 struct B : virtual A { void *b; void* g(); }; 415 struct C : virtual A, virtual B { }; 416 // CHECK-LABEL: define {{.*}} @_ZN15VBaseObjectSize1fERNS_1BE( 417 B &f(B &b) { 418 // Size check: check for nvsize(B) == 16 (do not require size(B) == 32) 419 // CHECK: [[SIZE:%.+]] = call i{{32|64}} @llvm.objectsize.i64.p0( 420 // CHECK: icmp uge i{{32|64}} [[SIZE]], 16, 421 422 // Alignment check: check for nvalign(B) == 8 (do not require align(B) == 16) 423 // CHECK: [[PTRTOINT:%.+]] = ptrtoint {{.*}} to i64, 424 // CHECK: and i64 [[PTRTOINT]], 7, 425 return b; 426 } 427 428 // CHECK-LABEL: define {{.*}} @_ZN15VBaseObjectSize1B1gEv( 429 void *B::g() { 430 // Ensure that the check on the "this" pointer also uses the proper 431 // alignment. We should be using nvalign(B) == 8, not 16. 432 // CHECK: [[PTRTOINT:%.+]] = ptrtoint {{.*}} to i64, 433 // CHECK: and i64 [[PTRTOINT]], 7 434 return nullptr; 435 } 436 } 437 438 namespace FunctionSanitizerVirtualCalls { 439 struct A { 440 virtual void f() {} 441 virtual void g() {} 442 void h() {} 443 }; 444 445 struct B : virtual A { 446 virtual void b() {} 447 virtual void f(); 448 void g() final {} 449 static void q() {} 450 }; 451 452 void B::f() {} 453 454 void force_irgen() { 455 A a; 456 a.g(); 457 a.h(); 458 459 B b; 460 b.f(); 461 b.b(); 462 b.g(); 463 B::q(); 464 } 465 466 // CHECK-LABEL: define{{.*}} void @_ZN29FunctionSanitizerVirtualCalls1B1fEv 467 // CHECK-NOT: !func_sanitize 468 // 469 // CHECK-LABEL: define{{.*}} void @_ZTv0_n24_N29FunctionSanitizerVirtualCalls1B1fEv 470 // CHECK-NOT: !func_sanitize 471 // 472 // CHECK-LABEL: define{{.*}} void @_ZN29FunctionSanitizerVirtualCalls11force_irgenEv() 473 // CHECK: !func_sanitize 474 // 475 // CHECK-LABEL: define linkonce_odr void @_ZN29FunctionSanitizerVirtualCalls1AC1Ev 476 // CHECK-NOT: !func_sanitize 477 // 478 // CHECK-LABEL: define linkonce_odr void @_ZN29FunctionSanitizerVirtualCalls1A1gEv 479 // CHECK-NOT: !func_sanitize 480 // 481 // CHECK-LABEL: define linkonce_odr void @_ZN29FunctionSanitizerVirtualCalls1A1hEv 482 // CHECK-NOT: !func_sanitize 483 // 484 // CHECK-LABEL: define linkonce_odr void @_ZN29FunctionSanitizerVirtualCalls1BC1Ev 485 // CHECK-NOT: !func_sanitize 486 // 487 // CHECK-LABEL: define linkonce_odr void @_ZN29FunctionSanitizerVirtualCalls1B1bEv 488 // CHECK-NOT: !func_sanitize 489 // 490 // CHECK-LABEL: define linkonce_odr void @_ZN29FunctionSanitizerVirtualCalls1B1gEv 491 // CHECK-NOT: !func_sanitize 492 // 493 // CHECK-LABEL: define linkonce_odr void @_ZN29FunctionSanitizerVirtualCalls1B1qEv 494 // CHECK: !func_sanitize 495 496 } 497 498 namespace UpcastPointerTest { 499 struct S {}; 500 struct T : S { double d; }; 501 struct V : virtual S {}; 502 503 // CHECK-LABEL: upcast_pointer 504 S* upcast_pointer(T* t) { 505 // Check for null pointer 506 // CHECK: %[[NONNULL:.*]] = icmp ne {{.*}}, null 507 // CHECK: br i1 %[[NONNULL]] 508 509 // Check alignment 510 // CHECK: %[[MISALIGN:.*]] = and i64 %{{.*}}, 7 511 // CHECK: icmp eq i64 %[[MISALIGN]], 0 512 513 // CHECK: call void @__ubsan_handle_type_mismatch 514 return t; 515 } 516 517 V getV(); 518 519 // CHECK-LABEL: upcast_to_vbase 520 void upcast_to_vbase() { 521 // No need to check for null here, as we have a temporary here. 522 523 // CHECK-NOT: br i1 524 525 // CHECK: call i64 @llvm.objectsize 526 // CHECK: call void @__ubsan_handle_type_mismatch 527 // CHECK: call void @__ubsan_handle_dynamic_type_cache_miss 528 const S& s = getV(); 529 } 530 } 531 532 struct nothrow {}; 533 void *operator new[](__SIZE_TYPE__, nothrow) noexcept; 534 535 namespace NothrowNew { 536 struct X { X(); }; 537 538 // CHECK-LABEL: define{{.*}}nothrow_new_trivial 539 void *nothrow_new_trivial() { 540 // CHECK: %[[is_null:.*]] = icmp eq ptr{{.*}}, null 541 // CHECK: br i1 %[[is_null]], label %[[null:.*]], label %[[nonnull:.*]] 542 543 // CHECK: [[nonnull]]: 544 // CHECK: llvm.objectsize 545 // CHECK: icmp uge i64 {{.*}}, 123456, 546 // CHECK: br i1 547 // 548 // CHECK: call {{.*}}__ubsan_handle_type_mismatch 549 // 550 // CHECK: [[null]]: 551 // CHECK-NOT: {{ }}br{{ }} 552 // CHECK: ret 553 return new (nothrow{}) char[123456]; 554 } 555 556 // CHECK-LABEL: define{{.*}}nothrow_new_nontrivial 557 void *nothrow_new_nontrivial() { 558 // CHECK: %[[is_null:.*]] = icmp eq ptr{{.*}}, null 559 // CHECK: br i1 %[[is_null]], label %[[null:.*]], label %[[nonnull:.*]] 560 561 // CHECK: [[nonnull]]: 562 // CHECK: llvm.objectsize 563 // CHECK: icmp uge i64 {{.*}}, 123456, 564 // CHECK: br i1 565 // 566 // CHECK: call {{.*}}__ubsan_handle_type_mismatch 567 // 568 // CHECK: call {{.*}}_ZN10NothrowNew1XC1Ev 569 // 570 // CHECK: [[null]]: 571 // CHECK-NOT: {{ }}br{{ }} 572 // CHECK: ret 573 return new (nothrow{}) X[123456]; 574 } 575 576 // CHECK-LABEL: define{{.*}}throwing_new 577 void *throwing_new(int size) { 578 // CHECK: icmp ne ptr{{.*}}, null 579 // CHECK: %[[size:.*]] = mul 580 // CHECK: llvm.objectsize 581 // CHECK: icmp uge i64 {{.*}}, %[[size]], 582 // CHECK: %[[ok:.*]] = and 583 // CHECK: br i1 %[[ok]], label %[[good:.*]], label %[[bad:[^,]*]] 584 // 585 // CHECK: [[bad]]: 586 // CHECK: call {{.*}}__ubsan_handle_type_mismatch 587 // 588 // CHECK: [[good]]: 589 // CHECK-NOT: {{ }}br{{ }} 590 // CHECK: ret 591 return new char[size]; 592 } 593 594 // CHECK-LABEL: define{{.*}}nothrow_new_zero_size 595 void *nothrow_new_zero_size() { 596 // CHECK: %[[nonnull:.*]] = icmp ne ptr{{.*}}, null 597 // CHECK-NOT: llvm.objectsize 598 // CHECK: br i1 %[[nonnull]], label %[[good:.*]], label %[[bad:[^,]*]] 599 // 600 // CHECK: [[bad]]: 601 // CHECK: call {{.*}}__ubsan_handle_type_mismatch 602 // 603 // CHECK: [[good]]: 604 // CHECK-NOT: {{ }}br{{ }} 605 // CHECK: ret 606 return new char[0]; 607 } 608 609 // CHECK-LABEL: define{{.*}}throwing_new_zero_size 610 void *throwing_new_zero_size() { 611 // Nothing to check here. 612 // CHECK-NOT: __ubsan_handle_type_mismatch 613 return new (nothrow{}) char[0]; 614 // CHECK: ret 615 } 616 } 617 618 struct ThisAlign { 619 void this_align_lambda(); 620 void this_align_lambda_2(); 621 }; 622 void ThisAlign::this_align_lambda() { 623 // CHECK-LABEL: define internal ptr @"_ZZN9ThisAlign17this_align_lambdaEvENK3$_0clEv" 624 // CHECK-SAME: (ptr {{[^,]*}} %[[this:[^)]*]]) 625 // CHECK: %[[this_addr:.*]] = alloca 626 // CHECK: store ptr %[[this]], ptr %[[this_addr]], 627 // CHECK: %[[this_inner:.*]] = load ptr, ptr %[[this_addr]], 628 // CHECK: %[[this_outer_addr:.*]] = getelementptr inbounds nuw %{{.*}}, ptr %[[this_inner]], i32 0, i32 0 629 // CHECK: %[[this_outer:.*]] = load ptr, ptr %[[this_outer_addr]], 630 // 631 // CHECK: %[[this_inner_isnonnull:.*]] = icmp ne ptr %[[this_inner]], null 632 // CHECK: %[[this_inner_asint:.*]] = ptrtoint ptr %[[this_inner]] to i 633 // CHECK: %[[this_inner_misalignment:.*]] = and i{{32|64}} %[[this_inner_asint]], {{3|7}}, 634 // CHECK: %[[this_inner_isaligned:.*]] = icmp eq i{{32|64}} %[[this_inner_misalignment]], 0 635 // CHECK: %[[this_inner_valid:.*]] = and i1 %[[this_inner_isnonnull]], %[[this_inner_isaligned]], 636 // CHECK: br i1 %[[this_inner_valid:.*]] 637 [&] { return this; } (); 638 } 639 640 namespace CopyValueRepresentation { 641 // CHECK-LABEL: define {{.*}} @_ZN23CopyValueRepresentation2S3aSERKS0_ 642 // CHECK-NOT: call {{.*}} @__ubsan_handle_load_invalid_value 643 // CHECK-LABEL: define {{.*}} @_ZN23CopyValueRepresentation2S4aSEOS0_ 644 // CHECK-NOT: call {{.*}} @__ubsan_handle_load_invalid_value 645 // CHECK-LABEL: define {{.*}} @_ZN23CopyValueRepresentation2S1C2ERKS0_ 646 // CHECK-NOT: call {{.*}} __ubsan_handle_load_invalid_value 647 // CHECK-LABEL: define {{.*}} @_ZN23CopyValueRepresentation2S2C2ERKS0_ 648 // CHECK: __ubsan_handle_load_invalid_value 649 // CHECK-LABEL: define {{.*}} @_ZN23CopyValueRepresentation2S5C2ERKS0_ 650 // CHECK-NOT: call {{.*}} __ubsan_handle_load_invalid_value 651 652 struct CustomCopy { CustomCopy(); CustomCopy(const CustomCopy&); }; 653 struct S1 { 654 CustomCopy CC; 655 bool b; 656 }; 657 void callee1(S1); 658 void test1() { 659 S1 s11; 660 callee1(s11); 661 S1 s12; 662 s12 = s11; 663 } 664 665 static bool some_global_bool; 666 struct ExprCopy { 667 ExprCopy(); 668 ExprCopy(const ExprCopy&, bool b = some_global_bool); 669 }; 670 struct S2 { 671 ExprCopy EC; 672 bool b; 673 }; 674 void callee2(S2); 675 void test2(void) { 676 S2 s21; 677 callee2(s21); 678 S2 s22; 679 s22 = s21; 680 } 681 682 struct CustomAssign { CustomAssign &operator=(const CustomAssign&); }; 683 struct S3 { 684 CustomAssign CA; 685 bool b; 686 }; 687 void test3() { 688 S3 x, y; 689 x = y; 690 } 691 692 struct CustomMove { 693 CustomMove(); 694 CustomMove(const CustomMove&&); 695 CustomMove &operator=(const CustomMove&&); 696 }; 697 struct S4 { 698 CustomMove CM; 699 bool b; 700 }; 701 void test4() { 702 S4 x, y; 703 x = static_cast<S4&&>(y); 704 } 705 706 struct EnumCustomCopy { 707 EnumCustomCopy(); 708 EnumCustomCopy(const EnumCustomCopy&); 709 }; 710 struct S5 { 711 EnumCustomCopy ECC; 712 bool b; 713 }; 714 void callee5(S5); 715 void test5() { 716 S5 s51; 717 callee5(s51); 718 S5 s52; 719 s52 = s51; 720 } 721 } 722 723 void ThisAlign::this_align_lambda_2() { 724 // CHECK-LABEL: define internal void @"_ZZN9ThisAlign19this_align_lambda_2EvENK3$_0clEv" 725 // CHECK-SAME: (ptr {{[^,]*}} %[[this:[^)]*]]) 726 // CHECK: %[[this_addr:.*]] = alloca 727 // CHECK: store ptr %[[this]], ptr %[[this_addr]], 728 // CHECK: %[[this_inner:.*]] = load ptr, ptr %[[this_addr]], 729 // 730 // Do not perform a null check on the 'this' pointer if the function might be 731 // called from a static invoker. 732 // CHECK-NOT: icmp ne ptr %[[this_inner]], null 733 auto *p = +[] {}; 734 p(); 735 } 736 737 // CHECK: attributes [[NR_NUW]] = { nomerge noreturn nounwind } 738 739 // CHECK-FUNCSAN: ![[FUNCSAN]] = !{i32 -1056584962, i32 -1000226989} 740