]> git.ipfire.org Git - thirdparty/gcc.git/blob - libsanitizer/ubsan/ubsan_handlers.cpp
Fix formatting in rs6000.c.
[thirdparty/gcc.git] / libsanitizer / ubsan / ubsan_handlers.cpp
1 //===-- ubsan_handlers.cpp ------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Error logging entry points for the UBSan runtime.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "ubsan_platform.h"
14 #if CAN_SANITIZE_UB
15 #include "ubsan_handlers.h"
16 #include "ubsan_diag.h"
17 #include "ubsan_flags.h"
18 #include "ubsan_monitor.h"
19
20 #include "sanitizer_common/sanitizer_common.h"
21
22 using namespace __sanitizer;
23 using namespace __ubsan;
24
25 namespace __ubsan {
26 bool ignoreReport(SourceLocation SLoc, ReportOptions Opts, ErrorType ET) {
27 // We are not allowed to skip error report: if we are in unrecoverable
28 // handler, we have to terminate the program right now, and therefore
29 // have to print some diagnostic.
30 //
31 // Even if source location is disabled, it doesn't mean that we have
32 // already report an error to the user: some concurrently running
33 // thread could have acquired it, but not yet printed the report.
34 if (Opts.FromUnrecoverableHandler)
35 return false;
36 return SLoc.isDisabled() || IsPCSuppressed(ET, Opts.pc, SLoc.getFilename());
37 }
38
39 /// Situations in which we might emit a check for the suitability of a
40 /// pointer or glvalue. Needs to be kept in sync with CodeGenFunction.h in
41 /// clang.
42 enum TypeCheckKind {
43 /// Checking the operand of a load. Must be suitably sized and aligned.
44 TCK_Load,
45 /// Checking the destination of a store. Must be suitably sized and aligned.
46 TCK_Store,
47 /// Checking the bound value in a reference binding. Must be suitably sized
48 /// and aligned, but is not required to refer to an object (until the
49 /// reference is used), per core issue 453.
50 TCK_ReferenceBinding,
51 /// Checking the object expression in a non-static data member access. Must
52 /// be an object within its lifetime.
53 TCK_MemberAccess,
54 /// Checking the 'this' pointer for a call to a non-static member function.
55 /// Must be an object within its lifetime.
56 TCK_MemberCall,
57 /// Checking the 'this' pointer for a constructor call.
58 TCK_ConstructorCall,
59 /// Checking the operand of a static_cast to a derived pointer type. Must be
60 /// null or an object within its lifetime.
61 TCK_DowncastPointer,
62 /// Checking the operand of a static_cast to a derived reference type. Must
63 /// be an object within its lifetime.
64 TCK_DowncastReference,
65 /// Checking the operand of a cast to a base object. Must be suitably sized
66 /// and aligned.
67 TCK_Upcast,
68 /// Checking the operand of a cast to a virtual base object. Must be an
69 /// object within its lifetime.
70 TCK_UpcastToVirtualBase,
71 /// Checking the value assigned to a _Nonnull pointer. Must not be null.
72 TCK_NonnullAssign,
73 /// Checking the operand of a dynamic_cast or a typeid expression. Must be
74 /// null or an object within its lifetime.
75 TCK_DynamicOperation
76 };
77
78 const char *TypeCheckKinds[] = {
79 "load of", "store to", "reference binding to", "member access within",
80 "member call on", "constructor call on", "downcast of", "downcast of",
81 "upcast of", "cast to virtual base of", "_Nonnull binding to",
82 "dynamic operation on"};
83 }
84
85 static void handleTypeMismatchImpl(TypeMismatchData *Data, ValueHandle Pointer,
86 ReportOptions Opts) {
87 Location Loc = Data->Loc.acquire();
88
89 uptr Alignment = (uptr)1 << Data->LogAlignment;
90 ErrorType ET;
91 if (!Pointer)
92 ET = (Data->TypeCheckKind == TCK_NonnullAssign)
93 ? ErrorType::NullPointerUseWithNullability
94 : ErrorType::NullPointerUse;
95 else if (Pointer & (Alignment - 1))
96 ET = ErrorType::MisalignedPointerUse;
97 else
98 ET = ErrorType::InsufficientObjectSize;
99
100 // Use the SourceLocation from Data to track deduplication, even if it's
101 // invalid.
102 if (ignoreReport(Loc.getSourceLocation(), Opts, ET))
103 return;
104
105 SymbolizedStackHolder FallbackLoc;
106 if (Data->Loc.isInvalid()) {
107 FallbackLoc.reset(getCallerLocation(Opts.pc));
108 Loc = FallbackLoc;
109 }
110
111 ScopedReport R(Opts, Loc, ET);
112
113 switch (ET) {
114 case ErrorType::NullPointerUse:
115 case ErrorType::NullPointerUseWithNullability:
116 Diag(Loc, DL_Error, ET, "%0 null pointer of type %1")
117 << TypeCheckKinds[Data->TypeCheckKind] << Data->Type;
118 break;
119 case ErrorType::MisalignedPointerUse:
120 Diag(Loc, DL_Error, ET, "%0 misaligned address %1 for type %3, "
121 "which requires %2 byte alignment")
122 << TypeCheckKinds[Data->TypeCheckKind] << (void *)Pointer << Alignment
123 << Data->Type;
124 break;
125 case ErrorType::InsufficientObjectSize:
126 Diag(Loc, DL_Error, ET, "%0 address %1 with insufficient space "
127 "for an object of type %2")
128 << TypeCheckKinds[Data->TypeCheckKind] << (void *)Pointer << Data->Type;
129 break;
130 default:
131 UNREACHABLE("unexpected error type!");
132 }
133
134 if (Pointer)
135 Diag(Pointer, DL_Note, ET, "pointer points here");
136 }
137
138 void __ubsan::__ubsan_handle_type_mismatch_v1(TypeMismatchData *Data,
139 ValueHandle Pointer) {
140 GET_REPORT_OPTIONS(false);
141 handleTypeMismatchImpl(Data, Pointer, Opts);
142 }
143 void __ubsan::__ubsan_handle_type_mismatch_v1_abort(TypeMismatchData *Data,
144 ValueHandle Pointer) {
145 GET_REPORT_OPTIONS(true);
146 handleTypeMismatchImpl(Data, Pointer, Opts);
147 Die();
148 }
149
150 static void handleAlignmentAssumptionImpl(AlignmentAssumptionData *Data,
151 ValueHandle Pointer,
152 ValueHandle Alignment,
153 ValueHandle Offset,
154 ReportOptions Opts) {
155 Location Loc = Data->Loc.acquire();
156 SourceLocation AssumptionLoc = Data->AssumptionLoc.acquire();
157
158 ErrorType ET = ErrorType::AlignmentAssumption;
159
160 if (ignoreReport(Loc.getSourceLocation(), Opts, ET))
161 return;
162
163 ScopedReport R(Opts, Loc, ET);
164
165 uptr RealPointer = Pointer - Offset;
166 uptr LSB = LeastSignificantSetBitIndex(RealPointer);
167 uptr ActualAlignment = uptr(1) << LSB;
168
169 uptr Mask = Alignment - 1;
170 uptr MisAlignmentOffset = RealPointer & Mask;
171
172 if (!Offset) {
173 Diag(Loc, DL_Error, ET,
174 "assumption of %0 byte alignment for pointer of type %1 failed")
175 << Alignment << Data->Type;
176 } else {
177 Diag(Loc, DL_Error, ET,
178 "assumption of %0 byte alignment (with offset of %1 byte) for pointer "
179 "of type %2 failed")
180 << Alignment << Offset << Data->Type;
181 }
182
183 if (!AssumptionLoc.isInvalid())
184 Diag(AssumptionLoc, DL_Note, ET, "alignment assumption was specified here");
185
186 Diag(RealPointer, DL_Note, ET,
187 "%0address is %1 aligned, misalignment offset is %2 bytes")
188 << (Offset ? "offset " : "") << ActualAlignment << MisAlignmentOffset;
189 }
190
191 void __ubsan::__ubsan_handle_alignment_assumption(AlignmentAssumptionData *Data,
192 ValueHandle Pointer,
193 ValueHandle Alignment,
194 ValueHandle Offset) {
195 GET_REPORT_OPTIONS(false);
196 handleAlignmentAssumptionImpl(Data, Pointer, Alignment, Offset, Opts);
197 }
198 void __ubsan::__ubsan_handle_alignment_assumption_abort(
199 AlignmentAssumptionData *Data, ValueHandle Pointer, ValueHandle Alignment,
200 ValueHandle Offset) {
201 GET_REPORT_OPTIONS(true);
202 handleAlignmentAssumptionImpl(Data, Pointer, Alignment, Offset, Opts);
203 Die();
204 }
205
206 /// \brief Common diagnostic emission for various forms of integer overflow.
207 template <typename T>
208 static void handleIntegerOverflowImpl(OverflowData *Data, ValueHandle LHS,
209 const char *Operator, T RHS,
210 ReportOptions Opts) {
211 SourceLocation Loc = Data->Loc.acquire();
212 bool IsSigned = Data->Type.isSignedIntegerTy();
213 ErrorType ET = IsSigned ? ErrorType::SignedIntegerOverflow
214 : ErrorType::UnsignedIntegerOverflow;
215
216 if (ignoreReport(Loc, Opts, ET))
217 return;
218
219 // If this is an unsigned overflow in non-fatal mode, potentially ignore it.
220 if (!IsSigned && !Opts.FromUnrecoverableHandler &&
221 flags()->silence_unsigned_overflow)
222 return;
223
224 ScopedReport R(Opts, Loc, ET);
225
226 Diag(Loc, DL_Error, ET, "%0 integer overflow: "
227 "%1 %2 %3 cannot be represented in type %4")
228 << (IsSigned ? "signed" : "unsigned") << Value(Data->Type, LHS)
229 << Operator << RHS << Data->Type;
230 }
231
232 #define UBSAN_OVERFLOW_HANDLER(handler_name, op, unrecoverable) \
233 void __ubsan::handler_name(OverflowData *Data, ValueHandle LHS, \
234 ValueHandle RHS) { \
235 GET_REPORT_OPTIONS(unrecoverable); \
236 handleIntegerOverflowImpl(Data, LHS, op, Value(Data->Type, RHS), Opts); \
237 if (unrecoverable) \
238 Die(); \
239 }
240
241 UBSAN_OVERFLOW_HANDLER(__ubsan_handle_add_overflow, "+", false)
242 UBSAN_OVERFLOW_HANDLER(__ubsan_handle_add_overflow_abort, "+", true)
243 UBSAN_OVERFLOW_HANDLER(__ubsan_handle_sub_overflow, "-", false)
244 UBSAN_OVERFLOW_HANDLER(__ubsan_handle_sub_overflow_abort, "-", true)
245 UBSAN_OVERFLOW_HANDLER(__ubsan_handle_mul_overflow, "*", false)
246 UBSAN_OVERFLOW_HANDLER(__ubsan_handle_mul_overflow_abort, "*", true)
247
248 static void handleNegateOverflowImpl(OverflowData *Data, ValueHandle OldVal,
249 ReportOptions Opts) {
250 SourceLocation Loc = Data->Loc.acquire();
251 bool IsSigned = Data->Type.isSignedIntegerTy();
252 ErrorType ET = IsSigned ? ErrorType::SignedIntegerOverflow
253 : ErrorType::UnsignedIntegerOverflow;
254
255 if (ignoreReport(Loc, Opts, ET))
256 return;
257
258 if (!IsSigned && flags()->silence_unsigned_overflow)
259 return;
260
261 ScopedReport R(Opts, Loc, ET);
262
263 if (IsSigned)
264 Diag(Loc, DL_Error, ET,
265 "negation of %0 cannot be represented in type %1; "
266 "cast to an unsigned type to negate this value to itself")
267 << Value(Data->Type, OldVal) << Data->Type;
268 else
269 Diag(Loc, DL_Error, ET, "negation of %0 cannot be represented in type %1")
270 << Value(Data->Type, OldVal) << Data->Type;
271 }
272
273 void __ubsan::__ubsan_handle_negate_overflow(OverflowData *Data,
274 ValueHandle OldVal) {
275 GET_REPORT_OPTIONS(false);
276 handleNegateOverflowImpl(Data, OldVal, Opts);
277 }
278 void __ubsan::__ubsan_handle_negate_overflow_abort(OverflowData *Data,
279 ValueHandle OldVal) {
280 GET_REPORT_OPTIONS(true);
281 handleNegateOverflowImpl(Data, OldVal, Opts);
282 Die();
283 }
284
285 static void handleDivremOverflowImpl(OverflowData *Data, ValueHandle LHS,
286 ValueHandle RHS, ReportOptions Opts) {
287 SourceLocation Loc = Data->Loc.acquire();
288 Value LHSVal(Data->Type, LHS);
289 Value RHSVal(Data->Type, RHS);
290
291 ErrorType ET;
292 if (RHSVal.isMinusOne())
293 ET = ErrorType::SignedIntegerOverflow;
294 else if (Data->Type.isIntegerTy())
295 ET = ErrorType::IntegerDivideByZero;
296 else
297 ET = ErrorType::FloatDivideByZero;
298
299 if (ignoreReport(Loc, Opts, ET))
300 return;
301
302 ScopedReport R(Opts, Loc, ET);
303
304 switch (ET) {
305 case ErrorType::SignedIntegerOverflow:
306 Diag(Loc, DL_Error, ET,
307 "division of %0 by -1 cannot be represented in type %1")
308 << LHSVal << Data->Type;
309 break;
310 default:
311 Diag(Loc, DL_Error, ET, "division by zero");
312 break;
313 }
314 }
315
316 void __ubsan::__ubsan_handle_divrem_overflow(OverflowData *Data,
317 ValueHandle LHS, ValueHandle RHS) {
318 GET_REPORT_OPTIONS(false);
319 handleDivremOverflowImpl(Data, LHS, RHS, Opts);
320 }
321 void __ubsan::__ubsan_handle_divrem_overflow_abort(OverflowData *Data,
322 ValueHandle LHS,
323 ValueHandle RHS) {
324 GET_REPORT_OPTIONS(true);
325 handleDivremOverflowImpl(Data, LHS, RHS, Opts);
326 Die();
327 }
328
329 static void handleShiftOutOfBoundsImpl(ShiftOutOfBoundsData *Data,
330 ValueHandle LHS, ValueHandle RHS,
331 ReportOptions Opts) {
332 SourceLocation Loc = Data->Loc.acquire();
333 Value LHSVal(Data->LHSType, LHS);
334 Value RHSVal(Data->RHSType, RHS);
335
336 ErrorType ET;
337 if (RHSVal.isNegative() ||
338 RHSVal.getPositiveIntValue() >= Data->LHSType.getIntegerBitWidth())
339 ET = ErrorType::InvalidShiftExponent;
340 else
341 ET = ErrorType::InvalidShiftBase;
342
343 if (ignoreReport(Loc, Opts, ET))
344 return;
345
346 ScopedReport R(Opts, Loc, ET);
347
348 if (ET == ErrorType::InvalidShiftExponent) {
349 if (RHSVal.isNegative())
350 Diag(Loc, DL_Error, ET, "shift exponent %0 is negative") << RHSVal;
351 else
352 Diag(Loc, DL_Error, ET,
353 "shift exponent %0 is too large for %1-bit type %2")
354 << RHSVal << Data->LHSType.getIntegerBitWidth() << Data->LHSType;
355 } else {
356 if (LHSVal.isNegative())
357 Diag(Loc, DL_Error, ET, "left shift of negative value %0") << LHSVal;
358 else
359 Diag(Loc, DL_Error, ET,
360 "left shift of %0 by %1 places cannot be represented in type %2")
361 << LHSVal << RHSVal << Data->LHSType;
362 }
363 }
364
365 void __ubsan::__ubsan_handle_shift_out_of_bounds(ShiftOutOfBoundsData *Data,
366 ValueHandle LHS,
367 ValueHandle RHS) {
368 GET_REPORT_OPTIONS(false);
369 handleShiftOutOfBoundsImpl(Data, LHS, RHS, Opts);
370 }
371 void __ubsan::__ubsan_handle_shift_out_of_bounds_abort(
372 ShiftOutOfBoundsData *Data,
373 ValueHandle LHS,
374 ValueHandle RHS) {
375 GET_REPORT_OPTIONS(true);
376 handleShiftOutOfBoundsImpl(Data, LHS, RHS, Opts);
377 Die();
378 }
379
380 static void handleOutOfBoundsImpl(OutOfBoundsData *Data, ValueHandle Index,
381 ReportOptions Opts) {
382 SourceLocation Loc = Data->Loc.acquire();
383 ErrorType ET = ErrorType::OutOfBoundsIndex;
384
385 if (ignoreReport(Loc, Opts, ET))
386 return;
387
388 ScopedReport R(Opts, Loc, ET);
389
390 Value IndexVal(Data->IndexType, Index);
391 Diag(Loc, DL_Error, ET, "index %0 out of bounds for type %1")
392 << IndexVal << Data->ArrayType;
393 }
394
395 void __ubsan::__ubsan_handle_out_of_bounds(OutOfBoundsData *Data,
396 ValueHandle Index) {
397 GET_REPORT_OPTIONS(false);
398 handleOutOfBoundsImpl(Data, Index, Opts);
399 }
400 void __ubsan::__ubsan_handle_out_of_bounds_abort(OutOfBoundsData *Data,
401 ValueHandle Index) {
402 GET_REPORT_OPTIONS(true);
403 handleOutOfBoundsImpl(Data, Index, Opts);
404 Die();
405 }
406
407 static void handleBuiltinUnreachableImpl(UnreachableData *Data,
408 ReportOptions Opts) {
409 ErrorType ET = ErrorType::UnreachableCall;
410 ScopedReport R(Opts, Data->Loc, ET);
411 Diag(Data->Loc, DL_Error, ET,
412 "execution reached an unreachable program point");
413 }
414
415 void __ubsan::__ubsan_handle_builtin_unreachable(UnreachableData *Data) {
416 GET_REPORT_OPTIONS(true);
417 handleBuiltinUnreachableImpl(Data, Opts);
418 Die();
419 }
420
421 static void handleMissingReturnImpl(UnreachableData *Data, ReportOptions Opts) {
422 ErrorType ET = ErrorType::MissingReturn;
423 ScopedReport R(Opts, Data->Loc, ET);
424 Diag(Data->Loc, DL_Error, ET,
425 "execution reached the end of a value-returning function "
426 "without returning a value");
427 }
428
429 void __ubsan::__ubsan_handle_missing_return(UnreachableData *Data) {
430 GET_REPORT_OPTIONS(true);
431 handleMissingReturnImpl(Data, Opts);
432 Die();
433 }
434
435 static void handleVLABoundNotPositive(VLABoundData *Data, ValueHandle Bound,
436 ReportOptions Opts) {
437 SourceLocation Loc = Data->Loc.acquire();
438 ErrorType ET = ErrorType::NonPositiveVLAIndex;
439
440 if (ignoreReport(Loc, Opts, ET))
441 return;
442
443 ScopedReport R(Opts, Loc, ET);
444
445 Diag(Loc, DL_Error, ET, "variable length array bound evaluates to "
446 "non-positive value %0")
447 << Value(Data->Type, Bound);
448 }
449
450 void __ubsan::__ubsan_handle_vla_bound_not_positive(VLABoundData *Data,
451 ValueHandle Bound) {
452 GET_REPORT_OPTIONS(false);
453 handleVLABoundNotPositive(Data, Bound, Opts);
454 }
455 void __ubsan::__ubsan_handle_vla_bound_not_positive_abort(VLABoundData *Data,
456 ValueHandle Bound) {
457 GET_REPORT_OPTIONS(true);
458 handleVLABoundNotPositive(Data, Bound, Opts);
459 Die();
460 }
461
462 static bool looksLikeFloatCastOverflowDataV1(void *Data) {
463 // First field is either a pointer to filename or a pointer to a
464 // TypeDescriptor.
465 u8 *FilenameOrTypeDescriptor;
466 internal_memcpy(&FilenameOrTypeDescriptor, Data,
467 sizeof(FilenameOrTypeDescriptor));
468
469 // Heuristic: For float_cast_overflow, the TypeKind will be either TK_Integer
470 // (0x0), TK_Float (0x1) or TK_Unknown (0xff). If both types are known,
471 // adding both bytes will be 0 or 1 (for BE or LE). If it were a filename,
472 // adding two printable characters will not yield such a value. Otherwise,
473 // if one of them is 0xff, this is most likely TK_Unknown type descriptor.
474 u16 MaybeFromTypeKind =
475 FilenameOrTypeDescriptor[0] + FilenameOrTypeDescriptor[1];
476 return MaybeFromTypeKind < 2 || FilenameOrTypeDescriptor[0] == 0xff ||
477 FilenameOrTypeDescriptor[1] == 0xff;
478 }
479
480 static void handleFloatCastOverflow(void *DataPtr, ValueHandle From,
481 ReportOptions Opts) {
482 SymbolizedStackHolder CallerLoc;
483 Location Loc;
484 const TypeDescriptor *FromType, *ToType;
485 ErrorType ET = ErrorType::FloatCastOverflow;
486
487 if (looksLikeFloatCastOverflowDataV1(DataPtr)) {
488 auto Data = reinterpret_cast<FloatCastOverflowData *>(DataPtr);
489 CallerLoc.reset(getCallerLocation(Opts.pc));
490 Loc = CallerLoc;
491 FromType = &Data->FromType;
492 ToType = &Data->ToType;
493 } else {
494 auto Data = reinterpret_cast<FloatCastOverflowDataV2 *>(DataPtr);
495 SourceLocation SLoc = Data->Loc.acquire();
496 if (ignoreReport(SLoc, Opts, ET))
497 return;
498 Loc = SLoc;
499 FromType = &Data->FromType;
500 ToType = &Data->ToType;
501 }
502
503 ScopedReport R(Opts, Loc, ET);
504
505 Diag(Loc, DL_Error, ET,
506 "%0 is outside the range of representable values of type %2")
507 << Value(*FromType, From) << *FromType << *ToType;
508 }
509
510 void __ubsan::__ubsan_handle_float_cast_overflow(void *Data, ValueHandle From) {
511 GET_REPORT_OPTIONS(false);
512 handleFloatCastOverflow(Data, From, Opts);
513 }
514 void __ubsan::__ubsan_handle_float_cast_overflow_abort(void *Data,
515 ValueHandle From) {
516 GET_REPORT_OPTIONS(true);
517 handleFloatCastOverflow(Data, From, Opts);
518 Die();
519 }
520
521 static void handleLoadInvalidValue(InvalidValueData *Data, ValueHandle Val,
522 ReportOptions Opts) {
523 SourceLocation Loc = Data->Loc.acquire();
524 // This check could be more precise if we used different handlers for
525 // -fsanitize=bool and -fsanitize=enum.
526 bool IsBool = (0 == internal_strcmp(Data->Type.getTypeName(), "'bool'")) ||
527 (0 == internal_strncmp(Data->Type.getTypeName(), "'BOOL'", 6));
528 ErrorType ET =
529 IsBool ? ErrorType::InvalidBoolLoad : ErrorType::InvalidEnumLoad;
530
531 if (ignoreReport(Loc, Opts, ET))
532 return;
533
534 ScopedReport R(Opts, Loc, ET);
535
536 Diag(Loc, DL_Error, ET,
537 "load of value %0, which is not a valid value for type %1")
538 << Value(Data->Type, Val) << Data->Type;
539 }
540
541 void __ubsan::__ubsan_handle_load_invalid_value(InvalidValueData *Data,
542 ValueHandle Val) {
543 GET_REPORT_OPTIONS(false);
544 handleLoadInvalidValue(Data, Val, Opts);
545 }
546 void __ubsan::__ubsan_handle_load_invalid_value_abort(InvalidValueData *Data,
547 ValueHandle Val) {
548 GET_REPORT_OPTIONS(true);
549 handleLoadInvalidValue(Data, Val, Opts);
550 Die();
551 }
552
553 static void handleImplicitConversion(ImplicitConversionData *Data,
554 ReportOptions Opts, ValueHandle Src,
555 ValueHandle Dst) {
556 SourceLocation Loc = Data->Loc.acquire();
557 ErrorType ET = ErrorType::GenericUB;
558
559 const TypeDescriptor &SrcTy = Data->FromType;
560 const TypeDescriptor &DstTy = Data->ToType;
561
562 bool SrcSigned = SrcTy.isSignedIntegerTy();
563 bool DstSigned = DstTy.isSignedIntegerTy();
564
565 switch (Data->Kind) {
566 case ICCK_IntegerTruncation: { // Legacy, no longer used.
567 // Let's figure out what it should be as per the new types, and upgrade.
568 // If both types are unsigned, then it's an unsigned truncation.
569 // Else, it is a signed truncation.
570 if (!SrcSigned && !DstSigned) {
571 ET = ErrorType::ImplicitUnsignedIntegerTruncation;
572 } else {
573 ET = ErrorType::ImplicitSignedIntegerTruncation;
574 }
575 break;
576 }
577 case ICCK_UnsignedIntegerTruncation:
578 ET = ErrorType::ImplicitUnsignedIntegerTruncation;
579 break;
580 case ICCK_SignedIntegerTruncation:
581 ET = ErrorType::ImplicitSignedIntegerTruncation;
582 break;
583 case ICCK_IntegerSignChange:
584 ET = ErrorType::ImplicitIntegerSignChange;
585 break;
586 case ICCK_SignedIntegerTruncationOrSignChange:
587 ET = ErrorType::ImplicitSignedIntegerTruncationOrSignChange;
588 break;
589 }
590
591 if (ignoreReport(Loc, Opts, ET))
592 return;
593
594 ScopedReport R(Opts, Loc, ET);
595
596 // FIXME: is it possible to dump the values as hex with fixed width?
597
598 Diag(Loc, DL_Error, ET,
599 "implicit conversion from type %0 of value %1 (%2-bit, %3signed) to "
600 "type %4 changed the value to %5 (%6-bit, %7signed)")
601 << SrcTy << Value(SrcTy, Src) << SrcTy.getIntegerBitWidth()
602 << (SrcSigned ? "" : "un") << DstTy << Value(DstTy, Dst)
603 << DstTy.getIntegerBitWidth() << (DstSigned ? "" : "un");
604 }
605
606 void __ubsan::__ubsan_handle_implicit_conversion(ImplicitConversionData *Data,
607 ValueHandle Src,
608 ValueHandle Dst) {
609 GET_REPORT_OPTIONS(false);
610 handleImplicitConversion(Data, Opts, Src, Dst);
611 }
612 void __ubsan::__ubsan_handle_implicit_conversion_abort(
613 ImplicitConversionData *Data, ValueHandle Src, ValueHandle Dst) {
614 GET_REPORT_OPTIONS(true);
615 handleImplicitConversion(Data, Opts, Src, Dst);
616 Die();
617 }
618
619 static void handleInvalidBuiltin(InvalidBuiltinData *Data, ReportOptions Opts) {
620 SourceLocation Loc = Data->Loc.acquire();
621 ErrorType ET = ErrorType::InvalidBuiltin;
622
623 if (ignoreReport(Loc, Opts, ET))
624 return;
625
626 ScopedReport R(Opts, Loc, ET);
627
628 Diag(Loc, DL_Error, ET,
629 "passing zero to %0, which is not a valid argument")
630 << ((Data->Kind == BCK_CTZPassedZero) ? "ctz()" : "clz()");
631 }
632
633 void __ubsan::__ubsan_handle_invalid_builtin(InvalidBuiltinData *Data) {
634 GET_REPORT_OPTIONS(true);
635 handleInvalidBuiltin(Data, Opts);
636 }
637 void __ubsan::__ubsan_handle_invalid_builtin_abort(InvalidBuiltinData *Data) {
638 GET_REPORT_OPTIONS(true);
639 handleInvalidBuiltin(Data, Opts);
640 Die();
641 }
642
643 static void handleNonNullReturn(NonNullReturnData *Data, SourceLocation *LocPtr,
644 ReportOptions Opts, bool IsAttr) {
645 if (!LocPtr)
646 UNREACHABLE("source location pointer is null!");
647
648 SourceLocation Loc = LocPtr->acquire();
649 ErrorType ET = IsAttr ? ErrorType::InvalidNullReturn
650 : ErrorType::InvalidNullReturnWithNullability;
651
652 if (ignoreReport(Loc, Opts, ET))
653 return;
654
655 ScopedReport R(Opts, Loc, ET);
656
657 Diag(Loc, DL_Error, ET,
658 "null pointer returned from function declared to never return null");
659 if (!Data->AttrLoc.isInvalid())
660 Diag(Data->AttrLoc, DL_Note, ET, "%0 specified here")
661 << (IsAttr ? "returns_nonnull attribute"
662 : "_Nonnull return type annotation");
663 }
664
665 void __ubsan::__ubsan_handle_nonnull_return_v1(NonNullReturnData *Data,
666 SourceLocation *LocPtr) {
667 GET_REPORT_OPTIONS(false);
668 handleNonNullReturn(Data, LocPtr, Opts, true);
669 }
670
671 void __ubsan::__ubsan_handle_nonnull_return_v1_abort(NonNullReturnData *Data,
672 SourceLocation *LocPtr) {
673 GET_REPORT_OPTIONS(true);
674 handleNonNullReturn(Data, LocPtr, Opts, true);
675 Die();
676 }
677
678 void __ubsan::__ubsan_handle_nullability_return_v1(NonNullReturnData *Data,
679 SourceLocation *LocPtr) {
680 GET_REPORT_OPTIONS(false);
681 handleNonNullReturn(Data, LocPtr, Opts, false);
682 }
683
684 void __ubsan::__ubsan_handle_nullability_return_v1_abort(
685 NonNullReturnData *Data, SourceLocation *LocPtr) {
686 GET_REPORT_OPTIONS(true);
687 handleNonNullReturn(Data, LocPtr, Opts, false);
688 Die();
689 }
690
691 static void handleNonNullArg(NonNullArgData *Data, ReportOptions Opts,
692 bool IsAttr) {
693 SourceLocation Loc = Data->Loc.acquire();
694 ErrorType ET = IsAttr ? ErrorType::InvalidNullArgument
695 : ErrorType::InvalidNullArgumentWithNullability;
696
697 if (ignoreReport(Loc, Opts, ET))
698 return;
699
700 ScopedReport R(Opts, Loc, ET);
701
702 Diag(Loc, DL_Error, ET,
703 "null pointer passed as argument %0, which is declared to "
704 "never be null")
705 << Data->ArgIndex;
706 if (!Data->AttrLoc.isInvalid())
707 Diag(Data->AttrLoc, DL_Note, ET, "%0 specified here")
708 << (IsAttr ? "nonnull attribute" : "_Nonnull type annotation");
709 }
710
711 void __ubsan::__ubsan_handle_nonnull_arg(NonNullArgData *Data) {
712 GET_REPORT_OPTIONS(false);
713 handleNonNullArg(Data, Opts, true);
714 }
715
716 void __ubsan::__ubsan_handle_nonnull_arg_abort(NonNullArgData *Data) {
717 GET_REPORT_OPTIONS(true);
718 handleNonNullArg(Data, Opts, true);
719 Die();
720 }
721
722 void __ubsan::__ubsan_handle_nullability_arg(NonNullArgData *Data) {
723 GET_REPORT_OPTIONS(false);
724 handleNonNullArg(Data, Opts, false);
725 }
726
727 void __ubsan::__ubsan_handle_nullability_arg_abort(NonNullArgData *Data) {
728 GET_REPORT_OPTIONS(true);
729 handleNonNullArg(Data, Opts, false);
730 Die();
731 }
732
733 static void handlePointerOverflowImpl(PointerOverflowData *Data,
734 ValueHandle Base,
735 ValueHandle Result,
736 ReportOptions Opts) {
737 SourceLocation Loc = Data->Loc.acquire();
738 ErrorType ET;
739
740 if (Base == 0 && Result == 0)
741 ET = ErrorType::NullptrWithOffset;
742 else if (Base == 0 && Result != 0)
743 ET = ErrorType::NullptrWithNonZeroOffset;
744 else if (Base != 0 && Result == 0)
745 ET = ErrorType::NullptrAfterNonZeroOffset;
746 else
747 ET = ErrorType::PointerOverflow;
748
749 if (ignoreReport(Loc, Opts, ET))
750 return;
751
752 ScopedReport R(Opts, Loc, ET);
753
754 if (ET == ErrorType::NullptrWithOffset) {
755 Diag(Loc, DL_Error, ET, "applying zero offset to null pointer");
756 } else if (ET == ErrorType::NullptrWithNonZeroOffset) {
757 Diag(Loc, DL_Error, ET, "applying non-zero offset %0 to null pointer")
758 << Result;
759 } else if (ET == ErrorType::NullptrAfterNonZeroOffset) {
760 Diag(
761 Loc, DL_Error, ET,
762 "applying non-zero offset to non-null pointer %0 produced null pointer")
763 << (void *)Base;
764 } else if ((sptr(Base) >= 0) == (sptr(Result) >= 0)) {
765 if (Base > Result)
766 Diag(Loc, DL_Error, ET,
767 "addition of unsigned offset to %0 overflowed to %1")
768 << (void *)Base << (void *)Result;
769 else
770 Diag(Loc, DL_Error, ET,
771 "subtraction of unsigned offset from %0 overflowed to %1")
772 << (void *)Base << (void *)Result;
773 } else {
774 Diag(Loc, DL_Error, ET,
775 "pointer index expression with base %0 overflowed to %1")
776 << (void *)Base << (void *)Result;
777 }
778 }
779
780 void __ubsan::__ubsan_handle_pointer_overflow(PointerOverflowData *Data,
781 ValueHandle Base,
782 ValueHandle Result) {
783 GET_REPORT_OPTIONS(false);
784 handlePointerOverflowImpl(Data, Base, Result, Opts);
785 }
786
787 void __ubsan::__ubsan_handle_pointer_overflow_abort(PointerOverflowData *Data,
788 ValueHandle Base,
789 ValueHandle Result) {
790 GET_REPORT_OPTIONS(true);
791 handlePointerOverflowImpl(Data, Base, Result, Opts);
792 Die();
793 }
794
795 static void handleCFIBadIcall(CFICheckFailData *Data, ValueHandle Function,
796 ReportOptions Opts) {
797 if (Data->CheckKind != CFITCK_ICall && Data->CheckKind != CFITCK_NVMFCall)
798 Die();
799
800 SourceLocation Loc = Data->Loc.acquire();
801 ErrorType ET = ErrorType::CFIBadType;
802
803 if (ignoreReport(Loc, Opts, ET))
804 return;
805
806 ScopedReport R(Opts, Loc, ET);
807
808 const char *CheckKindStr = Data->CheckKind == CFITCK_NVMFCall
809 ? "non-virtual pointer to member function call"
810 : "indirect function call";
811 Diag(Loc, DL_Error, ET,
812 "control flow integrity check for type %0 failed during %1")
813 << Data->Type << CheckKindStr;
814
815 SymbolizedStackHolder FLoc(getSymbolizedLocation(Function));
816 const char *FName = FLoc.get()->info.function;
817 if (!FName)
818 FName = "(unknown)";
819 Diag(FLoc, DL_Note, ET, "%0 defined here") << FName;
820
821 // If the failure involved different DSOs for the check location and icall
822 // target, report the DSO names.
823 const char *DstModule = FLoc.get()->info.module;
824 if (!DstModule)
825 DstModule = "(unknown)";
826
827 const char *SrcModule = Symbolizer::GetOrInit()->GetModuleNameForPc(Opts.pc);
828 if (!SrcModule)
829 SrcModule = "(unknown)";
830
831 if (internal_strcmp(SrcModule, DstModule))
832 Diag(Loc, DL_Note, ET,
833 "check failed in %0, destination function located in %1")
834 << SrcModule << DstModule;
835 }
836
837 namespace __ubsan {
838
839 #ifdef UBSAN_CAN_USE_CXXABI
840
841 #ifdef _WIN32
842
843 extern "C" void __ubsan_handle_cfi_bad_type_default(CFICheckFailData *Data,
844 ValueHandle Vtable,
845 bool ValidVtable,
846 ReportOptions Opts) {
847 Die();
848 }
849
850 WIN_WEAK_ALIAS(__ubsan_handle_cfi_bad_type, __ubsan_handle_cfi_bad_type_default)
851 #else
852 SANITIZER_WEAK_ATTRIBUTE
853 #endif
854 void __ubsan_handle_cfi_bad_type(CFICheckFailData *Data, ValueHandle Vtable,
855 bool ValidVtable, ReportOptions Opts);
856
857 #else
858 void __ubsan_handle_cfi_bad_type(CFICheckFailData *Data, ValueHandle Vtable,
859 bool ValidVtable, ReportOptions Opts) {
860 Die();
861 }
862 #endif
863
864 } // namespace __ubsan
865
866 void __ubsan::__ubsan_handle_cfi_bad_icall(CFIBadIcallData *CallData,
867 ValueHandle Function) {
868 GET_REPORT_OPTIONS(false);
869 CFICheckFailData Data = {CFITCK_ICall, CallData->Loc, CallData->Type};
870 handleCFIBadIcall(&Data, Function, Opts);
871 }
872
873 void __ubsan::__ubsan_handle_cfi_bad_icall_abort(CFIBadIcallData *CallData,
874 ValueHandle Function) {
875 GET_REPORT_OPTIONS(true);
876 CFICheckFailData Data = {CFITCK_ICall, CallData->Loc, CallData->Type};
877 handleCFIBadIcall(&Data, Function, Opts);
878 Die();
879 }
880
881 void __ubsan::__ubsan_handle_cfi_check_fail(CFICheckFailData *Data,
882 ValueHandle Value,
883 uptr ValidVtable) {
884 GET_REPORT_OPTIONS(false);
885 if (Data->CheckKind == CFITCK_ICall || Data->CheckKind == CFITCK_NVMFCall)
886 handleCFIBadIcall(Data, Value, Opts);
887 else
888 __ubsan_handle_cfi_bad_type(Data, Value, ValidVtable, Opts);
889 }
890
891 void __ubsan::__ubsan_handle_cfi_check_fail_abort(CFICheckFailData *Data,
892 ValueHandle Value,
893 uptr ValidVtable) {
894 GET_REPORT_OPTIONS(true);
895 if (Data->CheckKind == CFITCK_ICall || Data->CheckKind == CFITCK_NVMFCall)
896 handleCFIBadIcall(Data, Value, Opts);
897 else
898 __ubsan_handle_cfi_bad_type(Data, Value, ValidVtable, Opts);
899 Die();
900 }
901
902 #endif // CAN_SANITIZE_UB