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