]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
1 | //===-- ubsan_handlers_cxx.cc ---------------------------------------------===// |
2 | // | |
3 | // The LLVM Compiler Infrastructure | |
4 | // | |
5 | // This file is distributed under the University of Illinois Open Source | |
6 | // License. See LICENSE.TXT for details. | |
7 | // | |
8 | //===----------------------------------------------------------------------===// | |
9 | // | |
10 | // Error logging entry points for the UBSan runtime, which are only used for C++ | |
11 | // compilations. This file is permitted to use language features which require | |
12 | // linking against a C++ ABI library. | |
13 | // | |
14 | //===----------------------------------------------------------------------===// | |
15 | ||
92a42be0 SL |
16 | #include "ubsan_platform.h" |
17 | #if CAN_SANITIZE_UB | |
1a4d82fc JJ |
18 | #include "ubsan_handlers_cxx.h" |
19 | #include "ubsan_diag.h" | |
20 | #include "ubsan_type_hash.h" | |
21 | ||
22 | #include "sanitizer_common/sanitizer_common.h" | |
92a42be0 | 23 | #include "sanitizer_common/sanitizer_suppressions.h" |
1a4d82fc JJ |
24 | |
25 | using namespace __sanitizer; | |
26 | using namespace __ubsan; | |
27 | ||
28 | namespace __ubsan { | |
29 | extern const char *TypeCheckKinds[]; | |
30 | } | |
31 | ||
32 | static void HandleDynamicTypeCacheMiss( | |
33 | DynamicTypeCacheMissData *Data, ValueHandle Pointer, ValueHandle Hash, | |
92a42be0 | 34 | ReportOptions Opts) { |
1a4d82fc JJ |
35 | if (checkDynamicType((void*)Pointer, Data->TypeInfo, Hash)) |
36 | // Just a cache miss. The type matches after all. | |
37 | return; | |
38 | ||
92a42be0 SL |
39 | // Check if error report should be suppressed. |
40 | DynamicTypeInfo DTI = getDynamicTypeInfoFromObject((void*)Pointer); | |
41 | if (DTI.isValid() && IsVptrCheckSuppressed(DTI.getMostDerivedTypeName())) | |
42 | return; | |
43 | ||
1a4d82fc JJ |
44 | SourceLocation Loc = Data->Loc.acquire(); |
45 | if (Loc.isDisabled()) | |
46 | return; | |
47 | ||
92a42be0 SL |
48 | ScopedReport R(Opts, Loc, ErrorType::DynamicTypeMismatch); |
49 | ||
1a4d82fc JJ |
50 | Diag(Loc, DL_Error, |
51 | "%0 address %1 which does not point to an object of type %2") | |
52 | << TypeCheckKinds[Data->TypeCheckKind] << (void*)Pointer << Data->Type; | |
53 | ||
54 | // If possible, say what type it actually points to. | |
1a4d82fc JJ |
55 | if (!DTI.isValid()) |
56 | Diag(Pointer, DL_Note, "object has invalid vptr") | |
92a42be0 SL |
57 | << TypeName(DTI.getMostDerivedTypeName()) |
58 | << Range(Pointer, Pointer + sizeof(uptr), "invalid vptr"); | |
1a4d82fc JJ |
59 | else if (!DTI.getOffset()) |
60 | Diag(Pointer, DL_Note, "object is of type %0") | |
92a42be0 SL |
61 | << TypeName(DTI.getMostDerivedTypeName()) |
62 | << Range(Pointer, Pointer + sizeof(uptr), "vptr for %0"); | |
1a4d82fc JJ |
63 | else |
64 | // FIXME: Find the type at the specified offset, and include that | |
65 | // in the note. | |
66 | Diag(Pointer - DTI.getOffset(), DL_Note, | |
67 | "object is base class subobject at offset %0 within object of type %1") | |
92a42be0 SL |
68 | << DTI.getOffset() << TypeName(DTI.getMostDerivedTypeName()) |
69 | << TypeName(DTI.getSubobjectTypeName()) | |
70 | << Range(Pointer, Pointer + sizeof(uptr), | |
71 | "vptr for %2 base class of %1"); | |
1a4d82fc JJ |
72 | } |
73 | ||
74 | void __ubsan::__ubsan_handle_dynamic_type_cache_miss( | |
75 | DynamicTypeCacheMissData *Data, ValueHandle Pointer, ValueHandle Hash) { | |
92a42be0 SL |
76 | GET_REPORT_OPTIONS(false); |
77 | HandleDynamicTypeCacheMiss(Data, Pointer, Hash, Opts); | |
1a4d82fc JJ |
78 | } |
79 | void __ubsan::__ubsan_handle_dynamic_type_cache_miss_abort( | |
80 | DynamicTypeCacheMissData *Data, ValueHandle Pointer, ValueHandle Hash) { | |
92a42be0 SL |
81 | GET_REPORT_OPTIONS(true); |
82 | HandleDynamicTypeCacheMiss(Data, Pointer, Hash, Opts); | |
83 | } | |
84 | ||
85 | static void HandleCFIBadType(CFIBadTypeData *Data, ValueHandle Vtable, | |
86 | ReportOptions Opts) { | |
87 | SourceLocation Loc = Data->Loc.acquire(); | |
88 | ScopedReport R(Opts, Loc, ErrorType::CFIBadType); | |
89 | DynamicTypeInfo DTI = getDynamicTypeInfoFromVtable((void*)Vtable); | |
90 | ||
91 | static const char *TypeCheckKinds[] = { | |
92 | "virtual call", | |
93 | "non-virtual call", | |
94 | "base-to-derived cast", | |
95 | "cast to unrelated type", | |
96 | }; | |
97 | ||
98 | Diag(Loc, DL_Error, "control flow integrity check for type %0 failed during " | |
99 | "%1 (vtable address %2)") | |
100 | << Data->Type << TypeCheckKinds[Data->TypeCheckKind] << (void *)Vtable; | |
101 | ||
102 | // If possible, say what type it actually points to. | |
103 | if (!DTI.isValid()) | |
104 | Diag(Vtable, DL_Note, "invalid vtable"); | |
105 | else | |
106 | Diag(Vtable, DL_Note, "vtable is of type %0") | |
107 | << TypeName(DTI.getMostDerivedTypeName()); | |
1a4d82fc | 108 | } |
92a42be0 SL |
109 | |
110 | void __ubsan::__ubsan_handle_cfi_bad_type(CFIBadTypeData *Data, | |
111 | ValueHandle Vtable) { | |
112 | GET_REPORT_OPTIONS(false); | |
113 | HandleCFIBadType(Data, Vtable, Opts); | |
114 | } | |
115 | ||
116 | void __ubsan::__ubsan_handle_cfi_bad_type_abort(CFIBadTypeData *Data, | |
117 | ValueHandle Vtable) { | |
118 | GET_REPORT_OPTIONS(true); | |
119 | HandleCFIBadType(Data, Vtable, Opts); | |
120 | } | |
121 | ||
122 | #endif // CAN_SANITIZE_UB |