1245614Sandrew//===-- ubsan_handlers.cc -------------------------------------------------===//
2245614Sandrew//
3245614Sandrew//                     The LLVM Compiler Infrastructure
4245614Sandrew//
5245614Sandrew// This file is distributed under the University of Illinois Open Source
6245614Sandrew// License. See LICENSE.TXT for details.
7245614Sandrew//
8245614Sandrew//===----------------------------------------------------------------------===//
9245614Sandrew//
10245614Sandrew// Error logging entry points for the UBSan runtime.
11245614Sandrew//
12245614Sandrew//===----------------------------------------------------------------------===//
13245614Sandrew
14288943Sdim#include "ubsan_platform.h"
15288943Sdim#if CAN_SANITIZE_UB
16245614Sandrew#include "ubsan_handlers.h"
17245614Sandrew#include "ubsan_diag.h"
18245614Sandrew
19245614Sandrew#include "sanitizer_common/sanitizer_common.h"
20245614Sandrew
21245614Sandrewusing namespace __sanitizer;
22245614Sandrewusing namespace __ubsan;
23245614Sandrew
24296417Sdimnamespace __ubsan {
25296417Sdimbool ignoreReport(SourceLocation SLoc, ReportOptions Opts, ErrorType ET) {
26296417Sdim  // We are not allowed to skip error report: if we are in unrecoverable
27296417Sdim  // handler, we have to terminate the program right now, and therefore
28296417Sdim  // have to print some diagnostic.
29296417Sdim  //
30296417Sdim  // Even if source location is disabled, it doesn't mean that we have
31296417Sdim  // already report an error to the user: some concurrently running
32296417Sdim  // thread could have acquired it, but not yet printed the report.
33296417Sdim  if (Opts.FromUnrecoverableHandler)
34296417Sdim    return false;
35296417Sdim  return SLoc.isDisabled() || IsPCSuppressed(ET, Opts.pc, SLoc.getFilename());
36276789Sdim}
37276789Sdim
38276789Sdimconst char *TypeCheckKinds[] = {
39245614Sandrew    "load of", "store to", "reference binding to", "member access within",
40276789Sdim    "member call on", "constructor call on", "downcast of", "downcast of",
41276789Sdim    "upcast of", "cast to virtual base of"};
42245614Sandrew}
43245614Sandrew
44245614Sandrewstatic void handleTypeMismatchImpl(TypeMismatchData *Data, ValueHandle Pointer,
45280031Sdim                                   ReportOptions Opts) {
46245614Sandrew  Location Loc = Data->Loc.acquire();
47296417Sdim
48296417Sdim  ErrorType ET;
49296417Sdim  if (!Pointer)
50296417Sdim    ET = ErrorType::NullPointerUse;
51296417Sdim  else if (Data->Alignment && (Pointer & (Data->Alignment - 1)))
52296417Sdim    ET = ErrorType::MisalignedPointerUse;
53296417Sdim  else
54296417Sdim    ET = ErrorType::InsufficientObjectSize;
55296417Sdim
56296417Sdim  // Use the SourceLocation from Data to track deduplication, even if it's
57296417Sdim  // invalid.
58296417Sdim  if (ignoreReport(Loc.getSourceLocation(), Opts, ET))
59245614Sandrew    return;
60276789Sdim
61280031Sdim  SymbolizedStackHolder FallbackLoc;
62280031Sdim  if (Data->Loc.isInvalid()) {
63280031Sdim    FallbackLoc.reset(getCallerLocation(Opts.pc));
64245614Sandrew    Loc = FallbackLoc;
65280031Sdim  }
66245614Sandrew
67296417Sdim  ScopedReport R(Opts, Loc, ET);
68276789Sdim
69296417Sdim  switch (ET) {
70296417Sdim  case ErrorType::NullPointerUse:
71245614Sandrew    Diag(Loc, DL_Error, "%0 null pointer of type %1")
72296417Sdim        << TypeCheckKinds[Data->TypeCheckKind] << Data->Type;
73296417Sdim    break;
74296417Sdim  case ErrorType::MisalignedPointerUse:
75245614Sandrew    Diag(Loc, DL_Error, "%0 misaligned address %1 for type %3, "
76245614Sandrew                        "which requires %2 byte alignment")
77296417Sdim        << TypeCheckKinds[Data->TypeCheckKind] << (void *)Pointer
78296417Sdim        << Data->Alignment << Data->Type;
79296417Sdim    break;
80296417Sdim  case ErrorType::InsufficientObjectSize:
81245614Sandrew    Diag(Loc, DL_Error, "%0 address %1 with insufficient space "
82245614Sandrew                        "for an object of type %2")
83296417Sdim        << TypeCheckKinds[Data->TypeCheckKind] << (void *)Pointer << Data->Type;
84296417Sdim    break;
85296417Sdim  default:
86296417Sdim    UNREACHABLE("unexpected error type!");
87296417Sdim  }
88296417Sdim
89245614Sandrew  if (Pointer)
90245614Sandrew    Diag(Pointer, DL_Note, "pointer points here");
91245614Sandrew}
92276789Sdim
93245614Sandrewvoid __ubsan::__ubsan_handle_type_mismatch(TypeMismatchData *Data,
94245614Sandrew                                           ValueHandle Pointer) {
95276789Sdim  GET_REPORT_OPTIONS(false);
96280031Sdim  handleTypeMismatchImpl(Data, Pointer, Opts);
97245614Sandrew}
98245614Sandrewvoid __ubsan::__ubsan_handle_type_mismatch_abort(TypeMismatchData *Data,
99245614Sandrew                                                 ValueHandle Pointer) {
100276789Sdim  GET_REPORT_OPTIONS(true);
101280031Sdim  handleTypeMismatchImpl(Data, Pointer, Opts);
102245614Sandrew  Die();
103245614Sandrew}
104245614Sandrew
105245614Sandrew/// \brief Common diagnostic emission for various forms of integer overflow.
106276789Sdimtemplate <typename T>
107276789Sdimstatic void handleIntegerOverflowImpl(OverflowData *Data, ValueHandle LHS,
108276789Sdim                                      const char *Operator, T RHS,
109276789Sdim                                      ReportOptions Opts) {
110245614Sandrew  SourceLocation Loc = Data->Loc.acquire();
111296417Sdim  bool IsSigned = Data->Type.isSignedIntegerTy();
112296417Sdim  ErrorType ET = IsSigned ? ErrorType::SignedIntegerOverflow
113296417Sdim                          : ErrorType::UnsignedIntegerOverflow;
114296417Sdim
115296417Sdim  if (ignoreReport(Loc, Opts, ET))
116245614Sandrew    return;
117245614Sandrew
118296417Sdim  ScopedReport R(Opts, Loc, ET);
119276789Sdim
120245614Sandrew  Diag(Loc, DL_Error, "%0 integer overflow: "
121245614Sandrew                      "%1 %2 %3 cannot be represented in type %4")
122296417Sdim    << (IsSigned ? "signed" : "unsigned")
123245614Sandrew    << Value(Data->Type, LHS) << Operator << RHS << Data->Type;
124245614Sandrew}
125245614Sandrew
126296417Sdim#define UBSAN_OVERFLOW_HANDLER(handler_name, op, unrecoverable)                \
127276789Sdim  void __ubsan::handler_name(OverflowData *Data, ValueHandle LHS,              \
128276789Sdim                             ValueHandle RHS) {                                \
129296417Sdim    GET_REPORT_OPTIONS(unrecoverable);                                         \
130276789Sdim    handleIntegerOverflowImpl(Data, LHS, op, Value(Data->Type, RHS), Opts);    \
131296417Sdim    if (unrecoverable)                                                         \
132296417Sdim      Die();                                                                   \
133276789Sdim  }
134245614Sandrew
135276789SdimUBSAN_OVERFLOW_HANDLER(__ubsan_handle_add_overflow, "+", false)
136276789SdimUBSAN_OVERFLOW_HANDLER(__ubsan_handle_add_overflow_abort, "+", true)
137276789SdimUBSAN_OVERFLOW_HANDLER(__ubsan_handle_sub_overflow, "-", false)
138276789SdimUBSAN_OVERFLOW_HANDLER(__ubsan_handle_sub_overflow_abort, "-", true)
139276789SdimUBSAN_OVERFLOW_HANDLER(__ubsan_handle_mul_overflow, "*", false)
140276789SdimUBSAN_OVERFLOW_HANDLER(__ubsan_handle_mul_overflow_abort, "*", true)
141245614Sandrew
142276789Sdimstatic void handleNegateOverflowImpl(OverflowData *Data, ValueHandle OldVal,
143276789Sdim                                     ReportOptions Opts) {
144245614Sandrew  SourceLocation Loc = Data->Loc.acquire();
145296417Sdim  bool IsSigned = Data->Type.isSignedIntegerTy();
146296417Sdim  ErrorType ET = IsSigned ? ErrorType::SignedIntegerOverflow
147296417Sdim                          : ErrorType::UnsignedIntegerOverflow;
148296417Sdim
149296417Sdim  if (ignoreReport(Loc, Opts, ET))
150245614Sandrew    return;
151245614Sandrew
152296417Sdim  ScopedReport R(Opts, Loc, ET);
153276789Sdim
154296417Sdim  if (IsSigned)
155245614Sandrew    Diag(Loc, DL_Error,
156245614Sandrew         "negation of %0 cannot be represented in type %1; "
157245614Sandrew         "cast to an unsigned type to negate this value to itself")
158296417Sdim        << Value(Data->Type, OldVal) << Data->Type;
159245614Sandrew  else
160296417Sdim    Diag(Loc, DL_Error, "negation of %0 cannot be represented in type %1")
161296417Sdim        << Value(Data->Type, OldVal) << Data->Type;
162245614Sandrew}
163276789Sdim
164276789Sdimvoid __ubsan::__ubsan_handle_negate_overflow(OverflowData *Data,
165276789Sdim                                             ValueHandle OldVal) {
166276789Sdim  GET_REPORT_OPTIONS(false);
167276789Sdim  handleNegateOverflowImpl(Data, OldVal, Opts);
168276789Sdim}
169245614Sandrewvoid __ubsan::__ubsan_handle_negate_overflow_abort(OverflowData *Data,
170245614Sandrew                                                    ValueHandle OldVal) {
171276789Sdim  GET_REPORT_OPTIONS(true);
172276789Sdim  handleNegateOverflowImpl(Data, OldVal, Opts);
173245614Sandrew  Die();
174245614Sandrew}
175245614Sandrew
176276789Sdimstatic void handleDivremOverflowImpl(OverflowData *Data, ValueHandle LHS,
177276789Sdim                                     ValueHandle RHS, ReportOptions Opts) {
178245614Sandrew  SourceLocation Loc = Data->Loc.acquire();
179245614Sandrew  Value LHSVal(Data->Type, LHS);
180245614Sandrew  Value RHSVal(Data->Type, RHS);
181296417Sdim
182296417Sdim  ErrorType ET;
183245614Sandrew  if (RHSVal.isMinusOne())
184296417Sdim    ET = ErrorType::SignedIntegerOverflow;
185296417Sdim  else if (Data->Type.isIntegerTy())
186296417Sdim    ET = ErrorType::IntegerDivideByZero;
187245614Sandrew  else
188296417Sdim    ET = ErrorType::FloatDivideByZero;
189296417Sdim
190296417Sdim  if (ignoreReport(Loc, Opts, ET))
191296417Sdim    return;
192296417Sdim
193296417Sdim  ScopedReport R(Opts, Loc, ET);
194296417Sdim
195296417Sdim  switch (ET) {
196296417Sdim  case ErrorType::SignedIntegerOverflow:
197296417Sdim    Diag(Loc, DL_Error, "division of %0 by -1 cannot be represented in type %1")
198296417Sdim        << LHSVal << Data->Type;
199296417Sdim    break;
200296417Sdim  default:
201245614Sandrew    Diag(Loc, DL_Error, "division by zero");
202296417Sdim    break;
203296417Sdim  }
204245614Sandrew}
205276789Sdim
206276789Sdimvoid __ubsan::__ubsan_handle_divrem_overflow(OverflowData *Data,
207276789Sdim                                             ValueHandle LHS, ValueHandle RHS) {
208276789Sdim  GET_REPORT_OPTIONS(false);
209276789Sdim  handleDivremOverflowImpl(Data, LHS, RHS, Opts);
210276789Sdim}
211245614Sandrewvoid __ubsan::__ubsan_handle_divrem_overflow_abort(OverflowData *Data,
212245614Sandrew                                                    ValueHandle LHS,
213245614Sandrew                                                    ValueHandle RHS) {
214276789Sdim  GET_REPORT_OPTIONS(true);
215276789Sdim  handleDivremOverflowImpl(Data, LHS, RHS, Opts);
216245614Sandrew  Die();
217245614Sandrew}
218245614Sandrew
219276789Sdimstatic void handleShiftOutOfBoundsImpl(ShiftOutOfBoundsData *Data,
220276789Sdim                                       ValueHandle LHS, ValueHandle RHS,
221276789Sdim                                       ReportOptions Opts) {
222245614Sandrew  SourceLocation Loc = Data->Loc.acquire();
223296417Sdim  Value LHSVal(Data->LHSType, LHS);
224296417Sdim  Value RHSVal(Data->RHSType, RHS);
225296417Sdim
226296417Sdim  ErrorType ET;
227296417Sdim  if (RHSVal.isNegative() ||
228296417Sdim      RHSVal.getPositiveIntValue() >= Data->LHSType.getIntegerBitWidth())
229296417Sdim    ET = ErrorType::InvalidShiftExponent;
230296417Sdim  else
231296417Sdim    ET = ErrorType::InvalidShiftBase;
232296417Sdim
233296417Sdim  if (ignoreReport(Loc, Opts, ET))
234245614Sandrew    return;
235245614Sandrew
236296417Sdim  ScopedReport R(Opts, Loc, ET);
237276789Sdim
238296417Sdim  if (ET == ErrorType::InvalidShiftExponent) {
239296417Sdim    if (RHSVal.isNegative())
240296417Sdim      Diag(Loc, DL_Error, "shift exponent %0 is negative") << RHSVal;
241296417Sdim    else
242296417Sdim      Diag(Loc, DL_Error, "shift exponent %0 is too large for %1-bit type %2")
243296417Sdim          << RHSVal << Data->LHSType.getIntegerBitWidth() << Data->LHSType;
244296417Sdim  } else {
245296417Sdim    if (LHSVal.isNegative())
246296417Sdim      Diag(Loc, DL_Error, "left shift of negative value %0") << LHSVal;
247296417Sdim    else
248296417Sdim      Diag(Loc, DL_Error,
249296417Sdim           "left shift of %0 by %1 places cannot be represented in type %2")
250296417Sdim          << LHSVal << RHSVal << Data->LHSType;
251296417Sdim  }
252245614Sandrew}
253276789Sdim
254276789Sdimvoid __ubsan::__ubsan_handle_shift_out_of_bounds(ShiftOutOfBoundsData *Data,
255276789Sdim                                                 ValueHandle LHS,
256276789Sdim                                                 ValueHandle RHS) {
257276789Sdim  GET_REPORT_OPTIONS(false);
258276789Sdim  handleShiftOutOfBoundsImpl(Data, LHS, RHS, Opts);
259276789Sdim}
260245614Sandrewvoid __ubsan::__ubsan_handle_shift_out_of_bounds_abort(
261245614Sandrew                                                     ShiftOutOfBoundsData *Data,
262245614Sandrew                                                     ValueHandle LHS,
263245614Sandrew                                                     ValueHandle RHS) {
264276789Sdim  GET_REPORT_OPTIONS(true);
265276789Sdim  handleShiftOutOfBoundsImpl(Data, LHS, RHS, Opts);
266245614Sandrew  Die();
267245614Sandrew}
268245614Sandrew
269276789Sdimstatic void handleOutOfBoundsImpl(OutOfBoundsData *Data, ValueHandle Index,
270276789Sdim                                  ReportOptions Opts) {
271251034Sed  SourceLocation Loc = Data->Loc.acquire();
272296417Sdim  ErrorType ET = ErrorType::OutOfBoundsIndex;
273296417Sdim
274296417Sdim  if (ignoreReport(Loc, Opts, ET))
275251034Sed    return;
276251034Sed
277296417Sdim  ScopedReport R(Opts, Loc, ET);
278276789Sdim
279251034Sed  Value IndexVal(Data->IndexType, Index);
280251034Sed  Diag(Loc, DL_Error, "index %0 out of bounds for type %1")
281251034Sed    << IndexVal << Data->ArrayType;
282251034Sed}
283276789Sdim
284276789Sdimvoid __ubsan::__ubsan_handle_out_of_bounds(OutOfBoundsData *Data,
285276789Sdim                                           ValueHandle Index) {
286276789Sdim  GET_REPORT_OPTIONS(false);
287276789Sdim  handleOutOfBoundsImpl(Data, Index, Opts);
288276789Sdim}
289251034Sedvoid __ubsan::__ubsan_handle_out_of_bounds_abort(OutOfBoundsData *Data,
290251034Sed                                                 ValueHandle Index) {
291276789Sdim  GET_REPORT_OPTIONS(true);
292276789Sdim  handleOutOfBoundsImpl(Data, Index, Opts);
293251034Sed  Die();
294251034Sed}
295251034Sed
296276789Sdimstatic void handleBuiltinUnreachableImpl(UnreachableData *Data,
297276789Sdim                                         ReportOptions Opts) {
298296417Sdim  ScopedReport R(Opts, Data->Loc, ErrorType::UnreachableCall);
299276789Sdim  Diag(Data->Loc, DL_Error, "execution reached a __builtin_unreachable() call");
300276789Sdim}
301276789Sdim
302245614Sandrewvoid __ubsan::__ubsan_handle_builtin_unreachable(UnreachableData *Data) {
303276789Sdim  GET_REPORT_OPTIONS(true);
304276789Sdim  handleBuiltinUnreachableImpl(Data, Opts);
305245614Sandrew  Die();
306245614Sandrew}
307245614Sandrew
308276789Sdimstatic void handleMissingReturnImpl(UnreachableData *Data, ReportOptions Opts) {
309296417Sdim  ScopedReport R(Opts, Data->Loc, ErrorType::MissingReturn);
310245614Sandrew  Diag(Data->Loc, DL_Error,
311245614Sandrew       "execution reached the end of a value-returning function "
312245614Sandrew       "without returning a value");
313276789Sdim}
314276789Sdim
315276789Sdimvoid __ubsan::__ubsan_handle_missing_return(UnreachableData *Data) {
316276789Sdim  GET_REPORT_OPTIONS(true);
317276789Sdim  handleMissingReturnImpl(Data, Opts);
318245614Sandrew  Die();
319245614Sandrew}
320245614Sandrew
321276789Sdimstatic void handleVLABoundNotPositive(VLABoundData *Data, ValueHandle Bound,
322276789Sdim                                      ReportOptions Opts) {
323245614Sandrew  SourceLocation Loc = Data->Loc.acquire();
324296417Sdim  ErrorType ET = ErrorType::NonPositiveVLAIndex;
325296417Sdim
326296417Sdim  if (ignoreReport(Loc, Opts, ET))
327245614Sandrew    return;
328245614Sandrew
329296417Sdim  ScopedReport R(Opts, Loc, ET);
330276789Sdim
331245614Sandrew  Diag(Loc, DL_Error, "variable length array bound evaluates to "
332245614Sandrew                      "non-positive value %0")
333245614Sandrew    << Value(Data->Type, Bound);
334245614Sandrew}
335276789Sdim
336276789Sdimvoid __ubsan::__ubsan_handle_vla_bound_not_positive(VLABoundData *Data,
337276789Sdim                                                    ValueHandle Bound) {
338276789Sdim  GET_REPORT_OPTIONS(false);
339276789Sdim  handleVLABoundNotPositive(Data, Bound, Opts);
340276789Sdim}
341245614Sandrewvoid __ubsan::__ubsan_handle_vla_bound_not_positive_abort(VLABoundData *Data,
342276789Sdim                                                          ValueHandle Bound) {
343276789Sdim  GET_REPORT_OPTIONS(true);
344276789Sdim  handleVLABoundNotPositive(Data, Bound, Opts);
345245614Sandrew  Die();
346245614Sandrew}
347245614Sandrew
348296417Sdimstatic bool looksLikeFloatCastOverflowDataV1(void *Data) {
349296417Sdim  // First field is either a pointer to filename or a pointer to a
350296417Sdim  // TypeDescriptor.
351296417Sdim  u8 *FilenameOrTypeDescriptor;
352296417Sdim  internal_memcpy(&FilenameOrTypeDescriptor, Data,
353296417Sdim                  sizeof(FilenameOrTypeDescriptor));
354245614Sandrew
355296417Sdim  // Heuristic: For float_cast_overflow, the TypeKind will be either TK_Integer
356296417Sdim  // (0x0), TK_Float (0x1) or TK_Unknown (0xff). If both types are known,
357296417Sdim  // adding both bytes will be 0 or 1 (for BE or LE). If it were a filename,
358296417Sdim  // adding two printable characters will not yield such a value. Otherwise,
359296417Sdim  // if one of them is 0xff, this is most likely TK_Unknown type descriptor.
360296417Sdim  u16 MaybeFromTypeKind =
361296417Sdim      FilenameOrTypeDescriptor[0] + FilenameOrTypeDescriptor[1];
362296417Sdim  return MaybeFromTypeKind < 2 || FilenameOrTypeDescriptor[0] == 0xff ||
363296417Sdim         FilenameOrTypeDescriptor[1] == 0xff;
364296417Sdim}
365296417Sdim
366296417Sdimstatic void handleFloatCastOverflow(void *DataPtr, ValueHandle From,
367296417Sdim                                    ReportOptions Opts) {
368296417Sdim  SymbolizedStackHolder CallerLoc;
369296417Sdim  Location Loc;
370296417Sdim  const TypeDescriptor *FromType, *ToType;
371296417Sdim  ErrorType ET = ErrorType::FloatCastOverflow;
372296417Sdim
373296417Sdim  if (looksLikeFloatCastOverflowDataV1(DataPtr)) {
374296417Sdim    auto Data = reinterpret_cast<FloatCastOverflowData *>(DataPtr);
375296417Sdim    CallerLoc.reset(getCallerLocation(Opts.pc));
376296417Sdim    Loc = CallerLoc;
377296417Sdim    FromType = &Data->FromType;
378296417Sdim    ToType = &Data->ToType;
379296417Sdim  } else {
380296417Sdim    auto Data = reinterpret_cast<FloatCastOverflowDataV2 *>(DataPtr);
381296417Sdim    SourceLocation SLoc = Data->Loc.acquire();
382296417Sdim    if (ignoreReport(SLoc, Opts, ET))
383296417Sdim      return;
384296417Sdim    Loc = SLoc;
385296417Sdim    FromType = &Data->FromType;
386296417Sdim    ToType = &Data->ToType;
387296417Sdim  }
388296417Sdim
389296417Sdim  ScopedReport R(Opts, Loc, ET);
390296417Sdim
391276789Sdim  Diag(Loc, DL_Error,
392276789Sdim       "value %0 is outside the range of representable values of type %2")
393296417Sdim      << Value(*FromType, From) << *FromType << *ToType;
394276789Sdim}
395276789Sdim
396296417Sdimvoid __ubsan::__ubsan_handle_float_cast_overflow(void *Data, ValueHandle From) {
397276789Sdim  GET_REPORT_OPTIONS(false);
398276789Sdim  handleFloatCastOverflow(Data, From, Opts);
399245614Sandrew}
400296417Sdimvoid __ubsan::__ubsan_handle_float_cast_overflow_abort(void *Data,
401296417Sdim                                                       ValueHandle From) {
402276789Sdim  GET_REPORT_OPTIONS(true);
403276789Sdim  handleFloatCastOverflow(Data, From, Opts);
404245614Sandrew  Die();
405245614Sandrew}
406245614Sandrew
407276789Sdimstatic void handleLoadInvalidValue(InvalidValueData *Data, ValueHandle Val,
408276789Sdim                                   ReportOptions Opts) {
409274201Sdim  SourceLocation Loc = Data->Loc.acquire();
410296417Sdim  // This check could be more precise if we used different handlers for
411296417Sdim  // -fsanitize=bool and -fsanitize=enum.
412296417Sdim  bool IsBool = (0 == internal_strcmp(Data->Type.getTypeName(), "'bool'"));
413296417Sdim  ErrorType ET =
414296417Sdim      IsBool ? ErrorType::InvalidBoolLoad : ErrorType::InvalidEnumLoad;
415296417Sdim
416296417Sdim  if (ignoreReport(Loc, Opts, ET))
417274201Sdim    return;
418274201Sdim
419296417Sdim  ScopedReport R(Opts, Loc, ET);
420276789Sdim
421274201Sdim  Diag(Loc, DL_Error,
422245614Sandrew       "load of value %0, which is not a valid value for type %1")
423245614Sandrew    << Value(Data->Type, Val) << Data->Type;
424245614Sandrew}
425276789Sdim
426276789Sdimvoid __ubsan::__ubsan_handle_load_invalid_value(InvalidValueData *Data,
427276789Sdim                                                ValueHandle Val) {
428276789Sdim  GET_REPORT_OPTIONS(false);
429276789Sdim  handleLoadInvalidValue(Data, Val, Opts);
430276789Sdim}
431245614Sandrewvoid __ubsan::__ubsan_handle_load_invalid_value_abort(InvalidValueData *Data,
432245614Sandrew                                                      ValueHandle Val) {
433276789Sdim  GET_REPORT_OPTIONS(true);
434276789Sdim  handleLoadInvalidValue(Data, Val, Opts);
435245614Sandrew  Die();
436245614Sandrew}
437274201Sdim
438276789Sdimstatic void handleFunctionTypeMismatch(FunctionTypeMismatchData *Data,
439276789Sdim                                       ValueHandle Function,
440276789Sdim                                       ReportOptions Opts) {
441280031Sdim  SourceLocation CallLoc = Data->Loc.acquire();
442296417Sdim  ErrorType ET = ErrorType::FunctionTypeMismatch;
443296417Sdim
444296417Sdim  if (ignoreReport(CallLoc, Opts, ET))
445280031Sdim    return;
446274201Sdim
447296417Sdim  ScopedReport R(Opts, CallLoc, ET);
448274201Sdim
449280031Sdim  SymbolizedStackHolder FLoc(getSymbolizedLocation(Function));
450280031Sdim  const char *FName = FLoc.get()->info.function;
451280031Sdim  if (!FName)
452280031Sdim    FName = "(unknown)";
453276789Sdim
454280031Sdim  Diag(CallLoc, DL_Error,
455274201Sdim       "call to function %0 through pointer to incorrect function type %1")
456280031Sdim      << FName << Data->Type;
457280031Sdim  Diag(FLoc, DL_Note, "%0 defined here") << FName;
458274201Sdim}
459274201Sdim
460276789Sdimvoid
461276789Sdim__ubsan::__ubsan_handle_function_type_mismatch(FunctionTypeMismatchData *Data,
462276789Sdim                                               ValueHandle Function) {
463276789Sdim  GET_REPORT_OPTIONS(false);
464276789Sdim  handleFunctionTypeMismatch(Data, Function, Opts);
465276789Sdim}
466276789Sdim
467274201Sdimvoid __ubsan::__ubsan_handle_function_type_mismatch_abort(
468276789Sdim    FunctionTypeMismatchData *Data, ValueHandle Function) {
469276789Sdim  GET_REPORT_OPTIONS(true);
470276789Sdim  handleFunctionTypeMismatch(Data, Function, Opts);
471274201Sdim  Die();
472274201Sdim}
473276789Sdim
474276789Sdimstatic void handleNonNullReturn(NonNullReturnData *Data, ReportOptions Opts) {
475276789Sdim  SourceLocation Loc = Data->Loc.acquire();
476296417Sdim  ErrorType ET = ErrorType::InvalidNullReturn;
477296417Sdim
478296417Sdim  if (ignoreReport(Loc, Opts, ET))
479276789Sdim    return;
480276789Sdim
481296417Sdim  ScopedReport R(Opts, Loc, ET);
482276789Sdim
483276789Sdim  Diag(Loc, DL_Error, "null pointer returned from function declared to never "
484276789Sdim                      "return null");
485276789Sdim  if (!Data->AttrLoc.isInvalid())
486276789Sdim    Diag(Data->AttrLoc, DL_Note, "returns_nonnull attribute specified here");
487276789Sdim}
488276789Sdim
489276789Sdimvoid __ubsan::__ubsan_handle_nonnull_return(NonNullReturnData *Data) {
490276789Sdim  GET_REPORT_OPTIONS(false);
491276789Sdim  handleNonNullReturn(Data, Opts);
492276789Sdim}
493276789Sdim
494276789Sdimvoid __ubsan::__ubsan_handle_nonnull_return_abort(NonNullReturnData *Data) {
495276789Sdim  GET_REPORT_OPTIONS(true);
496276789Sdim  handleNonNullReturn(Data, Opts);
497276789Sdim  Die();
498276789Sdim}
499276789Sdim
500276789Sdimstatic void handleNonNullArg(NonNullArgData *Data, ReportOptions Opts) {
501276789Sdim  SourceLocation Loc = Data->Loc.acquire();
502296417Sdim  ErrorType ET = ErrorType::InvalidNullArgument;
503296417Sdim
504296417Sdim  if (ignoreReport(Loc, Opts, ET))
505276789Sdim    return;
506276789Sdim
507296417Sdim  ScopedReport R(Opts, Loc, ET);
508276789Sdim
509276789Sdim  Diag(Loc, DL_Error, "null pointer passed as argument %0, which is declared to "
510276789Sdim       "never be null") << Data->ArgIndex;
511276789Sdim  if (!Data->AttrLoc.isInvalid())
512276789Sdim    Diag(Data->AttrLoc, DL_Note, "nonnull attribute specified here");
513276789Sdim}
514276789Sdim
515276789Sdimvoid __ubsan::__ubsan_handle_nonnull_arg(NonNullArgData *Data) {
516276789Sdim  GET_REPORT_OPTIONS(false);
517276789Sdim  handleNonNullArg(Data, Opts);
518276789Sdim}
519276789Sdim
520276789Sdimvoid __ubsan::__ubsan_handle_nonnull_arg_abort(NonNullArgData *Data) {
521276789Sdim  GET_REPORT_OPTIONS(true);
522276789Sdim  handleNonNullArg(Data, Opts);
523276789Sdim  Die();
524276789Sdim}
525288943Sdim
526296417Sdimstatic void handleCFIBadIcall(CFIBadIcallData *Data, ValueHandle Function,
527296417Sdim                              ReportOptions Opts) {
528296417Sdim  SourceLocation Loc = Data->Loc.acquire();
529296417Sdim  ErrorType ET = ErrorType::CFIBadType;
530296417Sdim
531296417Sdim  if (ignoreReport(Loc, Opts, ET))
532296417Sdim    return;
533296417Sdim
534296417Sdim  ScopedReport R(Opts, Loc, ET);
535296417Sdim
536296417Sdim  Diag(Loc, DL_Error, "control flow integrity check for type %0 failed during "
537296417Sdim                      "indirect function call")
538296417Sdim      << Data->Type;
539296417Sdim
540296417Sdim  SymbolizedStackHolder FLoc(getSymbolizedLocation(Function));
541296417Sdim  const char *FName = FLoc.get()->info.function;
542296417Sdim  if (!FName)
543296417Sdim    FName = "(unknown)";
544296417Sdim  Diag(FLoc, DL_Note, "%0 defined here") << FName;
545296417Sdim}
546296417Sdim
547296417Sdimvoid __ubsan::__ubsan_handle_cfi_bad_icall(CFIBadIcallData *Data,
548296417Sdim                                           ValueHandle Function) {
549296417Sdim  GET_REPORT_OPTIONS(false);
550296417Sdim  handleCFIBadIcall(Data, Function, Opts);
551296417Sdim}
552296417Sdim
553296417Sdimvoid __ubsan::__ubsan_handle_cfi_bad_icall_abort(CFIBadIcallData *Data,
554296417Sdim                                                 ValueHandle Function) {
555296417Sdim  GET_REPORT_OPTIONS(true);
556296417Sdim  handleCFIBadIcall(Data, Function, Opts);
557296417Sdim  Die();
558296417Sdim}
559296417Sdim
560288943Sdim#endif  // CAN_SANITIZE_UB
561