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