CStringChecker.cpp revision 22d27178bf795145439b9588e260ccceab79a088
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" 16ec8605f1d7ec846dbf51047bfd5c56d32d1ff91cArgyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/Checker.h" 17695fb502825a53ccd178ec1c85c77929d88acb71Argyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/CheckerManager.h" 18183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 199b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 209b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h" 21ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose#include "llvm/ADT/StringSwitch.h" 22ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 23ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Roseusing namespace clang; 249ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenekusing namespace ento; 25ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 26ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rosenamespace { 27ec8605f1d7ec846dbf51047bfd5c56d32d1ff91cArgyrios Kyrtzidisclass CStringChecker : public Checker< eval::Call, 28183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis check::PreStmt<DeclStmt>, 29183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis check::LiveSymbols, 30183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis check::DeadSymbols, 31183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis check::RegionChanges 32183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis > { 33183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis mutable llvm::OwningPtr<BugType> BT_Null, BT_Bounds, BT_BoundsWrite, 34183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis BT_Overlap, BT_NotCString; 35ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rosepublic: 36ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose static void *getTag() { static int tag; return &tag; } 37ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 38183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis bool evalCall(const CallExpr *CE, CheckerContext &C) const; 39183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis void checkPreStmt(const DeclStmt *DS, CheckerContext &C) const; 40183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis void checkLiveSymbols(const GRState *state, SymbolReaper &SR) const; 41183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const; 42183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis bool wantsRegionChangeUpdate(const GRState *state) const; 43a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 44183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis const GRState *checkRegionChanges(const GRState *state, 4535bdbf40624beba3fc00cb72ab444659939c1a6bTed Kremenek const StoreManager::InvalidatedSymbols *, 46183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis const MemRegion * const *Begin, 47183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis const MemRegion * const *End) const; 48ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 49183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis typedef void (CStringChecker::*FnCheck)(CheckerContext &, 50183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis const CallExpr *) const; 51ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 52183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis void evalMemcpy(CheckerContext &C, const CallExpr *CE) const; 53b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani void evalMempcpy(CheckerContext &C, const CallExpr *CE) const; 54183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis void evalMemmove(CheckerContext &C, const CallExpr *CE) const; 55183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis void evalBcopy(CheckerContext &C, const CallExpr *CE) const; 56b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani void evalCopyCommon(CheckerContext &C, const CallExpr *CE, 57b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani const GRState *state, 58d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose const Expr *Size, const Expr *Source, const Expr *Dest, 59b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani bool Restricted = false, 60b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani bool IsMempcpy = false) const; 61d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 62183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis void evalMemcmp(CheckerContext &C, const CallExpr *CE) const; 63ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 64183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis void evalstrLength(CheckerContext &C, const CallExpr *CE) const; 65183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis void evalstrnLength(CheckerContext &C, const CallExpr *CE) const; 66be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek void evalstrLengthCommon(CheckerContext &C, const CallExpr *CE, 67183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis bool IsStrnlen = false) const; 6819c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 69183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis void evalStrcpy(CheckerContext &C, const CallExpr *CE) const; 70183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis void evalStrncpy(CheckerContext &C, const CallExpr *CE) const; 71183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis void evalStpcpy(CheckerContext &C, const CallExpr *CE) const; 720ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek void evalStrcpyCommon(CheckerContext &C, const CallExpr *CE, bool returnEnd, 73067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani bool isBounded, bool isAppending) const; 74067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani 75067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani void evalStrcat(CheckerContext &C, const CallExpr *CE) const; 76067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani void evalStrncat(CheckerContext &C, const CallExpr *CE) const; 77e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 78318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani void evalStrcmp(CheckerContext &C, const CallExpr *CE) const; 79357f6ee9f1f6f8e5027377cb3e5907c62c4fe3dfLenny Maiorani void evalStrncmp(CheckerContext &C, const CallExpr *CE) const; 80bd1d16a1792cd6ea5ede9869e18d781e3fc1a8c3Lenny Maiorani void evalStrcasecmp(CheckerContext &C, const CallExpr *CE) const; 81454fd2d3a1b6d0ef225c5d3927c1ad3b97510d1aLenny Maiorani void evalStrncasecmp(CheckerContext &C, const CallExpr *CE) const; 82357f6ee9f1f6f8e5027377cb3e5907c62c4fe3dfLenny Maiorani void evalStrcmpCommon(CheckerContext &C, const CallExpr *CE, 83bd1d16a1792cd6ea5ede9869e18d781e3fc1a8c3Lenny Maiorani bool isBounded = false, bool ignoreCase = false) const; 84318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani 85ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Utility methods 86d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose std::pair<const GRState*, const GRState*> 87183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis static assumeZero(CheckerContext &C, 88183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis const GRState *state, SVal V, QualType Ty); 89183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis 90183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis static const GRState *setCStringLength(const GRState *state, 91183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis const MemRegion *MR, SVal strLength); 92183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis static SVal getCStringLengthForRegion(CheckerContext &C, 93183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis const GRState *&state, 94183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis const Expr *Ex, const MemRegion *MR); 95c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal getCStringLength(CheckerContext &C, const GRState *&state, 96183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis const Expr *Ex, SVal Buf) const; 9719c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 98318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani const StringLiteral *getCStringLiteral(CheckerContext &C, 99318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani const GRState *&state, 100318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani const Expr *expr, 101318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani SVal val) const; 102318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani 103183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis static const GRState *InvalidateBuffer(CheckerContext &C, 104183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis const GRState *state, 105183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis const Expr *Ex, SVal V); 106e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 107183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis static bool SummarizeRegion(llvm::raw_ostream& os, ASTContext& Ctx, 108183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis const MemRegion *MR); 10919c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 11019c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose // Re-usable checks 111c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek const GRState *checkNonNull(CheckerContext &C, const GRState *state, 112183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis const Expr *S, SVal l) const; 113ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const GRState *CheckLocation(CheckerContext &C, const GRState *state, 114e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose const Expr *S, SVal l, 115183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis bool IsDestination = false) const; 116ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const GRState *CheckBufferAccess(CheckerContext &C, const GRState *state, 117ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const Expr *Size, 118ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const Expr *FirstBuf, 119e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose const Expr *SecondBuf = NULL, 120183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis bool FirstIsDestination = false) const; 121ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const GRState *CheckOverlap(CheckerContext &C, const GRState *state, 122d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose const Expr *Size, const Expr *First, 123183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis const Expr *Second) const; 124c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek void emitOverlapBug(CheckerContext &C, const GRState *state, 125183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis const Stmt *First, const Stmt *Second) const; 126ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose}; 127a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 128a5261549754fab80e30e893d8fa706bfb31e430aJordy Roseclass CStringLength { 129a5261549754fab80e30e893d8fa706bfb31e430aJordy Rosepublic: 130a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose typedef llvm::ImmutableMap<const MemRegion *, SVal> EntryMap; 131a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose}; 132ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose} //end anonymous namespace 133ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 134a5261549754fab80e30e893d8fa706bfb31e430aJordy Rosenamespace clang { 1359ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremeneknamespace ento { 136a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose template <> 137a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose struct GRStateTrait<CStringLength> 138a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose : public GRStatePartialTrait<CStringLength::EntryMap> { 139a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose static void *GDMIndex() { return CStringChecker::getTag(); } 140a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose }; 141a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose} 1425a4f98ff943e6a501b0fe47ade007c9bbf96cb88Argyrios Kyrtzidis} 143a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 144d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose//===----------------------------------------------------------------------===// 145d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose// Individual checks and utility methods. 146d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose//===----------------------------------------------------------------------===// 147d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 148d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rosestd::pair<const GRState*, const GRState*> 14928f47b92e760ccf641ac91cb0fe1c12d9ca89795Ted KremenekCStringChecker::assumeZero(CheckerContext &C, const GRState *state, SVal V, 150d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose QualType Ty) { 151c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek DefinedSVal *val = dyn_cast<DefinedSVal>(&V); 152c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek if (!val) 153d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose return std::pair<const GRState*, const GRState *>(state, state); 154a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose 155c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SValBuilder &svalBuilder = C.getSValBuilder(); 156c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek DefinedOrUnknownSVal zero = svalBuilder.makeZeroVal(Ty); 157c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek return state->assume(svalBuilder.evalEQ(state, *val, zero)); 158d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose} 159d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 160c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenekconst GRState *CStringChecker::checkNonNull(CheckerContext &C, 161d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose const GRState *state, 162183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis const Expr *S, SVal l) const { 163d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // If a previous check has failed, propagate the failure. 164d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (!state) 165d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose return NULL; 166a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose 167d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose const GRState *stateNull, *stateNonNull; 16828f47b92e760ccf641ac91cb0fe1c12d9ca89795Ted Kremenek llvm::tie(stateNull, stateNonNull) = assumeZero(C, state, l, S->getType()); 169a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose 170d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (stateNull && !stateNonNull) { 171d048c6ef5b6cfaa0cecb8cc1d4bdace32ed21d07Ted Kremenek ExplodedNode *N = C.generateSink(stateNull); 172a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose if (!N) 173a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose return NULL; 174a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose 175d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (!BT_Null) 176183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis BT_Null.reset(new BuiltinBug("API", 177183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis "Null pointer argument in call to byte string function")); 178a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose 179a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose // Generate a report for this bug. 180183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis BuiltinBug *BT = static_cast<BuiltinBug*>(BT_Null.get()); 181a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose EnhancedBugReport *report = new EnhancedBugReport(*BT, 182a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose BT->getDescription(), N); 183a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose 184a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose report->addRange(S->getSourceRange()); 185a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, S); 186a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose C.EmitReport(report); 187a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose return NULL; 188a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose } 189a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose 190a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose // From here on, assume that the value is non-null. 191d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose assert(stateNonNull); 192d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose return stateNonNull; 193a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose} 194a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose 195ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose// FIXME: This was originally copied from ArrayBoundChecker.cpp. Refactor? 196ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Roseconst GRState *CStringChecker::CheckLocation(CheckerContext &C, 197ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const GRState *state, 198e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose const Expr *S, SVal l, 199183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis bool IsDestination) const { 200d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // If a previous check has failed, propagate the failure. 201d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (!state) 202d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose return NULL; 203d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 204ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Check for out of bound array element access. 205ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const MemRegion *R = l.getAsRegion(); 206ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (!R) 207ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return state; 208ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 209ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const ElementRegion *ER = dyn_cast<ElementRegion>(R); 210ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (!ER) 211ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return state; 212ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 213018220c343c103b7dfaa117a7a474c7a7fd6d068Zhongxing Xu assert(ER->getValueType() == C.getASTContext().CharTy && 214ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose "CheckLocation should only be called with char* ElementRegions"); 215ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 216ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Get the size of the array. 217c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek const SubRegion *superReg = cast<SubRegion>(ER->getSuperRegion()); 218c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SValBuilder &svalBuilder = C.getSValBuilder(); 219c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal Extent = svalBuilder.convertToArrayIndex(superReg->getExtent(svalBuilder)); 220ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose DefinedOrUnknownSVal Size = cast<DefinedOrUnknownSVal>(Extent); 221ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 222ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Get the index of the accessed element. 22389b06584402a38933e108b66ded3a168cd492dffGabor Greif DefinedOrUnknownSVal Idx = cast<DefinedOrUnknownSVal>(ER->getIndex()); 224ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 22528f47b92e760ccf641ac91cb0fe1c12d9ca89795Ted Kremenek const GRState *StInBound = state->assumeInBound(Idx, Size, true); 22628f47b92e760ccf641ac91cb0fe1c12d9ca89795Ted Kremenek const GRState *StOutBound = state->assumeInBound(Idx, Size, false); 227ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (StOutBound && !StInBound) { 228d048c6ef5b6cfaa0cecb8cc1d4bdace32ed21d07Ted Kremenek ExplodedNode *N = C.generateSink(StOutBound); 229ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (!N) 230ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return NULL; 231ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 232e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose BuiltinBug *BT; 233e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose if (IsDestination) { 234e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose if (!BT_BoundsWrite) { 235183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis BT_BoundsWrite.reset(new BuiltinBug("Out-of-bound array access", 236183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis "Byte string function overflows destination buffer")); 237e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose } 238183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis BT = static_cast<BuiltinBug*>(BT_BoundsWrite.get()); 239e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose } else { 240e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose if (!BT_Bounds) { 241183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis BT_Bounds.reset(new BuiltinBug("Out-of-bound array access", 242183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis "Byte string function accesses out-of-bound array element")); 243e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose } 244183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis BT = static_cast<BuiltinBug*>(BT_Bounds.get()); 245e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose } 246ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 247ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // FIXME: It would be nice to eventually make this diagnostic more clear, 248ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // e.g., by referencing the original declaration or by saying *why* this 249ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // reference is outside the range. 250ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 251ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Generate a report for this bug. 252ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose RangedBugReport *report = new RangedBugReport(*BT, BT->getDescription(), N); 253ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 254ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose report->addRange(S->getSourceRange()); 255ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose C.EmitReport(report); 256ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return NULL; 257ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose } 258ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 259ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Array bound check succeeded. From this point forward the array bound 260ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // should always succeed. 261ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return StInBound; 262ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose} 263ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 264ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Roseconst GRState *CStringChecker::CheckBufferAccess(CheckerContext &C, 265ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const GRState *state, 266ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const Expr *Size, 267ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const Expr *FirstBuf, 268e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose const Expr *SecondBuf, 269183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis bool FirstIsDestination) const { 270d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // If a previous check has failed, propagate the failure. 271d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (!state) 272d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose return NULL; 273d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 274c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SValBuilder &svalBuilder = C.getSValBuilder(); 275ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose ASTContext &Ctx = C.getASTContext(); 276ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 277c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek QualType sizeTy = Size->getType(); 278ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose QualType PtrTy = Ctx.getPointerType(Ctx.CharTy); 279ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 280a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose // Check that the first buffer is non-null. 281a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose SVal BufVal = state->getSVal(FirstBuf); 282c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek state = checkNonNull(C, state, FirstBuf, BufVal); 283a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose if (!state) 284a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose return NULL; 285a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose 286d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // Get the access length and make sure it is known. 287d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose SVal LengthVal = state->getSVal(Size); 288d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose NonLoc *Length = dyn_cast<NonLoc>(&LengthVal); 289d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (!Length) 290d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose return state; 291d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 292ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Compute the offset of the last element to be accessed: size-1. 293c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek NonLoc One = cast<NonLoc>(svalBuilder.makeIntVal(1, sizeTy)); 294c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek NonLoc LastOffset = cast<NonLoc>(svalBuilder.evalBinOpNN(state, BO_Sub, 295c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek *Length, One, sizeTy)); 296ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 297fc8f0e14ad142ed811e90fbd9a30e419e301c717Chris Lattner // Check that the first buffer is sufficiently long. 298c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal BufStart = svalBuilder.evalCast(BufVal, PtrTy, FirstBuf->getType()); 299b6a4026de13909c2b145166ae0b7d96cf1948f64Jordy Rose if (Loc *BufLoc = dyn_cast<Loc>(&BufStart)) { 300c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal BufEnd = svalBuilder.evalBinOpLN(state, BO_Add, *BufLoc, 301c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek LastOffset, PtrTy); 302e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose state = CheckLocation(C, state, FirstBuf, BufEnd, FirstIsDestination); 303ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 304b6a4026de13909c2b145166ae0b7d96cf1948f64Jordy Rose // If the buffer isn't large enough, abort. 305b6a4026de13909c2b145166ae0b7d96cf1948f64Jordy Rose if (!state) 306b6a4026de13909c2b145166ae0b7d96cf1948f64Jordy Rose return NULL; 307b6a4026de13909c2b145166ae0b7d96cf1948f64Jordy Rose } 308ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 309ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // If there's a second buffer, check it as well. 310ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (SecondBuf) { 311ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose BufVal = state->getSVal(SecondBuf); 312c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek state = checkNonNull(C, state, SecondBuf, BufVal); 313a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose if (!state) 314a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose return NULL; 315a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose 316c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek BufStart = svalBuilder.evalCast(BufVal, PtrTy, SecondBuf->getType()); 317b6a4026de13909c2b145166ae0b7d96cf1948f64Jordy Rose if (Loc *BufLoc = dyn_cast<Loc>(&BufStart)) { 318c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal BufEnd = svalBuilder.evalBinOpLN(state, BO_Add, *BufLoc, 319c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek LastOffset, PtrTy); 320b6a4026de13909c2b145166ae0b7d96cf1948f64Jordy Rose state = CheckLocation(C, state, SecondBuf, BufEnd); 321b6a4026de13909c2b145166ae0b7d96cf1948f64Jordy Rose } 322ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose } 323ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 324ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Large enough or not, return this state! 325ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return state; 326ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose} 327ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 328ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Roseconst GRState *CStringChecker::CheckOverlap(CheckerContext &C, 329ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const GRState *state, 330d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose const Expr *Size, 331ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const Expr *First, 332183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis const Expr *Second) const { 333ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Do a simple check for overlap: if the two arguments are from the same 334ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // buffer, see if the end of the first is greater than the start of the second 335ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // or vice versa. 336ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 337d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // If a previous check has failed, propagate the failure. 338d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (!state) 339d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose return NULL; 340d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 341ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const GRState *stateTrue, *stateFalse; 342ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 343ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Get the buffer values and make sure they're known locations. 344c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal firstVal = state->getSVal(First); 345c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal secondVal = state->getSVal(Second); 346ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 347c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek Loc *firstLoc = dyn_cast<Loc>(&firstVal); 348c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek if (!firstLoc) 349ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return state; 350ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 351c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek Loc *secondLoc = dyn_cast<Loc>(&secondVal); 352c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek if (!secondLoc) 353ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return state; 354ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 355ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Are the two values the same? 356c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SValBuilder &svalBuilder = C.getSValBuilder(); 357c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek llvm::tie(stateTrue, stateFalse) = 358c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek state->assume(svalBuilder.evalEQ(state, *firstLoc, *secondLoc)); 359ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 360ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (stateTrue && !stateFalse) { 361ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // If the values are known to be equal, that's automatically an overlap. 362c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek emitOverlapBug(C, stateTrue, First, Second); 363ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return NULL; 364ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose } 365ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 36628f47b92e760ccf641ac91cb0fe1c12d9ca89795Ted Kremenek // assume the two expressions are not equal. 367ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose assert(stateFalse); 368ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose state = stateFalse; 369ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 370ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Which value comes first? 371c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek ASTContext &Ctx = svalBuilder.getContext(); 372c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek QualType cmpTy = Ctx.IntTy; 373c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal reverse = svalBuilder.evalBinOpLL(state, BO_GT, 374c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek *firstLoc, *secondLoc, cmpTy); 375c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek DefinedOrUnknownSVal *reverseTest = dyn_cast<DefinedOrUnknownSVal>(&reverse); 376c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek if (!reverseTest) 377ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return state; 378ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 379c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek llvm::tie(stateTrue, stateFalse) = state->assume(*reverseTest); 380ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (stateTrue) { 381ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (stateFalse) { 382ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // If we don't know which one comes first, we can't perform this test. 383ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return state; 384ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose } else { 385c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek // Switch the values so that firstVal is before secondVal. 386c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek Loc *tmpLoc = firstLoc; 387c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek firstLoc = secondLoc; 388c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek secondLoc = tmpLoc; 389ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 390ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Switch the Exprs as well, so that they still correspond. 391ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const Expr *tmpExpr = First; 392ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose First = Second; 393ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose Second = tmpExpr; 394ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose } 395ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose } 396ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 397ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Get the length, and make sure it too is known. 398ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose SVal LengthVal = state->getSVal(Size); 399ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose NonLoc *Length = dyn_cast<NonLoc>(&LengthVal); 400ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (!Length) 401ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return state; 402ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 403ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Convert the first buffer's start address to char*. 404ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Bail out if the cast fails. 405ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose QualType CharPtrTy = Ctx.getPointerType(Ctx.CharTy); 406c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal FirstStart = svalBuilder.evalCast(*firstLoc, CharPtrTy, First->getType()); 407ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose Loc *FirstStartLoc = dyn_cast<Loc>(&FirstStart); 408ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (!FirstStartLoc) 409ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return state; 410ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 411ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Compute the end of the first buffer. Bail out if THAT fails. 412c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal FirstEnd = svalBuilder.evalBinOpLN(state, BO_Add, 413ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose *FirstStartLoc, *Length, CharPtrTy); 414ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose Loc *FirstEndLoc = dyn_cast<Loc>(&FirstEnd); 415ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (!FirstEndLoc) 416ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return state; 417ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 418ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Is the end of the first buffer past the start of the second buffer? 419c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal Overlap = svalBuilder.evalBinOpLL(state, BO_GT, 420c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek *FirstEndLoc, *secondLoc, cmpTy); 421ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose DefinedOrUnknownSVal *OverlapTest = dyn_cast<DefinedOrUnknownSVal>(&Overlap); 422ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (!OverlapTest) 423ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return state; 424ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 42528f47b92e760ccf641ac91cb0fe1c12d9ca89795Ted Kremenek llvm::tie(stateTrue, stateFalse) = state->assume(*OverlapTest); 426ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 427ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (stateTrue && !stateFalse) { 428ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Overlap! 429c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek emitOverlapBug(C, stateTrue, First, Second); 430ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return NULL; 431ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose } 432ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 43328f47b92e760ccf641ac91cb0fe1c12d9ca89795Ted Kremenek // assume the two expressions don't overlap. 434ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose assert(stateFalse); 435ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return stateFalse; 436ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose} 437ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 438c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenekvoid CStringChecker::emitOverlapBug(CheckerContext &C, const GRState *state, 439183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis const Stmt *First, const Stmt *Second) const { 440d048c6ef5b6cfaa0cecb8cc1d4bdace32ed21d07Ted Kremenek ExplodedNode *N = C.generateSink(state); 441ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (!N) 442ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return; 443ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 444ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (!BT_Overlap) 445183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis BT_Overlap.reset(new BugType("Unix API", "Improper arguments")); 446ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 447ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Generate a report for this bug. 448ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose RangedBugReport *report = 449ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose new RangedBugReport(*BT_Overlap, 450ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose "Arguments must not be overlapping buffers", N); 451ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose report->addRange(First->getSourceRange()); 452ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose report->addRange(Second->getSourceRange()); 453ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 454ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose C.EmitReport(report); 455ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose} 456ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 457c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenekconst GRState *CStringChecker::setCStringLength(const GRState *state, 458e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose const MemRegion *MR, 459c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal strLength) { 460c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek assert(!strLength.isUndef() && "Attempt to set an undefined string length"); 461c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek if (strLength.isUnknown()) 462e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose return state; 463e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 464e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose MR = MR->StripCasts(); 465e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 466e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose switch (MR->getKind()) { 467e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose case MemRegion::StringRegionKind: 468e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // FIXME: This can happen if we strcpy() into a string region. This is 469e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // undefined [C99 6.4.5p6], but we should still warn about it. 470e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose return state; 471e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 472e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose case MemRegion::SymbolicRegionKind: 473e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose case MemRegion::AllocaRegionKind: 474e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose case MemRegion::VarRegionKind: 475e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose case MemRegion::FieldRegionKind: 476e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose case MemRegion::ObjCIvarRegionKind: 477c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek return state->set<CStringLength>(MR, strLength); 478e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 479e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose case MemRegion::ElementRegionKind: 480e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // FIXME: Handle element regions by upper-bounding the parent region's 481e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // string length. 482e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose return state; 483e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 484e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose default: 485e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // Other regions (mostly non-data) can't have a reliable C string length. 486e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // For now, just ignore the change. 487e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // FIXME: These are rare but not impossible. We should output some kind of 488e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // warning for things like strcpy((char[]){'a', 0}, "b"); 489e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose return state; 490e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose } 491e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose} 492e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 493c8413fd03f73084a5c93028f8b4db619fc388087Ted KremenekSVal CStringChecker::getCStringLengthForRegion(CheckerContext &C, 494a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose const GRState *&state, 495a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose const Expr *Ex, 496a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose const MemRegion *MR) { 497a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // If there's a recorded length, go ahead and return it. 498a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose const SVal *Recorded = state->get<CStringLength>(MR); 499a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (Recorded) 500a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose return *Recorded; 501a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 502a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // Otherwise, get a new symbol and update the state. 503a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose unsigned Count = C.getNodeBuilder().getCurrentBlockCount(); 504c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SValBuilder &svalBuilder = C.getSValBuilder(); 505c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek QualType sizeTy = svalBuilder.getContext().getSizeType(); 506183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis SVal strLength = svalBuilder.getMetadataSymbolVal(CStringChecker::getTag(), 507183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis MR, Ex, sizeTy, Count); 508c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek state = state->set<CStringLength>(MR, strLength); 509c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek return strLength; 510a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose} 511a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 512c8413fd03f73084a5c93028f8b4db619fc388087Ted KremenekSVal CStringChecker::getCStringLength(CheckerContext &C, const GRState *&state, 513183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis const Expr *Ex, SVal Buf) const { 51419c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose const MemRegion *MR = Buf.getAsRegion(); 51519c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose if (!MR) { 51619c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose // If we can't get a region, see if it's something we /know/ isn't a 51719c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose // C string. In the context of locations, the only time we can issue such 51819c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose // a warning is for labels. 51919c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose if (loc::GotoLabel *Label = dyn_cast<loc::GotoLabel>(&Buf)) { 520d048c6ef5b6cfaa0cecb8cc1d4bdace32ed21d07Ted Kremenek if (ExplodedNode *N = C.generateNode(state)) { 52119c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose if (!BT_NotCString) 522183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis BT_NotCString.reset(new BuiltinBug("API", 523183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis "Argument is not a null-terminated string.")); 52419c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 52519c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose llvm::SmallString<120> buf; 52619c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose llvm::raw_svector_ostream os(buf); 52719c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose os << "Argument to byte string function is the address of the label '" 5286810630bb00ba2944cbeb54834f38f69dbddfd7fChris Lattner << Label->getLabel()->getName() 52919c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose << "', which is not a null-terminated string"; 53019c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 53119c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose // Generate a report for this bug. 53219c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose EnhancedBugReport *report = new EnhancedBugReport(*BT_NotCString, 53319c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose os.str(), N); 53419c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 53519c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose report->addRange(Ex->getSourceRange()); 53619c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose C.EmitReport(report); 53719c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose } 53819c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 53919c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose return UndefinedVal(); 54019c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose } 54119c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 542a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // If it's not a region and not a label, give up. 543a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose return UnknownVal(); 544a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose } 54519c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 546a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // If we have a region, strip casts from it and see if we can figure out 547a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // its length. For anything we can't figure out, just return UnknownVal. 548a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose MR = MR->StripCasts(); 549a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 550a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose switch (MR->getKind()) { 551a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose case MemRegion::StringRegionKind: { 552a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // Modifying the contents of string regions is undefined [C99 6.4.5p6], 553a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // so we can assume that the byte length is the correct C string length. 554c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SValBuilder &svalBuilder = C.getSValBuilder(); 555c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek QualType sizeTy = svalBuilder.getContext().getSizeType(); 556c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek const StringLiteral *strLit = cast<StringRegion>(MR)->getStringLiteral(); 557c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek return svalBuilder.makeIntVal(strLit->getByteLength(), sizeTy); 558a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose } 559a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose case MemRegion::SymbolicRegionKind: 560a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose case MemRegion::AllocaRegionKind: 561a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose case MemRegion::VarRegionKind: 562a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose case MemRegion::FieldRegionKind: 563a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose case MemRegion::ObjCIvarRegionKind: 564c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek return getCStringLengthForRegion(C, state, Ex, MR); 565a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose case MemRegion::CompoundLiteralRegionKind: 566a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // FIXME: Can we track this? Is it necessary? 567a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose return UnknownVal(); 568a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose case MemRegion::ElementRegionKind: 569a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // FIXME: How can we handle this? It's not good enough to subtract the 570a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // offset from the base string length; consider "123\x00567" and &a[5]. 571a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose return UnknownVal(); 572a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose default: 573a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // Other regions (mostly non-data) can't have a reliable C string length. 574a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // In this case, an error is emitted and UndefinedVal is returned. 575a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // The caller should always be prepared to handle this case. 576d048c6ef5b6cfaa0cecb8cc1d4bdace32ed21d07Ted Kremenek if (ExplodedNode *N = C.generateNode(state)) { 577a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (!BT_NotCString) 578183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis BT_NotCString.reset(new BuiltinBug("API", 579183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis "Argument is not a null-terminated string.")); 580a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 581a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose llvm::SmallString<120> buf; 582a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose llvm::raw_svector_ostream os(buf); 583a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 584a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose os << "Argument to byte string function is "; 585a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 586a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (SummarizeRegion(os, C.getASTContext(), MR)) 587a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose os << ", which is not a null-terminated string"; 588a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose else 589a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose os << "not a null-terminated string"; 590a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 591a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // Generate a report for this bug. 592a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose EnhancedBugReport *report = new EnhancedBugReport(*BT_NotCString, 593a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose os.str(), N); 594a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 595a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose report->addRange(Ex->getSourceRange()); 596a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose C.EmitReport(report); 59719c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose } 59819c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 599a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose return UndefinedVal(); 60019c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose } 60119c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose} 60219c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 603318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maioraniconst StringLiteral *CStringChecker::getCStringLiteral(CheckerContext &C, 604318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani const GRState *&state, const Expr *expr, SVal val) const { 605318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani 606318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani // Get the memory region pointed to by the val. 607318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani const MemRegion *bufRegion = val.getAsRegion(); 608318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani if (!bufRegion) 609318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani return NULL; 610318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani 611318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani // Strip casts off the memory region. 612318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani bufRegion = bufRegion->StripCasts(); 613318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani 614318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani // Cast the memory region to a string region. 615318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani const StringRegion *strRegion= dyn_cast<StringRegion>(bufRegion); 616318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani if (!strRegion) 617318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani return NULL; 618318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani 619318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani // Return the actual string in the string region. 620318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani return strRegion->getStringLiteral(); 621318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani} 622318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani 623e64f311c11a8751867c2538807054f4817c1f5cbJordy Roseconst GRState *CStringChecker::InvalidateBuffer(CheckerContext &C, 624e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose const GRState *state, 625e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose const Expr *E, SVal V) { 626e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose Loc *L = dyn_cast<Loc>(&V); 627e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose if (!L) 628e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose return state; 629e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 630e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // FIXME: This is a simplified version of what's in CFRefCount.cpp -- it makes 631e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // some assumptions about the value that CFRefCount can't. Even so, it should 632e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // probably be refactored. 633e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose if (loc::MemRegionVal* MR = dyn_cast<loc::MemRegionVal>(L)) { 634e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose const MemRegion *R = MR->getRegion()->StripCasts(); 635e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 636e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // Are we dealing with an ElementRegion? If so, we should be invalidating 637e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // the super-region. 638e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) { 639e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose R = ER->getSuperRegion(); 640e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // FIXME: What about layers of ElementRegions? 641e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose } 642e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 643e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // Invalidate this region. 644e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose unsigned Count = C.getNodeBuilder().getCurrentBlockCount(); 6452534528c22260211a073e192c38d0db84c70c327Ted Kremenek return state->invalidateRegion(R, E, Count, NULL); 646e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose } 647e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 648e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // If we have a non-region value by chance, just remove the binding. 649e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // FIXME: is this necessary or correct? This handles the non-Region 650e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // cases. Is it ever valid to store to these? 651e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose return state->unbindLoc(*L); 652e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose} 653e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 65419c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rosebool CStringChecker::SummarizeRegion(llvm::raw_ostream& os, ASTContext& Ctx, 65519c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose const MemRegion *MR) { 65619c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose const TypedRegion *TR = dyn_cast<TypedRegion>(MR); 65719c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose if (!TR) 65819c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose return false; 65919c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 66019c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose switch (TR->getKind()) { 66119c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose case MemRegion::FunctionTextRegionKind: { 66219c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose const FunctionDecl *FD = cast<FunctionTextRegion>(TR)->getDecl(); 66319c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose if (FD) 66419c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose os << "the address of the function '" << FD << "'"; 66519c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose else 66619c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose os << "the address of a function"; 66719c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose return true; 66819c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose } 66919c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose case MemRegion::BlockTextRegionKind: 67019c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose os << "block text"; 67119c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose return true; 67219c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose case MemRegion::BlockDataRegionKind: 67319c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose os << "a block"; 67419c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose return true; 67519c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose case MemRegion::CXXThisRegionKind: 67602fe28c8a6da29d4ad88d0900c133dcf22d24a75Zhongxing Xu case MemRegion::CXXTempObjectRegionKind: 67702fe28c8a6da29d4ad88d0900c133dcf22d24a75Zhongxing Xu os << "a C++ temp object of type " << TR->getValueType().getAsString(); 67819c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose return true; 67919c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose case MemRegion::VarRegionKind: 680018220c343c103b7dfaa117a7a474c7a7fd6d068Zhongxing Xu os << "a variable of type" << TR->getValueType().getAsString(); 68119c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose return true; 68219c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose case MemRegion::FieldRegionKind: 683018220c343c103b7dfaa117a7a474c7a7fd6d068Zhongxing Xu os << "a field of type " << TR->getValueType().getAsString(); 68419c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose return true; 68519c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose case MemRegion::ObjCIvarRegionKind: 686018220c343c103b7dfaa117a7a474c7a7fd6d068Zhongxing Xu os << "an instance variable of type " << TR->getValueType().getAsString(); 68719c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose return true; 68819c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose default: 68919c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose return false; 69019c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose } 69119c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose} 69219c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 693d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose//===----------------------------------------------------------------------===// 6949c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek// evaluation of individual function calls. 695d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose//===----------------------------------------------------------------------===// 696ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 697b8b875be7b2d177d755641c6212111859372d611Lenny Maioranivoid CStringChecker::evalCopyCommon(CheckerContext &C, 698b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani const CallExpr *CE, 699b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani const GRState *state, 700d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose const Expr *Size, const Expr *Dest, 701b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani const Expr *Source, bool Restricted, 702b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani bool IsMempcpy) const { 703d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // See if the size argument is zero. 704c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal sizeVal = state->getSVal(Size); 705c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek QualType sizeTy = Size->getType(); 706d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 707c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek const GRState *stateZeroSize, *stateNonZeroSize; 708c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek llvm::tie(stateZeroSize, stateNonZeroSize) = assumeZero(C, state, sizeVal, sizeTy); 709d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 710b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani // Get the value of the Dest. 711b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani SVal destVal = state->getSVal(Dest); 712b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani 713b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani // If the size is zero, there won't be any actual memory access, so 714b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani // just bind the return value to the destination buffer and return. 715b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani if (stateZeroSize) { 71622d27178bf795145439b9588e260ccceab79a088Jordy Rose stateZeroSize = stateZeroSize->BindExpr(CE, destVal); 717c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek C.addTransition(stateZeroSize); 718b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani } 719d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 720d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // If the size can be nonzero, we have to check the other arguments. 721c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek if (stateNonZeroSize) { 72222d27178bf795145439b9588e260ccceab79a088Jordy Rose state = stateNonZeroSize; 723b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani 724b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani // Ensure the destination is not null. If it is NULL there will be a 725b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani // NULL pointer dereference. 726b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani state = checkNonNull(C, state, Dest, destVal); 727b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani if (!state) 728b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani return; 729b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani 730b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani // Get the value of the Src. 731b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani SVal srcVal = state->getSVal(Source); 732b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani 733b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani // Ensure the source is not null. If it is NULL there will be a 734b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani // NULL pointer dereference. 735b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani state = checkNonNull(C, state, Source, srcVal); 736b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani if (!state) 737b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani return; 738b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani 739b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani // Ensure the buffers do not overlap. 740c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek state = stateNonZeroSize; 741e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose state = CheckBufferAccess(C, state, Size, Dest, Source, 742e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose /* FirstIsDst = */ true); 743d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (Restricted) 744d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose state = CheckOverlap(C, state, Size, Dest, Source); 745e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 746e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose if (state) { 747b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani 748b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani // If this is mempcpy, get the byte after the last byte copied and 749b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani // bind the expr. 750b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani if (IsMempcpy) { 751b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani loc::MemRegionVal *destRegVal = dyn_cast<loc::MemRegionVal>(&destVal); 752b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani 753b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani // Get the length to copy. 754b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani SVal lenVal = state->getSVal(Size); 755b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani NonLoc *lenValNonLoc = dyn_cast<NonLoc>(&lenVal); 756b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani 757b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani // Get the byte after the last byte copied. 758b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani SVal lastElement = C.getSValBuilder().evalBinOpLN(state, BO_Add, 759b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani *destRegVal, 760b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani *lenValNonLoc, 761b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani Dest->getType()); 762b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani 763b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani // The byte after the last byte copied is the return value. 764b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani state = state->BindExpr(CE, lastElement); 765b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani } 766b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani 767e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // Invalidate the destination. 768e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // FIXME: Even if we can't perfectly model the copy, we should see if we 769e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // can use LazyCompoundVals to copy the source values into the destination. 770e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // This would probably remove any existing bindings past the end of the 771e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // copied region, but that's still an improvement over blank invalidation. 772e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose state = InvalidateBuffer(C, state, Dest, state->getSVal(Dest)); 773d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose C.addTransition(state); 774e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose } 775d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose } 776ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose} 777ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 778ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 779183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidisvoid CStringChecker::evalMemcpy(CheckerContext &C, const CallExpr *CE) const { 780d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // void *memcpy(void *restrict dst, const void *restrict src, size_t n); 781d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // The return value is the address of the destination buffer. 782d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose const Expr *Dest = CE->getArg(0); 783ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const GRState *state = C.getState(); 784d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose state = state->BindExpr(CE, state->getSVal(Dest)); 785b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani evalCopyCommon(C, CE, state, CE->getArg(2), Dest, CE->getArg(1), true); 786b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani} 787b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani 788b8b875be7b2d177d755641c6212111859372d611Lenny Maioranivoid CStringChecker::evalMempcpy(CheckerContext &C, const CallExpr *CE) const { 789b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani // void *mempcpy(void *restrict dst, const void *restrict src, size_t n); 790b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani // The return value is a pointer to the byte following the last written byte. 791b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani const Expr *Dest = CE->getArg(0); 792b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani const GRState *state = C.getState(); 793b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani 794b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani evalCopyCommon(C, CE, state, CE->getArg(2), Dest, CE->getArg(1), true, true); 795d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose} 796ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 797183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidisvoid CStringChecker::evalMemmove(CheckerContext &C, const CallExpr *CE) const { 798d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // void *memmove(void *dst, const void *src, size_t n); 799ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // The return value is the address of the destination buffer. 800d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose const Expr *Dest = CE->getArg(0); 801d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose const GRState *state = C.getState(); 802d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose state = state->BindExpr(CE, state->getSVal(Dest)); 803b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani evalCopyCommon(C, CE, state, CE->getArg(2), Dest, CE->getArg(1)); 804ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose} 805ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 806183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidisvoid CStringChecker::evalBcopy(CheckerContext &C, const CallExpr *CE) const { 807d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // void bcopy(const void *src, void *dst, size_t n); 808b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani evalCopyCommon(C, CE, C.getState(), 809b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani CE->getArg(2), CE->getArg(1), CE->getArg(0)); 810d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose} 811d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 812183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidisvoid CStringChecker::evalMemcmp(CheckerContext &C, const CallExpr *CE) const { 813bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose // int memcmp(const void *s1, const void *s2, size_t n); 814bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose const Expr *Left = CE->getArg(0); 815bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose const Expr *Right = CE->getArg(1); 816bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose const Expr *Size = CE->getArg(2); 817bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose 818bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose const GRState *state = C.getState(); 819c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SValBuilder &svalBuilder = C.getSValBuilder(); 820bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose 821d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // See if the size argument is zero. 822c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal sizeVal = state->getSVal(Size); 823c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek QualType sizeTy = Size->getType(); 824bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose 825c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek const GRState *stateZeroSize, *stateNonZeroSize; 826c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek llvm::tie(stateZeroSize, stateNonZeroSize) = 827c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek assumeZero(C, state, sizeVal, sizeTy); 828bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose 829d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // If the size can be zero, the result will be 0 in that case, and we don't 830d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // have to check either of the buffers. 831c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek if (stateZeroSize) { 832c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek state = stateZeroSize; 833c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek state = state->BindExpr(CE, svalBuilder.makeZeroVal(CE->getType())); 834d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose C.addTransition(state); 835bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose } 836bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose 837d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // If the size can be nonzero, we have to check the other arguments. 838c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek if (stateNonZeroSize) { 839c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek state = stateNonZeroSize; 840d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // If we know the two buffers are the same, we know the result is 0. 841d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // First, get the two buffers' addresses. Another checker will have already 842d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // made sure they're not undefined. 843d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose DefinedOrUnknownSVal LV = cast<DefinedOrUnknownSVal>(state->getSVal(Left)); 844d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose DefinedOrUnknownSVal RV = cast<DefinedOrUnknownSVal>(state->getSVal(Right)); 845d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 846d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // See if they are the same. 847c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek DefinedOrUnknownSVal SameBuf = svalBuilder.evalEQ(state, LV, RV); 848d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose const GRState *StSameBuf, *StNotSameBuf; 84928f47b92e760ccf641ac91cb0fe1c12d9ca89795Ted Kremenek llvm::tie(StSameBuf, StNotSameBuf) = state->assume(SameBuf); 850d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 851d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // If the two arguments might be the same buffer, we know the result is zero, 852d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // and we only need to check one size. 853d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (StSameBuf) { 854d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose state = StSameBuf; 855d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose state = CheckBufferAccess(C, state, Size, Left); 856d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (state) { 857c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek state = StSameBuf->BindExpr(CE, svalBuilder.makeZeroVal(CE->getType())); 858d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose C.addTransition(state); 859d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose } 860d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose } 861bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose 862d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // If the two arguments might be different buffers, we have to check the 863d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // size of both of them. 864d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (StNotSameBuf) { 865d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose state = StNotSameBuf; 866d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose state = CheckBufferAccess(C, state, Size, Left, Right); 867d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (state) { 868d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // The return value is the comparison result, which we don't know. 869d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose unsigned Count = C.getNodeBuilder().getCurrentBlockCount(); 870c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal CmpV = svalBuilder.getConjuredSymbolVal(NULL, CE, Count); 871d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose state = state->BindExpr(CE, CmpV); 872d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose C.addTransition(state); 873d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose } 874d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose } 875d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose } 876bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose} 877bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose 878183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidisvoid CStringChecker::evalstrLength(CheckerContext &C, 879183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis const CallExpr *CE) const { 88019c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose // size_t strlen(const char *s); 881be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek evalstrLengthCommon(C, CE, /* IsStrnlen = */ false); 882be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek} 883be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek 884183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidisvoid CStringChecker::evalstrnLength(CheckerContext &C, 885183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis const CallExpr *CE) const { 886be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek // size_t strnlen(const char *s, size_t maxlen); 887be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek evalstrLengthCommon(C, CE, /* IsStrnlen = */ true); 888be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek} 889be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek 890be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenekvoid CStringChecker::evalstrLengthCommon(CheckerContext &C, const CallExpr *CE, 891183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis bool IsStrnlen) const { 89219c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose const GRState *state = C.getState(); 89319c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose const Expr *Arg = CE->getArg(0); 89419c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose SVal ArgVal = state->getSVal(Arg); 89519c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 89619c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose // Check that the argument is non-null. 897c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek state = checkNonNull(C, state, Arg, ArgVal); 89819c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 89919c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose if (state) { 900c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal strLength = getCStringLength(C, state, Arg, ArgVal); 901a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 902a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // If the argument isn't a valid C string, there's no valid state to 903a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // transition to. 904c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek if (strLength.isUndef()) 905a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose return; 906a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 907be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek // If the check is for strnlen() then bind the return value to no more than 908be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek // the maxlen value. 909be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek if (IsStrnlen) { 910be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek const Expr *maxlenExpr = CE->getArg(1); 911be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek SVal maxlenVal = state->getSVal(maxlenExpr); 912be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek 913be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek NonLoc *strLengthNL = dyn_cast<NonLoc>(&strLength); 914be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek NonLoc *maxlenValNL = dyn_cast<NonLoc>(&maxlenVal); 915be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek 916be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek QualType cmpTy = C.getSValBuilder().getContext().IntTy; 917be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek const GRState *stateTrue, *stateFalse; 918be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek 919be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek // Check if the strLength is greater than or equal to the maxlen 920be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek llvm::tie(stateTrue, stateFalse) = 921be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek state->assume(cast<DefinedOrUnknownSVal> 922be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek (C.getSValBuilder().evalBinOpNN(state, BO_GE, 923be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek *strLengthNL, *maxlenValNL, 924be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek cmpTy))); 925be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek 926be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek // If the strLength is greater than or equal to the maxlen, set strLength 927be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek // to maxlen 928be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek if (stateTrue && !stateFalse) { 929be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek strLength = maxlenVal; 930be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek } 931be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek } 932be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek 933c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek // If getCStringLength couldn't figure out the length, conjure a return 934a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // value, so it can be used in constraints, at least. 935c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek if (strLength.isUnknown()) { 936a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose unsigned Count = C.getNodeBuilder().getCurrentBlockCount(); 937c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek strLength = C.getSValBuilder().getConjuredSymbolVal(NULL, CE, Count); 93819c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose } 939a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 940a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // Bind the return value. 941c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek state = state->BindExpr(CE, strLength); 942a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose C.addTransition(state); 94319c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose } 94419c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose} 94519c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 946183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidisvoid CStringChecker::evalStrcpy(CheckerContext &C, const CallExpr *CE) const { 947e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // char *strcpy(char *restrict dst, const char *restrict src); 948067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani evalStrcpyCommon(C, CE, 949067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani /* returnEnd = */ false, 950067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani /* isBounded = */ false, 951067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani /* isAppending = */ false); 9520ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek} 9530ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek 954183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidisvoid CStringChecker::evalStrncpy(CheckerContext &C, const CallExpr *CE) const { 9550ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek // char *strcpy(char *restrict dst, const char *restrict src); 956067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani evalStrcpyCommon(C, CE, 957067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani /* returnEnd = */ false, 958067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani /* isBounded = */ true, 959067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani /* isAppending = */ false); 960e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose} 961e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 962183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidisvoid CStringChecker::evalStpcpy(CheckerContext &C, const CallExpr *CE) const { 963e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // char *stpcpy(char *restrict dst, const char *restrict src); 964067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani evalStrcpyCommon(C, CE, 965067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani /* returnEnd = */ true, 966067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani /* isBounded = */ false, 967067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani /* isAppending = */ false); 968067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani} 969067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani 970067bbd0e11c71a33b51832532e836971be697699Lenny Maioranivoid CStringChecker::evalStrcat(CheckerContext &C, const CallExpr *CE) const { 971067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani //char *strcat(char *restrict s1, const char *restrict s2); 972067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani evalStrcpyCommon(C, CE, 973067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani /* returnEnd = */ false, 974067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani /* isBounded = */ false, 975067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani /* isAppending = */ true); 976067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani} 977067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani 978067bbd0e11c71a33b51832532e836971be697699Lenny Maioranivoid CStringChecker::evalStrncat(CheckerContext &C, const CallExpr *CE) const { 979067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani //char *strncat(char *restrict s1, const char *restrict s2, size_t n); 980067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani evalStrcpyCommon(C, CE, 981067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani /* returnEnd = */ false, 982067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani /* isBounded = */ true, 983067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani /* isAppending = */ true); 984e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose} 985e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 9869c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenekvoid CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE, 987067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani bool returnEnd, bool isBounded, 988067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani bool isAppending) const { 989e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose const GRState *state = C.getState(); 990e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 991067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani // Check that the destination is non-null. 992e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose const Expr *Dst = CE->getArg(0); 993e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose SVal DstVal = state->getSVal(Dst); 994e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 995c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek state = checkNonNull(C, state, Dst, DstVal); 996e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose if (!state) 997e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose return; 998e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 999e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // Check that the source is non-null. 1000c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek const Expr *srcExpr = CE->getArg(1); 1001c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal srcVal = state->getSVal(srcExpr); 1002c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek state = checkNonNull(C, state, srcExpr, srcVal); 1003e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose if (!state) 1004e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose return; 1005e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 1006e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // Get the string length of the source. 1007c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal strLength = getCStringLength(C, state, srcExpr, srcVal); 1008e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 1009e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // If the source isn't a valid C string, give up. 1010c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek if (strLength.isUndef()) 1011e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose return; 1012e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 1013067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani // If the function is strncpy, strncat, etc... it is bounded. 1014067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani if (isBounded) { 1015067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani // Get the max number of characters to copy. 10160ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek const Expr *lenExpr = CE->getArg(2); 10170ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek SVal lenVal = state->getSVal(lenExpr); 10180ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek 1019508c627db67ea4b53439fbcd688145f24d9c0400Lenny Maiorani // Cast the length to a NonLoc SVal. If it is not a NonLoc then give up. 10200ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek NonLoc *strLengthNL = dyn_cast<NonLoc>(&strLength); 1021508c627db67ea4b53439fbcd688145f24d9c0400Lenny Maiorani if (!strLengthNL) 1022508c627db67ea4b53439fbcd688145f24d9c0400Lenny Maiorani return; 1023508c627db67ea4b53439fbcd688145f24d9c0400Lenny Maiorani 1024508c627db67ea4b53439fbcd688145f24d9c0400Lenny Maiorani // Cast the max length to a NonLoc SVal. If it is not a NonLoc then give up. 10250ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek NonLoc *lenValNL = dyn_cast<NonLoc>(&lenVal); 1026508c627db67ea4b53439fbcd688145f24d9c0400Lenny Maiorani if (!lenValNL) 1027508c627db67ea4b53439fbcd688145f24d9c0400Lenny Maiorani return; 10280ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek 10290ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek QualType cmpTy = C.getSValBuilder().getContext().IntTy; 10300ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek const GRState *stateTrue, *stateFalse; 10310ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek 1032067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani // Check if the max number to copy is less than the length of the src. 10330ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek llvm::tie(stateTrue, stateFalse) = 10340ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek state->assume(cast<DefinedOrUnknownSVal> 10350ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek (C.getSValBuilder().evalBinOpNN(state, BO_GT, 10360ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek *strLengthNL, *lenValNL, 10370ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek cmpTy))); 10380ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek 10390ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek if (stateTrue) { 10400ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek // Max number to copy is less than the length of the src, so the actual 10410ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek // strLength copied is the max number arg. 10420ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek strLength = lenVal; 10430ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek } 10440ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek } 10450ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek 1046067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani // If this is an appending function (strcat, strncat...) then set the 1047067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani // string length to strlen(src) + strlen(dst) since the buffer will 1048067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani // ultimately contain both. 1049067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani if (isAppending) { 1050067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani // Get the string length of the destination, or give up. 1051067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani SVal dstStrLength = getCStringLength(C, state, Dst, DstVal); 1052067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani if (dstStrLength.isUndef()) 1053067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani return; 1054067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani 1055067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani NonLoc *srcStrLengthNL = dyn_cast<NonLoc>(&strLength); 1056067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani NonLoc *dstStrLengthNL = dyn_cast<NonLoc>(&dstStrLength); 1057067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani 1058067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani // If src or dst cast to NonLoc is NULL, give up. 1059067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani if ((!srcStrLengthNL) || (!dstStrLengthNL)) 1060067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani return; 1061067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani 1062067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani QualType addTy = C.getSValBuilder().getContext().getSizeType(); 1063067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani 1064067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani strLength = C.getSValBuilder().evalBinOpNN(state, BO_Add, 1065067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani *srcStrLengthNL, *dstStrLengthNL, 1066067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani addTy); 1067067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani } 1068067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani 1069c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal Result = (returnEnd ? UnknownVal() : DstVal); 1070e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 1071e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // If the destination is a MemRegion, try to check for a buffer overflow and 1072e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // record the new string length. 1073c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek if (loc::MemRegionVal *dstRegVal = dyn_cast<loc::MemRegionVal>(&DstVal)) { 1074e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // If the length is known, we can check for an overflow. 1075c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek if (NonLoc *knownStrLength = dyn_cast<NonLoc>(&strLength)) { 1076c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal lastElement = 1077c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek C.getSValBuilder().evalBinOpLN(state, BO_Add, *dstRegVal, 1078c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek *knownStrLength, Dst->getType()); 1079e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 1080c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek state = CheckLocation(C, state, Dst, lastElement, /* IsDst = */ true); 1081e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose if (!state) 1082e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose return; 1083e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 1084e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // If this is a stpcpy-style copy, the last element is the return value. 1085c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek if (returnEnd) 1086c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek Result = lastElement; 1087e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose } 1088e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 1089e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // Invalidate the destination. This must happen before we set the C string 1090e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // length because invalidation will clear the length. 1091e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // FIXME: Even if we can't perfectly model the copy, we should see if we 1092e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // can use LazyCompoundVals to copy the source values into the destination. 1093e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // This would probably remove any existing bindings past the end of the 1094e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // string, but that's still an improvement over blank invalidation. 1095c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek state = InvalidateBuffer(C, state, Dst, *dstRegVal); 1096e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 1097e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // Set the C string length of the destination. 1098c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek state = setCStringLength(state, dstRegVal->getRegion(), strLength); 1099e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose } 1100e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 1101e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // If this is a stpcpy-style copy, but we were unable to check for a buffer 1102e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // overflow, we still need a result. Conjure a return value. 1103c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek if (returnEnd && Result.isUnknown()) { 1104c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SValBuilder &svalBuilder = C.getSValBuilder(); 1105e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose unsigned Count = C.getNodeBuilder().getCurrentBlockCount(); 1106c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek strLength = svalBuilder.getConjuredSymbolVal(NULL, CE, Count); 1107e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose } 1108e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 1109e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // Set the return value. 1110e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose state = state->BindExpr(CE, Result); 1111e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose C.addTransition(state); 1112e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose} 1113e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 1114318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maioranivoid CStringChecker::evalStrcmp(CheckerContext &C, const CallExpr *CE) const { 1115318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani //int strcmp(const char *restrict s1, const char *restrict s2); 1116bd1d16a1792cd6ea5ede9869e18d781e3fc1a8c3Lenny Maiorani evalStrcmpCommon(C, CE, /* isBounded = */ false, /* ignoreCase = */ false); 1117357f6ee9f1f6f8e5027377cb3e5907c62c4fe3dfLenny Maiorani} 1118357f6ee9f1f6f8e5027377cb3e5907c62c4fe3dfLenny Maiorani 1119357f6ee9f1f6f8e5027377cb3e5907c62c4fe3dfLenny Maioranivoid CStringChecker::evalStrncmp(CheckerContext &C, const CallExpr *CE) const { 1120357f6ee9f1f6f8e5027377cb3e5907c62c4fe3dfLenny Maiorani //int strncmp(const char *restrict s1, const char *restrict s2, size_t n); 1121bd1d16a1792cd6ea5ede9869e18d781e3fc1a8c3Lenny Maiorani evalStrcmpCommon(C, CE, /* isBounded = */ true, /* ignoreCase = */ false); 1122bd1d16a1792cd6ea5ede9869e18d781e3fc1a8c3Lenny Maiorani} 1123bd1d16a1792cd6ea5ede9869e18d781e3fc1a8c3Lenny Maiorani 1124bd1d16a1792cd6ea5ede9869e18d781e3fc1a8c3Lenny Maioranivoid CStringChecker::evalStrcasecmp(CheckerContext &C, 1125bd1d16a1792cd6ea5ede9869e18d781e3fc1a8c3Lenny Maiorani const CallExpr *CE) const { 1126bd1d16a1792cd6ea5ede9869e18d781e3fc1a8c3Lenny Maiorani //int strcasecmp(const char *restrict s1, const char *restrict s2); 1127bd1d16a1792cd6ea5ede9869e18d781e3fc1a8c3Lenny Maiorani evalStrcmpCommon(C, CE, /* isBounded = */ false, /* ignoreCase = */ true); 1128357f6ee9f1f6f8e5027377cb3e5907c62c4fe3dfLenny Maiorani} 1129318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani 1130454fd2d3a1b6d0ef225c5d3927c1ad3b97510d1aLenny Maioranivoid CStringChecker::evalStrncasecmp(CheckerContext &C, 1131454fd2d3a1b6d0ef225c5d3927c1ad3b97510d1aLenny Maiorani const CallExpr *CE) const { 1132454fd2d3a1b6d0ef225c5d3927c1ad3b97510d1aLenny Maiorani //int strncasecmp(const char *restrict s1, const char *restrict s2, size_t n); 1133454fd2d3a1b6d0ef225c5d3927c1ad3b97510d1aLenny Maiorani evalStrcmpCommon(C, CE, /* isBounded = */ true, /* ignoreCase = */ true); 1134454fd2d3a1b6d0ef225c5d3927c1ad3b97510d1aLenny Maiorani} 1135454fd2d3a1b6d0ef225c5d3927c1ad3b97510d1aLenny Maiorani 1136357f6ee9f1f6f8e5027377cb3e5907c62c4fe3dfLenny Maioranivoid CStringChecker::evalStrcmpCommon(CheckerContext &C, const CallExpr *CE, 1137bd1d16a1792cd6ea5ede9869e18d781e3fc1a8c3Lenny Maiorani bool isBounded, bool ignoreCase) const { 1138318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani const GRState *state = C.getState(); 1139318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani 1140318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani // Check that the first string is non-null 1141318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani const Expr *s1 = CE->getArg(0); 1142318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani SVal s1Val = state->getSVal(s1); 1143318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani state = checkNonNull(C, state, s1, s1Val); 1144318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani if (!state) 1145318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani return; 1146318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani 1147318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani // Check that the second string is non-null. 1148318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani const Expr *s2 = CE->getArg(1); 1149318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani SVal s2Val = state->getSVal(s2); 1150318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani state = checkNonNull(C, state, s2, s2Val); 1151318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani if (!state) 1152318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani return; 1153318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani 1154318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani // Get the string length of the first string or give up. 1155318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani SVal s1Length = getCStringLength(C, state, s1, s1Val); 1156318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani if (s1Length.isUndef()) 1157318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani return; 1158318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani 1159318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani // Get the string length of the second string or give up. 1160318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani SVal s2Length = getCStringLength(C, state, s2, s2Val); 1161318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani if (s2Length.isUndef()) 1162318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani return; 1163318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani 1164318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani // Get the string literal of the first string. 1165318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani const StringLiteral *s1StrLiteral = getCStringLiteral(C, state, s1, s1Val); 1166318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani if (!s1StrLiteral) 1167318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani return; 1168318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani llvm::StringRef s1StrRef = s1StrLiteral->getString(); 1169318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani 1170318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani // Get the string literal of the second string. 1171318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani const StringLiteral *s2StrLiteral = getCStringLiteral(C, state, s2, s2Val); 1172318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani if (!s2StrLiteral) 1173318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani return; 1174318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani llvm::StringRef s2StrRef = s2StrLiteral->getString(); 1175318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani 1176357f6ee9f1f6f8e5027377cb3e5907c62c4fe3dfLenny Maiorani int result; 1177357f6ee9f1f6f8e5027377cb3e5907c62c4fe3dfLenny Maiorani if (isBounded) { 1178357f6ee9f1f6f8e5027377cb3e5907c62c4fe3dfLenny Maiorani // Get the max number of characters to compare. 1179357f6ee9f1f6f8e5027377cb3e5907c62c4fe3dfLenny Maiorani const Expr *lenExpr = CE->getArg(2); 1180357f6ee9f1f6f8e5027377cb3e5907c62c4fe3dfLenny Maiorani SVal lenVal = state->getSVal(lenExpr); 1181357f6ee9f1f6f8e5027377cb3e5907c62c4fe3dfLenny Maiorani 1182357f6ee9f1f6f8e5027377cb3e5907c62c4fe3dfLenny Maiorani // Dynamically cast the length to a ConcreteInt. If it is not a ConcreteInt 1183357f6ee9f1f6f8e5027377cb3e5907c62c4fe3dfLenny Maiorani // then give up, otherwise get the value and use it as the bounds. 1184357f6ee9f1f6f8e5027377cb3e5907c62c4fe3dfLenny Maiorani nonloc::ConcreteInt *CI = dyn_cast<nonloc::ConcreteInt>(&lenVal); 1185357f6ee9f1f6f8e5027377cb3e5907c62c4fe3dfLenny Maiorani if (!CI) 1186357f6ee9f1f6f8e5027377cb3e5907c62c4fe3dfLenny Maiorani return; 1187357f6ee9f1f6f8e5027377cb3e5907c62c4fe3dfLenny Maiorani llvm::APSInt lenInt(CI->getValue()); 1188357f6ee9f1f6f8e5027377cb3e5907c62c4fe3dfLenny Maiorani 1189454fd2d3a1b6d0ef225c5d3927c1ad3b97510d1aLenny Maiorani // Create substrings of each to compare the prefix. 1190454fd2d3a1b6d0ef225c5d3927c1ad3b97510d1aLenny Maiorani s1StrRef = s1StrRef.substr(0, (size_t)lenInt.getLimitedValue()); 1191454fd2d3a1b6d0ef225c5d3927c1ad3b97510d1aLenny Maiorani s2StrRef = s2StrRef.substr(0, (size_t)lenInt.getLimitedValue()); 1192454fd2d3a1b6d0ef225c5d3927c1ad3b97510d1aLenny Maiorani } 1193bd1d16a1792cd6ea5ede9869e18d781e3fc1a8c3Lenny Maiorani 1194454fd2d3a1b6d0ef225c5d3927c1ad3b97510d1aLenny Maiorani if (ignoreCase) { 1195454fd2d3a1b6d0ef225c5d3927c1ad3b97510d1aLenny Maiorani // Compare string 1 to string 2 the same way strcasecmp() does. 1196454fd2d3a1b6d0ef225c5d3927c1ad3b97510d1aLenny Maiorani result = s1StrRef.compare_lower(s2StrRef); 1197357f6ee9f1f6f8e5027377cb3e5907c62c4fe3dfLenny Maiorani } else { 1198357f6ee9f1f6f8e5027377cb3e5907c62c4fe3dfLenny Maiorani // Compare string 1 to string 2 the same way strcmp() does. 1199454fd2d3a1b6d0ef225c5d3927c1ad3b97510d1aLenny Maiorani result = s1StrRef.compare(s2StrRef); 1200357f6ee9f1f6f8e5027377cb3e5907c62c4fe3dfLenny Maiorani } 1201318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani 1202318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani // Build the SVal of the comparison to bind the return value. 1203318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani SValBuilder &svalBuilder = C.getSValBuilder(); 1204318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani QualType intTy = svalBuilder.getContext().IntTy; 1205318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani SVal resultVal = svalBuilder.makeIntVal(result, intTy); 1206318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani 1207318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani // Bind the return value of the expression. 1208318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani // Set the return value. 1209318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani state = state->BindExpr(CE, resultVal); 1210318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani C.addTransition(state); 1211318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani} 1212318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani 1213d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose//===----------------------------------------------------------------------===// 1214a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose// The driver method, and other Checker callbacks. 1215d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose//===----------------------------------------------------------------------===// 1216ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 1217183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidisbool CStringChecker::evalCall(const CallExpr *CE, CheckerContext &C) const { 1218ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Get the callee. All the functions we care about are C functions 1219ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // with simple identifiers. 1220ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const GRState *state = C.getState(); 1221ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const Expr *Callee = CE->getCallee(); 1222ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const FunctionDecl *FD = state->getSVal(Callee).getAsFunctionDecl(); 1223ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 1224ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (!FD) 1225ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return false; 1226ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 1227ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Get the name of the callee. If it's a builtin, strip off the prefix. 122890d26a4afdbf6d917a5241ef3b316e1c8337c9b8Douglas Gregor IdentifierInfo *II = FD->getIdentifier(); 122990d26a4afdbf6d917a5241ef3b316e1c8337c9b8Douglas Gregor if (!II) // if no identifier, not a simple C function 123090d26a4afdbf6d917a5241ef3b316e1c8337c9b8Douglas Gregor return false; 123190d26a4afdbf6d917a5241ef3b316e1c8337c9b8Douglas Gregor llvm::StringRef Name = II->getName(); 1232ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (Name.startswith("__builtin_")) 1233ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose Name = Name.substr(10); 1234ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 12359c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek FnCheck evalFunction = llvm::StringSwitch<FnCheck>(Name) 12369c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek .Cases("memcpy", "__memcpy_chk", &CStringChecker::evalMemcpy) 1237be460d8e5364c6bffeb7b27e4c0d4d5d16e39c59Jordy Rose .Cases("mempcpy", "__mempcpy_chk", &CStringChecker::evalMempcpy) 12389c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek .Cases("memcmp", "bcmp", &CStringChecker::evalMemcmp) 12399c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek .Cases("memmove", "__memmove_chk", &CStringChecker::evalMemmove) 12409c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek .Cases("strcpy", "__strcpy_chk", &CStringChecker::evalStrcpy) 1241094ea0afcfa79eb0c4a2c35a059491be3ab954a9Lenny Maiorani //.Cases("strncpy", "__strncpy_chk", &CStringChecker::evalStrncpy) 12429c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek .Cases("stpcpy", "__stpcpy_chk", &CStringChecker::evalStpcpy) 1243067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani .Cases("strcat", "__strcat_chk", &CStringChecker::evalStrcat) 1244067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani .Cases("strncat", "__strncat_chk", &CStringChecker::evalStrncat) 1245c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek .Case("strlen", &CStringChecker::evalstrLength) 1246be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek .Case("strnlen", &CStringChecker::evalstrnLength) 1247318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani .Case("strcmp", &CStringChecker::evalStrcmp) 1248357f6ee9f1f6f8e5027377cb3e5907c62c4fe3dfLenny Maiorani .Case("strncmp", &CStringChecker::evalStrncmp) 1249bd1d16a1792cd6ea5ede9869e18d781e3fc1a8c3Lenny Maiorani .Case("strcasecmp", &CStringChecker::evalStrcasecmp) 1250454fd2d3a1b6d0ef225c5d3927c1ad3b97510d1aLenny Maiorani .Case("strncasecmp", &CStringChecker::evalStrncasecmp) 12519c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek .Case("bcopy", &CStringChecker::evalBcopy) 1252ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose .Default(NULL); 1253ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 1254d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // If the callee isn't a string function, let another checker handle it. 12559c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek if (!evalFunction) 1256ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return false; 1257ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 1258d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // Check and evaluate the call. 12599c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek (this->*evalFunction)(C, CE); 1260ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return true; 1261ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose} 1262a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1263183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidisvoid CStringChecker::checkPreStmt(const DeclStmt *DS, CheckerContext &C) const { 1264a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // Record string length for char a[] = "abc"; 1265a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose const GRState *state = C.getState(); 1266a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1267a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose for (DeclStmt::const_decl_iterator I = DS->decl_begin(), E = DS->decl_end(); 1268a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose I != E; ++I) { 1269a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose const VarDecl *D = dyn_cast<VarDecl>(*I); 1270a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (!D) 1271a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose continue; 1272a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1273a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // FIXME: Handle array fields of structs. 1274a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (!D->getType()->isArrayType()) 1275a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose continue; 1276a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1277a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose const Expr *Init = D->getInit(); 1278a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (!Init) 1279a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose continue; 1280a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (!isa<StringLiteral>(Init)) 1281a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose continue; 1282a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1283a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose Loc VarLoc = state->getLValue(D, C.getPredecessor()->getLocationContext()); 1284a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose const MemRegion *MR = VarLoc.getAsRegion(); 1285a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (!MR) 1286a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose continue; 1287a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1288a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose SVal StrVal = state->getSVal(Init); 1289a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose assert(StrVal.isValid() && "Initializer string is unknown or undefined"); 1290c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek DefinedOrUnknownSVal strLength 1291c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek = cast<DefinedOrUnknownSVal>(getCStringLength(C, state, Init, StrVal)); 1292a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1293c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek state = state->set<CStringLength>(MR, strLength); 1294a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose } 1295a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1296a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose C.addTransition(state); 1297a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose} 1298a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1299183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidisbool CStringChecker::wantsRegionChangeUpdate(const GRState *state) const { 1300a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose CStringLength::EntryMap Entries = state->get<CStringLength>(); 1301a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose return !Entries.isEmpty(); 1302a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose} 1303a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1304183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidisconst GRState * 1305183ff98f425d470c2a0276880aaf43496c9dad14Argyrios KyrtzidisCStringChecker::checkRegionChanges(const GRState *state, 130635bdbf40624beba3fc00cb72ab444659939c1a6bTed Kremenek const StoreManager::InvalidatedSymbols *, 1307183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis const MemRegion * const *Begin, 1308183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis const MemRegion * const *End) const { 1309a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose CStringLength::EntryMap Entries = state->get<CStringLength>(); 1310a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (Entries.isEmpty()) 1311a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose return state; 1312a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1313a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose llvm::SmallPtrSet<const MemRegion *, 8> Invalidated; 1314a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose llvm::SmallPtrSet<const MemRegion *, 32> SuperRegions; 1315a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1316a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // First build sets for the changed regions and their super-regions. 1317a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose for ( ; Begin != End; ++Begin) { 1318a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose const MemRegion *MR = *Begin; 1319a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose Invalidated.insert(MR); 1320a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1321a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose SuperRegions.insert(MR); 1322a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose while (const SubRegion *SR = dyn_cast<SubRegion>(MR)) { 1323a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose MR = SR->getSuperRegion(); 1324a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose SuperRegions.insert(MR); 1325a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose } 1326a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose } 1327a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1328a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose CStringLength::EntryMap::Factory &F = state->get_context<CStringLength>(); 1329a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1330a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // Then loop over the entries in the current state. 1331a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose for (CStringLength::EntryMap::iterator I = Entries.begin(), 1332a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose E = Entries.end(); I != E; ++I) { 1333a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose const MemRegion *MR = I.getKey(); 1334a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1335a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // Is this entry for a super-region of a changed region? 1336a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (SuperRegions.count(MR)) { 13373baf672378f105602d2b12f03f00277ae1936fe9Ted Kremenek Entries = F.remove(Entries, MR); 1338a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose continue; 1339a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose } 1340a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1341a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // Is this entry for a sub-region of a changed region? 1342a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose const MemRegion *Super = MR; 1343a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose while (const SubRegion *SR = dyn_cast<SubRegion>(Super)) { 1344a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose Super = SR->getSuperRegion(); 1345a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (Invalidated.count(Super)) { 13463baf672378f105602d2b12f03f00277ae1936fe9Ted Kremenek Entries = F.remove(Entries, MR); 1347a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose break; 1348a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose } 1349a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose } 1350a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose } 1351a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1352a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose return state->set<CStringLength>(Entries); 1353a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose} 1354a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1355183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidisvoid CStringChecker::checkLiveSymbols(const GRState *state, 1356183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis SymbolReaper &SR) const { 1357a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // Mark all symbols in our string length map as valid. 1358a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose CStringLength::EntryMap Entries = state->get<CStringLength>(); 1359a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1360a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose for (CStringLength::EntryMap::iterator I = Entries.begin(), E = Entries.end(); 1361a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose I != E; ++I) { 1362a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose SVal Len = I.getData(); 1363a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (SymbolRef Sym = Len.getAsSymbol()) 1364a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose SR.markInUse(Sym); 1365a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose } 1366a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose} 1367a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1368183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidisvoid CStringChecker::checkDeadSymbols(SymbolReaper &SR, 1369183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis CheckerContext &C) const { 1370a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (!SR.hasDeadSymbols()) 1371a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose return; 1372a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1373a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose const GRState *state = C.getState(); 1374a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose CStringLength::EntryMap Entries = state->get<CStringLength>(); 1375a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (Entries.isEmpty()) 1376a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose return; 1377a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1378a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose CStringLength::EntryMap::Factory &F = state->get_context<CStringLength>(); 1379a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose for (CStringLength::EntryMap::iterator I = Entries.begin(), E = Entries.end(); 1380a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose I != E; ++I) { 1381a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose SVal Len = I.getData(); 1382a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (SymbolRef Sym = Len.getAsSymbol()) { 1383a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (SR.isDead(Sym)) 13843baf672378f105602d2b12f03f00277ae1936fe9Ted Kremenek Entries = F.remove(Entries, I.getKey()); 1385a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose } 1386a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose } 1387a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1388a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose state = state->set<CStringLength>(Entries); 1389d048c6ef5b6cfaa0cecb8cc1d4bdace32ed21d07Ted Kremenek C.generateNode(state); 1390a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose} 1391183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis 1392183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidisvoid ento::registerCStringChecker(CheckerManager &mgr) { 1393183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis mgr.registerChecker<CStringChecker>(); 1394183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis} 1395