CStringChecker.cpp revision 0ef473f75426f0a95635d0a9dd567d27b07dbd5b
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 15a0decc9a2481f938e1675b4f7bbd58761a882a36Argyrios Kyrtzidis#include "ClangSACheckers.h" 16695fb502825a53ccd178ec1c85c77929d88acb71Argyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/CheckerManager.h" 179b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 189b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h" 199b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h" 20ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose#include "llvm/ADT/StringSwitch.h" 21ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 22ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Roseusing namespace clang; 239ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenekusing namespace ento; 24ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 25ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rosenamespace { 26ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Roseclass CStringChecker : public CheckerVisitor<CStringChecker> { 27e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose BugType *BT_Null, *BT_Bounds, *BT_BoundsWrite, *BT_Overlap, *BT_NotCString; 28ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rosepublic: 29ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose CStringChecker() 30e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose : BT_Null(0), BT_Bounds(0), BT_BoundsWrite(0), BT_Overlap(0), BT_NotCString(0) 31e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose {} 32ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose static void *getTag() { static int tag; return &tag; } 33ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 349c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek bool evalCallExpr(CheckerContext &C, const CallExpr *CE); 35a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose void PreVisitDeclStmt(CheckerContext &C, const DeclStmt *DS); 36a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose void MarkLiveSymbols(const GRState *state, SymbolReaper &SR); 379c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek void evalDeadSymbols(CheckerContext &C, SymbolReaper &SR); 38e36de1fe51c39d9161915dd3dbef880954af6476Ted Kremenek bool wantsRegionChangeUpdate(const GRState *state); 39a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 40a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose const GRState *EvalRegionChanges(const GRState *state, 41a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose const MemRegion * const *Begin, 42a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose const MemRegion * const *End, 43a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose bool*); 44ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 45d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose typedef void (CStringChecker::*FnCheck)(CheckerContext &, const CallExpr *); 46ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 479c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek void evalMemcpy(CheckerContext &C, const CallExpr *CE); 489c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek void evalMemmove(CheckerContext &C, const CallExpr *CE); 499c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek void evalBcopy(CheckerContext &C, const CallExpr *CE); 509c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek void evalCopyCommon(CheckerContext &C, const GRState *state, 51d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose const Expr *Size, const Expr *Source, const Expr *Dest, 52d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose bool Restricted = false); 53d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 549c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek void evalMemcmp(CheckerContext &C, const CallExpr *CE); 55ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 56c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek void evalstrLength(CheckerContext &C, const CallExpr *CE); 57be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek void evalstrnLength(CheckerContext &C, const CallExpr *CE); 58be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek void evalstrLengthCommon(CheckerContext &C, const CallExpr *CE, 59be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek bool IsStrnlen = false); 6019c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 619c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek void evalStrcpy(CheckerContext &C, const CallExpr *CE); 620ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek void evalStrncpy(CheckerContext &C, const CallExpr *CE); 639c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek void evalStpcpy(CheckerContext &C, const CallExpr *CE); 640ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek void evalStrcpyCommon(CheckerContext &C, const CallExpr *CE, bool returnEnd, 650ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek bool isStrncpy); 66e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 67ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Utility methods 68d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose std::pair<const GRState*, const GRState*> 6928f47b92e760ccf641ac91cb0fe1c12d9ca89795Ted Kremenek assumeZero(CheckerContext &C, const GRState *state, SVal V, QualType Ty); 70d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 71c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek const GRState *setCStringLength(const GRState *state, const MemRegion *MR, 72c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal strLength); 73c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal getCStringLengthForRegion(CheckerContext &C, const GRState *&state, 74a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose const Expr *Ex, const MemRegion *MR); 75c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal getCStringLength(CheckerContext &C, const GRState *&state, 7619c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose const Expr *Ex, SVal Buf); 7719c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 78e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose const GRState *InvalidateBuffer(CheckerContext &C, const GRState *state, 79e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose const Expr *Ex, SVal V); 80e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 8119c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose bool SummarizeRegion(llvm::raw_ostream& os, ASTContext& Ctx, 8219c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose const MemRegion *MR); 8319c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 8419c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose // Re-usable checks 85c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek const GRState *checkNonNull(CheckerContext &C, const GRState *state, 86d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose const Expr *S, SVal l); 87ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const GRState *CheckLocation(CheckerContext &C, const GRState *state, 88e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose const Expr *S, SVal l, 89e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose bool IsDestination = false); 90ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const GRState *CheckBufferAccess(CheckerContext &C, const GRState *state, 91ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const Expr *Size, 92ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const Expr *FirstBuf, 93e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose const Expr *SecondBuf = NULL, 94e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose bool FirstIsDestination = false); 95ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const GRState *CheckOverlap(CheckerContext &C, const GRState *state, 96d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose const Expr *Size, const Expr *First, 97d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose const Expr *Second); 98c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek void emitOverlapBug(CheckerContext &C, const GRState *state, 99ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const Stmt *First, const Stmt *Second); 100ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose}; 101a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 102a5261549754fab80e30e893d8fa706bfb31e430aJordy Roseclass CStringLength { 103a5261549754fab80e30e893d8fa706bfb31e430aJordy Rosepublic: 104a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose typedef llvm::ImmutableMap<const MemRegion *, SVal> EntryMap; 105a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose}; 106ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose} //end anonymous namespace 107ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 108a5261549754fab80e30e893d8fa706bfb31e430aJordy Rosenamespace clang { 1099ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremeneknamespace ento { 110a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose template <> 111a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose struct GRStateTrait<CStringLength> 112a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose : public GRStatePartialTrait<CStringLength::EntryMap> { 113a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose static void *GDMIndex() { return CStringChecker::getTag(); } 114a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose }; 115a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose} 1165a4f98ff943e6a501b0fe47ade007c9bbf96cb88Argyrios Kyrtzidis} 117a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 118695fb502825a53ccd178ec1c85c77929d88acb71Argyrios Kyrtzidisstatic void RegisterCStringChecker(ExprEngine &Eng) { 119ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose Eng.registerCheck(new CStringChecker()); 120ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose} 121ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 122695fb502825a53ccd178ec1c85c77929d88acb71Argyrios Kyrtzidisvoid ento::registerCStringChecker(CheckerManager &mgr) { 123695fb502825a53ccd178ec1c85c77929d88acb71Argyrios Kyrtzidis mgr.addCheckerRegisterFunction(RegisterCStringChecker); 124695fb502825a53ccd178ec1c85c77929d88acb71Argyrios Kyrtzidis} 125695fb502825a53ccd178ec1c85c77929d88acb71Argyrios Kyrtzidis 126d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose//===----------------------------------------------------------------------===// 127d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose// Individual checks and utility methods. 128d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose//===----------------------------------------------------------------------===// 129d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 130d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rosestd::pair<const GRState*, const GRState*> 13128f47b92e760ccf641ac91cb0fe1c12d9ca89795Ted KremenekCStringChecker::assumeZero(CheckerContext &C, const GRState *state, SVal V, 132d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose QualType Ty) { 133c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek DefinedSVal *val = dyn_cast<DefinedSVal>(&V); 134c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek if (!val) 135d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose return std::pair<const GRState*, const GRState *>(state, state); 136a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose 137c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SValBuilder &svalBuilder = C.getSValBuilder(); 138c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek DefinedOrUnknownSVal zero = svalBuilder.makeZeroVal(Ty); 139c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek return state->assume(svalBuilder.evalEQ(state, *val, zero)); 140d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose} 141d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 142c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenekconst GRState *CStringChecker::checkNonNull(CheckerContext &C, 143d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose const GRState *state, 144d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose const Expr *S, SVal l) { 145d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // If a previous check has failed, propagate the failure. 146d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (!state) 147d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose return NULL; 148a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose 149d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose const GRState *stateNull, *stateNonNull; 15028f47b92e760ccf641ac91cb0fe1c12d9ca89795Ted Kremenek llvm::tie(stateNull, stateNonNull) = assumeZero(C, state, l, S->getType()); 151a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose 152d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (stateNull && !stateNonNull) { 153d048c6ef5b6cfaa0cecb8cc1d4bdace32ed21d07Ted Kremenek ExplodedNode *N = C.generateSink(stateNull); 154a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose if (!N) 155a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose return NULL; 156a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose 157d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (!BT_Null) 158d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose BT_Null = new BuiltinBug("API", 159a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose "Null pointer argument in call to byte string function"); 160a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose 161a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose // Generate a report for this bug. 162d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose BuiltinBug *BT = static_cast<BuiltinBug*>(BT_Null); 163a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose EnhancedBugReport *report = new EnhancedBugReport(*BT, 164a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose BT->getDescription(), N); 165a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose 166a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose report->addRange(S->getSourceRange()); 167a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, S); 168a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose C.EmitReport(report); 169a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose return NULL; 170a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose } 171a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose 172a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose // From here on, assume that the value is non-null. 173d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose assert(stateNonNull); 174d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose return stateNonNull; 175a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose} 176a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose 177ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose// FIXME: This was originally copied from ArrayBoundChecker.cpp. Refactor? 178ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Roseconst GRState *CStringChecker::CheckLocation(CheckerContext &C, 179ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const GRState *state, 180e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose const Expr *S, SVal l, 181e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose bool IsDestination) { 182d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // If a previous check has failed, propagate the failure. 183d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (!state) 184d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose return NULL; 185d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 186ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Check for out of bound array element access. 187ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const MemRegion *R = l.getAsRegion(); 188ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (!R) 189ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return state; 190ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 191ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const ElementRegion *ER = dyn_cast<ElementRegion>(R); 192ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (!ER) 193ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return state; 194ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 195018220c343c103b7dfaa117a7a474c7a7fd6d068Zhongxing Xu assert(ER->getValueType() == C.getASTContext().CharTy && 196ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose "CheckLocation should only be called with char* ElementRegions"); 197ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 198ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Get the size of the array. 199c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek const SubRegion *superReg = cast<SubRegion>(ER->getSuperRegion()); 200c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SValBuilder &svalBuilder = C.getSValBuilder(); 201c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal Extent = svalBuilder.convertToArrayIndex(superReg->getExtent(svalBuilder)); 202ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose DefinedOrUnknownSVal Size = cast<DefinedOrUnknownSVal>(Extent); 203ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 204ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Get the index of the accessed element. 20589b06584402a38933e108b66ded3a168cd492dffGabor Greif DefinedOrUnknownSVal Idx = cast<DefinedOrUnknownSVal>(ER->getIndex()); 206ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 20728f47b92e760ccf641ac91cb0fe1c12d9ca89795Ted Kremenek const GRState *StInBound = state->assumeInBound(Idx, Size, true); 20828f47b92e760ccf641ac91cb0fe1c12d9ca89795Ted Kremenek const GRState *StOutBound = state->assumeInBound(Idx, Size, false); 209ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (StOutBound && !StInBound) { 210d048c6ef5b6cfaa0cecb8cc1d4bdace32ed21d07Ted Kremenek ExplodedNode *N = C.generateSink(StOutBound); 211ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (!N) 212ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return NULL; 213ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 214e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose BuiltinBug *BT; 215e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose if (IsDestination) { 216e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose if (!BT_BoundsWrite) { 217e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose BT_BoundsWrite = new BuiltinBug("Out-of-bound array access", 218e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose "Byte string function overflows destination buffer"); 219e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose } 220e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose BT = static_cast<BuiltinBug*>(BT_BoundsWrite); 221e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose } else { 222e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose if (!BT_Bounds) { 223e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose BT_Bounds = new BuiltinBug("Out-of-bound array access", 224e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose "Byte string function accesses out-of-bound array element"); 225e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose } 226e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose BT = static_cast<BuiltinBug*>(BT_Bounds); 227e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose } 228ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 229ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // FIXME: It would be nice to eventually make this diagnostic more clear, 230ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // e.g., by referencing the original declaration or by saying *why* this 231ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // reference is outside the range. 232ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 233ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Generate a report for this bug. 234ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose RangedBugReport *report = new RangedBugReport(*BT, BT->getDescription(), N); 235ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 236ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose report->addRange(S->getSourceRange()); 237ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose C.EmitReport(report); 238ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return NULL; 239ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose } 240ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 241ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Array bound check succeeded. From this point forward the array bound 242ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // should always succeed. 243ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return StInBound; 244ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose} 245ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 246ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Roseconst GRState *CStringChecker::CheckBufferAccess(CheckerContext &C, 247ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const GRState *state, 248ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const Expr *Size, 249ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const Expr *FirstBuf, 250e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose const Expr *SecondBuf, 251e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose bool FirstIsDestination) { 252d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // If a previous check has failed, propagate the failure. 253d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (!state) 254d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose return NULL; 255d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 256c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SValBuilder &svalBuilder = C.getSValBuilder(); 257ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose ASTContext &Ctx = C.getASTContext(); 258ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 259c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek QualType sizeTy = Size->getType(); 260ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose QualType PtrTy = Ctx.getPointerType(Ctx.CharTy); 261ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 262a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose // Check that the first buffer is non-null. 263a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose SVal BufVal = state->getSVal(FirstBuf); 264c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek state = checkNonNull(C, state, FirstBuf, BufVal); 265a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose if (!state) 266a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose return NULL; 267a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose 268d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // Get the access length and make sure it is known. 269d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose SVal LengthVal = state->getSVal(Size); 270d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose NonLoc *Length = dyn_cast<NonLoc>(&LengthVal); 271d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (!Length) 272d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose return state; 273d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 274ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Compute the offset of the last element to be accessed: size-1. 275c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek NonLoc One = cast<NonLoc>(svalBuilder.makeIntVal(1, sizeTy)); 276c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek NonLoc LastOffset = cast<NonLoc>(svalBuilder.evalBinOpNN(state, BO_Sub, 277c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek *Length, One, sizeTy)); 278ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 279a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose // Check that the first buffer is sufficently long. 280c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal BufStart = svalBuilder.evalCast(BufVal, PtrTy, FirstBuf->getType()); 281b6a4026de13909c2b145166ae0b7d96cf1948f64Jordy Rose if (Loc *BufLoc = dyn_cast<Loc>(&BufStart)) { 282c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal BufEnd = svalBuilder.evalBinOpLN(state, BO_Add, *BufLoc, 283c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek LastOffset, PtrTy); 284e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose state = CheckLocation(C, state, FirstBuf, BufEnd, FirstIsDestination); 285ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 286b6a4026de13909c2b145166ae0b7d96cf1948f64Jordy Rose // If the buffer isn't large enough, abort. 287b6a4026de13909c2b145166ae0b7d96cf1948f64Jordy Rose if (!state) 288b6a4026de13909c2b145166ae0b7d96cf1948f64Jordy Rose return NULL; 289b6a4026de13909c2b145166ae0b7d96cf1948f64Jordy Rose } 290ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 291ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // If there's a second buffer, check it as well. 292ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (SecondBuf) { 293ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose BufVal = state->getSVal(SecondBuf); 294c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek state = checkNonNull(C, state, SecondBuf, BufVal); 295a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose if (!state) 296a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose return NULL; 297a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose 298c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek BufStart = svalBuilder.evalCast(BufVal, PtrTy, SecondBuf->getType()); 299b6a4026de13909c2b145166ae0b7d96cf1948f64Jordy Rose if (Loc *BufLoc = dyn_cast<Loc>(&BufStart)) { 300c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal BufEnd = svalBuilder.evalBinOpLN(state, BO_Add, *BufLoc, 301c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek LastOffset, PtrTy); 302b6a4026de13909c2b145166ae0b7d96cf1948f64Jordy Rose state = CheckLocation(C, state, SecondBuf, BufEnd); 303b6a4026de13909c2b145166ae0b7d96cf1948f64Jordy Rose } 304ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose } 305ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 306ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Large enough or not, return this state! 307ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return state; 308ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose} 309ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 310ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Roseconst GRState *CStringChecker::CheckOverlap(CheckerContext &C, 311ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const GRState *state, 312d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose const Expr *Size, 313ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const Expr *First, 314d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose const Expr *Second) { 315ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Do a simple check for overlap: if the two arguments are from the same 316ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // buffer, see if the end of the first is greater than the start of the second 317ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // or vice versa. 318ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 319d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // If a previous check has failed, propagate the failure. 320d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (!state) 321d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose return NULL; 322d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 323ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const GRState *stateTrue, *stateFalse; 324ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 325ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Get the buffer values and make sure they're known locations. 326c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal firstVal = state->getSVal(First); 327c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal secondVal = state->getSVal(Second); 328ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 329c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek Loc *firstLoc = dyn_cast<Loc>(&firstVal); 330c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek if (!firstLoc) 331ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return state; 332ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 333c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek Loc *secondLoc = dyn_cast<Loc>(&secondVal); 334c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek if (!secondLoc) 335ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return state; 336ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 337ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Are the two values the same? 338c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SValBuilder &svalBuilder = C.getSValBuilder(); 339c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek llvm::tie(stateTrue, stateFalse) = 340c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek state->assume(svalBuilder.evalEQ(state, *firstLoc, *secondLoc)); 341ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 342ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (stateTrue && !stateFalse) { 343ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // If the values are known to be equal, that's automatically an overlap. 344c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek emitOverlapBug(C, stateTrue, First, Second); 345ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return NULL; 346ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose } 347ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 34828f47b92e760ccf641ac91cb0fe1c12d9ca89795Ted Kremenek // assume the two expressions are not equal. 349ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose assert(stateFalse); 350ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose state = stateFalse; 351ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 352ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Which value comes first? 353c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek ASTContext &Ctx = svalBuilder.getContext(); 354c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek QualType cmpTy = Ctx.IntTy; 355c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal reverse = svalBuilder.evalBinOpLL(state, BO_GT, 356c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek *firstLoc, *secondLoc, cmpTy); 357c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek DefinedOrUnknownSVal *reverseTest = dyn_cast<DefinedOrUnknownSVal>(&reverse); 358c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek if (!reverseTest) 359ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return state; 360ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 361c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek llvm::tie(stateTrue, stateFalse) = state->assume(*reverseTest); 362ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (stateTrue) { 363ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (stateFalse) { 364ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // If we don't know which one comes first, we can't perform this test. 365ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return state; 366ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose } else { 367c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek // Switch the values so that firstVal is before secondVal. 368c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek Loc *tmpLoc = firstLoc; 369c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek firstLoc = secondLoc; 370c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek secondLoc = tmpLoc; 371ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 372ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Switch the Exprs as well, so that they still correspond. 373ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const Expr *tmpExpr = First; 374ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose First = Second; 375ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose Second = tmpExpr; 376ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose } 377ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose } 378ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 379ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Get the length, and make sure it too is known. 380ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose SVal LengthVal = state->getSVal(Size); 381ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose NonLoc *Length = dyn_cast<NonLoc>(&LengthVal); 382ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (!Length) 383ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return state; 384ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 385ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Convert the first buffer's start address to char*. 386ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Bail out if the cast fails. 387ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose QualType CharPtrTy = Ctx.getPointerType(Ctx.CharTy); 388c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal FirstStart = svalBuilder.evalCast(*firstLoc, CharPtrTy, First->getType()); 389ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose Loc *FirstStartLoc = dyn_cast<Loc>(&FirstStart); 390ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (!FirstStartLoc) 391ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return state; 392ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 393ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Compute the end of the first buffer. Bail out if THAT fails. 394c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal FirstEnd = svalBuilder.evalBinOpLN(state, BO_Add, 395ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose *FirstStartLoc, *Length, CharPtrTy); 396ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose Loc *FirstEndLoc = dyn_cast<Loc>(&FirstEnd); 397ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (!FirstEndLoc) 398ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return state; 399ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 400ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Is the end of the first buffer past the start of the second buffer? 401c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal Overlap = svalBuilder.evalBinOpLL(state, BO_GT, 402c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek *FirstEndLoc, *secondLoc, cmpTy); 403ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose DefinedOrUnknownSVal *OverlapTest = dyn_cast<DefinedOrUnknownSVal>(&Overlap); 404ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (!OverlapTest) 405ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return state; 406ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 40728f47b92e760ccf641ac91cb0fe1c12d9ca89795Ted Kremenek llvm::tie(stateTrue, stateFalse) = state->assume(*OverlapTest); 408ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 409ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (stateTrue && !stateFalse) { 410ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Overlap! 411c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek emitOverlapBug(C, stateTrue, First, Second); 412ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return NULL; 413ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose } 414ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 41528f47b92e760ccf641ac91cb0fe1c12d9ca89795Ted Kremenek // assume the two expressions don't overlap. 416ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose assert(stateFalse); 417ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return stateFalse; 418ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose} 419ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 420c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenekvoid CStringChecker::emitOverlapBug(CheckerContext &C, const GRState *state, 421ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const Stmt *First, const Stmt *Second) { 422d048c6ef5b6cfaa0cecb8cc1d4bdace32ed21d07Ted Kremenek ExplodedNode *N = C.generateSink(state); 423ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (!N) 424ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return; 425ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 426ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (!BT_Overlap) 427ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose BT_Overlap = new BugType("Unix API", "Improper arguments"); 428ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 429ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Generate a report for this bug. 430ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose RangedBugReport *report = 431ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose new RangedBugReport(*BT_Overlap, 432ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose "Arguments must not be overlapping buffers", N); 433ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose report->addRange(First->getSourceRange()); 434ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose report->addRange(Second->getSourceRange()); 435ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 436ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose C.EmitReport(report); 437ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose} 438ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 439c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenekconst GRState *CStringChecker::setCStringLength(const GRState *state, 440e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose const MemRegion *MR, 441c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal strLength) { 442c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek assert(!strLength.isUndef() && "Attempt to set an undefined string length"); 443c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek if (strLength.isUnknown()) 444e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose return state; 445e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 446e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose MR = MR->StripCasts(); 447e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 448e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose switch (MR->getKind()) { 449e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose case MemRegion::StringRegionKind: 450e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // FIXME: This can happen if we strcpy() into a string region. This is 451e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // undefined [C99 6.4.5p6], but we should still warn about it. 452e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose return state; 453e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 454e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose case MemRegion::SymbolicRegionKind: 455e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose case MemRegion::AllocaRegionKind: 456e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose case MemRegion::VarRegionKind: 457e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose case MemRegion::FieldRegionKind: 458e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose case MemRegion::ObjCIvarRegionKind: 459c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek return state->set<CStringLength>(MR, strLength); 460e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 461e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose case MemRegion::ElementRegionKind: 462e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // FIXME: Handle element regions by upper-bounding the parent region's 463e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // string length. 464e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose return state; 465e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 466e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose default: 467e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // Other regions (mostly non-data) can't have a reliable C string length. 468e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // For now, just ignore the change. 469e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // FIXME: These are rare but not impossible. We should output some kind of 470e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // warning for things like strcpy((char[]){'a', 0}, "b"); 471e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose return state; 472e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose } 473e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose} 474e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 475c8413fd03f73084a5c93028f8b4db619fc388087Ted KremenekSVal CStringChecker::getCStringLengthForRegion(CheckerContext &C, 476a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose const GRState *&state, 477a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose const Expr *Ex, 478a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose const MemRegion *MR) { 479a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // If there's a recorded length, go ahead and return it. 480a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose const SVal *Recorded = state->get<CStringLength>(MR); 481a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (Recorded) 482a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose return *Recorded; 483a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 484a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // Otherwise, get a new symbol and update the state. 485a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose unsigned Count = C.getNodeBuilder().getCurrentBlockCount(); 486c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SValBuilder &svalBuilder = C.getSValBuilder(); 487c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek QualType sizeTy = svalBuilder.getContext().getSizeType(); 488c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal strLength = svalBuilder.getMetadataSymbolVal(getTag(), MR, Ex, sizeTy, Count); 489c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek state = state->set<CStringLength>(MR, strLength); 490c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek return strLength; 491a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose} 492a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 493c8413fd03f73084a5c93028f8b4db619fc388087Ted KremenekSVal CStringChecker::getCStringLength(CheckerContext &C, const GRState *&state, 49419c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose const Expr *Ex, SVal Buf) { 49519c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose const MemRegion *MR = Buf.getAsRegion(); 49619c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose if (!MR) { 49719c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose // If we can't get a region, see if it's something we /know/ isn't a 49819c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose // C string. In the context of locations, the only time we can issue such 49919c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose // a warning is for labels. 50019c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose if (loc::GotoLabel *Label = dyn_cast<loc::GotoLabel>(&Buf)) { 501d048c6ef5b6cfaa0cecb8cc1d4bdace32ed21d07Ted Kremenek if (ExplodedNode *N = C.generateNode(state)) { 50219c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose if (!BT_NotCString) 50319c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose BT_NotCString = new BuiltinBug("API", 50419c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose "Argument is not a null-terminated string."); 50519c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 50619c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose llvm::SmallString<120> buf; 50719c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose llvm::raw_svector_ostream os(buf); 50819c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose os << "Argument to byte string function is the address of the label '" 5096810630bb00ba2944cbeb54834f38f69dbddfd7fChris Lattner << Label->getLabel()->getName() 51019c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose << "', which is not a null-terminated string"; 51119c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 51219c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose // Generate a report for this bug. 51319c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose EnhancedBugReport *report = new EnhancedBugReport(*BT_NotCString, 51419c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose os.str(), N); 51519c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 51619c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose report->addRange(Ex->getSourceRange()); 51719c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose C.EmitReport(report); 51819c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose } 51919c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 52019c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose return UndefinedVal(); 52119c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose } 52219c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 523a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // If it's not a region and not a label, give up. 524a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose return UnknownVal(); 525a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose } 52619c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 527a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // If we have a region, strip casts from it and see if we can figure out 528a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // its length. For anything we can't figure out, just return UnknownVal. 529a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose MR = MR->StripCasts(); 530a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 531a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose switch (MR->getKind()) { 532a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose case MemRegion::StringRegionKind: { 533a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // Modifying the contents of string regions is undefined [C99 6.4.5p6], 534a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // so we can assume that the byte length is the correct C string length. 535c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SValBuilder &svalBuilder = C.getSValBuilder(); 536c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek QualType sizeTy = svalBuilder.getContext().getSizeType(); 537c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek const StringLiteral *strLit = cast<StringRegion>(MR)->getStringLiteral(); 538c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek return svalBuilder.makeIntVal(strLit->getByteLength(), sizeTy); 539a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose } 540a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose case MemRegion::SymbolicRegionKind: 541a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose case MemRegion::AllocaRegionKind: 542a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose case MemRegion::VarRegionKind: 543a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose case MemRegion::FieldRegionKind: 544a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose case MemRegion::ObjCIvarRegionKind: 545c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek return getCStringLengthForRegion(C, state, Ex, MR); 546a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose case MemRegion::CompoundLiteralRegionKind: 547a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // FIXME: Can we track this? Is it necessary? 548a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose return UnknownVal(); 549a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose case MemRegion::ElementRegionKind: 550a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // FIXME: How can we handle this? It's not good enough to subtract the 551a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // offset from the base string length; consider "123\x00567" and &a[5]. 552a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose return UnknownVal(); 553a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose default: 554a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // Other regions (mostly non-data) can't have a reliable C string length. 555a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // In this case, an error is emitted and UndefinedVal is returned. 556a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // The caller should always be prepared to handle this case. 557d048c6ef5b6cfaa0cecb8cc1d4bdace32ed21d07Ted Kremenek if (ExplodedNode *N = C.generateNode(state)) { 558a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (!BT_NotCString) 559a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose BT_NotCString = new BuiltinBug("API", 560a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose "Argument is not a null-terminated string."); 561a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 562a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose llvm::SmallString<120> buf; 563a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose llvm::raw_svector_ostream os(buf); 564a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 565a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose os << "Argument to byte string function is "; 566a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 567a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (SummarizeRegion(os, C.getASTContext(), MR)) 568a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose os << ", which is not a null-terminated string"; 569a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose else 570a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose os << "not a null-terminated string"; 571a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 572a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // Generate a report for this bug. 573a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose EnhancedBugReport *report = new EnhancedBugReport(*BT_NotCString, 574a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose os.str(), N); 575a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 576a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose report->addRange(Ex->getSourceRange()); 577a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose C.EmitReport(report); 57819c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose } 57919c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 580a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose return UndefinedVal(); 58119c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose } 58219c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose} 58319c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 584e64f311c11a8751867c2538807054f4817c1f5cbJordy Roseconst GRState *CStringChecker::InvalidateBuffer(CheckerContext &C, 585e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose const GRState *state, 586e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose const Expr *E, SVal V) { 587e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose Loc *L = dyn_cast<Loc>(&V); 588e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose if (!L) 589e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose return state; 590e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 591e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // FIXME: This is a simplified version of what's in CFRefCount.cpp -- it makes 592e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // some assumptions about the value that CFRefCount can't. Even so, it should 593e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // probably be refactored. 594e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose if (loc::MemRegionVal* MR = dyn_cast<loc::MemRegionVal>(L)) { 595e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose const MemRegion *R = MR->getRegion()->StripCasts(); 596e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 597e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // Are we dealing with an ElementRegion? If so, we should be invalidating 598e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // the super-region. 599e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) { 600e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose R = ER->getSuperRegion(); 601e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // FIXME: What about layers of ElementRegions? 602e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose } 603e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 604e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // Invalidate this region. 605e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose unsigned Count = C.getNodeBuilder().getCurrentBlockCount(); 6062534528c22260211a073e192c38d0db84c70c327Ted Kremenek return state->invalidateRegion(R, E, Count, NULL); 607e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose } 608e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 609e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // If we have a non-region value by chance, just remove the binding. 610e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // FIXME: is this necessary or correct? This handles the non-Region 611e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // cases. Is it ever valid to store to these? 612e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose return state->unbindLoc(*L); 613e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose} 614e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 61519c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rosebool CStringChecker::SummarizeRegion(llvm::raw_ostream& os, ASTContext& Ctx, 61619c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose const MemRegion *MR) { 61719c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose const TypedRegion *TR = dyn_cast<TypedRegion>(MR); 61819c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose if (!TR) 61919c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose return false; 62019c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 62119c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose switch (TR->getKind()) { 62219c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose case MemRegion::FunctionTextRegionKind: { 62319c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose const FunctionDecl *FD = cast<FunctionTextRegion>(TR)->getDecl(); 62419c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose if (FD) 62519c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose os << "the address of the function '" << FD << "'"; 62619c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose else 62719c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose os << "the address of a function"; 62819c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose return true; 62919c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose } 63019c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose case MemRegion::BlockTextRegionKind: 63119c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose os << "block text"; 63219c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose return true; 63319c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose case MemRegion::BlockDataRegionKind: 63419c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose os << "a block"; 63519c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose return true; 63619c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose case MemRegion::CXXThisRegionKind: 63702fe28c8a6da29d4ad88d0900c133dcf22d24a75Zhongxing Xu case MemRegion::CXXTempObjectRegionKind: 63802fe28c8a6da29d4ad88d0900c133dcf22d24a75Zhongxing Xu os << "a C++ temp object of type " << TR->getValueType().getAsString(); 63919c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose return true; 64019c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose case MemRegion::VarRegionKind: 641018220c343c103b7dfaa117a7a474c7a7fd6d068Zhongxing Xu os << "a variable of type" << TR->getValueType().getAsString(); 64219c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose return true; 64319c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose case MemRegion::FieldRegionKind: 644018220c343c103b7dfaa117a7a474c7a7fd6d068Zhongxing Xu os << "a field of type " << TR->getValueType().getAsString(); 64519c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose return true; 64619c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose case MemRegion::ObjCIvarRegionKind: 647018220c343c103b7dfaa117a7a474c7a7fd6d068Zhongxing Xu os << "an instance variable of type " << TR->getValueType().getAsString(); 64819c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose return true; 64919c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose default: 65019c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose return false; 65119c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose } 65219c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose} 65319c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 654d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose//===----------------------------------------------------------------------===// 6559c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek// evaluation of individual function calls. 656d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose//===----------------------------------------------------------------------===// 657ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 6589c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenekvoid CStringChecker::evalCopyCommon(CheckerContext &C, const GRState *state, 659d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose const Expr *Size, const Expr *Dest, 660d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose const Expr *Source, bool Restricted) { 661d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // See if the size argument is zero. 662c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal sizeVal = state->getSVal(Size); 663c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek QualType sizeTy = Size->getType(); 664d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 665c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek const GRState *stateZeroSize, *stateNonZeroSize; 666c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek llvm::tie(stateZeroSize, stateNonZeroSize) = assumeZero(C, state, sizeVal, sizeTy); 667d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 668d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // If the size is zero, there won't be any actual memory access. 669c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek if (stateZeroSize) 670c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek C.addTransition(stateZeroSize); 671d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 672d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // If the size can be nonzero, we have to check the other arguments. 673c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek if (stateNonZeroSize) { 674c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek state = stateNonZeroSize; 675e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose state = CheckBufferAccess(C, state, Size, Dest, Source, 676e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose /* FirstIsDst = */ true); 677d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (Restricted) 678d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose state = CheckOverlap(C, state, Size, Dest, Source); 679e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 680e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose if (state) { 681e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // Invalidate the destination. 682e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // FIXME: Even if we can't perfectly model the copy, we should see if we 683e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // can use LazyCompoundVals to copy the source values into the destination. 684e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // This would probably remove any existing bindings past the end of the 685e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // copied region, but that's still an improvement over blank invalidation. 686e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose state = InvalidateBuffer(C, state, Dest, state->getSVal(Dest)); 687d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose C.addTransition(state); 688e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose } 689d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose } 690ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose} 691ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 692ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 6939c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenekvoid CStringChecker::evalMemcpy(CheckerContext &C, const CallExpr *CE) { 694d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // void *memcpy(void *restrict dst, const void *restrict src, size_t n); 695d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // The return value is the address of the destination buffer. 696d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose const Expr *Dest = CE->getArg(0); 697ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const GRState *state = C.getState(); 698d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose state = state->BindExpr(CE, state->getSVal(Dest)); 6999c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek evalCopyCommon(C, state, CE->getArg(2), Dest, CE->getArg(1), true); 700d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose} 701ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 7029c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenekvoid CStringChecker::evalMemmove(CheckerContext &C, const CallExpr *CE) { 703d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // void *memmove(void *dst, const void *src, size_t n); 704ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // The return value is the address of the destination buffer. 705d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose const Expr *Dest = CE->getArg(0); 706d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose const GRState *state = C.getState(); 707d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose state = state->BindExpr(CE, state->getSVal(Dest)); 7089c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek evalCopyCommon(C, state, CE->getArg(2), Dest, CE->getArg(1)); 709ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose} 710ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 7119c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenekvoid CStringChecker::evalBcopy(CheckerContext &C, const CallExpr *CE) { 712d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // void bcopy(const void *src, void *dst, size_t n); 7139c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek evalCopyCommon(C, C.getState(), CE->getArg(2), CE->getArg(1), CE->getArg(0)); 714d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose} 715d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 7169c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenekvoid CStringChecker::evalMemcmp(CheckerContext &C, const CallExpr *CE) { 717bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose // int memcmp(const void *s1, const void *s2, size_t n); 718bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose const Expr *Left = CE->getArg(0); 719bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose const Expr *Right = CE->getArg(1); 720bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose const Expr *Size = CE->getArg(2); 721bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose 722bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose const GRState *state = C.getState(); 723c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SValBuilder &svalBuilder = C.getSValBuilder(); 724bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose 725d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // See if the size argument is zero. 726c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal sizeVal = state->getSVal(Size); 727c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek QualType sizeTy = Size->getType(); 728bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose 729c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek const GRState *stateZeroSize, *stateNonZeroSize; 730c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek llvm::tie(stateZeroSize, stateNonZeroSize) = 731c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek assumeZero(C, state, sizeVal, sizeTy); 732bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose 733d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // If the size can be zero, the result will be 0 in that case, and we don't 734d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // have to check either of the buffers. 735c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek if (stateZeroSize) { 736c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek state = stateZeroSize; 737c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek state = state->BindExpr(CE, svalBuilder.makeZeroVal(CE->getType())); 738d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose C.addTransition(state); 739bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose } 740bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose 741d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // If the size can be nonzero, we have to check the other arguments. 742c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek if (stateNonZeroSize) { 743c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek state = stateNonZeroSize; 744d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // If we know the two buffers are the same, we know the result is 0. 745d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // First, get the two buffers' addresses. Another checker will have already 746d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // made sure they're not undefined. 747d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose DefinedOrUnknownSVal LV = cast<DefinedOrUnknownSVal>(state->getSVal(Left)); 748d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose DefinedOrUnknownSVal RV = cast<DefinedOrUnknownSVal>(state->getSVal(Right)); 749d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 750d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // See if they are the same. 751c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek DefinedOrUnknownSVal SameBuf = svalBuilder.evalEQ(state, LV, RV); 752d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose const GRState *StSameBuf, *StNotSameBuf; 75328f47b92e760ccf641ac91cb0fe1c12d9ca89795Ted Kremenek llvm::tie(StSameBuf, StNotSameBuf) = state->assume(SameBuf); 754d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 755d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // If the two arguments might be the same buffer, we know the result is zero, 756d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // and we only need to check one size. 757d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (StSameBuf) { 758d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose state = StSameBuf; 759d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose state = CheckBufferAccess(C, state, Size, Left); 760d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (state) { 761c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek state = StSameBuf->BindExpr(CE, svalBuilder.makeZeroVal(CE->getType())); 762d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose C.addTransition(state); 763d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose } 764d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose } 765bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose 766d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // If the two arguments might be different buffers, we have to check the 767d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // size of both of them. 768d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (StNotSameBuf) { 769d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose state = StNotSameBuf; 770d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose state = CheckBufferAccess(C, state, Size, Left, Right); 771d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (state) { 772d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // The return value is the comparison result, which we don't know. 773d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose unsigned Count = C.getNodeBuilder().getCurrentBlockCount(); 774c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal CmpV = svalBuilder.getConjuredSymbolVal(NULL, CE, Count); 775d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose state = state->BindExpr(CE, CmpV); 776d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose C.addTransition(state); 777d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose } 778d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose } 779d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose } 780bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose} 781bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose 782c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenekvoid CStringChecker::evalstrLength(CheckerContext &C, const CallExpr *CE) { 78319c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose // size_t strlen(const char *s); 784be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek evalstrLengthCommon(C, CE, /* IsStrnlen = */ false); 785be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek} 786be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek 787be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenekvoid CStringChecker::evalstrnLength(CheckerContext &C, const CallExpr *CE) { 788be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek // size_t strnlen(const char *s, size_t maxlen); 789be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek evalstrLengthCommon(C, CE, /* IsStrnlen = */ true); 790be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek} 791be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek 792be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenekvoid CStringChecker::evalstrLengthCommon(CheckerContext &C, const CallExpr *CE, 793be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek bool IsStrnlen) { 79419c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose const GRState *state = C.getState(); 79519c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose const Expr *Arg = CE->getArg(0); 79619c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose SVal ArgVal = state->getSVal(Arg); 79719c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 79819c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose // Check that the argument is non-null. 799c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek state = checkNonNull(C, state, Arg, ArgVal); 80019c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 80119c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose if (state) { 802c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal strLength = getCStringLength(C, state, Arg, ArgVal); 803a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 804a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // If the argument isn't a valid C string, there's no valid state to 805a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // transition to. 806c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek if (strLength.isUndef()) 807a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose return; 808a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 809be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek // If the check is for strnlen() then bind the return value to no more than 810be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek // the maxlen value. 811be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek if (IsStrnlen) { 812be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek const Expr *maxlenExpr = CE->getArg(1); 813be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek SVal maxlenVal = state->getSVal(maxlenExpr); 814be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek 815be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek NonLoc *strLengthNL = dyn_cast<NonLoc>(&strLength); 816be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek NonLoc *maxlenValNL = dyn_cast<NonLoc>(&maxlenVal); 817be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek 818be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek QualType cmpTy = C.getSValBuilder().getContext().IntTy; 819be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek const GRState *stateTrue, *stateFalse; 820be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek 821be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek // Check if the strLength is greater than or equal to the maxlen 822be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek llvm::tie(stateTrue, stateFalse) = 823be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek state->assume(cast<DefinedOrUnknownSVal> 824be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek (C.getSValBuilder().evalBinOpNN(state, BO_GE, 825be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek *strLengthNL, *maxlenValNL, 826be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek cmpTy))); 827be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek 828be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek // If the strLength is greater than or equal to the maxlen, set strLength 829be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek // to maxlen 830be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek if (stateTrue && !stateFalse) { 831be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek strLength = maxlenVal; 832be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek } 833be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek } 834be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek 835c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek // If getCStringLength couldn't figure out the length, conjure a return 836a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // value, so it can be used in constraints, at least. 837c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek if (strLength.isUnknown()) { 838a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose unsigned Count = C.getNodeBuilder().getCurrentBlockCount(); 839c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek strLength = C.getSValBuilder().getConjuredSymbolVal(NULL, CE, Count); 84019c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose } 841a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 842a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // Bind the return value. 843c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek state = state->BindExpr(CE, strLength); 844a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose C.addTransition(state); 84519c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose } 84619c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose} 84719c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 8489c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenekvoid CStringChecker::evalStrcpy(CheckerContext &C, const CallExpr *CE) { 849e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // char *strcpy(char *restrict dst, const char *restrict src); 8500ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek evalStrcpyCommon(C, CE, /* returnEnd = */ false, /* isStrncpy = */ false); 8510ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek} 8520ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek 8530ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenekvoid CStringChecker::evalStrncpy(CheckerContext &C, const CallExpr *CE) { 8540ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek // char *strcpy(char *restrict dst, const char *restrict src); 8550ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek evalStrcpyCommon(C, CE, /* returnEnd = */ false, /* isStrncpy = */ true); 856e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose} 857e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 8589c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenekvoid CStringChecker::evalStpcpy(CheckerContext &C, const CallExpr *CE) { 859e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // char *stpcpy(char *restrict dst, const char *restrict src); 8600ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek evalStrcpyCommon(C, CE, /* returnEnd = */ true, /* isStrncpy = */ false); 861e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose} 862e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 8639c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenekvoid CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE, 8640ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek bool returnEnd, bool isStrncpy) { 865e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose const GRState *state = C.getState(); 866e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 867e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // Check that the destination is non-null 868e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose const Expr *Dst = CE->getArg(0); 869e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose SVal DstVal = state->getSVal(Dst); 870e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 871c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek state = checkNonNull(C, state, Dst, DstVal); 872e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose if (!state) 873e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose return; 874e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 875e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // Check that the source is non-null. 876c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek const Expr *srcExpr = CE->getArg(1); 877c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal srcVal = state->getSVal(srcExpr); 878c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek state = checkNonNull(C, state, srcExpr, srcVal); 879e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose if (!state) 880e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose return; 881e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 882e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // Get the string length of the source. 883c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal strLength = getCStringLength(C, state, srcExpr, srcVal); 884e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 885e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // If the source isn't a valid C string, give up. 886c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek if (strLength.isUndef()) 887e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose return; 888e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 8890ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek if (isStrncpy) { 8900ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek // Get the max number of characters to copy 8910ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek const Expr *lenExpr = CE->getArg(2); 8920ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek SVal lenVal = state->getSVal(lenExpr); 8930ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek 8940ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek NonLoc *strLengthNL = dyn_cast<NonLoc>(&strLength); 8950ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek NonLoc *lenValNL = dyn_cast<NonLoc>(&lenVal); 8960ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek 8970ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek QualType cmpTy = C.getSValBuilder().getContext().IntTy; 8980ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek const GRState *stateTrue, *stateFalse; 8990ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek 9000ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek // Check if the max number to copy is less than the length of the src 9010ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek llvm::tie(stateTrue, stateFalse) = 9020ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek state->assume(cast<DefinedOrUnknownSVal> 9030ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek (C.getSValBuilder().evalBinOpNN(state, BO_GT, 9040ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek *strLengthNL, *lenValNL, 9050ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek cmpTy))); 9060ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek 9070ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek if (stateTrue) { 9080ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek // Max number to copy is less than the length of the src, so the actual 9090ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek // strLength copied is the max number arg. 9100ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek strLength = lenVal; 9110ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek } 9120ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek } 9130ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek 914c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal Result = (returnEnd ? UnknownVal() : DstVal); 915e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 916e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // If the destination is a MemRegion, try to check for a buffer overflow and 917e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // record the new string length. 918c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek if (loc::MemRegionVal *dstRegVal = dyn_cast<loc::MemRegionVal>(&DstVal)) { 919e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // If the length is known, we can check for an overflow. 920c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek if (NonLoc *knownStrLength = dyn_cast<NonLoc>(&strLength)) { 921c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal lastElement = 922c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek C.getSValBuilder().evalBinOpLN(state, BO_Add, *dstRegVal, 923c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek *knownStrLength, Dst->getType()); 924e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 925c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek state = CheckLocation(C, state, Dst, lastElement, /* IsDst = */ true); 926e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose if (!state) 927e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose return; 928e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 929e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // If this is a stpcpy-style copy, the last element is the return value. 930c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek if (returnEnd) 931c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek Result = lastElement; 932e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose } 933e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 934e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // Invalidate the destination. This must happen before we set the C string 935e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // length because invalidation will clear the length. 936e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // FIXME: Even if we can't perfectly model the copy, we should see if we 937e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // can use LazyCompoundVals to copy the source values into the destination. 938e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // This would probably remove any existing bindings past the end of the 939e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // string, but that's still an improvement over blank invalidation. 940c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek state = InvalidateBuffer(C, state, Dst, *dstRegVal); 941e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 942e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // Set the C string length of the destination. 943c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek state = setCStringLength(state, dstRegVal->getRegion(), strLength); 944e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose } 945e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 946e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // If this is a stpcpy-style copy, but we were unable to check for a buffer 947e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // overflow, we still need a result. Conjure a return value. 948c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek if (returnEnd && Result.isUnknown()) { 949c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SValBuilder &svalBuilder = C.getSValBuilder(); 950e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose unsigned Count = C.getNodeBuilder().getCurrentBlockCount(); 951c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek strLength = svalBuilder.getConjuredSymbolVal(NULL, CE, Count); 952e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose } 953e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 954e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // Set the return value. 955e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose state = state->BindExpr(CE, Result); 956e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose C.addTransition(state); 957e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose} 958e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 959d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose//===----------------------------------------------------------------------===// 960a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose// The driver method, and other Checker callbacks. 961d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose//===----------------------------------------------------------------------===// 962ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 9639c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenekbool CStringChecker::evalCallExpr(CheckerContext &C, const CallExpr *CE) { 964ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Get the callee. All the functions we care about are C functions 965ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // with simple identifiers. 966ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const GRState *state = C.getState(); 967ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const Expr *Callee = CE->getCallee(); 968ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const FunctionDecl *FD = state->getSVal(Callee).getAsFunctionDecl(); 969ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 970ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (!FD) 971ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return false; 972ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 973ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Get the name of the callee. If it's a builtin, strip off the prefix. 97490d26a4afdbf6d917a5241ef3b316e1c8337c9b8Douglas Gregor IdentifierInfo *II = FD->getIdentifier(); 97590d26a4afdbf6d917a5241ef3b316e1c8337c9b8Douglas Gregor if (!II) // if no identifier, not a simple C function 97690d26a4afdbf6d917a5241ef3b316e1c8337c9b8Douglas Gregor return false; 97790d26a4afdbf6d917a5241ef3b316e1c8337c9b8Douglas Gregor llvm::StringRef Name = II->getName(); 978ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (Name.startswith("__builtin_")) 979ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose Name = Name.substr(10); 980ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 9819c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek FnCheck evalFunction = llvm::StringSwitch<FnCheck>(Name) 9829c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek .Cases("memcpy", "__memcpy_chk", &CStringChecker::evalMemcpy) 9839c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek .Cases("memcmp", "bcmp", &CStringChecker::evalMemcmp) 9849c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek .Cases("memmove", "__memmove_chk", &CStringChecker::evalMemmove) 9859c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek .Cases("strcpy", "__strcpy_chk", &CStringChecker::evalStrcpy) 9860ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek .Cases("strncpy", "__strncpy_chk", &CStringChecker::evalStrncpy) 9879c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek .Cases("stpcpy", "__stpcpy_chk", &CStringChecker::evalStpcpy) 988c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek .Case("strlen", &CStringChecker::evalstrLength) 989be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek .Case("strnlen", &CStringChecker::evalstrnLength) 9909c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek .Case("bcopy", &CStringChecker::evalBcopy) 991ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose .Default(NULL); 992ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 993d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // If the callee isn't a string function, let another checker handle it. 9949c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek if (!evalFunction) 995ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return false; 996ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 997d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // Check and evaluate the call. 9989c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek (this->*evalFunction)(C, CE); 999ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return true; 1000ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose} 1001a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1002a5261549754fab80e30e893d8fa706bfb31e430aJordy Rosevoid CStringChecker::PreVisitDeclStmt(CheckerContext &C, const DeclStmt *DS) { 1003a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // Record string length for char a[] = "abc"; 1004a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose const GRState *state = C.getState(); 1005a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1006a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose for (DeclStmt::const_decl_iterator I = DS->decl_begin(), E = DS->decl_end(); 1007a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose I != E; ++I) { 1008a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose const VarDecl *D = dyn_cast<VarDecl>(*I); 1009a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (!D) 1010a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose continue; 1011a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1012a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // FIXME: Handle array fields of structs. 1013a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (!D->getType()->isArrayType()) 1014a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose continue; 1015a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1016a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose const Expr *Init = D->getInit(); 1017a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (!Init) 1018a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose continue; 1019a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (!isa<StringLiteral>(Init)) 1020a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose continue; 1021a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1022a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose Loc VarLoc = state->getLValue(D, C.getPredecessor()->getLocationContext()); 1023a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose const MemRegion *MR = VarLoc.getAsRegion(); 1024a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (!MR) 1025a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose continue; 1026a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1027a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose SVal StrVal = state->getSVal(Init); 1028a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose assert(StrVal.isValid() && "Initializer string is unknown or undefined"); 1029c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek DefinedOrUnknownSVal strLength 1030c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek = cast<DefinedOrUnknownSVal>(getCStringLength(C, state, Init, StrVal)); 1031a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1032c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek state = state->set<CStringLength>(MR, strLength); 1033a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose } 1034a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1035a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose C.addTransition(state); 1036a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose} 1037a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1038e36de1fe51c39d9161915dd3dbef880954af6476Ted Kremenekbool CStringChecker::wantsRegionChangeUpdate(const GRState *state) { 1039a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose CStringLength::EntryMap Entries = state->get<CStringLength>(); 1040a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose return !Entries.isEmpty(); 1041a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose} 1042a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1043a5261549754fab80e30e893d8fa706bfb31e430aJordy Roseconst GRState *CStringChecker::EvalRegionChanges(const GRState *state, 1044a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose const MemRegion * const *Begin, 1045a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose const MemRegion * const *End, 1046a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose bool *) { 1047a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose CStringLength::EntryMap Entries = state->get<CStringLength>(); 1048a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (Entries.isEmpty()) 1049a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose return state; 1050a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1051a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose llvm::SmallPtrSet<const MemRegion *, 8> Invalidated; 1052a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose llvm::SmallPtrSet<const MemRegion *, 32> SuperRegions; 1053a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1054a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // First build sets for the changed regions and their super-regions. 1055a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose for ( ; Begin != End; ++Begin) { 1056a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose const MemRegion *MR = *Begin; 1057a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose Invalidated.insert(MR); 1058a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1059a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose SuperRegions.insert(MR); 1060a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose while (const SubRegion *SR = dyn_cast<SubRegion>(MR)) { 1061a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose MR = SR->getSuperRegion(); 1062a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose SuperRegions.insert(MR); 1063a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose } 1064a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose } 1065a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1066a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose CStringLength::EntryMap::Factory &F = state->get_context<CStringLength>(); 1067a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1068a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // Then loop over the entries in the current state. 1069a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose for (CStringLength::EntryMap::iterator I = Entries.begin(), 1070a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose E = Entries.end(); I != E; ++I) { 1071a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose const MemRegion *MR = I.getKey(); 1072a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1073a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // Is this entry for a super-region of a changed region? 1074a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (SuperRegions.count(MR)) { 10753baf672378f105602d2b12f03f00277ae1936fe9Ted Kremenek Entries = F.remove(Entries, MR); 1076a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose continue; 1077a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose } 1078a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1079a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // Is this entry for a sub-region of a changed region? 1080a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose const MemRegion *Super = MR; 1081a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose while (const SubRegion *SR = dyn_cast<SubRegion>(Super)) { 1082a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose Super = SR->getSuperRegion(); 1083a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (Invalidated.count(Super)) { 10843baf672378f105602d2b12f03f00277ae1936fe9Ted Kremenek Entries = F.remove(Entries, MR); 1085a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose break; 1086a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose } 1087a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose } 1088a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose } 1089a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1090a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose return state->set<CStringLength>(Entries); 1091a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose} 1092a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1093a5261549754fab80e30e893d8fa706bfb31e430aJordy Rosevoid CStringChecker::MarkLiveSymbols(const GRState *state, SymbolReaper &SR) { 1094a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // Mark all symbols in our string length map as valid. 1095a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose CStringLength::EntryMap Entries = state->get<CStringLength>(); 1096a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1097a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose for (CStringLength::EntryMap::iterator I = Entries.begin(), E = Entries.end(); 1098a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose I != E; ++I) { 1099a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose SVal Len = I.getData(); 1100a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (SymbolRef Sym = Len.getAsSymbol()) 1101a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose SR.markInUse(Sym); 1102a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose } 1103a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose} 1104a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 11059c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenekvoid CStringChecker::evalDeadSymbols(CheckerContext &C, SymbolReaper &SR) { 1106a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (!SR.hasDeadSymbols()) 1107a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose return; 1108a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1109a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose const GRState *state = C.getState(); 1110a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose CStringLength::EntryMap Entries = state->get<CStringLength>(); 1111a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (Entries.isEmpty()) 1112a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose return; 1113a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1114a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose CStringLength::EntryMap::Factory &F = state->get_context<CStringLength>(); 1115a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose for (CStringLength::EntryMap::iterator I = Entries.begin(), E = Entries.end(); 1116a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose I != E; ++I) { 1117a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose SVal Len = I.getData(); 1118a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (SymbolRef Sym = Len.getAsSymbol()) { 1119a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (SR.isDead(Sym)) 11203baf672378f105602d2b12f03f00277ae1936fe9Ted Kremenek Entries = F.remove(Entries, I.getKey()); 1121a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose } 1122a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose } 1123a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1124a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose state = state->set<CStringLength>(Entries); 1125d048c6ef5b6cfaa0cecb8cc1d4bdace32ed21d07Ted Kremenek C.generateNode(state); 1126a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose} 1127