]> git.proxmox.com Git - rustc.git/blame - src/compiler-rt/lib/ubsan/ubsan_handlers.cc
Imported Upstream version 1.11.0+dfsg1
[rustc.git] / src / compiler-rt / lib / ubsan / ubsan_handlers.cc
CommitLineData
1a4d82fc
JJ
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
92a42be0
SL
14#include "ubsan_platform.h"
15#if CAN_SANITIZE_UB
1a4d82fc
JJ
16#include "ubsan_handlers.h"
17#include "ubsan_diag.h"
18
19#include "sanitizer_common/sanitizer_common.h"
20
21using namespace __sanitizer;
22using namespace __ubsan;
23
3157f602
XL
24namespace __ubsan {
25bool 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());
92a42be0
SL
36}
37
92a42be0 38const char *TypeCheckKinds[] = {
1a4d82fc 39 "load of", "store to", "reference binding to", "member access within",
92a42be0
SL
40 "member call on", "constructor call on", "downcast of", "downcast of",
41 "upcast of", "cast to virtual base of"};
1a4d82fc
JJ
42}
43
44static void handleTypeMismatchImpl(TypeMismatchData *Data, ValueHandle Pointer,
92a42be0 45 ReportOptions Opts) {
1a4d82fc 46 Location Loc = Data->Loc.acquire();
3157f602
XL
47
48 ErrorType ET;
49 if (!Pointer)
50 ET = ErrorType::NullPointerUse;
51 else if (Data->Alignment && (Pointer & (Data->Alignment - 1)))
52 ET = ErrorType::MisalignedPointerUse;
53 else
54 ET = ErrorType::InsufficientObjectSize;
55
56 // Use the SourceLocation from Data to track deduplication, even if it's
57 // invalid.
58 if (ignoreReport(Loc.getSourceLocation(), Opts, ET))
1a4d82fc 59 return;
92a42be0
SL
60
61 SymbolizedStackHolder FallbackLoc;
62 if (Data->Loc.isInvalid()) {
63 FallbackLoc.reset(getCallerLocation(Opts.pc));
1a4d82fc 64 Loc = FallbackLoc;
92a42be0 65 }
1a4d82fc 66
3157f602 67 ScopedReport R(Opts, Loc, ET);
92a42be0 68
3157f602
XL
69 switch (ET) {
70 case ErrorType::NullPointerUse:
1a4d82fc 71 Diag(Loc, DL_Error, "%0 null pointer of type %1")
3157f602
XL
72 << TypeCheckKinds[Data->TypeCheckKind] << Data->Type;
73 break;
74 case ErrorType::MisalignedPointerUse:
1a4d82fc
JJ
75 Diag(Loc, DL_Error, "%0 misaligned address %1 for type %3, "
76 "which requires %2 byte alignment")
3157f602
XL
77 << TypeCheckKinds[Data->TypeCheckKind] << (void *)Pointer
78 << Data->Alignment << Data->Type;
79 break;
80 case ErrorType::InsufficientObjectSize:
1a4d82fc
JJ
81 Diag(Loc, DL_Error, "%0 address %1 with insufficient space "
82 "for an object of type %2")
3157f602
XL
83 << TypeCheckKinds[Data->TypeCheckKind] << (void *)Pointer << Data->Type;
84 break;
85 default:
86 UNREACHABLE("unexpected error type!");
92a42be0 87 }
3157f602 88
1a4d82fc
JJ
89 if (Pointer)
90 Diag(Pointer, DL_Note, "pointer points here");
91}
92a42be0 92
1a4d82fc
JJ
93void __ubsan::__ubsan_handle_type_mismatch(TypeMismatchData *Data,
94 ValueHandle Pointer) {
92a42be0
SL
95 GET_REPORT_OPTIONS(false);
96 handleTypeMismatchImpl(Data, Pointer, Opts);
1a4d82fc
JJ
97}
98void __ubsan::__ubsan_handle_type_mismatch_abort(TypeMismatchData *Data,
99 ValueHandle Pointer) {
92a42be0
SL
100 GET_REPORT_OPTIONS(true);
101 handleTypeMismatchImpl(Data, Pointer, Opts);
1a4d82fc
JJ
102 Die();
103}
104
105/// \brief Common diagnostic emission for various forms of integer overflow.
92a42be0
SL
106template <typename T>
107static void handleIntegerOverflowImpl(OverflowData *Data, ValueHandle LHS,
108 const char *Operator, T RHS,
109 ReportOptions Opts) {
1a4d82fc 110 SourceLocation Loc = Data->Loc.acquire();
3157f602
XL
111 bool IsSigned = Data->Type.isSignedIntegerTy();
112 ErrorType ET = IsSigned ? ErrorType::SignedIntegerOverflow
113 : ErrorType::UnsignedIntegerOverflow;
114
115 if (ignoreReport(Loc, Opts, ET))
1a4d82fc
JJ
116 return;
117
3157f602 118 ScopedReport R(Opts, Loc, ET);
92a42be0 119
1a4d82fc
JJ
120 Diag(Loc, DL_Error, "%0 integer overflow: "
121 "%1 %2 %3 cannot be represented in type %4")
92a42be0 122 << (IsSigned ? "signed" : "unsigned")
1a4d82fc
JJ
123 << Value(Data->Type, LHS) << Operator << RHS << Data->Type;
124}
125
3157f602 126#define UBSAN_OVERFLOW_HANDLER(handler_name, op, unrecoverable) \
92a42be0
SL
127 void __ubsan::handler_name(OverflowData *Data, ValueHandle LHS, \
128 ValueHandle RHS) { \
3157f602 129 GET_REPORT_OPTIONS(unrecoverable); \
92a42be0 130 handleIntegerOverflowImpl(Data, LHS, op, Value(Data->Type, RHS), Opts); \
3157f602
XL
131 if (unrecoverable) \
132 Die(); \
92a42be0
SL
133 }
134
135UBSAN_OVERFLOW_HANDLER(__ubsan_handle_add_overflow, "+", false)
136UBSAN_OVERFLOW_HANDLER(__ubsan_handle_add_overflow_abort, "+", true)
137UBSAN_OVERFLOW_HANDLER(__ubsan_handle_sub_overflow, "-", false)
138UBSAN_OVERFLOW_HANDLER(__ubsan_handle_sub_overflow_abort, "-", true)
139UBSAN_OVERFLOW_HANDLER(__ubsan_handle_mul_overflow, "*", false)
140UBSAN_OVERFLOW_HANDLER(__ubsan_handle_mul_overflow_abort, "*", true)
141
142static void handleNegateOverflowImpl(OverflowData *Data, ValueHandle OldVal,
143 ReportOptions Opts) {
1a4d82fc 144 SourceLocation Loc = Data->Loc.acquire();
3157f602
XL
145 bool IsSigned = Data->Type.isSignedIntegerTy();
146 ErrorType ET = IsSigned ? ErrorType::SignedIntegerOverflow
147 : ErrorType::UnsignedIntegerOverflow;
148
149 if (ignoreReport(Loc, Opts, ET))
1a4d82fc
JJ
150 return;
151
3157f602 152 ScopedReport R(Opts, Loc, ET);
92a42be0
SL
153
154 if (IsSigned)
1a4d82fc
JJ
155 Diag(Loc, DL_Error,
156 "negation of %0 cannot be represented in type %1; "
157 "cast to an unsigned type to negate this value to itself")
92a42be0 158 << Value(Data->Type, OldVal) << Data->Type;
1a4d82fc 159 else
92a42be0
SL
160 Diag(Loc, DL_Error, "negation of %0 cannot be represented in type %1")
161 << Value(Data->Type, OldVal) << Data->Type;
162}
163
164void __ubsan::__ubsan_handle_negate_overflow(OverflowData *Data,
165 ValueHandle OldVal) {
166 GET_REPORT_OPTIONS(false);
167 handleNegateOverflowImpl(Data, OldVal, Opts);
1a4d82fc
JJ
168}
169void __ubsan::__ubsan_handle_negate_overflow_abort(OverflowData *Data,
170 ValueHandle OldVal) {
92a42be0
SL
171 GET_REPORT_OPTIONS(true);
172 handleNegateOverflowImpl(Data, OldVal, Opts);
1a4d82fc
JJ
173 Die();
174}
175
92a42be0
SL
176static void handleDivremOverflowImpl(OverflowData *Data, ValueHandle LHS,
177 ValueHandle RHS, ReportOptions Opts) {
1a4d82fc 178 SourceLocation Loc = Data->Loc.acquire();
3157f602
XL
179 Value LHSVal(Data->Type, LHS);
180 Value RHSVal(Data->Type, RHS);
181
182 ErrorType ET;
183 if (RHSVal.isMinusOne())
184 ET = ErrorType::SignedIntegerOverflow;
185 else if (Data->Type.isIntegerTy())
186 ET = ErrorType::IntegerDivideByZero;
187 else
188 ET = ErrorType::FloatDivideByZero;
189
190 if (ignoreReport(Loc, Opts, ET))
1a4d82fc
JJ
191 return;
192
3157f602 193 ScopedReport R(Opts, Loc, ET);
92a42be0 194
3157f602
XL
195 switch (ET) {
196 case ErrorType::SignedIntegerOverflow:
197 Diag(Loc, DL_Error, "division of %0 by -1 cannot be represented in type %1")
198 << LHSVal << Data->Type;
199 break;
200 default:
1a4d82fc 201 Diag(Loc, DL_Error, "division by zero");
3157f602 202 break;
92a42be0
SL
203 }
204}
205
206void __ubsan::__ubsan_handle_divrem_overflow(OverflowData *Data,
207 ValueHandle LHS, ValueHandle RHS) {
208 GET_REPORT_OPTIONS(false);
209 handleDivremOverflowImpl(Data, LHS, RHS, Opts);
1a4d82fc
JJ
210}
211void __ubsan::__ubsan_handle_divrem_overflow_abort(OverflowData *Data,
212 ValueHandle LHS,
213 ValueHandle RHS) {
92a42be0
SL
214 GET_REPORT_OPTIONS(true);
215 handleDivremOverflowImpl(Data, LHS, RHS, Opts);
1a4d82fc
JJ
216 Die();
217}
218
92a42be0
SL
219static void handleShiftOutOfBoundsImpl(ShiftOutOfBoundsData *Data,
220 ValueHandle LHS, ValueHandle RHS,
221 ReportOptions Opts) {
1a4d82fc 222 SourceLocation Loc = Data->Loc.acquire();
3157f602
XL
223 Value LHSVal(Data->LHSType, LHS);
224 Value RHSVal(Data->RHSType, RHS);
225
226 ErrorType ET;
227 if (RHSVal.isNegative() ||
228 RHSVal.getPositiveIntValue() >= Data->LHSType.getIntegerBitWidth())
229 ET = ErrorType::InvalidShiftExponent;
230 else
231 ET = ErrorType::InvalidShiftBase;
232
233 if (ignoreReport(Loc, Opts, ET))
1a4d82fc
JJ
234 return;
235
3157f602 236 ScopedReport R(Opts, Loc, ET);
92a42be0 237
3157f602
XL
238 if (ET == ErrorType::InvalidShiftExponent) {
239 if (RHSVal.isNegative())
240 Diag(Loc, DL_Error, "shift exponent %0 is negative") << RHSVal;
241 else
242 Diag(Loc, DL_Error, "shift exponent %0 is too large for %1-bit type %2")
243 << RHSVal << Data->LHSType.getIntegerBitWidth() << Data->LHSType;
92a42be0 244 } else {
3157f602
XL
245 if (LHSVal.isNegative())
246 Diag(Loc, DL_Error, "left shift of negative value %0") << LHSVal;
247 else
248 Diag(Loc, DL_Error,
249 "left shift of %0 by %1 places cannot be represented in type %2")
250 << LHSVal << RHSVal << Data->LHSType;
92a42be0
SL
251 }
252}
253
254void __ubsan::__ubsan_handle_shift_out_of_bounds(ShiftOutOfBoundsData *Data,
255 ValueHandle LHS,
256 ValueHandle RHS) {
257 GET_REPORT_OPTIONS(false);
258 handleShiftOutOfBoundsImpl(Data, LHS, RHS, Opts);
1a4d82fc
JJ
259}
260void __ubsan::__ubsan_handle_shift_out_of_bounds_abort(
261 ShiftOutOfBoundsData *Data,
262 ValueHandle LHS,
263 ValueHandle RHS) {
92a42be0
SL
264 GET_REPORT_OPTIONS(true);
265 handleShiftOutOfBoundsImpl(Data, LHS, RHS, Opts);
1a4d82fc
JJ
266 Die();
267}
268
92a42be0
SL
269static void handleOutOfBoundsImpl(OutOfBoundsData *Data, ValueHandle Index,
270 ReportOptions Opts) {
1a4d82fc 271 SourceLocation Loc = Data->Loc.acquire();
3157f602
XL
272 ErrorType ET = ErrorType::OutOfBoundsIndex;
273
274 if (ignoreReport(Loc, Opts, ET))
1a4d82fc
JJ
275 return;
276
3157f602 277 ScopedReport R(Opts, Loc, ET);
92a42be0 278
1a4d82fc
JJ
279 Value IndexVal(Data->IndexType, Index);
280 Diag(Loc, DL_Error, "index %0 out of bounds for type %1")
281 << IndexVal << Data->ArrayType;
282}
92a42be0
SL
283
284void __ubsan::__ubsan_handle_out_of_bounds(OutOfBoundsData *Data,
285 ValueHandle Index) {
286 GET_REPORT_OPTIONS(false);
287 handleOutOfBoundsImpl(Data, Index, Opts);
288}
1a4d82fc
JJ
289void __ubsan::__ubsan_handle_out_of_bounds_abort(OutOfBoundsData *Data,
290 ValueHandle Index) {
92a42be0
SL
291 GET_REPORT_OPTIONS(true);
292 handleOutOfBoundsImpl(Data, Index, Opts);
1a4d82fc
JJ
293 Die();
294}
295
92a42be0
SL
296static void handleBuiltinUnreachableImpl(UnreachableData *Data,
297 ReportOptions Opts) {
298 ScopedReport R(Opts, Data->Loc, ErrorType::UnreachableCall);
1a4d82fc 299 Diag(Data->Loc, DL_Error, "execution reached a __builtin_unreachable() call");
92a42be0
SL
300}
301
302void __ubsan::__ubsan_handle_builtin_unreachable(UnreachableData *Data) {
303 GET_REPORT_OPTIONS(true);
304 handleBuiltinUnreachableImpl(Data, Opts);
1a4d82fc
JJ
305 Die();
306}
307
92a42be0
SL
308static void handleMissingReturnImpl(UnreachableData *Data, ReportOptions Opts) {
309 ScopedReport R(Opts, Data->Loc, ErrorType::MissingReturn);
1a4d82fc
JJ
310 Diag(Data->Loc, DL_Error,
311 "execution reached the end of a value-returning function "
312 "without returning a value");
92a42be0
SL
313}
314
315void __ubsan::__ubsan_handle_missing_return(UnreachableData *Data) {
316 GET_REPORT_OPTIONS(true);
317 handleMissingReturnImpl(Data, Opts);
1a4d82fc
JJ
318 Die();
319}
320
92a42be0
SL
321static void handleVLABoundNotPositive(VLABoundData *Data, ValueHandle Bound,
322 ReportOptions Opts) {
1a4d82fc 323 SourceLocation Loc = Data->Loc.acquire();
3157f602
XL
324 ErrorType ET = ErrorType::NonPositiveVLAIndex;
325
326 if (ignoreReport(Loc, Opts, ET))
1a4d82fc
JJ
327 return;
328
3157f602 329 ScopedReport R(Opts, Loc, ET);
92a42be0 330
1a4d82fc
JJ
331 Diag(Loc, DL_Error, "variable length array bound evaluates to "
332 "non-positive value %0")
333 << Value(Data->Type, Bound);
334}
92a42be0
SL
335
336void __ubsan::__ubsan_handle_vla_bound_not_positive(VLABoundData *Data,
337 ValueHandle Bound) {
338 GET_REPORT_OPTIONS(false);
339 handleVLABoundNotPositive(Data, Bound, Opts);
340}
1a4d82fc 341void __ubsan::__ubsan_handle_vla_bound_not_positive_abort(VLABoundData *Data,
92a42be0
SL
342 ValueHandle Bound) {
343 GET_REPORT_OPTIONS(true);
344 handleVLABoundNotPositive(Data, Bound, Opts);
1a4d82fc
JJ
345 Die();
346}
347
92a42be0
SL
348static bool looksLikeFloatCastOverflowDataV1(void *Data) {
349 // First field is either a pointer to filename or a pointer to a
350 // TypeDescriptor.
351 u8 *FilenameOrTypeDescriptor;
352 internal_memcpy(&FilenameOrTypeDescriptor, Data,
353 sizeof(FilenameOrTypeDescriptor));
354
355 // Heuristic: For float_cast_overflow, the TypeKind will be either TK_Integer
356 // (0x0), TK_Float (0x1) or TK_Unknown (0xff). If both types are known,
357 // adding both bytes will be 0 or 1 (for BE or LE). If it were a filename,
358 // adding two printable characters will not yield such a value. Otherwise,
359 // if one of them is 0xff, this is most likely TK_Unknown type descriptor.
360 u16 MaybeFromTypeKind =
361 FilenameOrTypeDescriptor[0] + FilenameOrTypeDescriptor[1];
362 return MaybeFromTypeKind < 2 || FilenameOrTypeDescriptor[0] == 0xff ||
363 FilenameOrTypeDescriptor[1] == 0xff;
364}
365
366static void handleFloatCastOverflow(void *DataPtr, ValueHandle From,
367 ReportOptions Opts) {
368 SymbolizedStackHolder CallerLoc;
369 Location Loc;
370 const TypeDescriptor *FromType, *ToType;
3157f602 371 ErrorType ET = ErrorType::FloatCastOverflow;
92a42be0
SL
372
373 if (looksLikeFloatCastOverflowDataV1(DataPtr)) {
374 auto Data = reinterpret_cast<FloatCastOverflowData *>(DataPtr);
375 CallerLoc.reset(getCallerLocation(Opts.pc));
376 Loc = CallerLoc;
377 FromType = &Data->FromType;
378 ToType = &Data->ToType;
379 } else {
380 auto Data = reinterpret_cast<FloatCastOverflowDataV2 *>(DataPtr);
381 SourceLocation SLoc = Data->Loc.acquire();
3157f602 382 if (ignoreReport(SLoc, Opts, ET))
92a42be0
SL
383 return;
384 Loc = SLoc;
385 FromType = &Data->FromType;
386 ToType = &Data->ToType;
387 }
388
3157f602 389 ScopedReport R(Opts, Loc, ET);
1a4d82fc 390
92a42be0 391 Diag(Loc, DL_Error,
1a4d82fc 392 "value %0 is outside the range of representable values of type %2")
92a42be0 393 << Value(*FromType, From) << *FromType << *ToType;
1a4d82fc 394}
92a42be0
SL
395
396void __ubsan::__ubsan_handle_float_cast_overflow(void *Data, ValueHandle From) {
397 GET_REPORT_OPTIONS(false);
398 handleFloatCastOverflow(Data, From, Opts);
399}
400void __ubsan::__ubsan_handle_float_cast_overflow_abort(void *Data,
401 ValueHandle From) {
402 GET_REPORT_OPTIONS(true);
403 handleFloatCastOverflow(Data, From, Opts);
1a4d82fc
JJ
404 Die();
405}
406
92a42be0
SL
407static void handleLoadInvalidValue(InvalidValueData *Data, ValueHandle Val,
408 ReportOptions Opts) {
1a4d82fc 409 SourceLocation Loc = Data->Loc.acquire();
92a42be0
SL
410 // This check could be more precise if we used different handlers for
411 // -fsanitize=bool and -fsanitize=enum.
412 bool IsBool = (0 == internal_strcmp(Data->Type.getTypeName(), "'bool'"));
3157f602
XL
413 ErrorType ET =
414 IsBool ? ErrorType::InvalidBoolLoad : ErrorType::InvalidEnumLoad;
415
416 if (ignoreReport(Loc, Opts, ET))
417 return;
418
419 ScopedReport R(Opts, Loc, ET);
92a42be0 420
1a4d82fc
JJ
421 Diag(Loc, DL_Error,
422 "load of value %0, which is not a valid value for type %1")
423 << Value(Data->Type, Val) << Data->Type;
424}
92a42be0
SL
425
426void __ubsan::__ubsan_handle_load_invalid_value(InvalidValueData *Data,
427 ValueHandle Val) {
428 GET_REPORT_OPTIONS(false);
429 handleLoadInvalidValue(Data, Val, Opts);
430}
1a4d82fc
JJ
431void __ubsan::__ubsan_handle_load_invalid_value_abort(InvalidValueData *Data,
432 ValueHandle Val) {
92a42be0
SL
433 GET_REPORT_OPTIONS(true);
434 handleLoadInvalidValue(Data, Val, Opts);
1a4d82fc
JJ
435 Die();
436}
437
92a42be0
SL
438static void handleFunctionTypeMismatch(FunctionTypeMismatchData *Data,
439 ValueHandle Function,
440 ReportOptions Opts) {
441 SourceLocation CallLoc = Data->Loc.acquire();
3157f602
XL
442 ErrorType ET = ErrorType::FunctionTypeMismatch;
443
444 if (ignoreReport(CallLoc, Opts, ET))
92a42be0 445 return;
1a4d82fc 446
3157f602 447 ScopedReport R(Opts, CallLoc, ET);
1a4d82fc 448
92a42be0
SL
449 SymbolizedStackHolder FLoc(getSymbolizedLocation(Function));
450 const char *FName = FLoc.get()->info.function;
451 if (!FName)
452 FName = "(unknown)";
453
454 Diag(CallLoc, DL_Error,
1a4d82fc 455 "call to function %0 through pointer to incorrect function type %1")
92a42be0
SL
456 << FName << Data->Type;
457 Diag(FLoc, DL_Note, "%0 defined here") << FName;
458}
459
460void
461__ubsan::__ubsan_handle_function_type_mismatch(FunctionTypeMismatchData *Data,
462 ValueHandle Function) {
463 GET_REPORT_OPTIONS(false);
464 handleFunctionTypeMismatch(Data, Function, Opts);
1a4d82fc
JJ
465}
466
467void __ubsan::__ubsan_handle_function_type_mismatch_abort(
92a42be0
SL
468 FunctionTypeMismatchData *Data, ValueHandle Function) {
469 GET_REPORT_OPTIONS(true);
470 handleFunctionTypeMismatch(Data, Function, Opts);
471 Die();
472}
473
474static void handleNonNullReturn(NonNullReturnData *Data, ReportOptions Opts) {
475 SourceLocation Loc = Data->Loc.acquire();
3157f602
XL
476 ErrorType ET = ErrorType::InvalidNullReturn;
477
478 if (ignoreReport(Loc, Opts, ET))
92a42be0
SL
479 return;
480
3157f602 481 ScopedReport R(Opts, Loc, ET);
92a42be0
SL
482
483 Diag(Loc, DL_Error, "null pointer returned from function declared to never "
484 "return null");
485 if (!Data->AttrLoc.isInvalid())
486 Diag(Data->AttrLoc, DL_Note, "returns_nonnull attribute specified here");
487}
488
489void __ubsan::__ubsan_handle_nonnull_return(NonNullReturnData *Data) {
490 GET_REPORT_OPTIONS(false);
491 handleNonNullReturn(Data, Opts);
492}
493
494void __ubsan::__ubsan_handle_nonnull_return_abort(NonNullReturnData *Data) {
495 GET_REPORT_OPTIONS(true);
496 handleNonNullReturn(Data, Opts);
497 Die();
498}
499
500static void handleNonNullArg(NonNullArgData *Data, ReportOptions Opts) {
501 SourceLocation Loc = Data->Loc.acquire();
3157f602
XL
502 ErrorType ET = ErrorType::InvalidNullArgument;
503
504 if (ignoreReport(Loc, Opts, ET))
92a42be0
SL
505 return;
506
3157f602 507 ScopedReport R(Opts, Loc, ET);
92a42be0
SL
508
509 Diag(Loc, DL_Error, "null pointer passed as argument %0, which is declared to "
510 "never be null") << Data->ArgIndex;
511 if (!Data->AttrLoc.isInvalid())
512 Diag(Data->AttrLoc, DL_Note, "nonnull attribute specified here");
513}
514
515void __ubsan::__ubsan_handle_nonnull_arg(NonNullArgData *Data) {
516 GET_REPORT_OPTIONS(false);
517 handleNonNullArg(Data, Opts);
518}
519
520void __ubsan::__ubsan_handle_nonnull_arg_abort(NonNullArgData *Data) {
521 GET_REPORT_OPTIONS(true);
522 handleNonNullArg(Data, Opts);
523 Die();
524}
525
526static void handleCFIBadIcall(CFIBadIcallData *Data, ValueHandle Function,
527 ReportOptions Opts) {
528 SourceLocation Loc = Data->Loc.acquire();
3157f602
XL
529 ErrorType ET = ErrorType::CFIBadType;
530
531 if (ignoreReport(Loc, Opts, ET))
92a42be0
SL
532 return;
533
3157f602 534 ScopedReport R(Opts, Loc, ET);
92a42be0
SL
535
536 Diag(Loc, DL_Error, "control flow integrity check for type %0 failed during "
537 "indirect function call")
538 << Data->Type;
539
540 SymbolizedStackHolder FLoc(getSymbolizedLocation(Function));
541 const char *FName = FLoc.get()->info.function;
542 if (!FName)
543 FName = "(unknown)";
544 Diag(FLoc, DL_Note, "%0 defined here") << FName;
545}
546
547void __ubsan::__ubsan_handle_cfi_bad_icall(CFIBadIcallData *Data,
548 ValueHandle Function) {
549 GET_REPORT_OPTIONS(false);
550 handleCFIBadIcall(Data, Function, Opts);
551}
552
553void __ubsan::__ubsan_handle_cfi_bad_icall_abort(CFIBadIcallData *Data,
554 ValueHandle Function) {
555 GET_REPORT_OPTIONS(true);
556 handleCFIBadIcall(Data, Function, Opts);
1a4d82fc
JJ
557 Die();
558}
92a42be0
SL
559
560#endif // CAN_SANITIZE_UB