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