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_object_size: 99 case Builtin::BI__builtin_constant_p: { 100 // This must be resolvable at compile time, so we defer to the constant 101 // evaluator for a value. 102 SVal V = UnknownVal(); 103 Expr::EvalResult EVResult; 104 if (CE->EvaluateAsInt(EVResult, C.getASTContext(), Expr::SE_NoSideEffects)) { 105 // Make sure the result has the correct type. 106 llvm::APSInt Result = EVResult.Val.getInt(); 107 SValBuilder &SVB = C.getSValBuilder(); 108 BasicValueFactory &BVF = SVB.getBasicValueFactory(); 109 BVF.getAPSIntType(CE->getType()).apply(Result); 110 V = SVB.makeIntVal(Result); 111 } 112 113 C.addTransition(state->BindExpr(CE, LCtx, V)); 114 return true; 115 } 116 } 117 } 118 119 void ento::registerBuiltinFunctionChecker(CheckerManager &mgr) { 120 mgr.registerChecker<BuiltinFunctionChecker>(); 121 } 122