Clang Project

clang_source_code/test/CodeGenCXX/ubsan-type-checks.cpp
1// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin10 -emit-llvm -o - %s -fsanitize=alignment | FileCheck %s -check-prefixes=ALIGN,COMMON
2// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin10 -emit-llvm -o - %s -fsanitize=null | FileCheck %s -check-prefixes=NULL,COMMON
3// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin10 -emit-llvm -o - %s -fsanitize=object-size | FileCheck %s -check-prefixes=OBJSIZE,COMMON
4// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin10 -emit-llvm -o - %s -fsanitize=null,vptr | FileCheck %s -check-prefixes=VPTR
5// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin10 -emit-llvm -o - %s -fsanitize=vptr | FileCheck %s -check-prefixes=VPTR_NO_NULL
6
7struct A {
8  // COMMON-LABEL: define linkonce_odr void @_ZN1A10do_nothingEv
9  void do_nothing() {
10    // ALIGN-NOT: ptrtoint %struct.A* %{{.*}} to i64, !nosanitize
11 
12    // NULL: icmp ne %struct.A* %{{.*}}, null, !nosanitize
13 
14    // OBJSIZE-NOT: call i64 @llvm.objectsize
15  }
16};
17
18struct B {
19  int x;
20
21  // COMMON-LABEL: define linkonce_odr void @_ZN1B10do_nothingEv
22  void do_nothing() {
23    // ALIGN: ptrtoint %struct.B* %{{.*}} to i64, !nosanitize
24    // ALIGN: and i64 %{{.*}}, 3, !nosanitize
25
26    // NULL: icmp ne %struct.B* %{{.*}}, null, !nosanitize
27
28    // OBJSIZE-NOT: call i64 @llvm.objectsize
29    // OBJSIZE: ret void
30  }
31};
32
33struct Animal {
34  virtual const char *speak() = 0;
35};
36
37struct Cat : Animal {
38  const char *speak() override { return "meow"; }
39};
40
41struct Dog : Animal {
42  const char *speak() override { return "woof"; }
43};
44
45// VPTR-LABEL: define void @_Z12invalid_castP3Cat
46void invalid_cast(Cat *cat = nullptr) {
47  // If -fsanitize=null is available, we'll reuse its check:
48  //
49  // VPTR: [[ICMP:%.*]] = icmp ne %struct.Dog* {{.*}}, null
50  // VPTR-NEXT: br i1 [[ICMP]]
51  // VPTR: call void @__ubsan_handle_type_mismatch
52  // VPTR-NOT: icmp ne %struct.Dog* {{.*}}, null
53  // VPTR: br i1 [[ICMP]]
54  // VPTR: call void @__ubsan_handle_dynamic_type_cache_miss
55  //
56  // Fall back to the vptr sanitizer's null check when -fsanitize=null isn't
57  // available.
58  //
59  // VPTR_NO_NULL-NOT: call void @__ubsan_handle_type_mismatch
60  // VPTR_NO_NULL: [[ICMP:%.*]] = icmp ne %struct.Dog* {{.*}}, null
61  // VPTR_NO_NULL-NEXT: br i1 [[ICMP]]
62  // VPTR_NO_NULL: call void @__ubsan_handle_dynamic_type_cache_miss
63  auto *badDog = reinterpret_cast<Dog *>(cat);
64  badDog->speak();
65}
66
67// VPTR_NO_NULL-LABEL: define void @_Z13invalid_cast2v
68void invalid_cast2() {
69  // We've got a pointer to an alloca, so there's no run-time null check needed.
70  // VPTR_NO_NULL-NOT: call void @__ubsan_handle_type_mismatch
71  // VPTR_NO_NULL: call void @__ubsan_handle_dynamic_type_cache_miss
72  Cat cat;
73  cat.speak();
74}
75
76int main() {
77  A a;
78  a.do_nothing();
79
80  B b;
81  b.do_nothing();
82
83  invalid_cast();
84  return 0;
85}
86