CStringChecker.cpp revision a5261549754fab80e30e893d8fa706bfb31e430a
1ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose//= CStringChecker.h - Checks calls to C string functions ----------*- C++ -*-// 2ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose// 3ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose// The LLVM Compiler Infrastructure 4ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose// 5ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose// This file is distributed under the University of Illinois Open Source 6ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose// License. See LICENSE.TXT for details. 7ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose// 8ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose//===----------------------------------------------------------------------===// 9ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose// 10ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose// This defines CStringChecker, which is an assortment of checks on calls 11ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose// to functions in <string.h>. 12ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose// 13ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose//===----------------------------------------------------------------------===// 14ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 15ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose#include "GRExprEngineExperimentalChecks.h" 16ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose#include "clang/Checker/BugReporter/BugType.h" 17ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose#include "clang/Checker/PathSensitive/CheckerVisitor.h" 18a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose#include "clang/Checker/PathSensitive/GRStateTrait.h" 19ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose#include "llvm/ADT/StringSwitch.h" 20ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 21ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Roseusing namespace clang; 22ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 23ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rosenamespace { 24ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Roseclass CStringChecker : public CheckerVisitor<CStringChecker> { 2519c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose BugType *BT_Null, *BT_Bounds, *BT_Overlap, *BT_NotCString; 26ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rosepublic: 27ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose CStringChecker() 2819c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose : BT_Null(0), BT_Bounds(0), BT_Overlap(0), BT_NotCString(0) {} 29ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose static void *getTag() { static int tag; return &tag; } 30ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 31ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose bool EvalCallExpr(CheckerContext &C, const CallExpr *CE); 32a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose void PreVisitDeclStmt(CheckerContext &C, const DeclStmt *DS); 33a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose void MarkLiveSymbols(const GRState *state, SymbolReaper &SR); 34a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose void EvalDeadSymbols(CheckerContext &C, SymbolReaper &SR); 35a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose bool WantsRegionChangeUpdate(const GRState *state); 36a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 37a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose const GRState *EvalRegionChanges(const GRState *state, 38a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose const MemRegion * const *Begin, 39a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose const MemRegion * const *End, 40a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose bool*); 41ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 42d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose typedef void (CStringChecker::*FnCheck)(CheckerContext &, const CallExpr *); 43ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 44d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose void EvalMemcpy(CheckerContext &C, const CallExpr *CE); 45d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose void EvalMemmove(CheckerContext &C, const CallExpr *CE); 46d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose void EvalBcopy(CheckerContext &C, const CallExpr *CE); 47d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose void EvalCopyCommon(CheckerContext &C, const GRState *state, 48d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose const Expr *Size, const Expr *Source, const Expr *Dest, 49d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose bool Restricted = false); 50d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 51d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose void EvalMemcmp(CheckerContext &C, const CallExpr *CE); 52ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 5319c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose void EvalStrlen(CheckerContext &C, const CallExpr *CE); 5419c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 55ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Utility methods 56d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose std::pair<const GRState*, const GRState*> 57d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose AssumeZero(CheckerContext &C, const GRState *state, SVal V, QualType Ty); 58d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 59a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose SVal GetCStringLengthForRegion(CheckerContext &C, const GRState *&state, 60a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose const Expr *Ex, const MemRegion *MR); 61a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose SVal GetCStringLength(CheckerContext &C, const GRState *&state, 6219c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose const Expr *Ex, SVal Buf); 6319c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 6419c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose bool SummarizeRegion(llvm::raw_ostream& os, ASTContext& Ctx, 6519c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose const MemRegion *MR); 6619c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 6719c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose // Re-usable checks 68a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose const GRState *CheckNonNull(CheckerContext &C, const GRState *state, 69d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose const Expr *S, SVal l); 70ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const GRState *CheckLocation(CheckerContext &C, const GRState *state, 71d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose const Expr *S, SVal l); 72ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const GRState *CheckBufferAccess(CheckerContext &C, const GRState *state, 73ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const Expr *Size, 74ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const Expr *FirstBuf, 75ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const Expr *SecondBuf = NULL); 76ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const GRState *CheckOverlap(CheckerContext &C, const GRState *state, 77d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose const Expr *Size, const Expr *First, 78d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose const Expr *Second); 79ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose void EmitOverlapBug(CheckerContext &C, const GRState *state, 80ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const Stmt *First, const Stmt *Second); 81ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose}; 82a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 83a5261549754fab80e30e893d8fa706bfb31e430aJordy Roseclass CStringLength { 84a5261549754fab80e30e893d8fa706bfb31e430aJordy Rosepublic: 85a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose typedef llvm::ImmutableMap<const MemRegion *, SVal> EntryMap; 86a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose}; 87ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose} //end anonymous namespace 88ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 89a5261549754fab80e30e893d8fa706bfb31e430aJordy Rosenamespace clang { 90a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose template <> 91a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose struct GRStateTrait<CStringLength> 92a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose : public GRStatePartialTrait<CStringLength::EntryMap> { 93a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose static void *GDMIndex() { return CStringChecker::getTag(); } 94a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose }; 95a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose} 96a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 97ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rosevoid clang::RegisterCStringChecker(GRExprEngine &Eng) { 98ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose Eng.registerCheck(new CStringChecker()); 99ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose} 100ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 101d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose//===----------------------------------------------------------------------===// 102d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose// Individual checks and utility methods. 103d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose//===----------------------------------------------------------------------===// 104d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 105d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rosestd::pair<const GRState*, const GRState*> 106d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy RoseCStringChecker::AssumeZero(CheckerContext &C, const GRState *state, SVal V, 107d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose QualType Ty) { 108d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose DefinedSVal *Val = dyn_cast<DefinedSVal>(&V); 109d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (!Val) 110d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose return std::pair<const GRState*, const GRState *>(state, state); 111a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose 112a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose ValueManager &ValMgr = C.getValueManager(); 113a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose SValuator &SV = ValMgr.getSValuator(); 114a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose 115d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose DefinedOrUnknownSVal Zero = ValMgr.makeZeroVal(Ty); 116d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose DefinedOrUnknownSVal ValIsZero = SV.EvalEQ(state, *Val, Zero); 117d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 118d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose return state->Assume(ValIsZero); 119d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose} 120d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 121d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Roseconst GRState *CStringChecker::CheckNonNull(CheckerContext &C, 122d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose const GRState *state, 123d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose const Expr *S, SVal l) { 124d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // If a previous check has failed, propagate the failure. 125d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (!state) 126d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose return NULL; 127a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose 128d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose const GRState *stateNull, *stateNonNull; 129d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose llvm::tie(stateNull, stateNonNull) = AssumeZero(C, state, l, S->getType()); 130a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose 131d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (stateNull && !stateNonNull) { 132d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose ExplodedNode *N = C.GenerateSink(stateNull); 133a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose if (!N) 134a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose return NULL; 135a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose 136d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (!BT_Null) 137d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose BT_Null = new BuiltinBug("API", 138a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose "Null pointer argument in call to byte string function"); 139a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose 140a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose // Generate a report for this bug. 141d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose BuiltinBug *BT = static_cast<BuiltinBug*>(BT_Null); 142a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose EnhancedBugReport *report = new EnhancedBugReport(*BT, 143a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose BT->getDescription(), N); 144a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose 145a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose report->addRange(S->getSourceRange()); 146a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, S); 147a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose C.EmitReport(report); 148a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose return NULL; 149a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose } 150a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose 151a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose // From here on, assume that the value is non-null. 152d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose assert(stateNonNull); 153d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose return stateNonNull; 154a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose} 155a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose 156ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose// FIXME: This was originally copied from ArrayBoundChecker.cpp. Refactor? 157ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Roseconst GRState *CStringChecker::CheckLocation(CheckerContext &C, 158ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const GRState *state, 159d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose const Expr *S, SVal l) { 160d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // If a previous check has failed, propagate the failure. 161d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (!state) 162d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose return NULL; 163d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 164ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Check for out of bound array element access. 165ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const MemRegion *R = l.getAsRegion(); 166ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (!R) 167ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return state; 168ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 169ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const ElementRegion *ER = dyn_cast<ElementRegion>(R); 170ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (!ER) 171ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return state; 172ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 173018220c343c103b7dfaa117a7a474c7a7fd6d068Zhongxing Xu assert(ER->getValueType() == C.getASTContext().CharTy && 174ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose "CheckLocation should only be called with char* ElementRegions"); 175ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 176ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Get the size of the array. 177ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const SubRegion *Super = cast<SubRegion>(ER->getSuperRegion()); 178ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose ValueManager &ValMgr = C.getValueManager(); 179ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose SVal Extent = ValMgr.convertToArrayIndex(Super->getExtent(ValMgr)); 180ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose DefinedOrUnknownSVal Size = cast<DefinedOrUnknownSVal>(Extent); 181ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 182ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Get the index of the accessed element. 183ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose DefinedOrUnknownSVal &Idx = cast<DefinedOrUnknownSVal>(ER->getIndex()); 184ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 185ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const GRState *StInBound = state->AssumeInBound(Idx, Size, true); 186ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const GRState *StOutBound = state->AssumeInBound(Idx, Size, false); 187ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (StOutBound && !StInBound) { 188ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose ExplodedNode *N = C.GenerateSink(StOutBound); 189ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (!N) 190ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return NULL; 191ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 192ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (!BT_Bounds) 193ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose BT_Bounds = new BuiltinBug("Out-of-bound array access", 194ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose "Byte string function accesses out-of-bound array element " 195ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose "(buffer overflow)"); 196ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 197ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // FIXME: It would be nice to eventually make this diagnostic more clear, 198ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // e.g., by referencing the original declaration or by saying *why* this 199ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // reference is outside the range. 200ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 201ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Generate a report for this bug. 202ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose BuiltinBug *BT = static_cast<BuiltinBug*>(BT_Bounds); 203ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose RangedBugReport *report = new RangedBugReport(*BT, BT->getDescription(), N); 204ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 205ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose report->addRange(S->getSourceRange()); 206ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose C.EmitReport(report); 207ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return NULL; 208ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose } 209ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 210ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Array bound check succeeded. From this point forward the array bound 211ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // should always succeed. 212ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return StInBound; 213ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose} 214ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 215ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Roseconst GRState *CStringChecker::CheckBufferAccess(CheckerContext &C, 216ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const GRState *state, 217ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const Expr *Size, 218ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const Expr *FirstBuf, 219ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const Expr *SecondBuf) { 220d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // If a previous check has failed, propagate the failure. 221d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (!state) 222d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose return NULL; 223d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 224ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose ValueManager &VM = C.getValueManager(); 225ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose SValuator &SV = VM.getSValuator(); 226ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose ASTContext &Ctx = C.getASTContext(); 227ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 228ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose QualType SizeTy = Ctx.getSizeType(); 229ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose QualType PtrTy = Ctx.getPointerType(Ctx.CharTy); 230ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 231a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose // Check that the first buffer is non-null. 232a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose SVal BufVal = state->getSVal(FirstBuf); 233a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose state = CheckNonNull(C, state, FirstBuf, BufVal); 234a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose if (!state) 235a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose return NULL; 236a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose 237d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // Get the access length and make sure it is known. 238d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose SVal LengthVal = state->getSVal(Size); 239d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose NonLoc *Length = dyn_cast<NonLoc>(&LengthVal); 240d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (!Length) 241d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose return state; 242d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 243ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Compute the offset of the last element to be accessed: size-1. 244ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose NonLoc One = cast<NonLoc>(VM.makeIntVal(1, SizeTy)); 245ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose NonLoc LastOffset = cast<NonLoc>(SV.EvalBinOpNN(state, BinaryOperator::Sub, 246ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose *Length, One, SizeTy)); 247ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 248a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose // Check that the first buffer is sufficently long. 249b6a4026de13909c2b145166ae0b7d96cf1948f64Jordy Rose SVal BufStart = SV.EvalCast(BufVal, PtrTy, FirstBuf->getType()); 250b6a4026de13909c2b145166ae0b7d96cf1948f64Jordy Rose if (Loc *BufLoc = dyn_cast<Loc>(&BufStart)) { 251b6a4026de13909c2b145166ae0b7d96cf1948f64Jordy Rose SVal BufEnd = SV.EvalBinOpLN(state, BinaryOperator::Add, *BufLoc, 252b6a4026de13909c2b145166ae0b7d96cf1948f64Jordy Rose LastOffset, PtrTy); 253b6a4026de13909c2b145166ae0b7d96cf1948f64Jordy Rose state = CheckLocation(C, state, FirstBuf, BufEnd); 254ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 255b6a4026de13909c2b145166ae0b7d96cf1948f64Jordy Rose // If the buffer isn't large enough, abort. 256b6a4026de13909c2b145166ae0b7d96cf1948f64Jordy Rose if (!state) 257b6a4026de13909c2b145166ae0b7d96cf1948f64Jordy Rose return NULL; 258b6a4026de13909c2b145166ae0b7d96cf1948f64Jordy Rose } 259ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 260ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // If there's a second buffer, check it as well. 261ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (SecondBuf) { 262ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose BufVal = state->getSVal(SecondBuf); 263a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose state = CheckNonNull(C, state, SecondBuf, BufVal); 264a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose if (!state) 265a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose return NULL; 266a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose 267b6a4026de13909c2b145166ae0b7d96cf1948f64Jordy Rose BufStart = SV.EvalCast(BufVal, PtrTy, SecondBuf->getType()); 268b6a4026de13909c2b145166ae0b7d96cf1948f64Jordy Rose if (Loc *BufLoc = dyn_cast<Loc>(&BufStart)) { 269b6a4026de13909c2b145166ae0b7d96cf1948f64Jordy Rose SVal BufEnd = SV.EvalBinOpLN(state, BinaryOperator::Add, *BufLoc, 270b6a4026de13909c2b145166ae0b7d96cf1948f64Jordy Rose LastOffset, PtrTy); 271b6a4026de13909c2b145166ae0b7d96cf1948f64Jordy Rose state = CheckLocation(C, state, SecondBuf, BufEnd); 272b6a4026de13909c2b145166ae0b7d96cf1948f64Jordy Rose } 273ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose } 274ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 275ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Large enough or not, return this state! 276ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return state; 277ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose} 278ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 279ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Roseconst GRState *CStringChecker::CheckOverlap(CheckerContext &C, 280ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const GRState *state, 281d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose const Expr *Size, 282ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const Expr *First, 283d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose const Expr *Second) { 284ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Do a simple check for overlap: if the two arguments are from the same 285ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // buffer, see if the end of the first is greater than the start of the second 286ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // or vice versa. 287ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 288d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // If a previous check has failed, propagate the failure. 289d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (!state) 290d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose return NULL; 291d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 292ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose ValueManager &VM = state->getStateManager().getValueManager(); 293ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose SValuator &SV = VM.getSValuator(); 294ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose ASTContext &Ctx = VM.getContext(); 295ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const GRState *stateTrue, *stateFalse; 296ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 297ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Get the buffer values and make sure they're known locations. 298ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose SVal FirstVal = state->getSVal(First); 299ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose SVal SecondVal = state->getSVal(Second); 300ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 301ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose Loc *FirstLoc = dyn_cast<Loc>(&FirstVal); 302ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (!FirstLoc) 303ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return state; 304ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 305ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose Loc *SecondLoc = dyn_cast<Loc>(&SecondVal); 306ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (!SecondLoc) 307ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return state; 308ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 309ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Are the two values the same? 310ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose DefinedOrUnknownSVal EqualTest = SV.EvalEQ(state, *FirstLoc, *SecondLoc); 311ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose llvm::tie(stateTrue, stateFalse) = state->Assume(EqualTest); 312ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 313ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (stateTrue && !stateFalse) { 314ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // If the values are known to be equal, that's automatically an overlap. 315ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose EmitOverlapBug(C, stateTrue, First, Second); 316ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return NULL; 317ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose } 318ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 319ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Assume the two expressions are not equal. 320ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose assert(stateFalse); 321ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose state = stateFalse; 322ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 323ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Which value comes first? 324ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose QualType CmpTy = Ctx.IntTy; 325ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose SVal Reverse = SV.EvalBinOpLL(state, BinaryOperator::GT, 326ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose *FirstLoc, *SecondLoc, CmpTy); 327ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose DefinedOrUnknownSVal *ReverseTest = dyn_cast<DefinedOrUnknownSVal>(&Reverse); 328ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (!ReverseTest) 329ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return state; 330ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 331ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose llvm::tie(stateTrue, stateFalse) = state->Assume(*ReverseTest); 332ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 333ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (stateTrue) { 334ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (stateFalse) { 335ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // If we don't know which one comes first, we can't perform this test. 336ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return state; 337ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose } else { 338ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Switch the values so that FirstVal is before SecondVal. 339ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose Loc *tmpLoc = FirstLoc; 340ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose FirstLoc = SecondLoc; 341ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose SecondLoc = tmpLoc; 342ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 343ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Switch the Exprs as well, so that they still correspond. 344ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const Expr *tmpExpr = First; 345ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose First = Second; 346ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose Second = tmpExpr; 347ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose } 348ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose } 349ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 350ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Get the length, and make sure it too is known. 351ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose SVal LengthVal = state->getSVal(Size); 352ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose NonLoc *Length = dyn_cast<NonLoc>(&LengthVal); 353ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (!Length) 354ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return state; 355ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 356ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Convert the first buffer's start address to char*. 357ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Bail out if the cast fails. 358ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose QualType CharPtrTy = Ctx.getPointerType(Ctx.CharTy); 359ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose SVal FirstStart = SV.EvalCast(*FirstLoc, CharPtrTy, First->getType()); 360ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose Loc *FirstStartLoc = dyn_cast<Loc>(&FirstStart); 361ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (!FirstStartLoc) 362ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return state; 363ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 364ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Compute the end of the first buffer. Bail out if THAT fails. 365ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose SVal FirstEnd = SV.EvalBinOpLN(state, BinaryOperator::Add, 366ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose *FirstStartLoc, *Length, CharPtrTy); 367ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose Loc *FirstEndLoc = dyn_cast<Loc>(&FirstEnd); 368ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (!FirstEndLoc) 369ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return state; 370ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 371ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Is the end of the first buffer past the start of the second buffer? 372ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose SVal Overlap = SV.EvalBinOpLL(state, BinaryOperator::GT, 373ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose *FirstEndLoc, *SecondLoc, CmpTy); 374ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose DefinedOrUnknownSVal *OverlapTest = dyn_cast<DefinedOrUnknownSVal>(&Overlap); 375ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (!OverlapTest) 376ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return state; 377ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 378ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose llvm::tie(stateTrue, stateFalse) = state->Assume(*OverlapTest); 379ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 380ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (stateTrue && !stateFalse) { 381ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Overlap! 382ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose EmitOverlapBug(C, stateTrue, First, Second); 383ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return NULL; 384ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose } 385ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 386ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Assume the two expressions don't overlap. 387ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose assert(stateFalse); 388ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return stateFalse; 389ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose} 390ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 391ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rosevoid CStringChecker::EmitOverlapBug(CheckerContext &C, const GRState *state, 392ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const Stmt *First, const Stmt *Second) { 393ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose ExplodedNode *N = C.GenerateSink(state); 394ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (!N) 395ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return; 396ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 397ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (!BT_Overlap) 398ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose BT_Overlap = new BugType("Unix API", "Improper arguments"); 399ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 400ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Generate a report for this bug. 401ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose RangedBugReport *report = 402ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose new RangedBugReport(*BT_Overlap, 403ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose "Arguments must not be overlapping buffers", N); 404ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose report->addRange(First->getSourceRange()); 405ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose report->addRange(Second->getSourceRange()); 406ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 407ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose C.EmitReport(report); 408ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose} 409ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 410a5261549754fab80e30e893d8fa706bfb31e430aJordy RoseSVal CStringChecker::GetCStringLengthForRegion(CheckerContext &C, 411a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose const GRState *&state, 412a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose const Expr *Ex, 413a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose const MemRegion *MR) { 414a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // If there's a recorded length, go ahead and return it. 415a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose const SVal *Recorded = state->get<CStringLength>(MR); 416a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (Recorded) 417a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose return *Recorded; 418a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 419a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // Otherwise, get a new symbol and update the state. 420a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose unsigned Count = C.getNodeBuilder().getCurrentBlockCount(); 421a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose ValueManager &ValMgr = C.getValueManager(); 422a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose QualType SizeTy = ValMgr.getContext().getSizeType(); 423a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose SVal Strlen = ValMgr.getMetadataSymbolVal(getTag(), MR, Ex, SizeTy, Count); 424a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 425a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose state = state->set<CStringLength>(MR, Strlen); 426a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose return Strlen; 427a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose} 428a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 429a5261549754fab80e30e893d8fa706bfb31e430aJordy RoseSVal CStringChecker::GetCStringLength(CheckerContext &C, const GRState *&state, 43019c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose const Expr *Ex, SVal Buf) { 43119c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose const MemRegion *MR = Buf.getAsRegion(); 43219c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose if (!MR) { 43319c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose // If we can't get a region, see if it's something we /know/ isn't a 43419c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose // C string. In the context of locations, the only time we can issue such 43519c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose // a warning is for labels. 43619c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose if (loc::GotoLabel *Label = dyn_cast<loc::GotoLabel>(&Buf)) { 437a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (ExplodedNode *N = C.GenerateNode(state)) { 43819c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose if (!BT_NotCString) 43919c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose BT_NotCString = new BuiltinBug("API", 44019c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose "Argument is not a null-terminated string."); 44119c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 44219c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose llvm::SmallString<120> buf; 44319c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose llvm::raw_svector_ostream os(buf); 44419c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose os << "Argument to byte string function is the address of the label '" 44519c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose << Label->getLabel()->getID()->getName() 44619c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose << "', which is not a null-terminated string"; 44719c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 44819c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose // Generate a report for this bug. 44919c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose EnhancedBugReport *report = new EnhancedBugReport(*BT_NotCString, 45019c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose os.str(), N); 45119c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 45219c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose report->addRange(Ex->getSourceRange()); 45319c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose C.EmitReport(report); 45419c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose } 45519c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 45619c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose return UndefinedVal(); 45719c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose } 45819c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 459a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // If it's not a region and not a label, give up. 460a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose return UnknownVal(); 461a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose } 46219c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 463a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // If we have a region, strip casts from it and see if we can figure out 464a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // its length. For anything we can't figure out, just return UnknownVal. 465a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose MR = MR->StripCasts(); 466a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 467a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose switch (MR->getKind()) { 468a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose case MemRegion::StringRegionKind: { 469a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // Modifying the contents of string regions is undefined [C99 6.4.5p6], 470a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // so we can assume that the byte length is the correct C string length. 471a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose ValueManager &ValMgr = C.getValueManager(); 472a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose QualType SizeTy = ValMgr.getContext().getSizeType(); 473a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose const StringLiteral *Str = cast<StringRegion>(MR)->getStringLiteral(); 474a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose return ValMgr.makeIntVal(Str->getByteLength(), SizeTy); 475a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose } 476a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose case MemRegion::SymbolicRegionKind: 477a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose case MemRegion::AllocaRegionKind: 478a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose case MemRegion::VarRegionKind: 479a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose case MemRegion::FieldRegionKind: 480a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose case MemRegion::ObjCIvarRegionKind: 481a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose return GetCStringLengthForRegion(C, state, Ex, MR); 482a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose case MemRegion::CompoundLiteralRegionKind: 483a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // FIXME: Can we track this? Is it necessary? 484a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose return UnknownVal(); 485a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose case MemRegion::ElementRegionKind: 486a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // FIXME: How can we handle this? It's not good enough to subtract the 487a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // offset from the base string length; consider "123\x00567" and &a[5]. 488a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose return UnknownVal(); 489a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose default: 490a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // Other regions (mostly non-data) can't have a reliable C string length. 491a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // In this case, an error is emitted and UndefinedVal is returned. 492a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // The caller should always be prepared to handle this case. 493a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (ExplodedNode *N = C.GenerateNode(state)) { 494a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (!BT_NotCString) 495a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose BT_NotCString = new BuiltinBug("API", 496a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose "Argument is not a null-terminated string."); 497a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 498a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose llvm::SmallString<120> buf; 499a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose llvm::raw_svector_ostream os(buf); 500a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 501a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose os << "Argument to byte string function is "; 502a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 503a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (SummarizeRegion(os, C.getASTContext(), MR)) 504a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose os << ", which is not a null-terminated string"; 505a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose else 506a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose os << "not a null-terminated string"; 507a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 508a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // Generate a report for this bug. 509a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose EnhancedBugReport *report = new EnhancedBugReport(*BT_NotCString, 510a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose os.str(), N); 511a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 512a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose report->addRange(Ex->getSourceRange()); 513a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose C.EmitReport(report); 51419c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose } 51519c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 516a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose return UndefinedVal(); 51719c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose } 51819c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose} 51919c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 52019c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rosebool CStringChecker::SummarizeRegion(llvm::raw_ostream& os, ASTContext& Ctx, 52119c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose const MemRegion *MR) { 52219c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose const TypedRegion *TR = dyn_cast<TypedRegion>(MR); 52319c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose if (!TR) 52419c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose return false; 52519c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 52619c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose switch (TR->getKind()) { 52719c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose case MemRegion::FunctionTextRegionKind: { 52819c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose const FunctionDecl *FD = cast<FunctionTextRegion>(TR)->getDecl(); 52919c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose if (FD) 53019c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose os << "the address of the function '" << FD << "'"; 53119c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose else 53219c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose os << "the address of a function"; 53319c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose return true; 53419c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose } 53519c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose case MemRegion::BlockTextRegionKind: 53619c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose os << "block text"; 53719c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose return true; 53819c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose case MemRegion::BlockDataRegionKind: 53919c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose os << "a block"; 54019c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose return true; 54119c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose case MemRegion::CXXThisRegionKind: 54219c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose case MemRegion::CXXObjectRegionKind: 543018220c343c103b7dfaa117a7a474c7a7fd6d068Zhongxing Xu os << "a C++ object of type " << TR->getValueType().getAsString(); 54419c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose return true; 54519c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose case MemRegion::VarRegionKind: 546018220c343c103b7dfaa117a7a474c7a7fd6d068Zhongxing Xu os << "a variable of type" << TR->getValueType().getAsString(); 54719c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose return true; 54819c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose case MemRegion::FieldRegionKind: 549018220c343c103b7dfaa117a7a474c7a7fd6d068Zhongxing Xu os << "a field of type " << TR->getValueType().getAsString(); 55019c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose return true; 55119c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose case MemRegion::ObjCIvarRegionKind: 552018220c343c103b7dfaa117a7a474c7a7fd6d068Zhongxing Xu os << "an instance variable of type " << TR->getValueType().getAsString(); 55319c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose return true; 55419c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose default: 55519c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose return false; 55619c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose } 55719c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose} 55819c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 559d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose//===----------------------------------------------------------------------===// 560d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose// Evaluation of individual function calls. 561d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose//===----------------------------------------------------------------------===// 562ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 563d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rosevoid CStringChecker::EvalCopyCommon(CheckerContext &C, const GRState *state, 564d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose const Expr *Size, const Expr *Dest, 565d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose const Expr *Source, bool Restricted) { 566d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // See if the size argument is zero. 567d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose SVal SizeVal = state->getSVal(Size); 568d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose QualType SizeTy = Size->getType(); 569d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 570d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose const GRState *StZeroSize, *StNonZeroSize; 571d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose llvm::tie(StZeroSize, StNonZeroSize) = AssumeZero(C, state, SizeVal, SizeTy); 572d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 573d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // If the size is zero, there won't be any actual memory access. 574d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (StZeroSize) 575d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose C.addTransition(StZeroSize); 576d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 577d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // If the size can be nonzero, we have to check the other arguments. 578d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (StNonZeroSize) { 579d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose state = StNonZeroSize; 580d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose state = CheckBufferAccess(C, state, Size, Dest, Source); 581d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (Restricted) 582d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose state = CheckOverlap(C, state, Size, Dest, Source); 583d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (state) 584d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose C.addTransition(state); 585d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose } 586ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose} 587ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 588ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 589d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rosevoid CStringChecker::EvalMemcpy(CheckerContext &C, const CallExpr *CE) { 590d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // void *memcpy(void *restrict dst, const void *restrict src, size_t n); 591d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // The return value is the address of the destination buffer. 592d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose const Expr *Dest = CE->getArg(0); 593ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const GRState *state = C.getState(); 594d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose state = state->BindExpr(CE, state->getSVal(Dest)); 595d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose EvalCopyCommon(C, state, CE->getArg(2), Dest, CE->getArg(1), true); 596d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose} 597ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 598d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rosevoid CStringChecker::EvalMemmove(CheckerContext &C, const CallExpr *CE) { 599d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // void *memmove(void *dst, const void *src, size_t n); 600ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // The return value is the address of the destination buffer. 601d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose const Expr *Dest = CE->getArg(0); 602d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose const GRState *state = C.getState(); 603d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose state = state->BindExpr(CE, state->getSVal(Dest)); 604d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose EvalCopyCommon(C, state, CE->getArg(2), Dest, CE->getArg(1)); 605ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose} 606ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 607d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rosevoid CStringChecker::EvalBcopy(CheckerContext &C, const CallExpr *CE) { 608d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // void bcopy(const void *src, void *dst, size_t n); 609d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose EvalCopyCommon(C, C.getState(), CE->getArg(2), CE->getArg(1), CE->getArg(0)); 610d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose} 611d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 612d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rosevoid CStringChecker::EvalMemcmp(CheckerContext &C, const CallExpr *CE) { 613bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose // int memcmp(const void *s1, const void *s2, size_t n); 614bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose const Expr *Left = CE->getArg(0); 615bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose const Expr *Right = CE->getArg(1); 616bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose const Expr *Size = CE->getArg(2); 617bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose 618bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose const GRState *state = C.getState(); 619bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose ValueManager &ValMgr = C.getValueManager(); 620bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose SValuator &SV = ValMgr.getSValuator(); 621bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose 622d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // See if the size argument is zero. 623d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose SVal SizeVal = state->getSVal(Size); 624d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose QualType SizeTy = Size->getType(); 625bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose 626d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose const GRState *StZeroSize, *StNonZeroSize; 627d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose llvm::tie(StZeroSize, StNonZeroSize) = AssumeZero(C, state, SizeVal, SizeTy); 628bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose 629d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // If the size can be zero, the result will be 0 in that case, and we don't 630d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // have to check either of the buffers. 631d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (StZeroSize) { 632d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose state = StZeroSize; 633d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose state = state->BindExpr(CE, ValMgr.makeZeroVal(CE->getType())); 634d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose C.addTransition(state); 635bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose } 636bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose 637d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // If the size can be nonzero, we have to check the other arguments. 638d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (StNonZeroSize) { 639d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose state = StNonZeroSize; 640d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 641d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // If we know the two buffers are the same, we know the result is 0. 642d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // First, get the two buffers' addresses. Another checker will have already 643d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // made sure they're not undefined. 644d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose DefinedOrUnknownSVal LV = cast<DefinedOrUnknownSVal>(state->getSVal(Left)); 645d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose DefinedOrUnknownSVal RV = cast<DefinedOrUnknownSVal>(state->getSVal(Right)); 646d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 647d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // See if they are the same. 648d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose DefinedOrUnknownSVal SameBuf = SV.EvalEQ(state, LV, RV); 649d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose const GRState *StSameBuf, *StNotSameBuf; 650d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose llvm::tie(StSameBuf, StNotSameBuf) = state->Assume(SameBuf); 651d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 652d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // If the two arguments might be the same buffer, we know the result is zero, 653d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // and we only need to check one size. 654d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (StSameBuf) { 655d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose state = StSameBuf; 656d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose state = CheckBufferAccess(C, state, Size, Left); 657d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (state) { 658d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose state = StSameBuf->BindExpr(CE, ValMgr.makeZeroVal(CE->getType())); 659d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose C.addTransition(state); 660d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose } 661d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose } 662bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose 663d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // If the two arguments might be different buffers, we have to check the 664d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // size of both of them. 665d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (StNotSameBuf) { 666d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose state = StNotSameBuf; 667d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose state = CheckBufferAccess(C, state, Size, Left, Right); 668d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (state) { 669d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // The return value is the comparison result, which we don't know. 670d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose unsigned Count = C.getNodeBuilder().getCurrentBlockCount(); 671d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose SVal CmpV = ValMgr.getConjuredSymbolVal(NULL, CE, CE->getType(), Count); 672d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose state = state->BindExpr(CE, CmpV); 673d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose C.addTransition(state); 674d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose } 675d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose } 676d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose } 677bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose} 678bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose 67919c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rosevoid CStringChecker::EvalStrlen(CheckerContext &C, const CallExpr *CE) { 68019c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose // size_t strlen(const char *s); 68119c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose const GRState *state = C.getState(); 68219c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose const Expr *Arg = CE->getArg(0); 68319c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose SVal ArgVal = state->getSVal(Arg); 68419c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 68519c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose // Check that the argument is non-null. 68619c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose state = CheckNonNull(C, state, Arg, ArgVal); 68719c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 68819c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose if (state) { 68919c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose SVal StrLen = GetCStringLength(C, state, Arg, ArgVal); 690a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 691a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // If the argument isn't a valid C string, there's no valid state to 692a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // transition to. 693a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (StrLen.isUndef()) 694a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose return; 695a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 696a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // If GetCStringLength couldn't figure out the length, conjure a return 697a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // value, so it can be used in constraints, at least. 698a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (StrLen.isUnknown()) { 699a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose ValueManager &ValMgr = C.getValueManager(); 700a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose unsigned Count = C.getNodeBuilder().getCurrentBlockCount(); 701a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose StrLen = ValMgr.getConjuredSymbolVal(NULL, CE, CE->getType(), Count); 70219c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose } 703a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 704a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // Bind the return value. 705a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose state = state->BindExpr(CE, StrLen); 706a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose C.addTransition(state); 70719c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose } 70819c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose} 70919c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 710d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose//===----------------------------------------------------------------------===// 711a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose// The driver method, and other Checker callbacks. 712d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose//===----------------------------------------------------------------------===// 713ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 714ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rosebool CStringChecker::EvalCallExpr(CheckerContext &C, const CallExpr *CE) { 715ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Get the callee. All the functions we care about are C functions 716ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // with simple identifiers. 717ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const GRState *state = C.getState(); 718ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const Expr *Callee = CE->getCallee(); 719ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const FunctionDecl *FD = state->getSVal(Callee).getAsFunctionDecl(); 720ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 721ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (!FD) 722ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return false; 723ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 724ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Get the name of the callee. If it's a builtin, strip off the prefix. 725ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose llvm::StringRef Name = FD->getName(); 726ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (Name.startswith("__builtin_")) 727ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose Name = Name.substr(10); 728ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 729ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose FnCheck EvalFunction = llvm::StringSwitch<FnCheck>(Name) 730a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose .Cases("memcpy", "__memcpy_chk", &CStringChecker::EvalMemcpy) 731bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose .Cases("memcmp", "bcmp", &CStringChecker::EvalMemcmp) 732a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose .Cases("memmove", "__memmove_chk", &CStringChecker::EvalMemmove) 73319c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose .Case("strlen", &CStringChecker::EvalStrlen) 734ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose .Case("bcopy", &CStringChecker::EvalBcopy) 735ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose .Default(NULL); 736ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 737d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // If the callee isn't a string function, let another checker handle it. 738ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (!EvalFunction) 739ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return false; 740ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 741d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // Check and evaluate the call. 742d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose (this->*EvalFunction)(C, CE); 743ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return true; 744ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose} 745a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 746a5261549754fab80e30e893d8fa706bfb31e430aJordy Rosevoid CStringChecker::PreVisitDeclStmt(CheckerContext &C, const DeclStmt *DS) { 747a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // Record string length for char a[] = "abc"; 748a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose const GRState *state = C.getState(); 749a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 750a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose for (DeclStmt::const_decl_iterator I = DS->decl_begin(), E = DS->decl_end(); 751a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose I != E; ++I) { 752a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose const VarDecl *D = dyn_cast<VarDecl>(*I); 753a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (!D) 754a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose continue; 755a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 756a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // FIXME: Handle array fields of structs. 757a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (!D->getType()->isArrayType()) 758a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose continue; 759a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 760a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose const Expr *Init = D->getInit(); 761a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (!Init) 762a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose continue; 763a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (!isa<StringLiteral>(Init)) 764a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose continue; 765a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 766a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose Loc VarLoc = state->getLValue(D, C.getPredecessor()->getLocationContext()); 767a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose const MemRegion *MR = VarLoc.getAsRegion(); 768a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (!MR) 769a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose continue; 770a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 771a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose SVal StrVal = state->getSVal(Init); 772a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose assert(StrVal.isValid() && "Initializer string is unknown or undefined"); 773a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose DefinedOrUnknownSVal StrLen 774a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose = cast<DefinedOrUnknownSVal>(GetCStringLength(C, state, Init, StrVal)); 775a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 776a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose state = state->set<CStringLength>(MR, StrLen); 777a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose } 778a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 779a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose C.addTransition(state); 780a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose} 781a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 782a5261549754fab80e30e893d8fa706bfb31e430aJordy Rosebool CStringChecker::WantsRegionChangeUpdate(const GRState *state) { 783a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose CStringLength::EntryMap Entries = state->get<CStringLength>(); 784a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose return !Entries.isEmpty(); 785a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose} 786a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 787a5261549754fab80e30e893d8fa706bfb31e430aJordy Roseconst GRState *CStringChecker::EvalRegionChanges(const GRState *state, 788a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose const MemRegion * const *Begin, 789a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose const MemRegion * const *End, 790a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose bool *) { 791a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose CStringLength::EntryMap Entries = state->get<CStringLength>(); 792a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (Entries.isEmpty()) 793a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose return state; 794a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 795a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose llvm::SmallPtrSet<const MemRegion *, 8> Invalidated; 796a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose llvm::SmallPtrSet<const MemRegion *, 32> SuperRegions; 797a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 798a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // First build sets for the changed regions and their super-regions. 799a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose for ( ; Begin != End; ++Begin) { 800a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose const MemRegion *MR = *Begin; 801a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose Invalidated.insert(MR); 802a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 803a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose SuperRegions.insert(MR); 804a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose while (const SubRegion *SR = dyn_cast<SubRegion>(MR)) { 805a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose MR = SR->getSuperRegion(); 806a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose SuperRegions.insert(MR); 807a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose } 808a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose } 809a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 810a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose CStringLength::EntryMap::Factory &F = state->get_context<CStringLength>(); 811a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 812a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // Then loop over the entries in the current state. 813a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose for (CStringLength::EntryMap::iterator I = Entries.begin(), 814a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose E = Entries.end(); I != E; ++I) { 815a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose const MemRegion *MR = I.getKey(); 816a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 817a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // Is this entry for a super-region of a changed region? 818a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (SuperRegions.count(MR)) { 819a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose Entries = F.Remove(Entries, MR); 820a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose continue; 821a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose } 822a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 823a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // Is this entry for a sub-region of a changed region? 824a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose const MemRegion *Super = MR; 825a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose while (const SubRegion *SR = dyn_cast<SubRegion>(Super)) { 826a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose Super = SR->getSuperRegion(); 827a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (Invalidated.count(Super)) { 828a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose Entries = F.Remove(Entries, MR); 829a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose break; 830a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose } 831a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose } 832a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose } 833a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 834a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose return state->set<CStringLength>(Entries); 835a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose} 836a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 837a5261549754fab80e30e893d8fa706bfb31e430aJordy Rosevoid CStringChecker::MarkLiveSymbols(const GRState *state, SymbolReaper &SR) { 838a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // Mark all symbols in our string length map as valid. 839a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose CStringLength::EntryMap Entries = state->get<CStringLength>(); 840a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 841a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose for (CStringLength::EntryMap::iterator I = Entries.begin(), E = Entries.end(); 842a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose I != E; ++I) { 843a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose SVal Len = I.getData(); 844a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (SymbolRef Sym = Len.getAsSymbol()) 845a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose SR.markInUse(Sym); 846a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose } 847a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose} 848a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 849a5261549754fab80e30e893d8fa706bfb31e430aJordy Rosevoid CStringChecker::EvalDeadSymbols(CheckerContext &C, SymbolReaper &SR) { 850a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (!SR.hasDeadSymbols()) 851a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose return; 852a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 853a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose const GRState *state = C.getState(); 854a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose CStringLength::EntryMap Entries = state->get<CStringLength>(); 855a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (Entries.isEmpty()) 856a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose return; 857a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 858a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose CStringLength::EntryMap::Factory &F = state->get_context<CStringLength>(); 859a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose for (CStringLength::EntryMap::iterator I = Entries.begin(), E = Entries.end(); 860a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose I != E; ++I) { 861a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose SVal Len = I.getData(); 862a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (SymbolRef Sym = Len.getAsSymbol()) { 863a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (SR.isDead(Sym)) 864a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose Entries = F.Remove(Entries, I.getKey()); 865a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose } 866a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose } 867a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 868a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose state = state->set<CStringLength>(Entries); 869a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose C.GenerateNode(state); 870a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose} 871