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 19 using namespace clang; 20 using namespace ento; 21 22 namespace { 23 24 class BuiltinFunctionChecker : public Checker<eval::Call> { 25 public: 26 bool evalCall(const CallExpr *CE, CheckerContext &C) const; 27 }; 28 29 } 30 31 bool BuiltinFunctionChecker::evalCall(const CallExpr *CE, 32 CheckerContext &C) const { 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 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 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 MemRegionManager& RM = C.getStoreManager().getRegionManager(); 79 const AllocaRegion* R = 80 RM.getAllocaRegion(CE, C.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 SValBuilder& svalBuilder = C.getSValBuilder(); 88 DefinedOrUnknownSVal Extent = R->getExtent(svalBuilder); 89 DefinedOrUnknownSVal extentMatchesSizeArg = 90 svalBuilder.evalEQ(state, Extent, Size); 91 state = state->assume(extentMatchesSizeArg, true); 92 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(EVResult, C.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 120 void ento::registerBuiltinFunctionChecker(CheckerManager &mgr) { 121 mgr.registerChecker<BuiltinFunctionChecker>(); 122 } 123 124 bool ento::shouldRegisterBuiltinFunctionChecker(const LangOptions &LO) { 125 return true; 126 } 127