BuiltinFunctionChecker.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. //=== BuiltinFunctionChecker.cpp --------------------------------*- C++ -*-===//
  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. // This checker evaluates clang builtin functions.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #include "clang/Basic/Builtins.h"
  13. #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
  14. #include "clang/StaticAnalyzer/Core/Checker.h"
  15. #include "clang/StaticAnalyzer/Core/CheckerManager.h"
  16. #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
  17. #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
  18. #include "clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h"
  19. using namespace clang;
  20. using namespace ento;
  21. namespace {
  22. class BuiltinFunctionChecker : public Checker<eval::Call> {
  23. public:
  24. bool evalCall(const CallEvent &Call, CheckerContext &C) const;
  25. };
  26. }
  27. bool BuiltinFunctionChecker::evalCall(const CallEvent &Call,
  28. CheckerContext &C) const {
  29. ProgramStateRef state = C.getState();
  30. const auto *FD = dyn_cast_or_null<FunctionDecl>(Call.getDecl());
  31. if (!FD)
  32. return false;
  33. const LocationContext *LCtx = C.getLocationContext();
  34. const Expr *CE = Call.getOriginExpr();
  35. switch (FD->getBuiltinID()) {
  36. default:
  37. return false;
  38. case Builtin::BI__builtin_assume: {
  39. assert (Call.getNumArgs() > 0);
  40. SVal Arg = Call.getArgSVal(0);
  41. if (Arg.isUndef())
  42. return true; // Return true to model purity.
  43. state = state->assume(Arg.castAs<DefinedOrUnknownSVal>(), true);
  44. // FIXME: do we want to warn here? Not right now. The most reports might
  45. // come from infeasible paths, thus being false positives.
  46. if (!state) {
  47. C.generateSink(C.getState(), C.getPredecessor());
  48. return true;
  49. }
  50. C.addTransition(state);
  51. return true;
  52. }
  53. case Builtin::BI__builtin_unpredictable:
  54. case Builtin::BI__builtin_expect:
  55. case Builtin::BI__builtin_expect_with_probability:
  56. case Builtin::BI__builtin_assume_aligned:
  57. case Builtin::BI__builtin_addressof:
  58. case Builtin::BI__builtin_function_start: {
  59. // For __builtin_unpredictable, __builtin_expect,
  60. // __builtin_expect_with_probability and __builtin_assume_aligned,
  61. // just return the value of the subexpression.
  62. // __builtin_addressof is going from a reference to a pointer, but those
  63. // are represented the same way in the analyzer.
  64. assert (Call.getNumArgs() > 0);
  65. SVal Arg = Call.getArgSVal(0);
  66. C.addTransition(state->BindExpr(CE, LCtx, Arg));
  67. return true;
  68. }
  69. case Builtin::BI__builtin_alloca_with_align:
  70. case Builtin::BI__builtin_alloca: {
  71. // FIXME: Refactor into StoreManager itself?
  72. MemRegionManager& RM = C.getStoreManager().getRegionManager();
  73. const AllocaRegion* R =
  74. RM.getAllocaRegion(CE, C.blockCount(), C.getLocationContext());
  75. // Set the extent of the region in bytes. This enables us to use the
  76. // SVal of the argument directly. If we save the extent in bits, we
  77. // cannot represent values like symbol*8.
  78. auto Size = Call.getArgSVal(0);
  79. if (Size.isUndef())
  80. return true; // Return true to model purity.
  81. state = setDynamicExtent(state, R, Size.castAs<DefinedOrUnknownSVal>(),
  82. C.getSValBuilder());
  83. C.addTransition(state->BindExpr(CE, LCtx, loc::MemRegionVal(R)));
  84. return true;
  85. }
  86. case Builtin::BI__builtin_dynamic_object_size:
  87. case Builtin::BI__builtin_object_size:
  88. case Builtin::BI__builtin_constant_p: {
  89. // This must be resolvable at compile time, so we defer to the constant
  90. // evaluator for a value.
  91. SValBuilder &SVB = C.getSValBuilder();
  92. SVal V = UnknownVal();
  93. Expr::EvalResult EVResult;
  94. if (CE->EvaluateAsInt(EVResult, C.getASTContext(), Expr::SE_NoSideEffects)) {
  95. // Make sure the result has the correct type.
  96. llvm::APSInt Result = EVResult.Val.getInt();
  97. BasicValueFactory &BVF = SVB.getBasicValueFactory();
  98. BVF.getAPSIntType(CE->getType()).apply(Result);
  99. V = SVB.makeIntVal(Result);
  100. }
  101. if (FD->getBuiltinID() == Builtin::BI__builtin_constant_p) {
  102. // If we didn't manage to figure out if the value is constant or not,
  103. // it is safe to assume that it's not constant and unsafe to assume
  104. // that it's constant.
  105. if (V.isUnknown())
  106. V = SVB.makeIntVal(0, CE->getType());
  107. }
  108. C.addTransition(state->BindExpr(CE, LCtx, V));
  109. return true;
  110. }
  111. }
  112. }
  113. void ento::registerBuiltinFunctionChecker(CheckerManager &mgr) {
  114. mgr.registerChecker<BuiltinFunctionChecker>();
  115. }
  116. bool ento::shouldRegisterBuiltinFunctionChecker(const CheckerManager &mgr) {
  117. return true;
  118. }