ubsan_handlers.cpp 32 KB

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