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