1c800f68f8e61007a6dc5dc8213629fb423e76cd9Anna Zaks//= CStringChecker.cpp - 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" 2018c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.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 > { 339e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose mutable llvm::OwningPtr<BugType> BT_Null, BT_Bounds, 34d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose BT_Overlap, BT_NotCString, 35d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose BT_AdditionOverflow; 369e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose mutable const char *CurrentFunctionDescription; 379e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose 38ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rosepublic: 39ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose static void *getTag() { static int tag; return &tag; } 40ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 41183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis bool evalCall(const CallExpr *CE, CheckerContext &C) const; 42183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis void checkPreStmt(const DeclStmt *DS, CheckerContext &C) const; 4318c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek void checkLiveSymbols(const ProgramState *state, SymbolReaper &SR) const; 44183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const; 4518c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek bool wantsRegionChangeUpdate(const ProgramState *state) const; 46a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 4718c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const ProgramState * 4818c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek checkRegionChanges(const ProgramState *state, 4918c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const StoreManager::InvalidatedSymbols *, 50537716ad8dd10f984b6cfe6985afade1185c5e3cJordy Rose ArrayRef<const MemRegion *> ExplicitRegions, 51537716ad8dd10f984b6cfe6985afade1185c5e3cJordy Rose ArrayRef<const MemRegion *> Regions) const; 52ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 53183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis typedef void (CStringChecker::*FnCheck)(CheckerContext &, 54183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis const CallExpr *) const; 55ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 56183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis void evalMemcpy(CheckerContext &C, const CallExpr *CE) const; 57b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani void evalMempcpy(CheckerContext &C, const CallExpr *CE) const; 58183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis void evalMemmove(CheckerContext &C, const CallExpr *CE) const; 59183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis void evalBcopy(CheckerContext &C, const CallExpr *CE) const; 60b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani void evalCopyCommon(CheckerContext &C, const CallExpr *CE, 6118c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const ProgramState *state, 6218c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const Expr *Size, 6318c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const Expr *Source, 6418c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const Expr *Dest, 65b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani bool Restricted = false, 66b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani bool IsMempcpy = false) const; 67d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 68183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis void evalMemcmp(CheckerContext &C, const CallExpr *CE) const; 69ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 70183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis void evalstrLength(CheckerContext &C, const CallExpr *CE) const; 71183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis void evalstrnLength(CheckerContext &C, const CallExpr *CE) const; 7218c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek void evalstrLengthCommon(CheckerContext &C, 7318c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const CallExpr *CE, 74183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis bool IsStrnlen = false) const; 7519c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 76183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis void evalStrcpy(CheckerContext &C, const CallExpr *CE) const; 77183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis void evalStrncpy(CheckerContext &C, const CallExpr *CE) const; 78183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis void evalStpcpy(CheckerContext &C, const CallExpr *CE) const; 7918c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek void evalStrcpyCommon(CheckerContext &C, 8018c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const CallExpr *CE, 8118c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek bool returnEnd, 8218c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek bool isBounded, 8318c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek bool isAppending) const; 84067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani 85067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani void evalStrcat(CheckerContext &C, const CallExpr *CE) const; 86067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani void evalStrncat(CheckerContext &C, const CallExpr *CE) const; 87e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 88318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani void evalStrcmp(CheckerContext &C, const CallExpr *CE) const; 89357f6ee9f1f6f8e5027377cb3e5907c62c4fe3dfLenny Maiorani void evalStrncmp(CheckerContext &C, const CallExpr *CE) const; 90bd1d16a1792cd6ea5ede9869e18d781e3fc1a8c3Lenny Maiorani void evalStrcasecmp(CheckerContext &C, const CallExpr *CE) const; 91454fd2d3a1b6d0ef225c5d3927c1ad3b97510d1aLenny Maiorani void evalStrncasecmp(CheckerContext &C, const CallExpr *CE) const; 9218c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek void evalStrcmpCommon(CheckerContext &C, 9318c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const CallExpr *CE, 9418c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek bool isBounded = false, 9518c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek bool ignoreCase = false) const; 96318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani 97ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Utility methods 9818c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek std::pair<const ProgramState*, const ProgramState*> 99183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis static assumeZero(CheckerContext &C, 10018c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const ProgramState *state, SVal V, QualType Ty); 101183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis 10218c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek static const ProgramState *setCStringLength(const ProgramState *state, 10318c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const MemRegion *MR, 10418c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek SVal strLength); 105183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis static SVal getCStringLengthForRegion(CheckerContext &C, 10618c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const ProgramState *&state, 10718c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const Expr *Ex, 10818c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const MemRegion *MR, 109d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose bool hypothetical); 11018c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek SVal getCStringLength(CheckerContext &C, 11118c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const ProgramState *&state, 11218c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const Expr *Ex, 11318c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek SVal Buf, 114d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose bool hypothetical = false) const; 11519c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 116318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani const StringLiteral *getCStringLiteral(CheckerContext &C, 11718c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const ProgramState *&state, 118318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani const Expr *expr, 119318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani SVal val) const; 120318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani 12118c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek static const ProgramState *InvalidateBuffer(CheckerContext &C, 12218c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const ProgramState *state, 12318c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const Expr *Ex, SVal V); 124e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 1259c378f705405d37f49795d5e915989de774fe11fTed Kremenek static bool SummarizeRegion(raw_ostream &os, ASTContext &Ctx, 126183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis const MemRegion *MR); 12719c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 12819c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose // Re-usable checks 12918c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const ProgramState *checkNonNull(CheckerContext &C, 13018c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const ProgramState *state, 13118c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const Expr *S, 13218c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek SVal l) const; 13318c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const ProgramState *CheckLocation(CheckerContext &C, 13418c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const ProgramState *state, 13518c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const Expr *S, 13618c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek SVal l, 13718c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const char *message = NULL) const; 13818c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const ProgramState *CheckBufferAccess(CheckerContext &C, 13918c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const ProgramState *state, 14018c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const Expr *Size, 14118c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const Expr *FirstBuf, 14218c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const Expr *SecondBuf, 14318c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const char *firstMessage = NULL, 14418c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const char *secondMessage = NULL, 14518c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek bool WarnAboutSize = false) const; 14618c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek 14718c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const ProgramState *CheckBufferAccess(CheckerContext &C, 14818c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const ProgramState *state, 14918c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const Expr *Size, 15018c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const Expr *Buf, 15118c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const char *message = NULL, 15218c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek bool WarnAboutSize = false) const { 1539e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose // This is a convenience override. 1545e5f15062bcf4b62fda9062b453178f8b9bd0c2dJordy Rose return CheckBufferAccess(C, state, Size, Buf, NULL, message, NULL, 1555e5f15062bcf4b62fda9062b453178f8b9bd0c2dJordy Rose WarnAboutSize); 1569e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose } 15718c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const ProgramState *CheckOverlap(CheckerContext &C, 15818c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const ProgramState *state, 15918c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const Expr *Size, 16018c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const Expr *First, 16118c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const Expr *Second) const; 16218c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek void emitOverlapBug(CheckerContext &C, 16318c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const ProgramState *state, 16418c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const Stmt *First, 16518c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const Stmt *Second) const; 16618c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek 16718c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const ProgramState *checkAdditionOverflow(CheckerContext &C, 16818c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const ProgramState *state, 16918c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek NonLoc left, 17018c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek NonLoc right) const; 171ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose}; 172a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 173a5261549754fab80e30e893d8fa706bfb31e430aJordy Roseclass CStringLength { 174a5261549754fab80e30e893d8fa706bfb31e430aJordy Rosepublic: 175a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose typedef llvm::ImmutableMap<const MemRegion *, SVal> EntryMap; 176a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose}; 177ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose} //end anonymous namespace 178ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 179a5261549754fab80e30e893d8fa706bfb31e430aJordy Rosenamespace clang { 1809ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremeneknamespace ento { 181a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose template <> 18218c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek struct ProgramStateTrait<CStringLength> 18318c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek : public ProgramStatePartialTrait<CStringLength::EntryMap> { 184a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose static void *GDMIndex() { return CStringChecker::getTag(); } 185a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose }; 186a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose} 1875a4f98ff943e6a501b0fe47ade007c9bbf96cb88Argyrios Kyrtzidis} 188a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 189d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose//===----------------------------------------------------------------------===// 190d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose// Individual checks and utility methods. 191d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose//===----------------------------------------------------------------------===// 192d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 19318c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenekstd::pair<const ProgramState*, const ProgramState*> 19418c66fdc3c4008d335885695fe36fb5353c5f672Ted KremenekCStringChecker::assumeZero(CheckerContext &C, const ProgramState *state, SVal V, 195d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose QualType Ty) { 196c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek DefinedSVal *val = dyn_cast<DefinedSVal>(&V); 197c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek if (!val) 19818c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek return std::pair<const ProgramState*, const ProgramState *>(state, state); 199a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose 200c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SValBuilder &svalBuilder = C.getSValBuilder(); 201c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek DefinedOrUnknownSVal zero = svalBuilder.makeZeroVal(Ty); 202c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek return state->assume(svalBuilder.evalEQ(state, *val, zero)); 203d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose} 204d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 20518c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenekconst ProgramState *CStringChecker::checkNonNull(CheckerContext &C, 20618c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const ProgramState *state, 207183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis const Expr *S, SVal l) const { 208d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // If a previous check has failed, propagate the failure. 209d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (!state) 210d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose return NULL; 211a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose 21218c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const ProgramState *stateNull, *stateNonNull; 21328f47b92e760ccf641ac91cb0fe1c12d9ca89795Ted Kremenek llvm::tie(stateNull, stateNonNull) = assumeZero(C, state, l, S->getType()); 214a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose 215d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (stateNull && !stateNonNull) { 216d048c6ef5b6cfaa0cecb8cc1d4bdace32ed21d07Ted Kremenek ExplodedNode *N = C.generateSink(stateNull); 217a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose if (!N) 218a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose return NULL; 219a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose 220d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (!BT_Null) 221183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis BT_Null.reset(new BuiltinBug("API", 222183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis "Null pointer argument in call to byte string function")); 223a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose 2249e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose llvm::SmallString<80> buf; 2259e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose llvm::raw_svector_ostream os(buf); 2269e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose assert(CurrentFunctionDescription); 2279e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose os << "Null pointer argument in call to " << CurrentFunctionDescription; 2289e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose 229a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose // Generate a report for this bug. 230183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis BuiltinBug *BT = static_cast<BuiltinBug*>(BT_Null.get()); 231e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks BugReport *report = new BugReport(*BT, os.str(), N); 232a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose 233a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose report->addRange(S->getSourceRange()); 23450bbc165b063155cc23c360deb7b865502e068e2Anna Zaks report->addVisitor(bugreporter::getTrackNullOrUndefValueVisitor(N, S)); 235a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose C.EmitReport(report); 236a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose return NULL; 237a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose } 238a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose 239a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose // From here on, assume that the value is non-null. 240d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose assert(stateNonNull); 241d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose return stateNonNull; 242a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose} 243a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose 244ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose// FIXME: This was originally copied from ArrayBoundChecker.cpp. Refactor? 24518c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenekconst ProgramState *CStringChecker::CheckLocation(CheckerContext &C, 24618c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const ProgramState *state, 247e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose const Expr *S, SVal l, 2489e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose const char *warningMsg) const { 249d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // If a previous check has failed, propagate the failure. 250d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (!state) 251d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose return NULL; 252d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 253ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Check for out of bound array element access. 254ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const MemRegion *R = l.getAsRegion(); 255ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (!R) 256ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return state; 257ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 258ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const ElementRegion *ER = dyn_cast<ElementRegion>(R); 259ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (!ER) 260ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return state; 261ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 262018220c343c103b7dfaa117a7a474c7a7fd6d068Zhongxing Xu assert(ER->getValueType() == C.getASTContext().CharTy && 263ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose "CheckLocation should only be called with char* ElementRegions"); 264ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 265ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Get the size of the array. 266c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek const SubRegion *superReg = cast<SubRegion>(ER->getSuperRegion()); 267c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SValBuilder &svalBuilder = C.getSValBuilder(); 2681e022415b9a66c84a9005b4e0bb2d4becb76d189Jordy Rose SVal Extent = 2691e022415b9a66c84a9005b4e0bb2d4becb76d189Jordy Rose svalBuilder.convertToArrayIndex(superReg->getExtent(svalBuilder)); 270ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose DefinedOrUnknownSVal Size = cast<DefinedOrUnknownSVal>(Extent); 271ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 272ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Get the index of the accessed element. 27389b06584402a38933e108b66ded3a168cd492dffGabor Greif DefinedOrUnknownSVal Idx = cast<DefinedOrUnknownSVal>(ER->getIndex()); 274ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 27518c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const ProgramState *StInBound = state->assumeInBound(Idx, Size, true); 27618c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const ProgramState *StOutBound = state->assumeInBound(Idx, Size, false); 277ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (StOutBound && !StInBound) { 278d048c6ef5b6cfaa0cecb8cc1d4bdace32ed21d07Ted Kremenek ExplodedNode *N = C.generateSink(StOutBound); 279ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (!N) 280ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return NULL; 281ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 2829e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose if (!BT_Bounds) { 2839e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose BT_Bounds.reset(new BuiltinBug("Out-of-bound array access", 2849e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose "Byte string function accesses out-of-bound array element")); 2859e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose } 2869e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose BuiltinBug *BT = static_cast<BuiltinBug*>(BT_Bounds.get()); 2879e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose 2889e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose // Generate a report for this bug. 289e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks BugReport *report; 2909e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose if (warningMsg) { 291e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks report = new BugReport(*BT, warningMsg, N); 292e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose } else { 2939e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose assert(CurrentFunctionDescription); 2949e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose assert(CurrentFunctionDescription[0] != '\0'); 2959e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose 2969e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose llvm::SmallString<80> buf; 2979e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose llvm::raw_svector_ostream os(buf); 2989e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose os << (char)toupper(CurrentFunctionDescription[0]) 2999e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose << &CurrentFunctionDescription[1] 3009e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose << " accesses out-of-bound array element"; 301e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks report = new BugReport(*BT, os.str(), N); 302e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose } 303ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 304ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // FIXME: It would be nice to eventually make this diagnostic more clear, 305ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // e.g., by referencing the original declaration or by saying *why* this 306ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // reference is outside the range. 307ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 308ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose report->addRange(S->getSourceRange()); 309ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose C.EmitReport(report); 310ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return NULL; 311ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose } 312ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 313ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Array bound check succeeded. From this point forward the array bound 314ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // should always succeed. 315ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return StInBound; 316ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose} 317ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 31818c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenekconst ProgramState *CStringChecker::CheckBufferAccess(CheckerContext &C, 31918c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const ProgramState *state, 320ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const Expr *Size, 321ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const Expr *FirstBuf, 322e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose const Expr *SecondBuf, 3239e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose const char *firstMessage, 3245e5f15062bcf4b62fda9062b453178f8b9bd0c2dJordy Rose const char *secondMessage, 3255e5f15062bcf4b62fda9062b453178f8b9bd0c2dJordy Rose bool WarnAboutSize) const { 326d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // If a previous check has failed, propagate the failure. 327d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (!state) 328d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose return NULL; 329d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 330c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SValBuilder &svalBuilder = C.getSValBuilder(); 3311e022415b9a66c84a9005b4e0bb2d4becb76d189Jordy Rose ASTContext &Ctx = svalBuilder.getContext(); 332ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 333c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek QualType sizeTy = Size->getType(); 334ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose QualType PtrTy = Ctx.getPointerType(Ctx.CharTy); 335ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 336a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose // Check that the first buffer is non-null. 337a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose SVal BufVal = state->getSVal(FirstBuf); 338c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek state = checkNonNull(C, state, FirstBuf, BufVal); 339a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose if (!state) 340a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose return NULL; 341a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose 342d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // Get the access length and make sure it is known. 3439e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose // FIXME: This assumes the caller has already checked that the access length 3449e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose // is positive. And that it's unsigned. 345d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose SVal LengthVal = state->getSVal(Size); 346d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose NonLoc *Length = dyn_cast<NonLoc>(&LengthVal); 347d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (!Length) 348d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose return state; 349d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 350ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Compute the offset of the last element to be accessed: size-1. 351c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek NonLoc One = cast<NonLoc>(svalBuilder.makeIntVal(1, sizeTy)); 352c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek NonLoc LastOffset = cast<NonLoc>(svalBuilder.evalBinOpNN(state, BO_Sub, 353c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek *Length, One, sizeTy)); 354ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 355fc8f0e14ad142ed811e90fbd9a30e419e301c717Chris Lattner // Check that the first buffer is sufficiently long. 356c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal BufStart = svalBuilder.evalCast(BufVal, PtrTy, FirstBuf->getType()); 357b6a4026de13909c2b145166ae0b7d96cf1948f64Jordy Rose if (Loc *BufLoc = dyn_cast<Loc>(&BufStart)) { 3585e5f15062bcf4b62fda9062b453178f8b9bd0c2dJordy Rose const Expr *warningExpr = (WarnAboutSize ? Size : FirstBuf); 3595e5f15062bcf4b62fda9062b453178f8b9bd0c2dJordy Rose 360c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal BufEnd = svalBuilder.evalBinOpLN(state, BO_Add, *BufLoc, 361c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek LastOffset, PtrTy); 3625e5f15062bcf4b62fda9062b453178f8b9bd0c2dJordy Rose state = CheckLocation(C, state, warningExpr, BufEnd, firstMessage); 363ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 364b6a4026de13909c2b145166ae0b7d96cf1948f64Jordy Rose // If the buffer isn't large enough, abort. 365b6a4026de13909c2b145166ae0b7d96cf1948f64Jordy Rose if (!state) 366b6a4026de13909c2b145166ae0b7d96cf1948f64Jordy Rose return NULL; 367b6a4026de13909c2b145166ae0b7d96cf1948f64Jordy Rose } 368ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 369ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // If there's a second buffer, check it as well. 370ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (SecondBuf) { 371ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose BufVal = state->getSVal(SecondBuf); 372c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek state = checkNonNull(C, state, SecondBuf, BufVal); 373a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose if (!state) 374a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose return NULL; 375a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose 376c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek BufStart = svalBuilder.evalCast(BufVal, PtrTy, SecondBuf->getType()); 377b6a4026de13909c2b145166ae0b7d96cf1948f64Jordy Rose if (Loc *BufLoc = dyn_cast<Loc>(&BufStart)) { 3785e5f15062bcf4b62fda9062b453178f8b9bd0c2dJordy Rose const Expr *warningExpr = (WarnAboutSize ? Size : SecondBuf); 3795e5f15062bcf4b62fda9062b453178f8b9bd0c2dJordy Rose 380c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal BufEnd = svalBuilder.evalBinOpLN(state, BO_Add, *BufLoc, 381c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek LastOffset, PtrTy); 3825e5f15062bcf4b62fda9062b453178f8b9bd0c2dJordy Rose state = CheckLocation(C, state, warningExpr, BufEnd, secondMessage); 383b6a4026de13909c2b145166ae0b7d96cf1948f64Jordy Rose } 384ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose } 385ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 386ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Large enough or not, return this state! 387ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return state; 388ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose} 389ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 39018c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenekconst ProgramState *CStringChecker::CheckOverlap(CheckerContext &C, 39118c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const ProgramState *state, 392d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose const Expr *Size, 393ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const Expr *First, 394183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis const Expr *Second) const { 395ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Do a simple check for overlap: if the two arguments are from the same 396ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // buffer, see if the end of the first is greater than the start of the second 397ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // or vice versa. 398ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 399d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // If a previous check has failed, propagate the failure. 400d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (!state) 401d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose return NULL; 402d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 40318c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const ProgramState *stateTrue, *stateFalse; 404ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 405ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Get the buffer values and make sure they're known locations. 406c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal firstVal = state->getSVal(First); 407c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal secondVal = state->getSVal(Second); 408ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 409c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek Loc *firstLoc = dyn_cast<Loc>(&firstVal); 410c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek if (!firstLoc) 411ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return state; 412ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 413c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek Loc *secondLoc = dyn_cast<Loc>(&secondVal); 414c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek if (!secondLoc) 415ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return state; 416ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 417ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Are the two values the same? 418c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SValBuilder &svalBuilder = C.getSValBuilder(); 419c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek llvm::tie(stateTrue, stateFalse) = 420c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek state->assume(svalBuilder.evalEQ(state, *firstLoc, *secondLoc)); 421ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 422ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (stateTrue && !stateFalse) { 423ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // If the values are known to be equal, that's automatically an overlap. 424c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek emitOverlapBug(C, stateTrue, First, Second); 425ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return NULL; 426ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose } 427ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 42828f47b92e760ccf641ac91cb0fe1c12d9ca89795Ted Kremenek // assume the two expressions are not equal. 429ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose assert(stateFalse); 430ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose state = stateFalse; 431ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 432ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Which value comes first? 433ee2fde12934c0b11a71db286d1dc9ee8341802a5Jordy Rose QualType cmpTy = svalBuilder.getConditionType(); 434c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal reverse = svalBuilder.evalBinOpLL(state, BO_GT, 435c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek *firstLoc, *secondLoc, cmpTy); 436c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek DefinedOrUnknownSVal *reverseTest = dyn_cast<DefinedOrUnknownSVal>(&reverse); 437c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek if (!reverseTest) 438ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return state; 439ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 440c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek llvm::tie(stateTrue, stateFalse) = state->assume(*reverseTest); 441ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (stateTrue) { 442ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (stateFalse) { 443ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // If we don't know which one comes first, we can't perform this test. 444ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return state; 445ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose } else { 446c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek // Switch the values so that firstVal is before secondVal. 447c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek Loc *tmpLoc = firstLoc; 448c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek firstLoc = secondLoc; 449c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek secondLoc = tmpLoc; 450ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 451ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Switch the Exprs as well, so that they still correspond. 452ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const Expr *tmpExpr = First; 453ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose First = Second; 454ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose Second = tmpExpr; 455ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose } 456ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose } 457ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 458ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Get the length, and make sure it too is known. 459ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose SVal LengthVal = state->getSVal(Size); 460ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose NonLoc *Length = dyn_cast<NonLoc>(&LengthVal); 461ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (!Length) 462ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return state; 463ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 464ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Convert the first buffer's start address to char*. 465ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Bail out if the cast fails. 466ee2fde12934c0b11a71db286d1dc9ee8341802a5Jordy Rose ASTContext &Ctx = svalBuilder.getContext(); 467ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose QualType CharPtrTy = Ctx.getPointerType(Ctx.CharTy); 4681e022415b9a66c84a9005b4e0bb2d4becb76d189Jordy Rose SVal FirstStart = svalBuilder.evalCast(*firstLoc, CharPtrTy, 4691e022415b9a66c84a9005b4e0bb2d4becb76d189Jordy Rose First->getType()); 470ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose Loc *FirstStartLoc = dyn_cast<Loc>(&FirstStart); 471ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (!FirstStartLoc) 472ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return state; 473ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 474ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Compute the end of the first buffer. Bail out if THAT fails. 475c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal FirstEnd = svalBuilder.evalBinOpLN(state, BO_Add, 476ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose *FirstStartLoc, *Length, CharPtrTy); 477ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose Loc *FirstEndLoc = dyn_cast<Loc>(&FirstEnd); 478ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (!FirstEndLoc) 479ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return state; 480ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 481ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Is the end of the first buffer past the start of the second buffer? 482c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal Overlap = svalBuilder.evalBinOpLL(state, BO_GT, 483c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek *FirstEndLoc, *secondLoc, cmpTy); 484ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose DefinedOrUnknownSVal *OverlapTest = dyn_cast<DefinedOrUnknownSVal>(&Overlap); 485ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (!OverlapTest) 486ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return state; 487ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 48828f47b92e760ccf641ac91cb0fe1c12d9ca89795Ted Kremenek llvm::tie(stateTrue, stateFalse) = state->assume(*OverlapTest); 489ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 490ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (stateTrue && !stateFalse) { 491ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Overlap! 492c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek emitOverlapBug(C, stateTrue, First, Second); 493ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return NULL; 494ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose } 495ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 49628f47b92e760ccf641ac91cb0fe1c12d9ca89795Ted Kremenek // assume the two expressions don't overlap. 497ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose assert(stateFalse); 498ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return stateFalse; 499ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose} 500ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 50118c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenekvoid CStringChecker::emitOverlapBug(CheckerContext &C, const ProgramState *state, 502183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis const Stmt *First, const Stmt *Second) const { 503d048c6ef5b6cfaa0cecb8cc1d4bdace32ed21d07Ted Kremenek ExplodedNode *N = C.generateSink(state); 504ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (!N) 505ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return; 506ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 507ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (!BT_Overlap) 508183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis BT_Overlap.reset(new BugType("Unix API", "Improper arguments")); 509ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 510ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Generate a report for this bug. 511e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks BugReport *report = 512e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks new BugReport(*BT_Overlap, 513ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose "Arguments must not be overlapping buffers", N); 514ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose report->addRange(First->getSourceRange()); 515ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose report->addRange(Second->getSourceRange()); 516ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 517ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose C.EmitReport(report); 518ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose} 519ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 52018c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenekconst ProgramState *CStringChecker::checkAdditionOverflow(CheckerContext &C, 52118c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const ProgramState *state, 522d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose NonLoc left, 523d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose NonLoc right) const { 524d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // If a previous check has failed, propagate the failure. 525d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose if (!state) 526d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose return NULL; 527d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 528d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose SValBuilder &svalBuilder = C.getSValBuilder(); 529d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose BasicValueFactory &BVF = svalBuilder.getBasicValueFactory(); 530d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 531d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose QualType sizeTy = svalBuilder.getContext().getSizeType(); 532d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose const llvm::APSInt &maxValInt = BVF.getMaxValue(sizeTy); 533d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose NonLoc maxVal = svalBuilder.makeIntVal(maxValInt); 534d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 535d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose SVal maxMinusRight = svalBuilder.evalBinOpNN(state, BO_Sub, maxVal, right, 536d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose sizeTy); 537d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 538d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose if (maxMinusRight.isUnknownOrUndef()) { 539d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // Try switching the operands. (The order of these two assignments is 540d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // important!) 541d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose maxMinusRight = svalBuilder.evalBinOpNN(state, BO_Sub, maxVal, left, 542d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose sizeTy); 543d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose left = right; 544d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose } 545d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 546d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose if (NonLoc *maxMinusRightNL = dyn_cast<NonLoc>(&maxMinusRight)) { 547d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose QualType cmpTy = svalBuilder.getConditionType(); 548d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // If left > max - right, we have an overflow. 549d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose SVal willOverflow = svalBuilder.evalBinOpNN(state, BO_GT, left, 550d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose *maxMinusRightNL, cmpTy); 551d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 55218c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const ProgramState *stateOverflow, *stateOkay; 553d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose llvm::tie(stateOverflow, stateOkay) = 554d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose state->assume(cast<DefinedOrUnknownSVal>(willOverflow)); 555d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 556d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose if (stateOverflow && !stateOkay) { 557d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // We have an overflow. Emit a bug report. 558d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose ExplodedNode *N = C.generateSink(stateOverflow); 559d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose if (!N) 560d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose return NULL; 561d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 562d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose if (!BT_AdditionOverflow) 563d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose BT_AdditionOverflow.reset(new BuiltinBug("API", 564d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose "Sum of expressions causes overflow")); 565d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 566d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // This isn't a great error message, but this should never occur in real 567d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // code anyway -- you'd have to create a buffer longer than a size_t can 568d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // represent, which is sort of a contradiction. 5698cc2491239f0b9de35985a1650fffc05c1ca8242Jordy Rose const char *warning = 5708cc2491239f0b9de35985a1650fffc05c1ca8242Jordy Rose "This expression will create a string whose length is too big to " 5718cc2491239f0b9de35985a1650fffc05c1ca8242Jordy Rose "be represented as a size_t"; 572d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 573d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // Generate a report for this bug. 5748cc2491239f0b9de35985a1650fffc05c1ca8242Jordy Rose BugReport *report = new BugReport(*BT_AdditionOverflow, warning, N); 575d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose C.EmitReport(report); 576d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 577d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose return NULL; 578d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose } 579d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 580d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // From now on, assume an overflow didn't occur. 581d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose assert(stateOkay); 582d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose state = stateOkay; 583d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose } 584d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 585d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose return state; 586d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose} 587d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 58818c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenekconst ProgramState *CStringChecker::setCStringLength(const ProgramState *state, 589e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose const MemRegion *MR, 590c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal strLength) { 591c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek assert(!strLength.isUndef() && "Attempt to set an undefined string length"); 592e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 593e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose MR = MR->StripCasts(); 594e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 595e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose switch (MR->getKind()) { 596e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose case MemRegion::StringRegionKind: 597e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // FIXME: This can happen if we strcpy() into a string region. This is 598e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // undefined [C99 6.4.5p6], but we should still warn about it. 599e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose return state; 600e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 601e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose case MemRegion::SymbolicRegionKind: 602e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose case MemRegion::AllocaRegionKind: 603e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose case MemRegion::VarRegionKind: 604e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose case MemRegion::FieldRegionKind: 605e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose case MemRegion::ObjCIvarRegionKind: 606210c05b10317a11971f87e474ffa4c30bb8e4df9Jordy Rose // These are the types we can currently track string lengths for. 607210c05b10317a11971f87e474ffa4c30bb8e4df9Jordy Rose break; 608e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 609e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose case MemRegion::ElementRegionKind: 610e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // FIXME: Handle element regions by upper-bounding the parent region's 611e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // string length. 612e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose return state; 613e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 614e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose default: 615e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // Other regions (mostly non-data) can't have a reliable C string length. 616e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // For now, just ignore the change. 617e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // FIXME: These are rare but not impossible. We should output some kind of 618e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // warning for things like strcpy((char[]){'a', 0}, "b"); 619e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose return state; 620e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose } 621210c05b10317a11971f87e474ffa4c30bb8e4df9Jordy Rose 622210c05b10317a11971f87e474ffa4c30bb8e4df9Jordy Rose if (strLength.isUnknown()) 623210c05b10317a11971f87e474ffa4c30bb8e4df9Jordy Rose return state->remove<CStringLength>(MR); 624210c05b10317a11971f87e474ffa4c30bb8e4df9Jordy Rose 625210c05b10317a11971f87e474ffa4c30bb8e4df9Jordy Rose return state->set<CStringLength>(MR, strLength); 626e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose} 627e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 628c8413fd03f73084a5c93028f8b4db619fc388087Ted KremenekSVal CStringChecker::getCStringLengthForRegion(CheckerContext &C, 62918c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const ProgramState *&state, 630a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose const Expr *Ex, 631d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose const MemRegion *MR, 632d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose bool hypothetical) { 633d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose if (!hypothetical) { 634d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // If there's a recorded length, go ahead and return it. 635d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose const SVal *Recorded = state->get<CStringLength>(MR); 636d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose if (Recorded) 637d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose return *Recorded; 638d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose } 639a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 640a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // Otherwise, get a new symbol and update the state. 6415d0ea6d62e076c776ddad028c4eb615783be1323Anna Zaks unsigned Count = C.getCurrentBlockCount(); 642c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SValBuilder &svalBuilder = C.getSValBuilder(); 643c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek QualType sizeTy = svalBuilder.getContext().getSizeType(); 644183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis SVal strLength = svalBuilder.getMetadataSymbolVal(CStringChecker::getTag(), 645183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis MR, Ex, sizeTy, Count); 646d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 647d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose if (!hypothetical) 648d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose state = state->set<CStringLength>(MR, strLength); 649d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 650c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek return strLength; 651a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose} 652a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 65318c66fdc3c4008d335885695fe36fb5353c5f672Ted KremenekSVal CStringChecker::getCStringLength(CheckerContext &C, const ProgramState *&state, 654d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose const Expr *Ex, SVal Buf, 655d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose bool hypothetical) const { 65619c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose const MemRegion *MR = Buf.getAsRegion(); 65719c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose if (!MR) { 65819c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose // If we can't get a region, see if it's something we /know/ isn't a 65919c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose // C string. In the context of locations, the only time we can issue such 66019c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose // a warning is for labels. 66119c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose if (loc::GotoLabel *Label = dyn_cast<loc::GotoLabel>(&Buf)) { 662d048c6ef5b6cfaa0cecb8cc1d4bdace32ed21d07Ted Kremenek if (ExplodedNode *N = C.generateNode(state)) { 66319c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose if (!BT_NotCString) 664183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis BT_NotCString.reset(new BuiltinBug("API", 665183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis "Argument is not a null-terminated string.")); 66619c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 66719c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose llvm::SmallString<120> buf; 66819c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose llvm::raw_svector_ostream os(buf); 6699e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose assert(CurrentFunctionDescription); 6709e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose os << "Argument to " << CurrentFunctionDescription 6719e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose << " is the address of the label '" << Label->getLabel()->getName() 67219c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose << "', which is not a null-terminated string"; 67319c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 67419c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose // Generate a report for this bug. 675e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks BugReport *report = new BugReport(*BT_NotCString, 67619c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose os.str(), N); 67719c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 67819c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose report->addRange(Ex->getSourceRange()); 67919c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose C.EmitReport(report); 68019c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose } 68119c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 68219c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose return UndefinedVal(); 68319c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose } 68419c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 685a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // If it's not a region and not a label, give up. 686a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose return UnknownVal(); 687a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose } 68819c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 689a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // If we have a region, strip casts from it and see if we can figure out 690a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // its length. For anything we can't figure out, just return UnknownVal. 691a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose MR = MR->StripCasts(); 692a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 693a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose switch (MR->getKind()) { 694a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose case MemRegion::StringRegionKind: { 695a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // Modifying the contents of string regions is undefined [C99 6.4.5p6], 696a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // so we can assume that the byte length is the correct C string length. 697c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SValBuilder &svalBuilder = C.getSValBuilder(); 698c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek QualType sizeTy = svalBuilder.getContext().getSizeType(); 699c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek const StringLiteral *strLit = cast<StringRegion>(MR)->getStringLiteral(); 700c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek return svalBuilder.makeIntVal(strLit->getByteLength(), sizeTy); 701a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose } 702a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose case MemRegion::SymbolicRegionKind: 703a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose case MemRegion::AllocaRegionKind: 704a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose case MemRegion::VarRegionKind: 705a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose case MemRegion::FieldRegionKind: 706a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose case MemRegion::ObjCIvarRegionKind: 707d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose return getCStringLengthForRegion(C, state, Ex, MR, hypothetical); 708a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose case MemRegion::CompoundLiteralRegionKind: 709a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // FIXME: Can we track this? Is it necessary? 710a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose return UnknownVal(); 711a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose case MemRegion::ElementRegionKind: 712a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // FIXME: How can we handle this? It's not good enough to subtract the 713a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // offset from the base string length; consider "123\x00567" and &a[5]. 714a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose return UnknownVal(); 715a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose default: 716a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // Other regions (mostly non-data) can't have a reliable C string length. 717a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // In this case, an error is emitted and UndefinedVal is returned. 718a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // The caller should always be prepared to handle this case. 719d048c6ef5b6cfaa0cecb8cc1d4bdace32ed21d07Ted Kremenek if (ExplodedNode *N = C.generateNode(state)) { 720a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (!BT_NotCString) 721183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis BT_NotCString.reset(new BuiltinBug("API", 722183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis "Argument is not a null-terminated string.")); 723a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 724a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose llvm::SmallString<120> buf; 725a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose llvm::raw_svector_ostream os(buf); 726a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 7279e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose assert(CurrentFunctionDescription); 7289e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose os << "Argument to " << CurrentFunctionDescription << " is "; 729a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 730a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (SummarizeRegion(os, C.getASTContext(), MR)) 731a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose os << ", which is not a null-terminated string"; 732a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose else 733a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose os << "not a null-terminated string"; 734a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 735a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // Generate a report for this bug. 736e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks BugReport *report = new BugReport(*BT_NotCString, 737a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose os.str(), N); 738a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 739a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose report->addRange(Ex->getSourceRange()); 740a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose C.EmitReport(report); 74119c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose } 74219c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 743a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose return UndefinedVal(); 74419c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose } 74519c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose} 74619c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 747318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maioraniconst StringLiteral *CStringChecker::getCStringLiteral(CheckerContext &C, 74818c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const ProgramState *&state, const Expr *expr, SVal val) const { 749318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani 750318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani // Get the memory region pointed to by the val. 751318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani const MemRegion *bufRegion = val.getAsRegion(); 752318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani if (!bufRegion) 753318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani return NULL; 754318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani 755318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani // Strip casts off the memory region. 756318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani bufRegion = bufRegion->StripCasts(); 757318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani 758318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani // Cast the memory region to a string region. 759318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani const StringRegion *strRegion= dyn_cast<StringRegion>(bufRegion); 760318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani if (!strRegion) 761318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani return NULL; 762318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani 763318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani // Return the actual string in the string region. 764318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani return strRegion->getStringLiteral(); 765318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani} 766318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani 76718c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenekconst ProgramState *CStringChecker::InvalidateBuffer(CheckerContext &C, 76818c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const ProgramState *state, 769e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose const Expr *E, SVal V) { 770e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose Loc *L = dyn_cast<Loc>(&V); 771e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose if (!L) 772e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose return state; 773e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 774e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // FIXME: This is a simplified version of what's in CFRefCount.cpp -- it makes 775e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // some assumptions about the value that CFRefCount can't. Even so, it should 776e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // probably be refactored. 777e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose if (loc::MemRegionVal* MR = dyn_cast<loc::MemRegionVal>(L)) { 778e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose const MemRegion *R = MR->getRegion()->StripCasts(); 779e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 780e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // Are we dealing with an ElementRegion? If so, we should be invalidating 781e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // the super-region. 782e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) { 783e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose R = ER->getSuperRegion(); 784e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // FIXME: What about layers of ElementRegions? 785e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose } 786e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 787e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // Invalidate this region. 7885d0ea6d62e076c776ddad028c4eb615783be1323Anna Zaks unsigned Count = C.getCurrentBlockCount(); 789537716ad8dd10f984b6cfe6985afade1185c5e3cJordy Rose return state->invalidateRegions(R, E, Count); 790e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose } 791e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 792e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // If we have a non-region value by chance, just remove the binding. 793e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // FIXME: is this necessary or correct? This handles the non-Region 794e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // cases. Is it ever valid to store to these? 795e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose return state->unbindLoc(*L); 796e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose} 797e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 7989c378f705405d37f49795d5e915989de774fe11fTed Kremenekbool CStringChecker::SummarizeRegion(raw_ostream &os, ASTContext &Ctx, 79919c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose const MemRegion *MR) { 8009697934650354bed2e509d8e7e44f21a1fb00f76Ted Kremenek const TypedValueRegion *TVR = dyn_cast<TypedValueRegion>(MR); 80119c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 802096aef9597b263b4cd6a0feaacf9e7214fa9c75aJordy Rose switch (MR->getKind()) { 80319c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose case MemRegion::FunctionTextRegionKind: { 804096aef9597b263b4cd6a0feaacf9e7214fa9c75aJordy Rose const FunctionDecl *FD = cast<FunctionTextRegion>(MR)->getDecl(); 80519c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose if (FD) 806b8989f27f116ff2400e92a52c067a69846119eb5Benjamin Kramer os << "the address of the function '" << *FD << '\''; 80719c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose else 80819c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose os << "the address of a function"; 80919c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose return true; 81019c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose } 81119c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose case MemRegion::BlockTextRegionKind: 81219c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose os << "block text"; 81319c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose return true; 81419c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose case MemRegion::BlockDataRegionKind: 81519c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose os << "a block"; 81619c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose return true; 81719c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose case MemRegion::CXXThisRegionKind: 81802fe28c8a6da29d4ad88d0900c133dcf22d24a75Zhongxing Xu case MemRegion::CXXTempObjectRegionKind: 8199697934650354bed2e509d8e7e44f21a1fb00f76Ted Kremenek os << "a C++ temp object of type " << TVR->getValueType().getAsString(); 82019c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose return true; 82119c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose case MemRegion::VarRegionKind: 8229697934650354bed2e509d8e7e44f21a1fb00f76Ted Kremenek os << "a variable of type" << TVR->getValueType().getAsString(); 82319c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose return true; 82419c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose case MemRegion::FieldRegionKind: 8259697934650354bed2e509d8e7e44f21a1fb00f76Ted Kremenek os << "a field of type " << TVR->getValueType().getAsString(); 82619c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose return true; 82719c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose case MemRegion::ObjCIvarRegionKind: 8289697934650354bed2e509d8e7e44f21a1fb00f76Ted Kremenek os << "an instance variable of type " << TVR->getValueType().getAsString(); 82919c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose return true; 83019c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose default: 83119c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose return false; 83219c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose } 83319c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose} 83419c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 835d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose//===----------------------------------------------------------------------===// 8369c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek// evaluation of individual function calls. 837d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose//===----------------------------------------------------------------------===// 838ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 839b8b875be7b2d177d755641c6212111859372d611Lenny Maioranivoid CStringChecker::evalCopyCommon(CheckerContext &C, 840b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani const CallExpr *CE, 84118c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const ProgramState *state, 842d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose const Expr *Size, const Expr *Dest, 843b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani const Expr *Source, bool Restricted, 844b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani bool IsMempcpy) const { 8459e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose CurrentFunctionDescription = "memory copy function"; 8469e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose 847d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // See if the size argument is zero. 848c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal sizeVal = state->getSVal(Size); 849c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek QualType sizeTy = Size->getType(); 850d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 85118c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const ProgramState *stateZeroSize, *stateNonZeroSize; 8521e022415b9a66c84a9005b4e0bb2d4becb76d189Jordy Rose llvm::tie(stateZeroSize, stateNonZeroSize) = 8531e022415b9a66c84a9005b4e0bb2d4becb76d189Jordy Rose assumeZero(C, state, sizeVal, sizeTy); 854d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 855b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani // Get the value of the Dest. 856b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani SVal destVal = state->getSVal(Dest); 857b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani 858b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani // If the size is zero, there won't be any actual memory access, so 859b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani // just bind the return value to the destination buffer and return. 860b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani if (stateZeroSize) { 86122d27178bf795145439b9588e260ccceab79a088Jordy Rose stateZeroSize = stateZeroSize->BindExpr(CE, destVal); 862c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek C.addTransition(stateZeroSize); 863b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani } 864d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 865d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // If the size can be nonzero, we have to check the other arguments. 866c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek if (stateNonZeroSize) { 86722d27178bf795145439b9588e260ccceab79a088Jordy Rose state = stateNonZeroSize; 868b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani 869b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani // Ensure the destination is not null. If it is NULL there will be a 870b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani // NULL pointer dereference. 871b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani state = checkNonNull(C, state, Dest, destVal); 872b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani if (!state) 873b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani return; 874b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani 875b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani // Get the value of the Src. 876b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani SVal srcVal = state->getSVal(Source); 877b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani 878b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani // Ensure the source is not null. If it is NULL there will be a 879b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani // NULL pointer dereference. 880b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani state = checkNonNull(C, state, Source, srcVal); 881b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani if (!state) 882b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani return; 883b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani 8847182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose // Ensure the accesses are valid and that the buffers do not overlap. 8859e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose const char * const writeWarning = 8869e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose "Memory copy function overflows destination buffer"; 887e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose state = CheckBufferAccess(C, state, Size, Dest, Source, 8889e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose writeWarning, /* sourceWarning = */ NULL); 889d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (Restricted) 890d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose state = CheckOverlap(C, state, Size, Dest, Source); 891e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 8927182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose if (!state) 8937182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose return; 8943f8bb2fa289c956a66613b0f09e3df5e25d27c66Jordy Rose 8957182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose // If this is mempcpy, get the byte after the last byte copied and 8967182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose // bind the expr. 8977182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose if (IsMempcpy) { 8987182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose loc::MemRegionVal *destRegVal = dyn_cast<loc::MemRegionVal>(&destVal); 8997182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose assert(destRegVal && "Destination should be a known MemRegionVal here"); 9007182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose 9017182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose // Get the length to copy. 9027182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose NonLoc *lenValNonLoc = dyn_cast<NonLoc>(&sizeVal); 9037182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose 9047182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose if (lenValNonLoc) { 9057182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose // Get the byte after the last byte copied. 9067182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose SVal lastElement = C.getSValBuilder().evalBinOpLN(state, BO_Add, 9077182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose *destRegVal, 9087182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose *lenValNonLoc, 9097182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose Dest->getType()); 9107182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose 9117182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose // The byte after the last byte copied is the return value. 9127182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose state = state->BindExpr(CE, lastElement); 9133f8bb2fa289c956a66613b0f09e3df5e25d27c66Jordy Rose } else { 9147182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose // If we don't know how much we copied, we can at least 9157182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose // conjure a return value for later. 9165d0ea6d62e076c776ddad028c4eb615783be1323Anna Zaks unsigned Count = C.getCurrentBlockCount(); 9177182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose SVal result = 9187182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose C.getSValBuilder().getConjuredSymbolVal(NULL, CE, Count); 9197182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose state = state->BindExpr(CE, result); 920b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani } 921b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani 9227182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose } else { 9237182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose // All other copies return the destination buffer. 9247182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose // (Well, bcopy() has a void return type, but this won't hurt.) 9257182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose state = state->BindExpr(CE, destVal); 926e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose } 9277182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose 9287182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose // Invalidate the destination. 9297182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose // FIXME: Even if we can't perfectly model the copy, we should see if we 9307182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose // can use LazyCompoundVals to copy the source values into the destination. 9317182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose // This would probably remove any existing bindings past the end of the 9327182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose // copied region, but that's still an improvement over blank invalidation. 9337182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose state = InvalidateBuffer(C, state, Dest, state->getSVal(Dest)); 9347182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose C.addTransition(state); 935d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose } 936ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose} 937ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 938ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 939183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidisvoid CStringChecker::evalMemcpy(CheckerContext &C, const CallExpr *CE) const { 940d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // void *memcpy(void *restrict dst, const void *restrict src, size_t n); 941d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // The return value is the address of the destination buffer. 942d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose const Expr *Dest = CE->getArg(0); 94318c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const ProgramState *state = C.getState(); 9443f8bb2fa289c956a66613b0f09e3df5e25d27c66Jordy Rose 945b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani evalCopyCommon(C, CE, state, CE->getArg(2), Dest, CE->getArg(1), true); 946b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani} 947b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani 948b8b875be7b2d177d755641c6212111859372d611Lenny Maioranivoid CStringChecker::evalMempcpy(CheckerContext &C, const CallExpr *CE) const { 949b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani // void *mempcpy(void *restrict dst, const void *restrict src, size_t n); 950b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani // The return value is a pointer to the byte following the last written byte. 951b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani const Expr *Dest = CE->getArg(0); 95218c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const ProgramState *state = C.getState(); 953b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani 954b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani evalCopyCommon(C, CE, state, CE->getArg(2), Dest, CE->getArg(1), true, true); 955d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose} 956ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 957183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidisvoid CStringChecker::evalMemmove(CheckerContext &C, const CallExpr *CE) const { 958d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // void *memmove(void *dst, const void *src, size_t n); 959ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // The return value is the address of the destination buffer. 960d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose const Expr *Dest = CE->getArg(0); 96118c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const ProgramState *state = C.getState(); 9623f8bb2fa289c956a66613b0f09e3df5e25d27c66Jordy Rose 963b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani evalCopyCommon(C, CE, state, CE->getArg(2), Dest, CE->getArg(1)); 964ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose} 965ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 966183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidisvoid CStringChecker::evalBcopy(CheckerContext &C, const CallExpr *CE) const { 967d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // void bcopy(const void *src, void *dst, size_t n); 968b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani evalCopyCommon(C, CE, C.getState(), 969b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani CE->getArg(2), CE->getArg(1), CE->getArg(0)); 970d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose} 971d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 972183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidisvoid CStringChecker::evalMemcmp(CheckerContext &C, const CallExpr *CE) const { 973bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose // int memcmp(const void *s1, const void *s2, size_t n); 9749e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose CurrentFunctionDescription = "memory comparison function"; 9759e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose 976bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose const Expr *Left = CE->getArg(0); 977bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose const Expr *Right = CE->getArg(1); 978bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose const Expr *Size = CE->getArg(2); 979bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose 98018c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const ProgramState *state = C.getState(); 981c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SValBuilder &svalBuilder = C.getSValBuilder(); 982bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose 983d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // See if the size argument is zero. 984c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal sizeVal = state->getSVal(Size); 985c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek QualType sizeTy = Size->getType(); 986bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose 98718c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const ProgramState *stateZeroSize, *stateNonZeroSize; 988c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek llvm::tie(stateZeroSize, stateNonZeroSize) = 989c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek assumeZero(C, state, sizeVal, sizeTy); 990bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose 991d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // If the size can be zero, the result will be 0 in that case, and we don't 992d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // have to check either of the buffers. 993c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek if (stateZeroSize) { 994c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek state = stateZeroSize; 995c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek state = state->BindExpr(CE, svalBuilder.makeZeroVal(CE->getType())); 996d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose C.addTransition(state); 997bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose } 998bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose 999d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // If the size can be nonzero, we have to check the other arguments. 1000c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek if (stateNonZeroSize) { 1001c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek state = stateNonZeroSize; 1002d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // If we know the two buffers are the same, we know the result is 0. 1003d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // First, get the two buffers' addresses. Another checker will have already 1004d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // made sure they're not undefined. 1005d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose DefinedOrUnknownSVal LV = cast<DefinedOrUnknownSVal>(state->getSVal(Left)); 1006d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose DefinedOrUnknownSVal RV = cast<DefinedOrUnknownSVal>(state->getSVal(Right)); 1007d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 1008d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // See if they are the same. 1009c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek DefinedOrUnknownSVal SameBuf = svalBuilder.evalEQ(state, LV, RV); 101018c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const ProgramState *StSameBuf, *StNotSameBuf; 101128f47b92e760ccf641ac91cb0fe1c12d9ca89795Ted Kremenek llvm::tie(StSameBuf, StNotSameBuf) = state->assume(SameBuf); 1012d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 10131e022415b9a66c84a9005b4e0bb2d4becb76d189Jordy Rose // If the two arguments might be the same buffer, we know the result is 0, 1014d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // and we only need to check one size. 1015d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (StSameBuf) { 1016d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose state = StSameBuf; 1017d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose state = CheckBufferAccess(C, state, Size, Left); 1018d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (state) { 1019c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek state = StSameBuf->BindExpr(CE, svalBuilder.makeZeroVal(CE->getType())); 1020d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose C.addTransition(state); 1021d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose } 1022d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose } 1023bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose 1024d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // If the two arguments might be different buffers, we have to check the 1025d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // size of both of them. 1026d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (StNotSameBuf) { 1027d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose state = StNotSameBuf; 1028d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose state = CheckBufferAccess(C, state, Size, Left, Right); 1029d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (state) { 1030d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // The return value is the comparison result, which we don't know. 10315d0ea6d62e076c776ddad028c4eb615783be1323Anna Zaks unsigned Count = C.getCurrentBlockCount(); 1032c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal CmpV = svalBuilder.getConjuredSymbolVal(NULL, CE, Count); 1033d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose state = state->BindExpr(CE, CmpV); 1034d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose C.addTransition(state); 1035d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose } 1036d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose } 1037d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose } 1038bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose} 1039bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose 1040183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidisvoid CStringChecker::evalstrLength(CheckerContext &C, 1041183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis const CallExpr *CE) const { 104219c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose // size_t strlen(const char *s); 1043be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek evalstrLengthCommon(C, CE, /* IsStrnlen = */ false); 1044be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek} 1045be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek 1046183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidisvoid CStringChecker::evalstrnLength(CheckerContext &C, 1047183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis const CallExpr *CE) const { 1048be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek // size_t strnlen(const char *s, size_t maxlen); 1049be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek evalstrLengthCommon(C, CE, /* IsStrnlen = */ true); 1050be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek} 1051be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek 1052be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenekvoid CStringChecker::evalstrLengthCommon(CheckerContext &C, const CallExpr *CE, 1053183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis bool IsStrnlen) const { 10549e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose CurrentFunctionDescription = "string length function"; 105518c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const ProgramState *state = C.getState(); 1056793bff3fb7ca2a31e81aa7f4f3f21f921459010bJordy Rose 1057793bff3fb7ca2a31e81aa7f4f3f21f921459010bJordy Rose if (IsStrnlen) { 1058793bff3fb7ca2a31e81aa7f4f3f21f921459010bJordy Rose const Expr *maxlenExpr = CE->getArg(1); 1059793bff3fb7ca2a31e81aa7f4f3f21f921459010bJordy Rose SVal maxlenVal = state->getSVal(maxlenExpr); 1060793bff3fb7ca2a31e81aa7f4f3f21f921459010bJordy Rose 106118c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const ProgramState *stateZeroSize, *stateNonZeroSize; 1062793bff3fb7ca2a31e81aa7f4f3f21f921459010bJordy Rose llvm::tie(stateZeroSize, stateNonZeroSize) = 1063793bff3fb7ca2a31e81aa7f4f3f21f921459010bJordy Rose assumeZero(C, state, maxlenVal, maxlenExpr->getType()); 1064793bff3fb7ca2a31e81aa7f4f3f21f921459010bJordy Rose 1065793bff3fb7ca2a31e81aa7f4f3f21f921459010bJordy Rose // If the size can be zero, the result will be 0 in that case, and we don't 1066793bff3fb7ca2a31e81aa7f4f3f21f921459010bJordy Rose // have to check the string itself. 1067793bff3fb7ca2a31e81aa7f4f3f21f921459010bJordy Rose if (stateZeroSize) { 1068793bff3fb7ca2a31e81aa7f4f3f21f921459010bJordy Rose SVal zero = C.getSValBuilder().makeZeroVal(CE->getType()); 1069793bff3fb7ca2a31e81aa7f4f3f21f921459010bJordy Rose stateZeroSize = stateZeroSize->BindExpr(CE, zero); 1070793bff3fb7ca2a31e81aa7f4f3f21f921459010bJordy Rose C.addTransition(stateZeroSize); 1071793bff3fb7ca2a31e81aa7f4f3f21f921459010bJordy Rose } 1072793bff3fb7ca2a31e81aa7f4f3f21f921459010bJordy Rose 1073793bff3fb7ca2a31e81aa7f4f3f21f921459010bJordy Rose // If the size is GUARANTEED to be zero, we're done! 1074793bff3fb7ca2a31e81aa7f4f3f21f921459010bJordy Rose if (!stateNonZeroSize) 1075793bff3fb7ca2a31e81aa7f4f3f21f921459010bJordy Rose return; 1076793bff3fb7ca2a31e81aa7f4f3f21f921459010bJordy Rose 1077793bff3fb7ca2a31e81aa7f4f3f21f921459010bJordy Rose // Otherwise, record the assumption that the size is nonzero. 1078793bff3fb7ca2a31e81aa7f4f3f21f921459010bJordy Rose state = stateNonZeroSize; 1079793bff3fb7ca2a31e81aa7f4f3f21f921459010bJordy Rose } 1080793bff3fb7ca2a31e81aa7f4f3f21f921459010bJordy Rose 1081793bff3fb7ca2a31e81aa7f4f3f21f921459010bJordy Rose // Check that the string argument is non-null. 108219c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose const Expr *Arg = CE->getArg(0); 108319c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose SVal ArgVal = state->getSVal(Arg); 108419c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 1085c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek state = checkNonNull(C, state, Arg, ArgVal); 108619c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 1087bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose if (!state) 1088bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose return; 1089a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1090bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose SVal strLength = getCStringLength(C, state, Arg, ArgVal); 1091a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1092bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose // If the argument isn't a valid C string, there's no valid state to 1093bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose // transition to. 1094bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose if (strLength.isUndef()) 1095bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose return; 1096be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek 1097bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose DefinedOrUnknownSVal result = UnknownVal(); 1098793bff3fb7ca2a31e81aa7f4f3f21f921459010bJordy Rose 1099bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose // If the check is for strnlen() then bind the return value to no more than 1100bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose // the maxlen value. 1101bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose if (IsStrnlen) { 1102ee2fde12934c0b11a71db286d1dc9ee8341802a5Jordy Rose QualType cmpTy = C.getSValBuilder().getConditionType(); 1103793bff3fb7ca2a31e81aa7f4f3f21f921459010bJordy Rose 1104bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose // It's a little unfortunate to be getting this again, 1105bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose // but it's not that expensive... 1106bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose const Expr *maxlenExpr = CE->getArg(1); 1107bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose SVal maxlenVal = state->getSVal(maxlenExpr); 1108bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose 1109bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose NonLoc *strLengthNL = dyn_cast<NonLoc>(&strLength); 1110bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose NonLoc *maxlenValNL = dyn_cast<NonLoc>(&maxlenVal); 1111bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose 1112bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose if (strLengthNL && maxlenValNL) { 111318c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const ProgramState *stateStringTooLong, *stateStringNotTooLong; 1114bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose 1115bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose // Check if the strLength is greater than the maxlen. 1116bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose llvm::tie(stateStringTooLong, stateStringNotTooLong) = 1117bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose state->assume(cast<DefinedOrUnknownSVal> 1118bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose (C.getSValBuilder().evalBinOpNN(state, BO_GT, 1119bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose *strLengthNL, 1120bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose *maxlenValNL, 1121bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose cmpTy))); 1122bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose 1123bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose if (stateStringTooLong && !stateStringNotTooLong) { 1124bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose // If the string is longer than maxlen, return maxlen. 1125bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose result = *maxlenValNL; 1126bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose } else if (stateStringNotTooLong && !stateStringTooLong) { 1127bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose // If the string is shorter than maxlen, return its length. 1128bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose result = *strLengthNL; 1129793bff3fb7ca2a31e81aa7f4f3f21f921459010bJordy Rose } 113019c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose } 1131a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1132bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose if (result.isUnknown()) { 1133bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose // If we don't have enough information for a comparison, there's 1134bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose // no guarantee the full string length will actually be returned. 1135bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose // All we know is the return value is the min of the string length 1136bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose // and the limit. This is better than nothing. 11375d0ea6d62e076c776ddad028c4eb615783be1323Anna Zaks unsigned Count = C.getCurrentBlockCount(); 1138bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose result = C.getSValBuilder().getConjuredSymbolVal(NULL, CE, Count); 1139bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose NonLoc *resultNL = cast<NonLoc>(&result); 1140bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose 1141bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose if (strLengthNL) { 1142bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose state = state->assume(cast<DefinedOrUnknownSVal> 1143bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose (C.getSValBuilder().evalBinOpNN(state, BO_LE, 1144bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose *resultNL, 1145bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose *strLengthNL, 1146bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose cmpTy)), true); 1147bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose } 1148bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose 1149bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose if (maxlenValNL) { 1150bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose state = state->assume(cast<DefinedOrUnknownSVal> 1151bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose (C.getSValBuilder().evalBinOpNN(state, BO_LE, 1152bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose *resultNL, 1153bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose *maxlenValNL, 1154bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose cmpTy)), true); 1155bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose } 1156bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose } 1157bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose 1158bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose } else { 1159bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose // This is a plain strlen(), not strnlen(). 1160bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose result = cast<DefinedOrUnknownSVal>(strLength); 1161bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose 1162bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose // If we don't know the length of the string, conjure a return 1163bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose // value, so it can be used in constraints, at least. 1164bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose if (result.isUnknown()) { 11655d0ea6d62e076c776ddad028c4eb615783be1323Anna Zaks unsigned Count = C.getCurrentBlockCount(); 1166bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose result = C.getSValBuilder().getConjuredSymbolVal(NULL, CE, Count); 1167bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose } 116819c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose } 1169bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose 1170bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose // Bind the return value. 1171bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose assert(!result.isUnknown() && "Should have conjured a value by now"); 1172bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose state = state->BindExpr(CE, result); 1173bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose C.addTransition(state); 117419c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose} 117519c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 1176183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidisvoid CStringChecker::evalStrcpy(CheckerContext &C, const CallExpr *CE) const { 1177e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // char *strcpy(char *restrict dst, const char *restrict src); 1178067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani evalStrcpyCommon(C, CE, 1179067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani /* returnEnd = */ false, 1180067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani /* isBounded = */ false, 1181067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani /* isAppending = */ false); 11820ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek} 11830ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek 1184183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidisvoid CStringChecker::evalStrncpy(CheckerContext &C, const CallExpr *CE) const { 1185c152586baf0fcdfd4c660e5dcd7b6857f13203d6Jordy Rose // char *strncpy(char *restrict dst, const char *restrict src, size_t n); 1186067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani evalStrcpyCommon(C, CE, 1187067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani /* returnEnd = */ false, 1188067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani /* isBounded = */ true, 1189067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani /* isAppending = */ false); 1190e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose} 1191e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 1192183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidisvoid CStringChecker::evalStpcpy(CheckerContext &C, const CallExpr *CE) const { 1193e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // char *stpcpy(char *restrict dst, const char *restrict src); 1194067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani evalStrcpyCommon(C, CE, 1195067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani /* returnEnd = */ true, 1196067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani /* isBounded = */ false, 1197067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani /* isAppending = */ false); 1198067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani} 1199067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani 1200067bbd0e11c71a33b51832532e836971be697699Lenny Maioranivoid CStringChecker::evalStrcat(CheckerContext &C, const CallExpr *CE) const { 1201067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani //char *strcat(char *restrict s1, const char *restrict s2); 1202067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani evalStrcpyCommon(C, CE, 1203067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani /* returnEnd = */ false, 1204067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani /* isBounded = */ false, 1205067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani /* isAppending = */ true); 1206067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani} 1207067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani 1208067bbd0e11c71a33b51832532e836971be697699Lenny Maioranivoid CStringChecker::evalStrncat(CheckerContext &C, const CallExpr *CE) const { 1209067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani //char *strncat(char *restrict s1, const char *restrict s2, size_t n); 1210067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani evalStrcpyCommon(C, CE, 1211067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani /* returnEnd = */ false, 1212067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani /* isBounded = */ true, 1213067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani /* isAppending = */ true); 1214e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose} 1215e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 12169c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenekvoid CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE, 1217067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani bool returnEnd, bool isBounded, 1218067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani bool isAppending) const { 12199e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose CurrentFunctionDescription = "string copy function"; 122018c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const ProgramState *state = C.getState(); 1221e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 1222067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani // Check that the destination is non-null. 1223e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose const Expr *Dst = CE->getArg(0); 1224e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose SVal DstVal = state->getSVal(Dst); 1225e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 1226c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek state = checkNonNull(C, state, Dst, DstVal); 1227e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose if (!state) 1228e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose return; 1229e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 1230e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // Check that the source is non-null. 1231c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek const Expr *srcExpr = CE->getArg(1); 1232c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal srcVal = state->getSVal(srcExpr); 1233c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek state = checkNonNull(C, state, srcExpr, srcVal); 1234e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose if (!state) 1235e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose return; 1236e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 1237e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // Get the string length of the source. 1238c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal strLength = getCStringLength(C, state, srcExpr, srcVal); 1239e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 1240e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // If the source isn't a valid C string, give up. 1241c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek if (strLength.isUndef()) 1242e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose return; 1243e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 1244d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose SValBuilder &svalBuilder = C.getSValBuilder(); 1245d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose QualType cmpTy = svalBuilder.getConditionType(); 12468912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose QualType sizeTy = svalBuilder.getContext().getSizeType(); 1247d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 12488912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose // These two values allow checking two kinds of errors: 12498912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose // - actual overflows caused by a source that doesn't fit in the destination 12508912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose // - potential overflows caused by a bound that could exceed the destination 1251d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose SVal amountCopied = UnknownVal(); 12528912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose SVal maxLastElementIndex = UnknownVal(); 12538912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose const char *boundWarning = NULL; 1254d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 1255067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani // If the function is strncpy, strncat, etc... it is bounded. 1256067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani if (isBounded) { 1257067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani // Get the max number of characters to copy. 12580ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek const Expr *lenExpr = CE->getArg(2); 12590ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek SVal lenVal = state->getSVal(lenExpr); 12600ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek 1261d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // Protect against misdeclared strncpy(). 12628912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose lenVal = svalBuilder.evalCast(lenVal, sizeTy, lenExpr->getType()); 1263508c627db67ea4b53439fbcd688145f24d9c0400Lenny Maiorani 1264d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose NonLoc *strLengthNL = dyn_cast<NonLoc>(&strLength); 12650ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek NonLoc *lenValNL = dyn_cast<NonLoc>(&lenVal); 12660ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek 1267d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // If we know both values, we might be able to figure out how much 1268d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // we're copying. 1269d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose if (strLengthNL && lenValNL) { 127018c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const ProgramState *stateSourceTooLong, *stateSourceNotTooLong; 1271d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 1272d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // Check if the max number to copy is less than the length of the src. 12738912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose // If the bound is equal to the source length, strncpy won't null- 12748912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose // terminate the result! 1275d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose llvm::tie(stateSourceTooLong, stateSourceNotTooLong) = 1276d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose state->assume(cast<DefinedOrUnknownSVal> 12778912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose (svalBuilder.evalBinOpNN(state, BO_GE, *strLengthNL, 1278d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose *lenValNL, cmpTy))); 1279d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 1280d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose if (stateSourceTooLong && !stateSourceNotTooLong) { 1281d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // Max number to copy is less than the length of the src, so the actual 1282d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // strLength copied is the max number arg. 1283d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose state = stateSourceTooLong; 1284d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose amountCopied = lenVal; 1285d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 1286d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose } else if (!stateSourceTooLong && stateSourceNotTooLong) { 1287d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // The source buffer entirely fits in the bound. 1288d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose state = stateSourceNotTooLong; 1289d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose amountCopied = strLength; 1290d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose } 1291d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose } 1292d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 12935e5f15062bcf4b62fda9062b453178f8b9bd0c2dJordy Rose // We still want to know if the bound is known to be too large. 12948912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose if (lenValNL) { 12958912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose if (isAppending) { 12968912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose // For strncat, the check is strlen(dst) + lenVal < sizeof(dst) 12978912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose 12988912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose // Get the string length of the destination. If the destination is 12998912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose // memory that can't have a string length, we shouldn't be copying 13008912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose // into it anyway. 13018912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose SVal dstStrLength = getCStringLength(C, state, Dst, DstVal); 13028912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose if (dstStrLength.isUndef()) 13038912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose return; 13048912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose 13058912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose if (NonLoc *dstStrLengthNL = dyn_cast<NonLoc>(&dstStrLength)) { 13068912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose maxLastElementIndex = svalBuilder.evalBinOpNN(state, BO_Add, 13078912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose *lenValNL, 13088912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose *dstStrLengthNL, 13098912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose sizeTy); 13108912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose boundWarning = "Size argument is greater than the free space in the " 13118912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose "destination buffer"; 13128912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose } 13138912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose 13148912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose } else { 13158912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose // For strncpy, this is just checking that lenVal <= sizeof(dst) 13168912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose // (Yes, strncpy and strncat differ in how they treat termination. 13178912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose // strncat ALWAYS terminates, but strncpy doesn't.) 13188912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose NonLoc one = cast<NonLoc>(svalBuilder.makeIntVal(1, sizeTy)); 13198912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose maxLastElementIndex = svalBuilder.evalBinOpNN(state, BO_Sub, *lenValNL, 13208912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose one, sizeTy); 13218912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose boundWarning = "Size argument is greater than the length of the " 13228912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose "destination buffer"; 13238912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose } 13248912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose } 13255e5f15062bcf4b62fda9062b453178f8b9bd0c2dJordy Rose 1326d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // If we couldn't pin down the copy length, at least bound it. 13278912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose // FIXME: We should actually run this code path for append as well, but 13288912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose // right now it creates problems with constraints (since we can end up 13298912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose // trying to pass constraints from symbol to symbol). 13308912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose if (amountCopied.isUnknown() && !isAppending) { 1331d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // Try to get a "hypothetical" string length symbol, which we can later 1332d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // set as a real value if that turns out to be the case. 1333d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose amountCopied = getCStringLength(C, state, lenExpr, srcVal, true); 1334d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose assert(!amountCopied.isUndef()); 1335d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 1336d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose if (NonLoc *amountCopiedNL = dyn_cast<NonLoc>(&amountCopied)) { 1337d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose if (lenValNL) { 1338d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // amountCopied <= lenVal 1339d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose SVal copiedLessThanBound = svalBuilder.evalBinOpNN(state, BO_LE, 1340d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose *amountCopiedNL, 1341d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose *lenValNL, 1342d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose cmpTy); 1343d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose state = state->assume(cast<DefinedOrUnknownSVal>(copiedLessThanBound), 1344d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose true); 1345d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose if (!state) 1346d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose return; 1347d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose } 1348d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 1349d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose if (strLengthNL) { 1350d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // amountCopied <= strlen(source) 1351d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose SVal copiedLessThanSrc = svalBuilder.evalBinOpNN(state, BO_LE, 1352d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose *amountCopiedNL, 1353d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose *strLengthNL, 1354d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose cmpTy); 1355d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose state = state->assume(cast<DefinedOrUnknownSVal>(copiedLessThanSrc), 1356d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose true); 1357d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose if (!state) 1358d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose return; 1359d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose } 1360d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose } 1361d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose } 1362d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 1363d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose } else { 1364d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // The function isn't bounded. The amount copied should match the length 1365d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // of the source buffer. 1366d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose amountCopied = strLength; 13670ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek } 13680ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek 1369d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose assert(state); 1370d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 1371d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // This represents the number of characters copied into the destination 1372d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // buffer. (It may not actually be the strlen if the destination buffer 1373d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // is not terminated.) 1374d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose SVal finalStrLength = UnknownVal(); 1375d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 1376067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani // If this is an appending function (strcat, strncat...) then set the 1377067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani // string length to strlen(src) + strlen(dst) since the buffer will 1378067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani // ultimately contain both. 1379067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani if (isAppending) { 13801e022415b9a66c84a9005b4e0bb2d4becb76d189Jordy Rose // Get the string length of the destination. If the destination is memory 13811e022415b9a66c84a9005b4e0bb2d4becb76d189Jordy Rose // that can't have a string length, we shouldn't be copying into it anyway. 1382067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani SVal dstStrLength = getCStringLength(C, state, Dst, DstVal); 1383067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani if (dstStrLength.isUndef()) 1384067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani return; 1385067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani 1386d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose NonLoc *srcStrLengthNL = dyn_cast<NonLoc>(&amountCopied); 1387067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani NonLoc *dstStrLengthNL = dyn_cast<NonLoc>(&dstStrLength); 1388067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani 1389d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // If we know both string lengths, we might know the final string length. 1390d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose if (srcStrLengthNL && dstStrLengthNL) { 1391d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // Make sure the two lengths together don't overflow a size_t. 1392d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose state = checkAdditionOverflow(C, state, *srcStrLengthNL, *dstStrLengthNL); 1393d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose if (!state) 1394d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose return; 1395d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 1396d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose finalStrLength = svalBuilder.evalBinOpNN(state, BO_Add, *srcStrLengthNL, 1397d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose *dstStrLengthNL, sizeTy); 1398d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose } 1399067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani 1400d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // If we couldn't get a single value for the final string length, 1401d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // we can at least bound it by the individual lengths. 1402d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose if (finalStrLength.isUnknown()) { 1403d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // Try to get a "hypothetical" string length symbol, which we can later 1404d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // set as a real value if that turns out to be the case. 1405d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose finalStrLength = getCStringLength(C, state, CE, DstVal, true); 1406d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose assert(!finalStrLength.isUndef()); 1407d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 1408d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose if (NonLoc *finalStrLengthNL = dyn_cast<NonLoc>(&finalStrLength)) { 1409d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose if (srcStrLengthNL) { 1410d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // finalStrLength >= srcStrLength 1411d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose SVal sourceInResult = svalBuilder.evalBinOpNN(state, BO_GE, 1412d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose *finalStrLengthNL, 1413d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose *srcStrLengthNL, 1414d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose cmpTy); 1415d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose state = state->assume(cast<DefinedOrUnknownSVal>(sourceInResult), 1416d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose true); 1417d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose if (!state) 1418d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose return; 1419d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose } 1420d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 1421d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose if (dstStrLengthNL) { 1422d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // finalStrLength >= dstStrLength 1423d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose SVal destInResult = svalBuilder.evalBinOpNN(state, BO_GE, 1424d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose *finalStrLengthNL, 1425d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose *dstStrLengthNL, 1426d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose cmpTy); 1427d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose state = state->assume(cast<DefinedOrUnknownSVal>(destInResult), 1428d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose true); 1429d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose if (!state) 1430d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose return; 1431d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose } 1432d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose } 1433d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose } 1434067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani 1435d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose } else { 1436d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // Otherwise, this is a copy-over function (strcpy, strncpy, ...), and 1437d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // the final string length will match the input string length. 1438d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose finalStrLength = amountCopied; 1439067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani } 1440067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani 1441d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // The final result of the function will either be a pointer past the last 1442d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // copied element, or a pointer to the start of the destination buffer. 1443c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal Result = (returnEnd ? UnknownVal() : DstVal); 1444e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 1445d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose assert(state); 1446d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 1447e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // If the destination is a MemRegion, try to check for a buffer overflow and 1448e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // record the new string length. 1449c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek if (loc::MemRegionVal *dstRegVal = dyn_cast<loc::MemRegionVal>(&DstVal)) { 14508912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose QualType ptrTy = Dst->getType(); 14518912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose 14528912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose // If we have an exact value on a bounded copy, use that to check for 14538912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose // overflows, rather than our estimate about how much is actually copied. 14548912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose if (boundWarning) { 14558912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose if (NonLoc *maxLastNL = dyn_cast<NonLoc>(&maxLastElementIndex)) { 14568912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose SVal maxLastElement = svalBuilder.evalBinOpLN(state, BO_Add, *dstRegVal, 14578912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose *maxLastNL, ptrTy); 14588912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose state = CheckLocation(C, state, CE->getArg(2), maxLastElement, 14598912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose boundWarning); 14608912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose if (!state) 14618912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose return; 14628912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose } 14638912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose } 14648912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose 14658912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose // Then, if the final length is known... 1466d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose if (NonLoc *knownStrLength = dyn_cast<NonLoc>(&finalStrLength)) { 1467d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose SVal lastElement = svalBuilder.evalBinOpLN(state, BO_Add, *dstRegVal, 14688912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose *knownStrLength, ptrTy); 14698912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose 14708912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose // ...and we haven't checked the bound, we'll check the actual copy. 14718912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose if (!boundWarning) { 14728912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose const char * const warningMsg = 14738912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose "String copy function overflows destination buffer"; 14748912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose state = CheckLocation(C, state, Dst, lastElement, warningMsg); 14758912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose if (!state) 14768912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose return; 14778912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose } 1478e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 1479e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // If this is a stpcpy-style copy, the last element is the return value. 1480c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek if (returnEnd) 1481c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek Result = lastElement; 1482e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose } 1483e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 1484e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // Invalidate the destination. This must happen before we set the C string 1485e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // length because invalidation will clear the length. 1486e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // FIXME: Even if we can't perfectly model the copy, we should see if we 1487e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // can use LazyCompoundVals to copy the source values into the destination. 1488e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // This would probably remove any existing bindings past the end of the 1489e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // string, but that's still an improvement over blank invalidation. 1490c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek state = InvalidateBuffer(C, state, Dst, *dstRegVal); 1491e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 14925e5f15062bcf4b62fda9062b453178f8b9bd0c2dJordy Rose // Set the C string length of the destination, if we know it. 14938912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose if (isBounded && !isAppending) { 14948912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose // strncpy is annoying in that it doesn't guarantee to null-terminate 14958912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose // the result string. If the original string didn't fit entirely inside 14968912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose // the bound (including the null-terminator), we don't know how long the 14978912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose // result is. 14988912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose if (amountCopied != strLength) 14998912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose finalStrLength = UnknownVal(); 15008912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose } 15018912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose state = setCStringLength(state, dstRegVal->getRegion(), finalStrLength); 1502e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose } 1503e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 1504d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose assert(state); 1505d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 1506e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // If this is a stpcpy-style copy, but we were unable to check for a buffer 1507e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // overflow, we still need a result. Conjure a return value. 1508c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek if (returnEnd && Result.isUnknown()) { 15095d0ea6d62e076c776ddad028c4eb615783be1323Anna Zaks unsigned Count = C.getCurrentBlockCount(); 1510d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose Result = svalBuilder.getConjuredSymbolVal(NULL, CE, Count); 1511e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose } 1512e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 1513e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // Set the return value. 1514e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose state = state->BindExpr(CE, Result); 1515e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose C.addTransition(state); 1516e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose} 1517e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 1518318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maioranivoid CStringChecker::evalStrcmp(CheckerContext &C, const CallExpr *CE) const { 1519adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose //int strcmp(const char *s1, const char *s2); 1520bd1d16a1792cd6ea5ede9869e18d781e3fc1a8c3Lenny Maiorani evalStrcmpCommon(C, CE, /* isBounded = */ false, /* ignoreCase = */ false); 1521357f6ee9f1f6f8e5027377cb3e5907c62c4fe3dfLenny Maiorani} 1522357f6ee9f1f6f8e5027377cb3e5907c62c4fe3dfLenny Maiorani 1523357f6ee9f1f6f8e5027377cb3e5907c62c4fe3dfLenny Maioranivoid CStringChecker::evalStrncmp(CheckerContext &C, const CallExpr *CE) const { 1524adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose //int strncmp(const char *s1, const char *s2, size_t n); 1525bd1d16a1792cd6ea5ede9869e18d781e3fc1a8c3Lenny Maiorani evalStrcmpCommon(C, CE, /* isBounded = */ true, /* ignoreCase = */ false); 1526bd1d16a1792cd6ea5ede9869e18d781e3fc1a8c3Lenny Maiorani} 1527bd1d16a1792cd6ea5ede9869e18d781e3fc1a8c3Lenny Maiorani 1528bd1d16a1792cd6ea5ede9869e18d781e3fc1a8c3Lenny Maioranivoid CStringChecker::evalStrcasecmp(CheckerContext &C, 1529bd1d16a1792cd6ea5ede9869e18d781e3fc1a8c3Lenny Maiorani const CallExpr *CE) const { 1530adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose //int strcasecmp(const char *s1, const char *s2); 1531bd1d16a1792cd6ea5ede9869e18d781e3fc1a8c3Lenny Maiorani evalStrcmpCommon(C, CE, /* isBounded = */ false, /* ignoreCase = */ true); 1532357f6ee9f1f6f8e5027377cb3e5907c62c4fe3dfLenny Maiorani} 1533318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani 1534454fd2d3a1b6d0ef225c5d3927c1ad3b97510d1aLenny Maioranivoid CStringChecker::evalStrncasecmp(CheckerContext &C, 1535454fd2d3a1b6d0ef225c5d3927c1ad3b97510d1aLenny Maiorani const CallExpr *CE) const { 1536adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose //int strncasecmp(const char *s1, const char *s2, size_t n); 1537454fd2d3a1b6d0ef225c5d3927c1ad3b97510d1aLenny Maiorani evalStrcmpCommon(C, CE, /* isBounded = */ true, /* ignoreCase = */ true); 1538454fd2d3a1b6d0ef225c5d3927c1ad3b97510d1aLenny Maiorani} 1539454fd2d3a1b6d0ef225c5d3927c1ad3b97510d1aLenny Maiorani 1540357f6ee9f1f6f8e5027377cb3e5907c62c4fe3dfLenny Maioranivoid CStringChecker::evalStrcmpCommon(CheckerContext &C, const CallExpr *CE, 1541bd1d16a1792cd6ea5ede9869e18d781e3fc1a8c3Lenny Maiorani bool isBounded, bool ignoreCase) const { 15429e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose CurrentFunctionDescription = "string comparison function"; 154318c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const ProgramState *state = C.getState(); 1544318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani 1545318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani // Check that the first string is non-null 1546318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani const Expr *s1 = CE->getArg(0); 1547318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani SVal s1Val = state->getSVal(s1); 1548318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani state = checkNonNull(C, state, s1, s1Val); 1549318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani if (!state) 1550318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani return; 1551318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani 1552318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani // Check that the second string is non-null. 1553318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani const Expr *s2 = CE->getArg(1); 1554318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani SVal s2Val = state->getSVal(s2); 1555318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani state = checkNonNull(C, state, s2, s2Val); 1556318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani if (!state) 1557318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani return; 1558318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani 1559318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani // Get the string length of the first string or give up. 1560318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani SVal s1Length = getCStringLength(C, state, s1, s1Val); 1561318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani if (s1Length.isUndef()) 1562318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani return; 1563318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani 1564318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani // Get the string length of the second string or give up. 1565318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani SVal s2Length = getCStringLength(C, state, s2, s2Val); 1566318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani if (s2Length.isUndef()) 1567318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani return; 1568318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani 1569adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose // If we know the two buffers are the same, we know the result is 0. 1570adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose // First, get the two buffers' addresses. Another checker will have already 1571adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose // made sure they're not undefined. 1572adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose DefinedOrUnknownSVal LV = cast<DefinedOrUnknownSVal>(s1Val); 1573adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose DefinedOrUnknownSVal RV = cast<DefinedOrUnknownSVal>(s2Val); 1574adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose 1575adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose // See if they are the same. 1576adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose SValBuilder &svalBuilder = C.getSValBuilder(); 1577adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose DefinedOrUnknownSVal SameBuf = svalBuilder.evalEQ(state, LV, RV); 157818c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const ProgramState *StSameBuf, *StNotSameBuf; 1579adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose llvm::tie(StSameBuf, StNotSameBuf) = state->assume(SameBuf); 1580adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose 1581adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose // If the two arguments might be the same buffer, we know the result is 0, 1582adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose // and we only need to check one size. 1583adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose if (StSameBuf) { 1584adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose StSameBuf = StSameBuf->BindExpr(CE, svalBuilder.makeZeroVal(CE->getType())); 1585adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose C.addTransition(StSameBuf); 1586adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose 1587adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose // If the two arguments are GUARANTEED to be the same, we're done! 1588adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose if (!StNotSameBuf) 1589adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose return; 1590adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose } 1591adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose 1592adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose assert(StNotSameBuf); 1593adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose state = StNotSameBuf; 1594318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani 1595adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose // At this point we can go about comparing the two buffers. 1596adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose // For now, we only do this if they're both known string literals. 1597adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose 1598adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose // Attempt to extract string literals from both expressions. 1599adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose const StringLiteral *s1StrLiteral = getCStringLiteral(C, state, s1, s1Val); 1600318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani const StringLiteral *s2StrLiteral = getCStringLiteral(C, state, s2, s2Val); 1601adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose bool canComputeResult = false; 1602adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose 1603adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose if (s1StrLiteral && s2StrLiteral) { 16045f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef s1StrRef = s1StrLiteral->getString(); 16055f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef s2StrRef = s2StrLiteral->getString(); 1606adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose 1607adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose if (isBounded) { 1608adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose // Get the max number of characters to compare. 1609adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose const Expr *lenExpr = CE->getArg(2); 1610adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose SVal lenVal = state->getSVal(lenExpr); 1611adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose 1612adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose // If the length is known, we can get the right substrings. 1613adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose if (const llvm::APSInt *len = svalBuilder.getKnownValue(state, lenVal)) { 1614adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose // Create substrings of each to compare the prefix. 1615adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose s1StrRef = s1StrRef.substr(0, (size_t)len->getZExtValue()); 1616adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose s2StrRef = s2StrRef.substr(0, (size_t)len->getZExtValue()); 1617adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose canComputeResult = true; 1618adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose } 1619adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose } else { 1620adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose // This is a normal, unbounded strcmp. 1621adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose canComputeResult = true; 1622adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose } 1623318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani 1624adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose if (canComputeResult) { 1625adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose // Real strcmp stops at null characters. 1626adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose size_t s1Term = s1StrRef.find('\0'); 16275f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner if (s1Term != StringRef::npos) 1628adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose s1StrRef = s1StrRef.substr(0, s1Term); 1629357f6ee9f1f6f8e5027377cb3e5907c62c4fe3dfLenny Maiorani 1630adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose size_t s2Term = s2StrRef.find('\0'); 16315f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner if (s2Term != StringRef::npos) 1632adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose s2StrRef = s2StrRef.substr(0, s2Term); 1633adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose 1634adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose // Use StringRef's comparison methods to compute the actual result. 1635adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose int result; 1636adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose 1637adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose if (ignoreCase) { 1638adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose // Compare string 1 to string 2 the same way strcasecmp() does. 1639adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose result = s1StrRef.compare_lower(s2StrRef); 1640adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose } else { 1641adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose // Compare string 1 to string 2 the same way strcmp() does. 1642adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose result = s1StrRef.compare(s2StrRef); 1643adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose } 1644357f6ee9f1f6f8e5027377cb3e5907c62c4fe3dfLenny Maiorani 1645adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose // Build the SVal of the comparison and bind the return value. 1646adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose SVal resultVal = svalBuilder.makeIntVal(result, CE->getType()); 1647adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose state = state->BindExpr(CE, resultVal); 1648adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose } 1649454fd2d3a1b6d0ef225c5d3927c1ad3b97510d1aLenny Maiorani } 1650bd1d16a1792cd6ea5ede9869e18d781e3fc1a8c3Lenny Maiorani 1651adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose if (!canComputeResult) { 1652adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose // Conjure a symbolic value. It's the best we can do. 16535d0ea6d62e076c776ddad028c4eb615783be1323Anna Zaks unsigned Count = C.getCurrentBlockCount(); 1654adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose SVal resultVal = svalBuilder.getConjuredSymbolVal(NULL, CE, Count); 1655adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose state = state->BindExpr(CE, resultVal); 1656357f6ee9f1f6f8e5027377cb3e5907c62c4fe3dfLenny Maiorani } 1657318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani 1658adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose // Record this as a possible path. 1659318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani C.addTransition(state); 1660318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani} 1661318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani 1662d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose//===----------------------------------------------------------------------===// 1663a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose// The driver method, and other Checker callbacks. 1664d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose//===----------------------------------------------------------------------===// 1665ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 1666183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidisbool CStringChecker::evalCall(const CallExpr *CE, CheckerContext &C) const { 1667ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Get the callee. All the functions we care about are C functions 1668ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // with simple identifiers. 166918c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const ProgramState *state = C.getState(); 1670ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const Expr *Callee = CE->getCallee(); 1671ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const FunctionDecl *FD = state->getSVal(Callee).getAsFunctionDecl(); 1672ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 1673ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (!FD) 1674ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return false; 1675ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 1676ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Get the name of the callee. If it's a builtin, strip off the prefix. 167790d26a4afdbf6d917a5241ef3b316e1c8337c9b8Douglas Gregor IdentifierInfo *II = FD->getIdentifier(); 167890d26a4afdbf6d917a5241ef3b316e1c8337c9b8Douglas Gregor if (!II) // if no identifier, not a simple C function 167990d26a4afdbf6d917a5241ef3b316e1c8337c9b8Douglas Gregor return false; 16805f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef Name = II->getName(); 1681ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (Name.startswith("__builtin_")) 1682ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose Name = Name.substr(10); 1683ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 16849c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek FnCheck evalFunction = llvm::StringSwitch<FnCheck>(Name) 16859c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek .Cases("memcpy", "__memcpy_chk", &CStringChecker::evalMemcpy) 1686be460d8e5364c6bffeb7b27e4c0d4d5d16e39c59Jordy Rose .Cases("mempcpy", "__mempcpy_chk", &CStringChecker::evalMempcpy) 16879c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek .Cases("memcmp", "bcmp", &CStringChecker::evalMemcmp) 16889c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek .Cases("memmove", "__memmove_chk", &CStringChecker::evalMemmove) 16899c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek .Cases("strcpy", "__strcpy_chk", &CStringChecker::evalStrcpy) 16905e5f15062bcf4b62fda9062b453178f8b9bd0c2dJordy Rose .Cases("strncpy", "__strncpy_chk", &CStringChecker::evalStrncpy) 16919c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek .Cases("stpcpy", "__stpcpy_chk", &CStringChecker::evalStpcpy) 1692067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani .Cases("strcat", "__strcat_chk", &CStringChecker::evalStrcat) 1693067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani .Cases("strncat", "__strncat_chk", &CStringChecker::evalStrncat) 1694c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek .Case("strlen", &CStringChecker::evalstrLength) 1695be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek .Case("strnlen", &CStringChecker::evalstrnLength) 1696318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani .Case("strcmp", &CStringChecker::evalStrcmp) 1697357f6ee9f1f6f8e5027377cb3e5907c62c4fe3dfLenny Maiorani .Case("strncmp", &CStringChecker::evalStrncmp) 1698bd1d16a1792cd6ea5ede9869e18d781e3fc1a8c3Lenny Maiorani .Case("strcasecmp", &CStringChecker::evalStrcasecmp) 1699454fd2d3a1b6d0ef225c5d3927c1ad3b97510d1aLenny Maiorani .Case("strncasecmp", &CStringChecker::evalStrncasecmp) 17009c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek .Case("bcopy", &CStringChecker::evalBcopy) 1701ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose .Default(NULL); 1702ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 1703d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // If the callee isn't a string function, let another checker handle it. 17049c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek if (!evalFunction) 1705ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return false; 1706ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 17079e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose // Make sure each function sets its own description. 17089e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose // (But don't bother in a release build.) 17099e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose assert(!(CurrentFunctionDescription = NULL)); 17109e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose 1711d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // Check and evaluate the call. 17129c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek (this->*evalFunction)(C, CE); 1713ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return true; 1714ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose} 1715a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1716183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidisvoid CStringChecker::checkPreStmt(const DeclStmt *DS, CheckerContext &C) const { 1717a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // Record string length for char a[] = "abc"; 171818c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const ProgramState *state = C.getState(); 1719a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1720a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose for (DeclStmt::const_decl_iterator I = DS->decl_begin(), E = DS->decl_end(); 1721a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose I != E; ++I) { 1722a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose const VarDecl *D = dyn_cast<VarDecl>(*I); 1723a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (!D) 1724a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose continue; 1725a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1726a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // FIXME: Handle array fields of structs. 1727a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (!D->getType()->isArrayType()) 1728a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose continue; 1729a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1730a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose const Expr *Init = D->getInit(); 1731a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (!Init) 1732a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose continue; 1733a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (!isa<StringLiteral>(Init)) 1734a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose continue; 1735a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1736a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose Loc VarLoc = state->getLValue(D, C.getPredecessor()->getLocationContext()); 1737a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose const MemRegion *MR = VarLoc.getAsRegion(); 1738a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (!MR) 1739a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose continue; 1740a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1741a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose SVal StrVal = state->getSVal(Init); 1742a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose assert(StrVal.isValid() && "Initializer string is unknown or undefined"); 1743c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek DefinedOrUnknownSVal strLength 1744c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek = cast<DefinedOrUnknownSVal>(getCStringLength(C, state, Init, StrVal)); 1745a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1746c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek state = state->set<CStringLength>(MR, strLength); 1747a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose } 1748a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1749a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose C.addTransition(state); 1750a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose} 1751a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 175218c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenekbool CStringChecker::wantsRegionChangeUpdate(const ProgramState *state) const { 1753a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose CStringLength::EntryMap Entries = state->get<CStringLength>(); 1754a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose return !Entries.isEmpty(); 1755a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose} 1756a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 175718c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenekconst ProgramState * 175818c66fdc3c4008d335885695fe36fb5353c5f672Ted KremenekCStringChecker::checkRegionChanges(const ProgramState *state, 175935bdbf40624beba3fc00cb72ab444659939c1a6bTed Kremenek const StoreManager::InvalidatedSymbols *, 1760537716ad8dd10f984b6cfe6985afade1185c5e3cJordy Rose ArrayRef<const MemRegion *> ExplicitRegions, 1761537716ad8dd10f984b6cfe6985afade1185c5e3cJordy Rose ArrayRef<const MemRegion *> Regions) const { 1762a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose CStringLength::EntryMap Entries = state->get<CStringLength>(); 1763a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (Entries.isEmpty()) 1764a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose return state; 1765a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1766a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose llvm::SmallPtrSet<const MemRegion *, 8> Invalidated; 1767a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose llvm::SmallPtrSet<const MemRegion *, 32> SuperRegions; 1768a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1769a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // First build sets for the changed regions and their super-regions. 1770537716ad8dd10f984b6cfe6985afade1185c5e3cJordy Rose for (ArrayRef<const MemRegion *>::iterator 1771537716ad8dd10f984b6cfe6985afade1185c5e3cJordy Rose I = Regions.begin(), E = Regions.end(); I != E; ++I) { 1772537716ad8dd10f984b6cfe6985afade1185c5e3cJordy Rose const MemRegion *MR = *I; 1773a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose Invalidated.insert(MR); 1774a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1775a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose SuperRegions.insert(MR); 1776a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose while (const SubRegion *SR = dyn_cast<SubRegion>(MR)) { 1777a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose MR = SR->getSuperRegion(); 1778a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose SuperRegions.insert(MR); 1779a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose } 1780a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose } 1781a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1782a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose CStringLength::EntryMap::Factory &F = state->get_context<CStringLength>(); 1783a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1784a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // Then loop over the entries in the current state. 1785a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose for (CStringLength::EntryMap::iterator I = Entries.begin(), 1786a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose E = Entries.end(); I != E; ++I) { 1787a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose const MemRegion *MR = I.getKey(); 1788a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1789a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // Is this entry for a super-region of a changed region? 1790a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (SuperRegions.count(MR)) { 17913baf672378f105602d2b12f03f00277ae1936fe9Ted Kremenek Entries = F.remove(Entries, MR); 1792a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose continue; 1793a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose } 1794a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1795a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // Is this entry for a sub-region of a changed region? 1796a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose const MemRegion *Super = MR; 1797a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose while (const SubRegion *SR = dyn_cast<SubRegion>(Super)) { 1798a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose Super = SR->getSuperRegion(); 1799a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (Invalidated.count(Super)) { 18003baf672378f105602d2b12f03f00277ae1936fe9Ted Kremenek Entries = F.remove(Entries, MR); 1801a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose break; 1802a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose } 1803a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose } 1804a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose } 1805a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1806a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose return state->set<CStringLength>(Entries); 1807a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose} 1808a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 180918c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenekvoid CStringChecker::checkLiveSymbols(const ProgramState *state, 1810183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis SymbolReaper &SR) const { 1811a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // Mark all symbols in our string length map as valid. 1812a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose CStringLength::EntryMap Entries = state->get<CStringLength>(); 1813a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1814a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose for (CStringLength::EntryMap::iterator I = Entries.begin(), E = Entries.end(); 1815a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose I != E; ++I) { 1816a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose SVal Len = I.getData(); 1817d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 1818d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose for (SVal::symbol_iterator si = Len.symbol_begin(), se = Len.symbol_end(); 1819d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose si != se; ++si) 1820d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose SR.markInUse(*si); 1821a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose } 1822a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose} 1823a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1824183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidisvoid CStringChecker::checkDeadSymbols(SymbolReaper &SR, 1825183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis CheckerContext &C) const { 1826a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (!SR.hasDeadSymbols()) 1827a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose return; 1828a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 182918c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const ProgramState *state = C.getState(); 1830a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose CStringLength::EntryMap Entries = state->get<CStringLength>(); 1831a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (Entries.isEmpty()) 1832a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose return; 1833a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1834a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose CStringLength::EntryMap::Factory &F = state->get_context<CStringLength>(); 1835a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose for (CStringLength::EntryMap::iterator I = Entries.begin(), E = Entries.end(); 1836a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose I != E; ++I) { 1837a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose SVal Len = I.getData(); 1838a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (SymbolRef Sym = Len.getAsSymbol()) { 1839a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (SR.isDead(Sym)) 18403baf672378f105602d2b12f03f00277ae1936fe9Ted Kremenek Entries = F.remove(Entries, I.getKey()); 1841a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose } 1842a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose } 1843a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1844a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose state = state->set<CStringLength>(Entries); 1845d048c6ef5b6cfaa0cecb8cc1d4bdace32ed21d07Ted Kremenek C.generateNode(state); 1846a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose} 1847183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis 1848183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidisvoid ento::registerCStringChecker(CheckerManager &mgr) { 1849183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis mgr.registerChecker<CStringChecker>(); 1850183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis} 1851