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