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