Clang Project

clang_source_code/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp
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
13#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
14#include "clang/Basic/Builtins.h"
15#include "clang/StaticAnalyzer/Core/Checker.h"
16#include "clang/StaticAnalyzer/Core/CheckerManager.h"
17#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
18
19using namespace clang;
20using namespace ento;
21
22namespace {
23
24class BuiltinFunctionChecker : public Checker<eval::Call> {
25public:
26  bool evalCall(const CallExpr *CECheckerContext &Cconst;
27};
28
29}
30
31bool BuiltinFunctionChecker::evalCall(const CallExpr *CE,
32                                      CheckerContext &Cconst {
33  ProgramStateRef state = C.getState();
34  const FunctionDecl *FD = C.getCalleeDecl(CE);
35  const LocationContext *LCtx = C.getLocationContext();
36  if (!FD)
37    return false;
38
39  switch (FD->getBuiltinID()) {
40  default:
41    return false;
42
43  case Builtin::BI__builtin_assume: {
44    arg_begin() != CE->arg_end()", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp", 44, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert (CE->arg_begin() != CE->arg_end());
45    SVal ArgSVal = C.getSVal(CE->getArg(0));
46    if (ArgSVal.isUndef())
47      return true// Return true to model purity.
48
49    state = state->assume(ArgSVal.castAs<DefinedOrUnknownSVal>(), true);
50    // FIXME: do we want to warn here? Not right now. The most reports might
51    // come from infeasible paths, thus being false positives.
52    if (!state) {
53      C.generateSink(C.getState(), C.getPredecessor());
54      return true;
55    }
56
57    C.addTransition(state);
58    return true;
59  }
60
61  case Builtin::BI__builtin_unpredictable:
62  case Builtin::BI__builtin_expect:
63  case Builtin::BI__builtin_assume_aligned:
64  case Builtin::BI__builtin_addressof: {
65    // For __builtin_unpredictable, __builtin_expect, and
66    // __builtin_assume_aligned, just return the value of the subexpression.
67    // __builtin_addressof is going from a reference to a pointer, but those
68    // are represented the same way in the analyzer.
69    arg_begin() != CE->arg_end()", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp", 69, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert (CE->arg_begin() != CE->arg_end());
70    SVal X = C.getSVal(*(CE->arg_begin()));
71    C.addTransition(state->BindExpr(CE, LCtx, X));
72    return true;
73  }
74
75  case Builtin::BI__builtin_alloca_with_align:
76  case Builtin::BI__builtin_alloca: {
77    // FIXME: Refactor into StoreManager itself?
78    MemRegionManagerRM = C.getStoreManager().getRegionManager();
79    const AllocaRegionR =
80      RM.getAllocaRegion(CEC.blockCount(), C.getLocationContext());
81
82    // Set the extent of the region in bytes. This enables us to use the
83    // SVal of the argument directly. If we save the extent in bits, we
84    // cannot represent values like symbol*8.
85    auto Size = C.getSVal(*(CE->arg_begin())).castAs<DefinedOrUnknownSVal>();
86
87    SValBuildersvalBuilder = C.getSValBuilder();
88    DefinedOrUnknownSVal Extent = R->getExtent(svalBuilder);
89    DefinedOrUnknownSVal extentMatchesSizeArg =
90      svalBuilder.evalEQ(state, Extent, Size);
91    state = state->assume(extentMatchesSizeArg, true);
92     (0) . __assert_fail ("state && \"The region should not have any previous constraints\"", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp", 92, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(state && "The region should not have any previous constraints");
93
94    C.addTransition(state->BindExpr(CE, LCtx, loc::MemRegionVal(R)));
95    return true;
96  }
97
98  case Builtin::BI__builtin_dynamic_object_size:
99  case Builtin::BI__builtin_object_size:
100  case Builtin::BI__builtin_constant_p: {
101    // This must be resolvable at compile time, so we defer to the constant
102    // evaluator for a value.
103    SVal V = UnknownVal();
104    Expr::EvalResult EVResult;
105    if (CE->EvaluateAsInt(EVResultC.getASTContext(), Expr::SE_NoSideEffects)) {
106      // Make sure the result has the correct type.
107      llvm::APSInt Result = EVResult.Val.getInt();
108      SValBuilder &SVB = C.getSValBuilder();
109      BasicValueFactory &BVF = SVB.getBasicValueFactory();
110      BVF.getAPSIntType(CE->getType()).apply(Result);
111      V = SVB.makeIntVal(Result);
112    }
113
114    C.addTransition(state->BindExpr(CE, LCtx, V));
115    return true;
116  }
117  }
118}
119
120void ento::registerBuiltinFunctionChecker(CheckerManager &mgr) {
121  mgr.registerChecker<BuiltinFunctionChecker>();
122}
123
124bool ento::shouldRegisterBuiltinFunctionChecker(const LangOptions &LO) {
125  return true;
126}
127