blob: 3e81be67163b703ddd9c58bf02faee4754ed86e6 [file] [log] [blame]
Richard Smitheda8bd02012-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
Pirama Arumuga Nainar7c915052015-04-08 08:58:29 -070016#include "ubsan_platform.h"
17#if CAN_SANITIZE_UB
Richard Smitheda8bd02012-10-25 02:07:02 +000018#include "ubsan_handlers_cxx.h"
19#include "ubsan_diag.h"
20#include "ubsan_type_hash.h"
21
22#include "sanitizer_common/sanitizer_common.h"
Stephen Hines6d186232014-11-26 17:56:19 -080023#include "sanitizer_common/sanitizer_suppressions.h"
Richard Smitheda8bd02012-10-25 02:07:02 +000024
25using namespace __sanitizer;
26using namespace __ubsan;
27
28namespace __ubsan {
29 extern const char *TypeCheckKinds[];
30}
31
Pirama Arumuga Nainar799172d2016-03-03 15:50:30 -080032// Returns true if UBSan has printed an error report.
33static bool HandleDynamicTypeCacheMiss(
Richard Smith25ee97f2012-12-18 06:30:32 +000034 DynamicTypeCacheMissData *Data, ValueHandle Pointer, ValueHandle Hash,
Stephen Hines6d186232014-11-26 17:56:19 -080035 ReportOptions Opts) {
Richard Smitheda8bd02012-10-25 02:07:02 +000036 if (checkDynamicType((void*)Pointer, Data->TypeInfo, Hash))
37 // Just a cache miss. The type matches after all.
Pirama Arumuga Nainar799172d2016-03-03 15:50:30 -080038 return false;
Richard Smitheda8bd02012-10-25 02:07:02 +000039
Stephen Hines6d186232014-11-26 17:56:19 -080040 // Check if error report should be suppressed.
Pirama Arumuga Nainar799172d2016-03-03 15:50:30 -080041 DynamicTypeInfo DTI = getDynamicTypeInfoFromObject((void*)Pointer);
Stephen Hines86277eb2015-03-23 12:06:32 -070042 if (DTI.isValid() && IsVptrCheckSuppressed(DTI.getMostDerivedTypeName()))
Pirama Arumuga Nainar799172d2016-03-03 15:50:30 -080043 return false;
Stephen Hines6d186232014-11-26 17:56:19 -080044
Will Dietz2af552f2013-01-09 03:40:03 +000045 SourceLocation Loc = Data->Loc.acquire();
Pirama Arumuga Nainar799172d2016-03-03 15:50:30 -080046 ErrorType ET = ErrorType::DynamicTypeMismatch;
47 if (ignoreReport(Loc, Opts, ET))
48 return false;
Will Dietz2af552f2013-01-09 03:40:03 +000049
Pirama Arumuga Nainar799172d2016-03-03 15:50:30 -080050 ScopedReport R(Opts, Loc, ET);
Stephen Hines6d186232014-11-26 17:56:19 -080051
Will Dietz2af552f2013-01-09 03:40:03 +000052 Diag(Loc, DL_Error,
Richard Smith25ee97f2012-12-18 06:30:32 +000053 "%0 address %1 which does not point to an object of type %2")
Richard Smitheda8bd02012-10-25 02:07:02 +000054 << TypeCheckKinds[Data->TypeCheckKind] << (void*)Pointer << Data->Type;
Richard Smith25ee97f2012-12-18 06:30:32 +000055
56 // If possible, say what type it actually points to.
Richard Smith25ee97f2012-12-18 06:30:32 +000057 if (!DTI.isValid())
58 Diag(Pointer, DL_Note, "object has invalid vptr")
Pirama Arumuga Nainar799172d2016-03-03 15:50:30 -080059 << TypeName(DTI.getMostDerivedTypeName())
Stephen Hines6d186232014-11-26 17:56:19 -080060 << Range(Pointer, Pointer + sizeof(uptr), "invalid vptr");
Richard Smith25ee97f2012-12-18 06:30:32 +000061 else if (!DTI.getOffset())
62 Diag(Pointer, DL_Note, "object is of type %0")
Pirama Arumuga Nainar799172d2016-03-03 15:50:30 -080063 << TypeName(DTI.getMostDerivedTypeName())
Stephen Hines6d186232014-11-26 17:56:19 -080064 << Range(Pointer, Pointer + sizeof(uptr), "vptr for %0");
Richard Smith25ee97f2012-12-18 06:30:32 +000065 else
Richard Smith0ad23f72012-12-18 09:30:21 +000066 // FIXME: Find the type at the specified offset, and include that
67 // in the note.
Richard Smith25ee97f2012-12-18 06:30:32 +000068 Diag(Pointer - DTI.getOffset(), DL_Note,
69 "object is base class subobject at offset %0 within object of type %1")
Pirama Arumuga Nainar799172d2016-03-03 15:50:30 -080070 << DTI.getOffset() << TypeName(DTI.getMostDerivedTypeName())
71 << TypeName(DTI.getSubobjectTypeName())
Stephen Hines6d186232014-11-26 17:56:19 -080072 << Range(Pointer, Pointer + sizeof(uptr),
73 "vptr for %2 base class of %1");
Pirama Arumuga Nainar799172d2016-03-03 15:50:30 -080074 return true;
Will Dietza82a5d32012-12-02 19:47:29 +000075}
76
77void __ubsan::__ubsan_handle_dynamic_type_cache_miss(
Richard Smith25ee97f2012-12-18 06:30:32 +000078 DynamicTypeCacheMissData *Data, ValueHandle Pointer, ValueHandle Hash) {
Stephen Hines6d186232014-11-26 17:56:19 -080079 GET_REPORT_OPTIONS(false);
80 HandleDynamicTypeCacheMiss(Data, Pointer, Hash, Opts);
Will Dietza82a5d32012-12-02 19:47:29 +000081}
82void __ubsan::__ubsan_handle_dynamic_type_cache_miss_abort(
Richard Smith25ee97f2012-12-18 06:30:32 +000083 DynamicTypeCacheMissData *Data, ValueHandle Pointer, ValueHandle Hash) {
Pirama Arumuga Nainar799172d2016-03-03 15:50:30 -080084 // Note: -fsanitize=vptr is always recoverable.
85 GET_REPORT_OPTIONS(false);
86 if (HandleDynamicTypeCacheMiss(Data, Pointer, Hash, Opts))
87 Die();
88}
89
90static void HandleCFIBadType(CFIBadTypeData *Data, ValueHandle Vtable,
91 ReportOptions Opts) {
92 SourceLocation Loc = Data->Loc.acquire();
93 ErrorType ET = ErrorType::CFIBadType;
94
95 if (ignoreReport(Loc, Opts, ET))
96 return;
97
98 ScopedReport R(Opts, Loc, ET);
99 DynamicTypeInfo DTI = getDynamicTypeInfoFromVtable((void*)Vtable);
100
101 static const char *TypeCheckKinds[] = {
102 "virtual call",
103 "non-virtual call",
104 "base-to-derived cast",
105 "cast to unrelated type",
106 };
107
108 Diag(Loc, DL_Error, "control flow integrity check for type %0 failed during "
109 "%1 (vtable address %2)")
110 << Data->Type << TypeCheckKinds[Data->TypeCheckKind] << (void *)Vtable;
111
112 // If possible, say what type it actually points to.
113 if (!DTI.isValid())
114 Diag(Vtable, DL_Note, "invalid vtable");
115 else
116 Diag(Vtable, DL_Note, "vtable is of type %0")
117 << TypeName(DTI.getMostDerivedTypeName());
118}
119
120void __ubsan::__ubsan_handle_cfi_bad_type(CFIBadTypeData *Data,
121 ValueHandle Vtable) {
122 GET_REPORT_OPTIONS(false);
123 HandleCFIBadType(Data, Vtable, Opts);
124}
125
126void __ubsan::__ubsan_handle_cfi_bad_type_abort(CFIBadTypeData *Data,
127 ValueHandle Vtable) {
Stephen Hines6d186232014-11-26 17:56:19 -0800128 GET_REPORT_OPTIONS(true);
Pirama Arumuga Nainar799172d2016-03-03 15:50:30 -0800129 HandleCFIBadType(Data, Vtable, Opts);
130 Die();
Richard Smitheda8bd02012-10-25 02:07:02 +0000131}
Pirama Arumuga Nainar7c915052015-04-08 08:58:29 -0700132
133#endif // CAN_SANITIZE_UB