]> git.ipfire.org Git - thirdparty/gcc.git/blame - libsanitizer/ubsan/ubsan_handlers.cc
ubsan.c (ubsan_expand_null_ifn): Use _v1 suffixed type mismatch builtins...
[thirdparty/gcc.git] / libsanitizer / ubsan / ubsan_handlers.cc
CommitLineData
de5a5fa1
MP
1//===-- ubsan_handlers.cc -------------------------------------------------===//
2//
3// This file is distributed under the University of Illinois Open Source
4// License. See LICENSE.TXT for details.
5//
6//===----------------------------------------------------------------------===//
7//
8// Error logging entry points for the UBSan runtime.
9//
10//===----------------------------------------------------------------------===//
11
696d846a
MO
12#include "ubsan_platform.h"
13#if CAN_SANITIZE_UB
de5a5fa1
MP
14#include "ubsan_handlers.h"
15#include "ubsan_diag.h"
16
17#include "sanitizer_common/sanitizer_common.h"
18
19using namespace __sanitizer;
20using namespace __ubsan;
21
10189819
MO
22namespace __ubsan {
23bool ignoreReport(SourceLocation SLoc, ReportOptions Opts, ErrorType ET) {
24 // We are not allowed to skip error report: if we are in unrecoverable
25 // handler, we have to terminate the program right now, and therefore
26 // have to print some diagnostic.
27 //
28 // Even if source location is disabled, it doesn't mean that we have
29 // already report an error to the user: some concurrently running
30 // thread could have acquired it, but not yet printed the report.
31 if (Opts.FromUnrecoverableHandler)
32 return false;
33 return SLoc.isDisabled() || IsPCSuppressed(ET, Opts.pc, SLoc.getFilename());
866e32ad
KS
34}
35
c5be964a 36const char *TypeCheckKinds[] = {
de5a5fa1 37 "load of", "store to", "reference binding to", "member access within",
c5be964a 38 "member call on", "constructor call on", "downcast of", "downcast of",
5d3805fc 39 "upcast of", "cast to virtual base of", "_Nonnull binding to"};
de5a5fa1
MP
40}
41
42static void handleTypeMismatchImpl(TypeMismatchData *Data, ValueHandle Pointer,
696d846a 43 ReportOptions Opts) {
de5a5fa1 44 Location Loc = Data->Loc.acquire();
10189819 45
5d3805fc 46 uptr Alignment = (uptr)1 << Data->LogAlignment;
10189819
MO
47 ErrorType ET;
48 if (!Pointer)
49 ET = ErrorType::NullPointerUse;
5d3805fc 50 else if (Pointer & (Alignment - 1))
10189819
MO
51 ET = ErrorType::MisalignedPointerUse;
52 else
53 ET = ErrorType::InsufficientObjectSize;
54
55 // Use the SourceLocation from Data to track deduplication, even if it's
56 // invalid.
57 if (ignoreReport(Loc.getSourceLocation(), Opts, ET))
de5a5fa1 58 return;
866e32ad 59
696d846a
MO
60 SymbolizedStackHolder FallbackLoc;
61 if (Data->Loc.isInvalid()) {
62 FallbackLoc.reset(getCallerLocation(Opts.pc));
de5a5fa1 63 Loc = FallbackLoc;
696d846a 64 }
de5a5fa1 65
10189819 66 ScopedReport R(Opts, Loc, ET);
866e32ad 67
10189819
MO
68 switch (ET) {
69 case ErrorType::NullPointerUse:
de5a5fa1 70 Diag(Loc, DL_Error, "%0 null pointer of type %1")
10189819
MO
71 << TypeCheckKinds[Data->TypeCheckKind] << Data->Type;
72 break;
73 case ErrorType::MisalignedPointerUse:
de5a5fa1
MP
74 Diag(Loc, DL_Error, "%0 misaligned address %1 for type %3, "
75 "which requires %2 byte alignment")
5d3805fc
JJ
76 << TypeCheckKinds[Data->TypeCheckKind] << (void *)Pointer << Alignment
77 << Data->Type;
10189819
MO
78 break;
79 case ErrorType::InsufficientObjectSize:
de5a5fa1
MP
80 Diag(Loc, DL_Error, "%0 address %1 with insufficient space "
81 "for an object of type %2")
10189819
MO
82 << TypeCheckKinds[Data->TypeCheckKind] << (void *)Pointer << Data->Type;
83 break;
84 default:
85 UNREACHABLE("unexpected error type!");
696d846a 86 }
10189819 87
de5a5fa1
MP
88 if (Pointer)
89 Diag(Pointer, DL_Note, "pointer points here");
90}
866e32ad 91
5d3805fc
JJ
92void __ubsan::__ubsan_handle_type_mismatch_v1(TypeMismatchData *Data,
93 ValueHandle Pointer) {
866e32ad 94 GET_REPORT_OPTIONS(false);
696d846a 95 handleTypeMismatchImpl(Data, Pointer, Opts);
de5a5fa1 96}
5d3805fc
JJ
97void __ubsan::__ubsan_handle_type_mismatch_v1_abort(TypeMismatchData *Data,
98 ValueHandle Pointer) {
866e32ad 99 GET_REPORT_OPTIONS(true);
696d846a 100 handleTypeMismatchImpl(Data, Pointer, Opts);
de5a5fa1
MP
101 Die();
102}
103
104/// \brief Common diagnostic emission for various forms of integer overflow.
866e32ad
KS
105template <typename T>
106static void handleIntegerOverflowImpl(OverflowData *Data, ValueHandle LHS,
107 const char *Operator, T RHS,
108 ReportOptions Opts) {
de5a5fa1 109 SourceLocation Loc = Data->Loc.acquire();
10189819
MO
110 bool IsSigned = Data->Type.isSignedIntegerTy();
111 ErrorType ET = IsSigned ? ErrorType::SignedIntegerOverflow
112 : ErrorType::UnsignedIntegerOverflow;
113
114 if (ignoreReport(Loc, Opts, ET))
de5a5fa1
MP
115 return;
116
10189819 117 ScopedReport R(Opts, Loc, ET);
866e32ad 118
de5a5fa1
MP
119 Diag(Loc, DL_Error, "%0 integer overflow: "
120 "%1 %2 %3 cannot be represented in type %4")
696d846a 121 << (IsSigned ? "signed" : "unsigned")
de5a5fa1
MP
122 << Value(Data->Type, LHS) << Operator << RHS << Data->Type;
123}
124
10189819 125#define UBSAN_OVERFLOW_HANDLER(handler_name, op, unrecoverable) \
866e32ad
KS
126 void __ubsan::handler_name(OverflowData *Data, ValueHandle LHS, \
127 ValueHandle RHS) { \
10189819 128 GET_REPORT_OPTIONS(unrecoverable); \
866e32ad 129 handleIntegerOverflowImpl(Data, LHS, op, Value(Data->Type, RHS), Opts); \
10189819
MO
130 if (unrecoverable) \
131 Die(); \
866e32ad 132 }
de5a5fa1 133
866e32ad
KS
134UBSAN_OVERFLOW_HANDLER(__ubsan_handle_add_overflow, "+", false)
135UBSAN_OVERFLOW_HANDLER(__ubsan_handle_add_overflow_abort, "+", true)
136UBSAN_OVERFLOW_HANDLER(__ubsan_handle_sub_overflow, "-", false)
137UBSAN_OVERFLOW_HANDLER(__ubsan_handle_sub_overflow_abort, "-", true)
138UBSAN_OVERFLOW_HANDLER(__ubsan_handle_mul_overflow, "*", false)
139UBSAN_OVERFLOW_HANDLER(__ubsan_handle_mul_overflow_abort, "*", true)
de5a5fa1 140
866e32ad
KS
141static void handleNegateOverflowImpl(OverflowData *Data, ValueHandle OldVal,
142 ReportOptions Opts) {
de5a5fa1 143 SourceLocation Loc = Data->Loc.acquire();
10189819
MO
144 bool IsSigned = Data->Type.isSignedIntegerTy();
145 ErrorType ET = IsSigned ? ErrorType::SignedIntegerOverflow
146 : ErrorType::UnsignedIntegerOverflow;
147
148 if (ignoreReport(Loc, Opts, ET))
de5a5fa1
MP
149 return;
150
10189819 151 ScopedReport R(Opts, Loc, ET);
866e32ad 152
696d846a 153 if (IsSigned)
de5a5fa1
MP
154 Diag(Loc, DL_Error,
155 "negation of %0 cannot be represented in type %1; "
156 "cast to an unsigned type to negate this value to itself")
696d846a 157 << Value(Data->Type, OldVal) << Data->Type;
de5a5fa1 158 else
696d846a
MO
159 Diag(Loc, DL_Error, "negation of %0 cannot be represented in type %1")
160 << Value(Data->Type, OldVal) << Data->Type;
de5a5fa1 161}
866e32ad
KS
162
163void __ubsan::__ubsan_handle_negate_overflow(OverflowData *Data,
164 ValueHandle OldVal) {
165 GET_REPORT_OPTIONS(false);
166 handleNegateOverflowImpl(Data, OldVal, Opts);
167}
de5a5fa1
MP
168void __ubsan::__ubsan_handle_negate_overflow_abort(OverflowData *Data,
169 ValueHandle OldVal) {
866e32ad
KS
170 GET_REPORT_OPTIONS(true);
171 handleNegateOverflowImpl(Data, OldVal, Opts);
de5a5fa1
MP
172 Die();
173}
174
866e32ad
KS
175static void handleDivremOverflowImpl(OverflowData *Data, ValueHandle LHS,
176 ValueHandle RHS, ReportOptions Opts) {
de5a5fa1 177 SourceLocation Loc = Data->Loc.acquire();
10189819
MO
178 Value LHSVal(Data->Type, LHS);
179 Value RHSVal(Data->Type, RHS);
180
181 ErrorType ET;
182 if (RHSVal.isMinusOne())
183 ET = ErrorType::SignedIntegerOverflow;
184 else if (Data->Type.isIntegerTy())
185 ET = ErrorType::IntegerDivideByZero;
186 else
187 ET = ErrorType::FloatDivideByZero;
188
189 if (ignoreReport(Loc, Opts, ET))
de5a5fa1
MP
190 return;
191
10189819 192 ScopedReport R(Opts, Loc, ET);
866e32ad 193
10189819
MO
194 switch (ET) {
195 case ErrorType::SignedIntegerOverflow:
196 Diag(Loc, DL_Error, "division of %0 by -1 cannot be represented in type %1")
197 << LHSVal << Data->Type;
198 break;
199 default:
de5a5fa1 200 Diag(Loc, DL_Error, "division by zero");
10189819 201 break;
696d846a 202 }
de5a5fa1 203}
866e32ad
KS
204
205void __ubsan::__ubsan_handle_divrem_overflow(OverflowData *Data,
206 ValueHandle LHS, ValueHandle RHS) {
207 GET_REPORT_OPTIONS(false);
208 handleDivremOverflowImpl(Data, LHS, RHS, Opts);
209}
de5a5fa1
MP
210void __ubsan::__ubsan_handle_divrem_overflow_abort(OverflowData *Data,
211 ValueHandle LHS,
212 ValueHandle RHS) {
866e32ad
KS
213 GET_REPORT_OPTIONS(true);
214 handleDivremOverflowImpl(Data, LHS, RHS, Opts);
de5a5fa1
MP
215 Die();
216}
217
866e32ad
KS
218static void handleShiftOutOfBoundsImpl(ShiftOutOfBoundsData *Data,
219 ValueHandle LHS, ValueHandle RHS,
220 ReportOptions Opts) {
de5a5fa1 221 SourceLocation Loc = Data->Loc.acquire();
10189819
MO
222 Value LHSVal(Data->LHSType, LHS);
223 Value RHSVal(Data->RHSType, RHS);
224
225 ErrorType ET;
226 if (RHSVal.isNegative() ||
227 RHSVal.getPositiveIntValue() >= Data->LHSType.getIntegerBitWidth())
228 ET = ErrorType::InvalidShiftExponent;
229 else
230 ET = ErrorType::InvalidShiftBase;
231
232 if (ignoreReport(Loc, Opts, ET))
de5a5fa1
MP
233 return;
234
10189819 235 ScopedReport R(Opts, Loc, ET);
866e32ad 236
10189819
MO
237 if (ET == ErrorType::InvalidShiftExponent) {
238 if (RHSVal.isNegative())
239 Diag(Loc, DL_Error, "shift exponent %0 is negative") << RHSVal;
240 else
241 Diag(Loc, DL_Error, "shift exponent %0 is too large for %1-bit type %2")
242 << RHSVal << Data->LHSType.getIntegerBitWidth() << Data->LHSType;
696d846a 243 } else {
10189819
MO
244 if (LHSVal.isNegative())
245 Diag(Loc, DL_Error, "left shift of negative value %0") << LHSVal;
246 else
247 Diag(Loc, DL_Error,
248 "left shift of %0 by %1 places cannot be represented in type %2")
249 << LHSVal << RHSVal << Data->LHSType;
696d846a 250 }
de5a5fa1 251}
866e32ad
KS
252
253void __ubsan::__ubsan_handle_shift_out_of_bounds(ShiftOutOfBoundsData *Data,
254 ValueHandle LHS,
255 ValueHandle RHS) {
256 GET_REPORT_OPTIONS(false);
257 handleShiftOutOfBoundsImpl(Data, LHS, RHS, Opts);
258}
de5a5fa1
MP
259void __ubsan::__ubsan_handle_shift_out_of_bounds_abort(
260 ShiftOutOfBoundsData *Data,
261 ValueHandle LHS,
262 ValueHandle RHS) {
866e32ad
KS
263 GET_REPORT_OPTIONS(true);
264 handleShiftOutOfBoundsImpl(Data, LHS, RHS, Opts);
de5a5fa1
MP
265 Die();
266}
267
866e32ad
KS
268static void handleOutOfBoundsImpl(OutOfBoundsData *Data, ValueHandle Index,
269 ReportOptions Opts) {
de5a5fa1 270 SourceLocation Loc = Data->Loc.acquire();
10189819
MO
271 ErrorType ET = ErrorType::OutOfBoundsIndex;
272
273 if (ignoreReport(Loc, Opts, ET))
de5a5fa1
MP
274 return;
275
10189819 276 ScopedReport R(Opts, Loc, ET);
866e32ad 277
de5a5fa1
MP
278 Value IndexVal(Data->IndexType, Index);
279 Diag(Loc, DL_Error, "index %0 out of bounds for type %1")
280 << IndexVal << Data->ArrayType;
281}
866e32ad
KS
282
283void __ubsan::__ubsan_handle_out_of_bounds(OutOfBoundsData *Data,
284 ValueHandle Index) {
285 GET_REPORT_OPTIONS(false);
286 handleOutOfBoundsImpl(Data, Index, Opts);
287}
de5a5fa1
MP
288void __ubsan::__ubsan_handle_out_of_bounds_abort(OutOfBoundsData *Data,
289 ValueHandle Index) {
866e32ad
KS
290 GET_REPORT_OPTIONS(true);
291 handleOutOfBoundsImpl(Data, Index, Opts);
de5a5fa1
MP
292 Die();
293}
294
866e32ad
KS
295static void handleBuiltinUnreachableImpl(UnreachableData *Data,
296 ReportOptions Opts) {
696d846a 297 ScopedReport R(Opts, Data->Loc, ErrorType::UnreachableCall);
de5a5fa1 298 Diag(Data->Loc, DL_Error, "execution reached a __builtin_unreachable() call");
866e32ad
KS
299}
300
301void __ubsan::__ubsan_handle_builtin_unreachable(UnreachableData *Data) {
302 GET_REPORT_OPTIONS(true);
303 handleBuiltinUnreachableImpl(Data, Opts);
de5a5fa1
MP
304 Die();
305}
306
866e32ad 307static void handleMissingReturnImpl(UnreachableData *Data, ReportOptions Opts) {
696d846a 308 ScopedReport R(Opts, Data->Loc, ErrorType::MissingReturn);
de5a5fa1
MP
309 Diag(Data->Loc, DL_Error,
310 "execution reached the end of a value-returning function "
311 "without returning a value");
866e32ad
KS
312}
313
314void __ubsan::__ubsan_handle_missing_return(UnreachableData *Data) {
315 GET_REPORT_OPTIONS(true);
316 handleMissingReturnImpl(Data, Opts);
de5a5fa1
MP
317 Die();
318}
319
866e32ad
KS
320static void handleVLABoundNotPositive(VLABoundData *Data, ValueHandle Bound,
321 ReportOptions Opts) {
de5a5fa1 322 SourceLocation Loc = Data->Loc.acquire();
10189819
MO
323 ErrorType ET = ErrorType::NonPositiveVLAIndex;
324
325 if (ignoreReport(Loc, Opts, ET))
de5a5fa1
MP
326 return;
327
10189819 328 ScopedReport R(Opts, Loc, ET);
866e32ad 329
de5a5fa1
MP
330 Diag(Loc, DL_Error, "variable length array bound evaluates to "
331 "non-positive value %0")
332 << Value(Data->Type, Bound);
333}
866e32ad
KS
334
335void __ubsan::__ubsan_handle_vla_bound_not_positive(VLABoundData *Data,
336 ValueHandle Bound) {
337 GET_REPORT_OPTIONS(false);
338 handleVLABoundNotPositive(Data, Bound, Opts);
339}
de5a5fa1 340void __ubsan::__ubsan_handle_vla_bound_not_positive_abort(VLABoundData *Data,
866e32ad
KS
341 ValueHandle Bound) {
342 GET_REPORT_OPTIONS(true);
343 handleVLABoundNotPositive(Data, Bound, Opts);
de5a5fa1
MP
344 Die();
345}
346
696d846a
MO
347static bool looksLikeFloatCastOverflowDataV1(void *Data) {
348 // First field is either a pointer to filename or a pointer to a
349 // TypeDescriptor.
350 u8 *FilenameOrTypeDescriptor;
351 internal_memcpy(&FilenameOrTypeDescriptor, Data,
352 sizeof(FilenameOrTypeDescriptor));
353
354 // Heuristic: For float_cast_overflow, the TypeKind will be either TK_Integer
355 // (0x0), TK_Float (0x1) or TK_Unknown (0xff). If both types are known,
356 // adding both bytes will be 0 or 1 (for BE or LE). If it were a filename,
357 // adding two printable characters will not yield such a value. Otherwise,
358 // if one of them is 0xff, this is most likely TK_Unknown type descriptor.
359 u16 MaybeFromTypeKind =
360 FilenameOrTypeDescriptor[0] + FilenameOrTypeDescriptor[1];
361 return MaybeFromTypeKind < 2 || FilenameOrTypeDescriptor[0] == 0xff ||
362 FilenameOrTypeDescriptor[1] == 0xff;
363}
364
365static void handleFloatCastOverflow(void *DataPtr, ValueHandle From,
366 ReportOptions Opts) {
367 SymbolizedStackHolder CallerLoc;
368 Location Loc;
369 const TypeDescriptor *FromType, *ToType;
10189819 370 ErrorType ET = ErrorType::FloatCastOverflow;
696d846a
MO
371
372 if (looksLikeFloatCastOverflowDataV1(DataPtr)) {
373 auto Data = reinterpret_cast<FloatCastOverflowData *>(DataPtr);
374 CallerLoc.reset(getCallerLocation(Opts.pc));
375 Loc = CallerLoc;
376 FromType = &Data->FromType;
377 ToType = &Data->ToType;
378 } else {
379 auto Data = reinterpret_cast<FloatCastOverflowDataV2 *>(DataPtr);
380 SourceLocation SLoc = Data->Loc.acquire();
10189819 381 if (ignoreReport(SLoc, Opts, ET))
696d846a
MO
382 return;
383 Loc = SLoc;
384 FromType = &Data->FromType;
385 ToType = &Data->ToType;
386 }
387
10189819 388 ScopedReport R(Opts, Loc, ET);
866e32ad
KS
389
390 Diag(Loc, DL_Error,
5d3805fc 391 "%0 is outside the range of representable values of type %2")
696d846a 392 << Value(*FromType, From) << *FromType << *ToType;
de5a5fa1 393}
866e32ad 394
696d846a 395void __ubsan::__ubsan_handle_float_cast_overflow(void *Data, ValueHandle From) {
866e32ad
KS
396 GET_REPORT_OPTIONS(false);
397 handleFloatCastOverflow(Data, From, Opts);
398}
696d846a
MO
399void __ubsan::__ubsan_handle_float_cast_overflow_abort(void *Data,
400 ValueHandle From) {
866e32ad
KS
401 GET_REPORT_OPTIONS(true);
402 handleFloatCastOverflow(Data, From, Opts);
de5a5fa1
MP
403 Die();
404}
405
866e32ad
KS
406static void handleLoadInvalidValue(InvalidValueData *Data, ValueHandle Val,
407 ReportOptions Opts) {
df77f0e4 408 SourceLocation Loc = Data->Loc.acquire();
696d846a
MO
409 // This check could be more precise if we used different handlers for
410 // -fsanitize=bool and -fsanitize=enum.
5d3805fc
JJ
411 bool IsBool = (0 == internal_strcmp(Data->Type.getTypeName(), "'bool'")) ||
412 (0 == internal_strncmp(Data->Type.getTypeName(), "'BOOL'", 6));
10189819
MO
413 ErrorType ET =
414 IsBool ? ErrorType::InvalidBoolLoad : ErrorType::InvalidEnumLoad;
415
416 if (ignoreReport(Loc, Opts, ET))
417 return;
418
419 ScopedReport R(Opts, Loc, ET);
866e32ad 420
df77f0e4 421 Diag(Loc, DL_Error,
de5a5fa1
MP
422 "load of value %0, which is not a valid value for type %1")
423 << Value(Data->Type, Val) << Data->Type;
424}
866e32ad
KS
425
426void __ubsan::__ubsan_handle_load_invalid_value(InvalidValueData *Data,
427 ValueHandle Val) {
428 GET_REPORT_OPTIONS(false);
429 handleLoadInvalidValue(Data, Val, Opts);
430}
de5a5fa1
MP
431void __ubsan::__ubsan_handle_load_invalid_value_abort(InvalidValueData *Data,
432 ValueHandle Val) {
866e32ad
KS
433 GET_REPORT_OPTIONS(true);
434 handleLoadInvalidValue(Data, Val, Opts);
df77f0e4
KS
435 Die();
436}
437
5d3805fc
JJ
438static void handleInvalidBuiltin(InvalidBuiltinData *Data, ReportOptions Opts) {
439 SourceLocation Loc = Data->Loc.acquire();
440 ErrorType ET = ErrorType::InvalidBuiltin;
441
442 if (ignoreReport(Loc, Opts, ET))
443 return;
444
445 ScopedReport R(Opts, Loc, ET);
446
447 Diag(Loc, DL_Error,
448 "passing zero to %0, which is not a valid argument")
449 << ((Data->Kind == BCK_CTZPassedZero) ? "ctz()" : "clz()");
450}
451
452void __ubsan::__ubsan_handle_invalid_builtin(InvalidBuiltinData *Data) {
453 GET_REPORT_OPTIONS(true);
454 handleInvalidBuiltin(Data, Opts);
455}
456void __ubsan::__ubsan_handle_invalid_builtin_abort(InvalidBuiltinData *Data) {
457 GET_REPORT_OPTIONS(true);
458 handleInvalidBuiltin(Data, Opts);
459 Die();
460}
461
866e32ad
KS
462static void handleFunctionTypeMismatch(FunctionTypeMismatchData *Data,
463 ValueHandle Function,
464 ReportOptions Opts) {
696d846a 465 SourceLocation CallLoc = Data->Loc.acquire();
10189819
MO
466 ErrorType ET = ErrorType::FunctionTypeMismatch;
467
468 if (ignoreReport(CallLoc, Opts, ET))
696d846a 469 return;
df77f0e4 470
10189819 471 ScopedReport R(Opts, CallLoc, ET);
df77f0e4 472
696d846a
MO
473 SymbolizedStackHolder FLoc(getSymbolizedLocation(Function));
474 const char *FName = FLoc.get()->info.function;
475 if (!FName)
476 FName = "(unknown)";
866e32ad 477
696d846a 478 Diag(CallLoc, DL_Error,
df77f0e4 479 "call to function %0 through pointer to incorrect function type %1")
696d846a
MO
480 << FName << Data->Type;
481 Diag(FLoc, DL_Note, "%0 defined here") << FName;
df77f0e4
KS
482}
483
866e32ad
KS
484void
485__ubsan::__ubsan_handle_function_type_mismatch(FunctionTypeMismatchData *Data,
486 ValueHandle Function) {
487 GET_REPORT_OPTIONS(false);
488 handleFunctionTypeMismatch(Data, Function, Opts);
489}
490
df77f0e4 491void __ubsan::__ubsan_handle_function_type_mismatch_abort(
866e32ad
KS
492 FunctionTypeMismatchData *Data, ValueHandle Function) {
493 GET_REPORT_OPTIONS(true);
494 handleFunctionTypeMismatch(Data, Function, Opts);
de5a5fa1
MP
495 Die();
496}
126edc3f 497
5d3805fc
JJ
498static void handleNonNullReturn(NonNullReturnData *Data, SourceLocation *LocPtr,
499 ReportOptions Opts, bool IsAttr) {
500 if (!LocPtr)
501 UNREACHABLE("source location pointer is null!");
502
503 SourceLocation Loc = LocPtr->acquire();
10189819
MO
504 ErrorType ET = ErrorType::InvalidNullReturn;
505
506 if (ignoreReport(Loc, Opts, ET))
126edc3f
JJ
507 return;
508
10189819 509 ScopedReport R(Opts, Loc, ET);
866e32ad 510
126edc3f
JJ
511 Diag(Loc, DL_Error, "null pointer returned from function declared to never "
512 "return null");
513 if (!Data->AttrLoc.isInvalid())
5d3805fc
JJ
514 Diag(Data->AttrLoc, DL_Note, "%0 specified here")
515 << (IsAttr ? "returns_nonnull attribute"
516 : "_Nonnull return type annotation");
517}
518
519void __ubsan::__ubsan_handle_nonnull_return_v1(NonNullReturnData *Data,
520 SourceLocation *LocPtr) {
521 GET_REPORT_OPTIONS(false);
522 handleNonNullReturn(Data, LocPtr, Opts, true);
126edc3f
JJ
523}
524
5d3805fc
JJ
525void __ubsan::__ubsan_handle_nonnull_return_v1_abort(NonNullReturnData *Data,
526 SourceLocation *LocPtr) {
527 GET_REPORT_OPTIONS(true);
528 handleNonNullReturn(Data, LocPtr, Opts, true);
529 Die();
530}
531
532void __ubsan::__ubsan_handle_nullability_return_v1(NonNullReturnData *Data,
533 SourceLocation *LocPtr) {
866e32ad 534 GET_REPORT_OPTIONS(false);
5d3805fc 535 handleNonNullReturn(Data, LocPtr, Opts, false);
126edc3f
JJ
536}
537
5d3805fc
JJ
538void __ubsan::__ubsan_handle_nullability_return_v1_abort(
539 NonNullReturnData *Data, SourceLocation *LocPtr) {
866e32ad 540 GET_REPORT_OPTIONS(true);
5d3805fc 541 handleNonNullReturn(Data, LocPtr, Opts, false);
126edc3f
JJ
542 Die();
543}
544
5d3805fc
JJ
545static void handleNonNullArg(NonNullArgData *Data, ReportOptions Opts,
546 bool IsAttr) {
126edc3f 547 SourceLocation Loc = Data->Loc.acquire();
10189819
MO
548 ErrorType ET = ErrorType::InvalidNullArgument;
549
550 if (ignoreReport(Loc, Opts, ET))
126edc3f
JJ
551 return;
552
10189819 553 ScopedReport R(Opts, Loc, ET);
866e32ad 554
5d3805fc
JJ
555 Diag(Loc, DL_Error,
556 "null pointer passed as argument %0, which is declared to "
557 "never be null")
558 << Data->ArgIndex;
126edc3f 559 if (!Data->AttrLoc.isInvalid())
5d3805fc
JJ
560 Diag(Data->AttrLoc, DL_Note, "%0 specified here")
561 << (IsAttr ? "nonnull attribute" : "_Nonnull type annotation");
126edc3f
JJ
562}
563
564void __ubsan::__ubsan_handle_nonnull_arg(NonNullArgData *Data) {
866e32ad 565 GET_REPORT_OPTIONS(false);
5d3805fc 566 handleNonNullArg(Data, Opts, true);
126edc3f
JJ
567}
568
569void __ubsan::__ubsan_handle_nonnull_arg_abort(NonNullArgData *Data) {
866e32ad 570 GET_REPORT_OPTIONS(true);
5d3805fc
JJ
571 handleNonNullArg(Data, Opts, true);
572 Die();
573}
574
575void __ubsan::__ubsan_handle_nullability_arg(NonNullArgData *Data) {
576 GET_REPORT_OPTIONS(false);
577 handleNonNullArg(Data, Opts, false);
578}
579
580void __ubsan::__ubsan_handle_nullability_arg_abort(NonNullArgData *Data) {
581 GET_REPORT_OPTIONS(true);
582 handleNonNullArg(Data, Opts, false);
126edc3f
JJ
583 Die();
584}
696d846a 585
c9b39a49
JJ
586static void handlePointerOverflowImpl(PointerOverflowData *Data,
587 ValueHandle Base,
588 ValueHandle Result,
589 ReportOptions Opts) {
590 SourceLocation Loc = Data->Loc.acquire();
591 ErrorType ET = ErrorType::PointerOverflow;
592
593 if (ignoreReport(Loc, Opts, ET))
594 return;
595
596 ScopedReport R(Opts, Loc, ET);
597
5d3805fc
JJ
598 if ((sptr(Base) >= 0) == (sptr(Result) >= 0)) {
599 if (Base > Result)
600 Diag(Loc, DL_Error, "addition of unsigned offset to %0 overflowed to %1")
601 << (void *)Base << (void *)Result;
602 else
603 Diag(Loc, DL_Error,
604 "subtraction of unsigned offset from %0 overflowed to %1")
605 << (void *)Base << (void *)Result;
606 } else {
607 Diag(Loc, DL_Error,
608 "pointer index expression with base %0 overflowed to %1")
609 << (void *)Base << (void *)Result;
610 }
c9b39a49
JJ
611}
612
613void __ubsan::__ubsan_handle_pointer_overflow(PointerOverflowData *Data,
614 ValueHandle Base,
615 ValueHandle Result) {
616 GET_REPORT_OPTIONS(false);
617 handlePointerOverflowImpl(Data, Base, Result, Opts);
618}
619
620void __ubsan::__ubsan_handle_pointer_overflow_abort(PointerOverflowData *Data,
621 ValueHandle Base,
622 ValueHandle Result) {
623 GET_REPORT_OPTIONS(true);
624 handlePointerOverflowImpl(Data, Base, Result, Opts);
625 Die();
626}
627
10189819 628static void handleCFIBadIcall(CFICheckFailData *Data, ValueHandle Function,
696d846a 629 ReportOptions Opts) {
10189819
MO
630 if (Data->CheckKind != CFITCK_ICall)
631 Die();
632
696d846a 633 SourceLocation Loc = Data->Loc.acquire();
10189819
MO
634 ErrorType ET = ErrorType::CFIBadType;
635
636 if (ignoreReport(Loc, Opts, ET))
696d846a
MO
637 return;
638
10189819 639 ScopedReport R(Opts, Loc, ET);
696d846a
MO
640
641 Diag(Loc, DL_Error, "control flow integrity check for type %0 failed during "
642 "indirect function call")
643 << Data->Type;
644
645 SymbolizedStackHolder FLoc(getSymbolizedLocation(Function));
646 const char *FName = FLoc.get()->info.function;
647 if (!FName)
648 FName = "(unknown)";
649 Diag(FLoc, DL_Note, "%0 defined here") << FName;
650}
651
10189819 652namespace __ubsan {
5d3805fc 653
10189819 654#ifdef UBSAN_CAN_USE_CXXABI
5d3805fc
JJ
655
656#ifdef _WIN32
657
658extern "C" void __ubsan_handle_cfi_bad_type_default(CFICheckFailData *Data,
659 ValueHandle Vtable,
660 bool ValidVtable,
661 ReportOptions Opts) {
10189819
MO
662 Die();
663}
10189819 664
5d3805fc
JJ
665WIN_WEAK_ALIAS(__ubsan_handle_cfi_bad_type, __ubsan_handle_cfi_bad_type_default)
666#else
667SANITIZER_WEAK_ATTRIBUTE
668#endif
669void __ubsan_handle_cfi_bad_type(CFICheckFailData *Data, ValueHandle Vtable,
670 bool ValidVtable, ReportOptions Opts);
511c8687 671
5d3805fc
JJ
672#else
673void __ubsan_handle_cfi_bad_type(CFICheckFailData *Data, ValueHandle Vtable,
674 bool ValidVtable, ReportOptions Opts) {
511c8687
MO
675 Die();
676}
5d3805fc
JJ
677#endif
678
679} // namespace __ubsan
511c8687 680
10189819
MO
681void __ubsan::__ubsan_handle_cfi_check_fail(CFICheckFailData *Data,
682 ValueHandle Value,
683 uptr ValidVtable) {
696d846a 684 GET_REPORT_OPTIONS(false);
10189819
MO
685 if (Data->CheckKind == CFITCK_ICall)
686 handleCFIBadIcall(Data, Value, Opts);
687 else
5d3805fc 688 __ubsan_handle_cfi_bad_type(Data, Value, ValidVtable, Opts);
696d846a
MO
689}
690
10189819
MO
691void __ubsan::__ubsan_handle_cfi_check_fail_abort(CFICheckFailData *Data,
692 ValueHandle Value,
693 uptr ValidVtable) {
696d846a 694 GET_REPORT_OPTIONS(true);
10189819
MO
695 if (Data->CheckKind == CFITCK_ICall)
696 handleCFIBadIcall(Data, Value, Opts);
697 else
5d3805fc 698 __ubsan_handle_cfi_bad_type(Data, Value, ValidVtable, Opts);
696d846a
MO
699 Die();
700}
701
702#endif // CAN_SANITIZE_UB