]>
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 | |
5bcae85e | 18 | #include "ubsan_handlers.h" |
1a4d82fc JJ |
19 | #include "ubsan_handlers_cxx.h" |
20 | #include "ubsan_diag.h" | |
21 | #include "ubsan_type_hash.h" | |
22 | ||
23 | #include "sanitizer_common/sanitizer_common.h" | |
92a42be0 | 24 | #include "sanitizer_common/sanitizer_suppressions.h" |
1a4d82fc JJ |
25 | |
26 | using namespace __sanitizer; | |
27 | using namespace __ubsan; | |
28 | ||
29 | namespace __ubsan { | |
30 | extern const char *TypeCheckKinds[]; | |
31 | } | |
32 | ||
3157f602 XL |
33 | // Returns true if UBSan has printed an error report. |
34 | static bool HandleDynamicTypeCacheMiss( | |
1a4d82fc | 35 | DynamicTypeCacheMissData *Data, ValueHandle Pointer, ValueHandle Hash, |
92a42be0 | 36 | ReportOptions Opts) { |
1a4d82fc JJ |
37 | if (checkDynamicType((void*)Pointer, Data->TypeInfo, Hash)) |
38 | // Just a cache miss. The type matches after all. | |
3157f602 | 39 | return false; |
1a4d82fc | 40 | |
92a42be0 SL |
41 | // Check if error report should be suppressed. |
42 | DynamicTypeInfo DTI = getDynamicTypeInfoFromObject((void*)Pointer); | |
43 | if (DTI.isValid() && IsVptrCheckSuppressed(DTI.getMostDerivedTypeName())) | |
3157f602 | 44 | return false; |
92a42be0 | 45 | |
1a4d82fc | 46 | SourceLocation Loc = Data->Loc.acquire(); |
3157f602 XL |
47 | ErrorType ET = ErrorType::DynamicTypeMismatch; |
48 | if (ignoreReport(Loc, Opts, ET)) | |
49 | return false; | |
1a4d82fc | 50 | |
3157f602 | 51 | ScopedReport R(Opts, Loc, ET); |
92a42be0 | 52 | |
1a4d82fc JJ |
53 | Diag(Loc, DL_Error, |
54 | "%0 address %1 which does not point to an object of type %2") | |
55 | << TypeCheckKinds[Data->TypeCheckKind] << (void*)Pointer << Data->Type; | |
56 | ||
57 | // If possible, say what type it actually points to. | |
5bcae85e SL |
58 | if (!DTI.isValid()) { |
59 | if (DTI.getOffset() < -VptrMaxOffsetToTop || DTI.getOffset() > VptrMaxOffsetToTop) { | |
60 | Diag(Pointer, DL_Note, "object has a possibly invalid vptr: abs(offset to top) too big") | |
61 | << TypeName(DTI.getMostDerivedTypeName()) | |
62 | << Range(Pointer, Pointer + sizeof(uptr), "possibly invalid vptr"); | |
63 | } else { | |
64 | Diag(Pointer, DL_Note, "object has invalid vptr") | |
65 | << TypeName(DTI.getMostDerivedTypeName()) | |
66 | << Range(Pointer, Pointer + sizeof(uptr), "invalid vptr"); | |
67 | } | |
68 | } else if (!DTI.getOffset()) | |
1a4d82fc | 69 | Diag(Pointer, DL_Note, "object is of type %0") |
92a42be0 SL |
70 | << TypeName(DTI.getMostDerivedTypeName()) |
71 | << Range(Pointer, Pointer + sizeof(uptr), "vptr for %0"); | |
1a4d82fc JJ |
72 | else |
73 | // FIXME: Find the type at the specified offset, and include that | |
74 | // in the note. | |
75 | Diag(Pointer - DTI.getOffset(), DL_Note, | |
76 | "object is base class subobject at offset %0 within object of type %1") | |
92a42be0 SL |
77 | << DTI.getOffset() << TypeName(DTI.getMostDerivedTypeName()) |
78 | << TypeName(DTI.getSubobjectTypeName()) | |
79 | << Range(Pointer, Pointer + sizeof(uptr), | |
80 | "vptr for %2 base class of %1"); | |
3157f602 | 81 | return true; |
1a4d82fc JJ |
82 | } |
83 | ||
84 | void __ubsan::__ubsan_handle_dynamic_type_cache_miss( | |
85 | DynamicTypeCacheMissData *Data, ValueHandle Pointer, ValueHandle Hash) { | |
92a42be0 SL |
86 | GET_REPORT_OPTIONS(false); |
87 | HandleDynamicTypeCacheMiss(Data, Pointer, Hash, Opts); | |
1a4d82fc JJ |
88 | } |
89 | void __ubsan::__ubsan_handle_dynamic_type_cache_miss_abort( | |
90 | DynamicTypeCacheMissData *Data, ValueHandle Pointer, ValueHandle Hash) { | |
3157f602 XL |
91 | // Note: -fsanitize=vptr is always recoverable. |
92 | GET_REPORT_OPTIONS(false); | |
93 | if (HandleDynamicTypeCacheMiss(Data, Pointer, Hash, Opts)) | |
94 | Die(); | |
92a42be0 SL |
95 | } |
96 | ||
5bcae85e SL |
97 | namespace __ubsan { |
98 | void HandleCFIBadType(CFICheckFailData *Data, ValueHandle Vtable, | |
99 | bool ValidVtable, ReportOptions Opts) { | |
92a42be0 | 100 | SourceLocation Loc = Data->Loc.acquire(); |
3157f602 XL |
101 | ErrorType ET = ErrorType::CFIBadType; |
102 | ||
103 | if (ignoreReport(Loc, Opts, ET)) | |
104 | return; | |
105 | ||
106 | ScopedReport R(Opts, Loc, ET); | |
5bcae85e SL |
107 | DynamicTypeInfo DTI = ValidVtable |
108 | ? getDynamicTypeInfoFromVtable((void *)Vtable) | |
109 | : DynamicTypeInfo(0, 0, 0); | |
110 | ||
111 | const char *CheckKindStr; | |
112 | switch (Data->CheckKind) { | |
113 | case CFITCK_VCall: | |
114 | CheckKindStr = "virtual call"; | |
115 | break; | |
116 | case CFITCK_NVCall: | |
117 | CheckKindStr = "non-virtual call"; | |
118 | break; | |
119 | case CFITCK_DerivedCast: | |
120 | CheckKindStr = "base-to-derived cast"; | |
121 | break; | |
122 | case CFITCK_UnrelatedCast: | |
123 | CheckKindStr = "cast to unrelated type"; | |
124 | break; | |
125 | case CFITCK_ICall: | |
126 | Die(); | |
127 | } | |
92a42be0 SL |
128 | |
129 | Diag(Loc, DL_Error, "control flow integrity check for type %0 failed during " | |
130 | "%1 (vtable address %2)") | |
5bcae85e | 131 | << Data->Type << CheckKindStr << (void *)Vtable; |
92a42be0 SL |
132 | |
133 | // If possible, say what type it actually points to. | |
5bcae85e SL |
134 | if (!DTI.isValid()) { |
135 | const char *module = Symbolizer::GetOrInit()->GetModuleNameForPc(Vtable); | |
136 | if (module) | |
137 | Diag(Vtable, DL_Note, "invalid vtable in module %0") << module; | |
138 | else | |
139 | Diag(Vtable, DL_Note, "invalid vtable"); | |
140 | } else { | |
92a42be0 SL |
141 | Diag(Vtable, DL_Note, "vtable is of type %0") |
142 | << TypeName(DTI.getMostDerivedTypeName()); | |
5bcae85e | 143 | } |
1a4d82fc | 144 | } |
5bcae85e | 145 | } // namespace __ubsan |
92a42be0 | 146 | |
5bcae85e | 147 | #endif // CAN_SANITIZE_UB |