blob: d97ec4813ccd4811db5873c073c7a03bc4964c6b [file] [log] [blame]
Richard Smith2f0d7d52012-10-25 02:07:02 +00001//===-- 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
Alexey Samsonov0781e982015-03-26 17:26:04 +000016#include "ubsan_platform.h"
17#if CAN_SANITIZE_UB
Evgeniy Stepanov22696522016-01-25 23:34:38 +000018#include "ubsan_handlers.h"
Richard Smith2f0d7d52012-10-25 02:07:02 +000019#include "ubsan_handlers_cxx.h"
20#include "ubsan_diag.h"
21#include "ubsan_type_hash.h"
22
23#include "sanitizer_common/sanitizer_common.h"
Alexey Samsonovff24fd22014-08-05 01:24:22 +000024#include "sanitizer_common/sanitizer_suppressions.h"
Richard Smith2f0d7d52012-10-25 02:07:02 +000025
26using namespace __sanitizer;
27using namespace __ubsan;
28
29namespace __ubsan {
30 extern const char *TypeCheckKinds[];
31}
32
Alexey Samsonovaff20ac2015-12-09 00:12:57 +000033// Returns true if UBSan has printed an error report.
34static bool HandleDynamicTypeCacheMiss(
Richard Smithcf56ebd2012-12-18 06:30:32 +000035 DynamicTypeCacheMissData *Data, ValueHandle Pointer, ValueHandle Hash,
Alexey Samsonov2ccbc622014-08-22 21:42:04 +000036 ReportOptions Opts) {
Richard Smith2f0d7d52012-10-25 02:07:02 +000037 if (checkDynamicType((void*)Pointer, Data->TypeInfo, Hash))
38 // Just a cache miss. The type matches after all.
Alexey Samsonovaff20ac2015-12-09 00:12:57 +000039 return false;
Richard Smith2f0d7d52012-10-25 02:07:02 +000040
Alexey Samsonovff24fd22014-08-05 01:24:22 +000041 // Check if error report should be suppressed.
Peter Collingbourne175d6332015-06-19 01:52:55 +000042 DynamicTypeInfo DTI = getDynamicTypeInfoFromObject((void*)Pointer);
Alexey Samsonovd1c31862015-02-20 17:41:59 +000043 if (DTI.isValid() && IsVptrCheckSuppressed(DTI.getMostDerivedTypeName()))
Alexey Samsonovaff20ac2015-12-09 00:12:57 +000044 return false;
Alexey Samsonovff24fd22014-08-05 01:24:22 +000045
Will Dietz765c2662013-01-09 03:40:03 +000046 SourceLocation Loc = Data->Loc.acquire();
Alexey Samsonov081a24e2015-12-18 19:56:42 +000047 ErrorType ET = ErrorType::DynamicTypeMismatch;
48 if (ignoreReport(Loc, Opts, ET))
Alexey Samsonovaff20ac2015-12-09 00:12:57 +000049 return false;
Will Dietz765c2662013-01-09 03:40:03 +000050
Alexey Samsonov081a24e2015-12-18 19:56:42 +000051 ScopedReport R(Opts, Loc, ET);
Alexey Samsonov96591cd2014-07-30 01:49:19 +000052
Will Dietz765c2662013-01-09 03:40:03 +000053 Diag(Loc, DL_Error,
Richard Smithcf56ebd2012-12-18 06:30:32 +000054 "%0 address %1 which does not point to an object of type %2")
Richard Smith2f0d7d52012-10-25 02:07:02 +000055 << TypeCheckKinds[Data->TypeCheckKind] << (void*)Pointer << Data->Type;
Richard Smithcf56ebd2012-12-18 06:30:32 +000056
57 // If possible, say what type it actually points to.
Ivan Krasin048155c2016-06-02 18:36:12 +000058 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())
Richard Smithcf56ebd2012-12-18 06:30:32 +000069 Diag(Pointer, DL_Note, "object is of type %0")
Peter Collingbourne702548d2015-07-08 22:10:34 +000070 << TypeName(DTI.getMostDerivedTypeName())
Alexey Samsonovff24fd22014-08-05 01:24:22 +000071 << Range(Pointer, Pointer + sizeof(uptr), "vptr for %0");
Richard Smithcf56ebd2012-12-18 06:30:32 +000072 else
Richard Smith7e455622012-12-18 09:30:21 +000073 // FIXME: Find the type at the specified offset, and include that
74 // in the note.
Richard Smithcf56ebd2012-12-18 06:30:32 +000075 Diag(Pointer - DTI.getOffset(), DL_Note,
76 "object is base class subobject at offset %0 within object of type %1")
Peter Collingbourne702548d2015-07-08 22:10:34 +000077 << DTI.getOffset() << TypeName(DTI.getMostDerivedTypeName())
78 << TypeName(DTI.getSubobjectTypeName())
Alexey Samsonovff24fd22014-08-05 01:24:22 +000079 << Range(Pointer, Pointer + sizeof(uptr),
80 "vptr for %2 base class of %1");
Alexey Samsonovaff20ac2015-12-09 00:12:57 +000081 return true;
Will Dietz2c36c712012-12-02 19:47:29 +000082}
83
84void __ubsan::__ubsan_handle_dynamic_type_cache_miss(
Richard Smithcf56ebd2012-12-18 06:30:32 +000085 DynamicTypeCacheMissData *Data, ValueHandle Pointer, ValueHandle Hash) {
Alexey Samsonov2ccbc622014-08-22 21:42:04 +000086 GET_REPORT_OPTIONS(false);
87 HandleDynamicTypeCacheMiss(Data, Pointer, Hash, Opts);
Will Dietz2c36c712012-12-02 19:47:29 +000088}
89void __ubsan::__ubsan_handle_dynamic_type_cache_miss_abort(
Richard Smithcf56ebd2012-12-18 06:30:32 +000090 DynamicTypeCacheMissData *Data, ValueHandle Pointer, ValueHandle Hash) {
Alexey Samsonovaff20ac2015-12-09 00:12:57 +000091 // Note: -fsanitize=vptr is always recoverable.
92 GET_REPORT_OPTIONS(false);
93 if (HandleDynamicTypeCacheMiss(Data, Pointer, Hash, Opts))
94 Die();
Richard Smith2f0d7d52012-10-25 02:07:02 +000095}
Alexey Samsonov0781e982015-03-26 17:26:04 +000096
Evgeniy Stepanov22696522016-01-25 23:34:38 +000097namespace __ubsan {
98void HandleCFIBadType(CFICheckFailData *Data, ValueHandle Vtable,
Evgeniy Stepanov73583d52016-02-03 22:19:04 +000099 bool ValidVtable, ReportOptions Opts) {
Peter Collingbourne175d6332015-06-19 01:52:55 +0000100 SourceLocation Loc = Data->Loc.acquire();
Alexey Samsonov081a24e2015-12-18 19:56:42 +0000101 ErrorType ET = ErrorType::CFIBadType;
Alexey Samsonovaff20ac2015-12-09 00:12:57 +0000102
Alexey Samsonov081a24e2015-12-18 19:56:42 +0000103 if (ignoreReport(Loc, Opts, ET))
Alexey Samsonovaff20ac2015-12-09 00:12:57 +0000104 return;
Alexey Samsonov081a24e2015-12-18 19:56:42 +0000105
106 ScopedReport R(Opts, Loc, ET);
Evgeniy Stepanov73583d52016-02-03 22:19:04 +0000107 DynamicTypeInfo DTI = ValidVtable
108 ? getDynamicTypeInfoFromVtable((void *)Vtable)
109 : DynamicTypeInfo(0, 0, 0);
Peter Collingbourne175d6332015-06-19 01:52:55 +0000110
Evgeniy Stepanov22696522016-01-25 23:34:38 +0000111 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 }
Peter Collingbourne175d6332015-06-19 01:52:55 +0000128
129 Diag(Loc, DL_Error, "control flow integrity check for type %0 failed during "
130 "%1 (vtable address %2)")
Evgeniy Stepanov22696522016-01-25 23:34:38 +0000131 << Data->Type << CheckKindStr << (void *)Vtable;
Peter Collingbourne175d6332015-06-19 01:52:55 +0000132
133 // If possible, say what type it actually points to.
Evgeniy Stepanov73583d52016-02-03 22:19:04 +0000134 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 {
Peter Collingbourne175d6332015-06-19 01:52:55 +0000141 Diag(Vtable, DL_Note, "vtable is of type %0")
Peter Collingbourne702548d2015-07-08 22:10:34 +0000142 << TypeName(DTI.getMostDerivedTypeName());
Evgeniy Stepanov73583d52016-02-03 22:19:04 +0000143 }
Peter Collingbourne175d6332015-06-19 01:52:55 +0000144}
Evgeniy Stepanov22696522016-01-25 23:34:38 +0000145} // namespace __ubsan
Peter Collingbourne175d6332015-06-19 01:52:55 +0000146
Evgeniy Stepanov22696522016-01-25 23:34:38 +0000147#endif // CAN_SANITIZE_UB