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" 16f0dfc9c0f29fd82552896558c04043731d30b851Anna Zaks#include "InterCheckerAPI.h" 17ec8605f1d7ec846dbf51047bfd5c56d32d1ff91cArgyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/Checker.h" 18695fb502825a53ccd178ec1c85c77929d88acb71Argyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/CheckerManager.h" 19183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 209b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 2118c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h" 228fe83e1df954d72c0f4ffc15d20a5222ec151c21Benjamin Kramer#include "llvm/ADT/SmallString.h" 2300bd44d5677783527d7517c1ffe45e4d75a0f56fBenjamin Kramer#include "llvm/ADT/STLExtras.h" 24ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose#include "llvm/ADT/StringSwitch.h" 25ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 26ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Roseusing namespace clang; 279ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenekusing namespace ento; 28ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 29ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rosenamespace { 30ec8605f1d7ec846dbf51047bfd5c56d32d1ff91cArgyrios Kyrtzidisclass CStringChecker : public Checker< eval::Call, 31183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis check::PreStmt<DeclStmt>, 32183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis check::LiveSymbols, 33183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis check::DeadSymbols, 34183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis check::RegionChanges 35183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis > { 3657300760964904cc022a175643342f29f46b7e6bAnna Zaks mutable OwningPtr<BugType> BT_Null, 3757300760964904cc022a175643342f29f46b7e6bAnna Zaks BT_Bounds, 3857300760964904cc022a175643342f29f46b7e6bAnna Zaks BT_Overlap, 3957300760964904cc022a175643342f29f46b7e6bAnna Zaks BT_NotCString, 4057300760964904cc022a175643342f29f46b7e6bAnna Zaks BT_AdditionOverflow; 4157300760964904cc022a175643342f29f46b7e6bAnna Zaks 429e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose mutable const char *CurrentFunctionDescription; 439e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose 44ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rosepublic: 4557300760964904cc022a175643342f29f46b7e6bAnna Zaks /// The filter is used to filter out the diagnostics which are not enabled by 4657300760964904cc022a175643342f29f46b7e6bAnna Zaks /// the user. 4757300760964904cc022a175643342f29f46b7e6bAnna Zaks struct CStringChecksFilter { 4857300760964904cc022a175643342f29f46b7e6bAnna Zaks DefaultBool CheckCStringNullArg; 4957300760964904cc022a175643342f29f46b7e6bAnna Zaks DefaultBool CheckCStringOutOfBounds; 5057300760964904cc022a175643342f29f46b7e6bAnna Zaks DefaultBool CheckCStringBufferOverlap; 5157300760964904cc022a175643342f29f46b7e6bAnna Zaks DefaultBool CheckCStringNotNullTerm; 5257300760964904cc022a175643342f29f46b7e6bAnna Zaks }; 5357300760964904cc022a175643342f29f46b7e6bAnna Zaks 5457300760964904cc022a175643342f29f46b7e6bAnna Zaks CStringChecksFilter Filter; 5557300760964904cc022a175643342f29f46b7e6bAnna Zaks 56ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose static void *getTag() { static int tag; return &tag; } 57ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 58183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis bool evalCall(const CallExpr *CE, CheckerContext &C) const; 59183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis void checkPreStmt(const DeclStmt *DS, CheckerContext &C) const; 608bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek void checkLiveSymbols(ProgramStateRef state, SymbolReaper &SR) const; 61183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const; 628bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek bool wantsRegionChangeUpdate(ProgramStateRef state) const; 63a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 648bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef 658bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek checkRegionChanges(ProgramStateRef state, 6618c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const StoreManager::InvalidatedSymbols *, 67537716ad8dd10f984b6cfe6985afade1185c5e3cJordy Rose ArrayRef<const MemRegion *> ExplicitRegions, 6866c40400e7d6272b0cd675ada18dd62c1f0362c7Anna Zaks ArrayRef<const MemRegion *> Regions, 69740d490593e0de8732a697c9f77b90ddd463863bJordan Rose const CallEvent *Call) const; 70ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 71183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis typedef void (CStringChecker::*FnCheck)(CheckerContext &, 72183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis const CallExpr *) const; 73ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 74183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis void evalMemcpy(CheckerContext &C, const CallExpr *CE) const; 75b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani void evalMempcpy(CheckerContext &C, const CallExpr *CE) const; 76183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis void evalMemmove(CheckerContext &C, const CallExpr *CE) const; 77183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis void evalBcopy(CheckerContext &C, const CallExpr *CE) const; 78b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani void evalCopyCommon(CheckerContext &C, const CallExpr *CE, 798bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state, 8018c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const Expr *Size, 8118c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const Expr *Source, 8218c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const Expr *Dest, 83b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani bool Restricted = false, 84b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani bool IsMempcpy = false) const; 85d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 86183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis void evalMemcmp(CheckerContext &C, const CallExpr *CE) const; 87ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 88183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis void evalstrLength(CheckerContext &C, const CallExpr *CE) const; 89183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis void evalstrnLength(CheckerContext &C, const CallExpr *CE) const; 9018c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek void evalstrLengthCommon(CheckerContext &C, 9118c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const CallExpr *CE, 92183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis bool IsStrnlen = false) const; 9319c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 94183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis void evalStrcpy(CheckerContext &C, const CallExpr *CE) const; 95183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis void evalStrncpy(CheckerContext &C, const CallExpr *CE) const; 96183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis void evalStpcpy(CheckerContext &C, const CallExpr *CE) const; 9718c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek void evalStrcpyCommon(CheckerContext &C, 9818c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const CallExpr *CE, 9918c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek bool returnEnd, 10018c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek bool isBounded, 10118c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek bool isAppending) const; 102067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani 103067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani void evalStrcat(CheckerContext &C, const CallExpr *CE) const; 104067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani void evalStrncat(CheckerContext &C, const CallExpr *CE) const; 105e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 106318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani void evalStrcmp(CheckerContext &C, const CallExpr *CE) const; 107357f6ee9f1f6f8e5027377cb3e5907c62c4fe3dfLenny Maiorani void evalStrncmp(CheckerContext &C, const CallExpr *CE) const; 108bd1d16a1792cd6ea5ede9869e18d781e3fc1a8c3Lenny Maiorani void evalStrcasecmp(CheckerContext &C, const CallExpr *CE) const; 109454fd2d3a1b6d0ef225c5d3927c1ad3b97510d1aLenny Maiorani void evalStrncasecmp(CheckerContext &C, const CallExpr *CE) const; 11018c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek void evalStrcmpCommon(CheckerContext &C, 11118c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const CallExpr *CE, 11218c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek bool isBounded = false, 11318c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek bool ignoreCase = false) const; 114318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani 115ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Utility methods 1168bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek std::pair<ProgramStateRef , ProgramStateRef > 117183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis static assumeZero(CheckerContext &C, 1188bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state, SVal V, QualType Ty); 119183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis 1208bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek static ProgramStateRef setCStringLength(ProgramStateRef state, 12118c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const MemRegion *MR, 12218c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek SVal strLength); 123183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis static SVal getCStringLengthForRegion(CheckerContext &C, 1248bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef &state, 12518c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const Expr *Ex, 12618c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const MemRegion *MR, 127d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose bool hypothetical); 12818c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek SVal getCStringLength(CheckerContext &C, 1298bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef &state, 13018c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const Expr *Ex, 13118c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek SVal Buf, 132d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose bool hypothetical = false) const; 13319c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 134318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani const StringLiteral *getCStringLiteral(CheckerContext &C, 1358bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef &state, 136318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani const Expr *expr, 137318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani SVal val) const; 138318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani 1398bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek static ProgramStateRef InvalidateBuffer(CheckerContext &C, 1408bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state, 14118c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const Expr *Ex, SVal V); 142e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 1439c378f705405d37f49795d5e915989de774fe11fTed Kremenek static bool SummarizeRegion(raw_ostream &os, ASTContext &Ctx, 144183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis const MemRegion *MR); 14519c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 14619c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose // Re-usable checks 1478bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef checkNonNull(CheckerContext &C, 1488bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state, 14918c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const Expr *S, 15018c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek SVal l) const; 1518bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef CheckLocation(CheckerContext &C, 1528bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state, 15318c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const Expr *S, 15418c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek SVal l, 15518c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const char *message = NULL) const; 1568bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef CheckBufferAccess(CheckerContext &C, 1578bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state, 15818c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const Expr *Size, 15918c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const Expr *FirstBuf, 16018c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const Expr *SecondBuf, 16118c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const char *firstMessage = NULL, 16218c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const char *secondMessage = NULL, 16318c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek bool WarnAboutSize = false) const; 16418c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek 1658bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef CheckBufferAccess(CheckerContext &C, 1668bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state, 16718c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const Expr *Size, 16818c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const Expr *Buf, 16918c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const char *message = NULL, 17018c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek bool WarnAboutSize = false) const { 1719e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose // This is a convenience override. 1725e5f15062bcf4b62fda9062b453178f8b9bd0c2dJordy Rose return CheckBufferAccess(C, state, Size, Buf, NULL, message, NULL, 1735e5f15062bcf4b62fda9062b453178f8b9bd0c2dJordy Rose WarnAboutSize); 1749e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose } 1758bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef CheckOverlap(CheckerContext &C, 1768bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state, 17718c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const Expr *Size, 17818c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const Expr *First, 17918c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const Expr *Second) const; 18018c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek void emitOverlapBug(CheckerContext &C, 1818bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state, 18218c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const Stmt *First, 18318c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek const Stmt *Second) const; 18418c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek 1858bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef checkAdditionOverflow(CheckerContext &C, 1868bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state, 18718c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek NonLoc left, 18818c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek NonLoc right) const; 189ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose}; 190a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 191a5261549754fab80e30e893d8fa706bfb31e430aJordy Roseclass CStringLength { 192a5261549754fab80e30e893d8fa706bfb31e430aJordy Rosepublic: 193a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose typedef llvm::ImmutableMap<const MemRegion *, SVal> EntryMap; 194a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose}; 195ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose} //end anonymous namespace 196ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 197a5261549754fab80e30e893d8fa706bfb31e430aJordy Rosenamespace clang { 1989ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremeneknamespace ento { 199a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose template <> 20018c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek struct ProgramStateTrait<CStringLength> 20118c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek : public ProgramStatePartialTrait<CStringLength::EntryMap> { 202a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose static void *GDMIndex() { return CStringChecker::getTag(); } 203a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose }; 204a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose} 2055a4f98ff943e6a501b0fe47ade007c9bbf96cb88Argyrios Kyrtzidis} 206a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 207d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose//===----------------------------------------------------------------------===// 208d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose// Individual checks and utility methods. 209d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose//===----------------------------------------------------------------------===// 210d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 2118bef8238181a30e52dea380789a7e2d760eac532Ted Kremenekstd::pair<ProgramStateRef , ProgramStateRef > 2128bef8238181a30e52dea380789a7e2d760eac532Ted KremenekCStringChecker::assumeZero(CheckerContext &C, ProgramStateRef state, SVal V, 213d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose QualType Ty) { 214c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek DefinedSVal *val = dyn_cast<DefinedSVal>(&V); 215c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek if (!val) 2168bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek return std::pair<ProgramStateRef , ProgramStateRef >(state, state); 217a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose 218c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SValBuilder &svalBuilder = C.getSValBuilder(); 219c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek DefinedOrUnknownSVal zero = svalBuilder.makeZeroVal(Ty); 220c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek return state->assume(svalBuilder.evalEQ(state, *val, zero)); 221d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose} 222d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 2238bef8238181a30e52dea380789a7e2d760eac532Ted KremenekProgramStateRef CStringChecker::checkNonNull(CheckerContext &C, 2248bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state, 225183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis const Expr *S, SVal l) const { 226d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // If a previous check has failed, propagate the failure. 227d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (!state) 228d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose return NULL; 229a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose 2308bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef stateNull, stateNonNull; 23128f47b92e760ccf641ac91cb0fe1c12d9ca89795Ted Kremenek llvm::tie(stateNull, stateNonNull) = assumeZero(C, state, l, S->getType()); 232a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose 233d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (stateNull && !stateNonNull) { 23457300760964904cc022a175643342f29f46b7e6bAnna Zaks if (!Filter.CheckCStringNullArg) 23557300760964904cc022a175643342f29f46b7e6bAnna Zaks return NULL; 23657300760964904cc022a175643342f29f46b7e6bAnna Zaks 237d048c6ef5b6cfaa0cecb8cc1d4bdace32ed21d07Ted Kremenek ExplodedNode *N = C.generateSink(stateNull); 238a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose if (!N) 239a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose return NULL; 240a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose 241d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (!BT_Null) 24257300760964904cc022a175643342f29f46b7e6bAnna Zaks BT_Null.reset(new BuiltinBug("Unix API", 243183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis "Null pointer argument in call to byte string function")); 244a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose 245f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith SmallString<80> buf; 2469e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose llvm::raw_svector_ostream os(buf); 2479e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose assert(CurrentFunctionDescription); 2489e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose os << "Null pointer argument in call to " << CurrentFunctionDescription; 2499e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose 250a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose // Generate a report for this bug. 251183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis BuiltinBug *BT = static_cast<BuiltinBug*>(BT_Null.get()); 252e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks BugReport *report = new BugReport(*BT, os.str(), N); 253a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose 254a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose report->addRange(S->getSourceRange()); 255a1f81bb0e55749a1414b1b5124bb83b9052ff2acJordan Rose bugreporter::trackNullOrUndefValue(N, S, *report); 256a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose C.EmitReport(report); 257a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose return NULL; 258a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose } 259a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose 260a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose // From here on, assume that the value is non-null. 261d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose assert(stateNonNull); 262d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose return stateNonNull; 263a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose} 264a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose 265ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose// FIXME: This was originally copied from ArrayBoundChecker.cpp. Refactor? 2668bef8238181a30e52dea380789a7e2d760eac532Ted KremenekProgramStateRef CStringChecker::CheckLocation(CheckerContext &C, 2678bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state, 268e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose const Expr *S, SVal l, 2699e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose const char *warningMsg) const { 270d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // If a previous check has failed, propagate the failure. 271d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (!state) 272d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose return NULL; 273d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 274ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Check for out of bound array element access. 275ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const MemRegion *R = l.getAsRegion(); 276ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (!R) 277ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return state; 278ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 279ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const ElementRegion *ER = dyn_cast<ElementRegion>(R); 280ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (!ER) 281ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return state; 282ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 283018220c343c103b7dfaa117a7a474c7a7fd6d068Zhongxing Xu assert(ER->getValueType() == C.getASTContext().CharTy && 284ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose "CheckLocation should only be called with char* ElementRegions"); 285ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 286ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Get the size of the array. 287c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek const SubRegion *superReg = cast<SubRegion>(ER->getSuperRegion()); 288c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SValBuilder &svalBuilder = C.getSValBuilder(); 2891e022415b9a66c84a9005b4e0bb2d4becb76d189Jordy Rose SVal Extent = 2901e022415b9a66c84a9005b4e0bb2d4becb76d189Jordy Rose svalBuilder.convertToArrayIndex(superReg->getExtent(svalBuilder)); 291ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose DefinedOrUnknownSVal Size = cast<DefinedOrUnknownSVal>(Extent); 292ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 293ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Get the index of the accessed element. 29489b06584402a38933e108b66ded3a168cd492dffGabor Greif DefinedOrUnknownSVal Idx = cast<DefinedOrUnknownSVal>(ER->getIndex()); 295ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 2968bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef StInBound = state->assumeInBound(Idx, Size, true); 2978bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef StOutBound = state->assumeInBound(Idx, Size, false); 298ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (StOutBound && !StInBound) { 299d048c6ef5b6cfaa0cecb8cc1d4bdace32ed21d07Ted Kremenek ExplodedNode *N = C.generateSink(StOutBound); 300ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (!N) 301ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return NULL; 302ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 3039e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose if (!BT_Bounds) { 3049e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose BT_Bounds.reset(new BuiltinBug("Out-of-bound array access", 3059e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose "Byte string function accesses out-of-bound array element")); 3069e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose } 3079e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose BuiltinBug *BT = static_cast<BuiltinBug*>(BT_Bounds.get()); 3089e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose 3099e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose // Generate a report for this bug. 310e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks BugReport *report; 3119e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose if (warningMsg) { 312e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks report = new BugReport(*BT, warningMsg, N); 313e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose } else { 3149e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose assert(CurrentFunctionDescription); 3159e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose assert(CurrentFunctionDescription[0] != '\0'); 3169e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose 317f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith SmallString<80> buf; 3189e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose llvm::raw_svector_ostream os(buf); 3199e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose os << (char)toupper(CurrentFunctionDescription[0]) 3209e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose << &CurrentFunctionDescription[1] 3219e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose << " accesses out-of-bound array element"; 322e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks report = new BugReport(*BT, os.str(), N); 323e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose } 324ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 325ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // FIXME: It would be nice to eventually make this diagnostic more clear, 326ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // e.g., by referencing the original declaration or by saying *why* this 327ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // reference is outside the range. 328ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 329ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose report->addRange(S->getSourceRange()); 330ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose C.EmitReport(report); 331ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return NULL; 332ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose } 333ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 334ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Array bound check succeeded. From this point forward the array bound 335ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // should always succeed. 336ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return StInBound; 337ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose} 338ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 3398bef8238181a30e52dea380789a7e2d760eac532Ted KremenekProgramStateRef CStringChecker::CheckBufferAccess(CheckerContext &C, 3408bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state, 341ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const Expr *Size, 342ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const Expr *FirstBuf, 343e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose const Expr *SecondBuf, 3449e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose const char *firstMessage, 3455e5f15062bcf4b62fda9062b453178f8b9bd0c2dJordy Rose const char *secondMessage, 3465e5f15062bcf4b62fda9062b453178f8b9bd0c2dJordy Rose bool WarnAboutSize) const { 347d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // If a previous check has failed, propagate the failure. 348d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (!state) 349d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose return NULL; 350d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 351c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SValBuilder &svalBuilder = C.getSValBuilder(); 3521e022415b9a66c84a9005b4e0bb2d4becb76d189Jordy Rose ASTContext &Ctx = svalBuilder.getContext(); 3535eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek const LocationContext *LCtx = C.getLocationContext(); 354ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 355c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek QualType sizeTy = Size->getType(); 356ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose QualType PtrTy = Ctx.getPointerType(Ctx.CharTy); 357ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 358a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose // Check that the first buffer is non-null. 3595eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek SVal BufVal = state->getSVal(FirstBuf, LCtx); 360c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek state = checkNonNull(C, state, FirstBuf, BufVal); 361a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose if (!state) 362a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose return NULL; 363a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose 36457300760964904cc022a175643342f29f46b7e6bAnna Zaks // If out-of-bounds checking is turned off, skip the rest. 36557300760964904cc022a175643342f29f46b7e6bAnna Zaks if (!Filter.CheckCStringOutOfBounds) 36657300760964904cc022a175643342f29f46b7e6bAnna Zaks return state; 36757300760964904cc022a175643342f29f46b7e6bAnna Zaks 368d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // Get the access length and make sure it is known. 3699e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose // FIXME: This assumes the caller has already checked that the access length 3709e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose // is positive. And that it's unsigned. 3715eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek SVal LengthVal = state->getSVal(Size, LCtx); 372d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose NonLoc *Length = dyn_cast<NonLoc>(&LengthVal); 373d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (!Length) 374d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose return state; 375d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 376ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Compute the offset of the last element to be accessed: size-1. 377c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek NonLoc One = cast<NonLoc>(svalBuilder.makeIntVal(1, sizeTy)); 378c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek NonLoc LastOffset = cast<NonLoc>(svalBuilder.evalBinOpNN(state, BO_Sub, 379c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek *Length, One, sizeTy)); 380ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 381fc8f0e14ad142ed811e90fbd9a30e419e301c717Chris Lattner // Check that the first buffer is sufficiently long. 382c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal BufStart = svalBuilder.evalCast(BufVal, PtrTy, FirstBuf->getType()); 383b6a4026de13909c2b145166ae0b7d96cf1948f64Jordy Rose if (Loc *BufLoc = dyn_cast<Loc>(&BufStart)) { 3845e5f15062bcf4b62fda9062b453178f8b9bd0c2dJordy Rose const Expr *warningExpr = (WarnAboutSize ? Size : FirstBuf); 3855e5f15062bcf4b62fda9062b453178f8b9bd0c2dJordy Rose 386c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal BufEnd = svalBuilder.evalBinOpLN(state, BO_Add, *BufLoc, 387c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek LastOffset, PtrTy); 3885e5f15062bcf4b62fda9062b453178f8b9bd0c2dJordy Rose state = CheckLocation(C, state, warningExpr, BufEnd, firstMessage); 389ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 390b6a4026de13909c2b145166ae0b7d96cf1948f64Jordy Rose // If the buffer isn't large enough, abort. 391b6a4026de13909c2b145166ae0b7d96cf1948f64Jordy Rose if (!state) 392b6a4026de13909c2b145166ae0b7d96cf1948f64Jordy Rose return NULL; 393b6a4026de13909c2b145166ae0b7d96cf1948f64Jordy Rose } 394ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 395ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // If there's a second buffer, check it as well. 396ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (SecondBuf) { 3975eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek BufVal = state->getSVal(SecondBuf, LCtx); 398c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek state = checkNonNull(C, state, SecondBuf, BufVal); 399a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose if (!state) 400a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose return NULL; 401a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose 402c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek BufStart = svalBuilder.evalCast(BufVal, PtrTy, SecondBuf->getType()); 403b6a4026de13909c2b145166ae0b7d96cf1948f64Jordy Rose if (Loc *BufLoc = dyn_cast<Loc>(&BufStart)) { 4045e5f15062bcf4b62fda9062b453178f8b9bd0c2dJordy Rose const Expr *warningExpr = (WarnAboutSize ? Size : SecondBuf); 4055e5f15062bcf4b62fda9062b453178f8b9bd0c2dJordy Rose 406c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal BufEnd = svalBuilder.evalBinOpLN(state, BO_Add, *BufLoc, 407c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek LastOffset, PtrTy); 4085e5f15062bcf4b62fda9062b453178f8b9bd0c2dJordy Rose state = CheckLocation(C, state, warningExpr, BufEnd, secondMessage); 409b6a4026de13909c2b145166ae0b7d96cf1948f64Jordy Rose } 410ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose } 411ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 412ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Large enough or not, return this state! 413ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return state; 414ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose} 415ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 4168bef8238181a30e52dea380789a7e2d760eac532Ted KremenekProgramStateRef CStringChecker::CheckOverlap(CheckerContext &C, 4178bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state, 418d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose const Expr *Size, 419ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const Expr *First, 420183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis const Expr *Second) const { 42157300760964904cc022a175643342f29f46b7e6bAnna Zaks if (!Filter.CheckCStringBufferOverlap) 42257300760964904cc022a175643342f29f46b7e6bAnna Zaks return state; 42357300760964904cc022a175643342f29f46b7e6bAnna Zaks 424ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Do a simple check for overlap: if the two arguments are from the same 425ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // buffer, see if the end of the first is greater than the start of the second 426ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // or vice versa. 427ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 428d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // If a previous check has failed, propagate the failure. 429d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (!state) 430d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose return NULL; 431d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 4328bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef stateTrue, stateFalse; 433ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 434ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Get the buffer values and make sure they're known locations. 4355eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek const LocationContext *LCtx = C.getLocationContext(); 4365eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek SVal firstVal = state->getSVal(First, LCtx); 4375eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek SVal secondVal = state->getSVal(Second, LCtx); 438ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 439c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek Loc *firstLoc = dyn_cast<Loc>(&firstVal); 440c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek if (!firstLoc) 441ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return state; 442ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 443c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek Loc *secondLoc = dyn_cast<Loc>(&secondVal); 444c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek if (!secondLoc) 445ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return state; 446ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 447ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Are the two values the same? 448c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SValBuilder &svalBuilder = C.getSValBuilder(); 449c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek llvm::tie(stateTrue, stateFalse) = 450c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek state->assume(svalBuilder.evalEQ(state, *firstLoc, *secondLoc)); 451ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 452ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (stateTrue && !stateFalse) { 453ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // If the values are known to be equal, that's automatically an overlap. 454c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek emitOverlapBug(C, stateTrue, First, Second); 455ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return NULL; 456ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose } 457ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 45828f47b92e760ccf641ac91cb0fe1c12d9ca89795Ted Kremenek // assume the two expressions are not equal. 459ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose assert(stateFalse); 460ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose state = stateFalse; 461ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 462ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Which value comes first? 463ee2fde12934c0b11a71db286d1dc9ee8341802a5Jordy Rose QualType cmpTy = svalBuilder.getConditionType(); 464c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal reverse = svalBuilder.evalBinOpLL(state, BO_GT, 465c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek *firstLoc, *secondLoc, cmpTy); 466c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek DefinedOrUnknownSVal *reverseTest = dyn_cast<DefinedOrUnknownSVal>(&reverse); 467c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek if (!reverseTest) 468ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return state; 469ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 470c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek llvm::tie(stateTrue, stateFalse) = state->assume(*reverseTest); 471ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (stateTrue) { 472ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (stateFalse) { 473ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // If we don't know which one comes first, we can't perform this test. 474ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return state; 475ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose } else { 476c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek // Switch the values so that firstVal is before secondVal. 477c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek Loc *tmpLoc = firstLoc; 478c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek firstLoc = secondLoc; 479c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek secondLoc = tmpLoc; 480ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 481ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Switch the Exprs as well, so that they still correspond. 482ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose const Expr *tmpExpr = First; 483ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose First = Second; 484ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose Second = tmpExpr; 485ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose } 486ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose } 487ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 488ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Get the length, and make sure it too is known. 4895eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek SVal LengthVal = state->getSVal(Size, LCtx); 490ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose NonLoc *Length = dyn_cast<NonLoc>(&LengthVal); 491ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (!Length) 492ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return state; 493ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 494ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Convert the first buffer's start address to char*. 495ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Bail out if the cast fails. 496ee2fde12934c0b11a71db286d1dc9ee8341802a5Jordy Rose ASTContext &Ctx = svalBuilder.getContext(); 497ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose QualType CharPtrTy = Ctx.getPointerType(Ctx.CharTy); 4981e022415b9a66c84a9005b4e0bb2d4becb76d189Jordy Rose SVal FirstStart = svalBuilder.evalCast(*firstLoc, CharPtrTy, 4991e022415b9a66c84a9005b4e0bb2d4becb76d189Jordy Rose First->getType()); 500ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose Loc *FirstStartLoc = dyn_cast<Loc>(&FirstStart); 501ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (!FirstStartLoc) 502ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return state; 503ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 504ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Compute the end of the first buffer. Bail out if THAT fails. 505c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal FirstEnd = svalBuilder.evalBinOpLN(state, BO_Add, 506ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose *FirstStartLoc, *Length, CharPtrTy); 507ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose Loc *FirstEndLoc = dyn_cast<Loc>(&FirstEnd); 508ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (!FirstEndLoc) 509ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return state; 510ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 511ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Is the end of the first buffer past the start of the second buffer? 512c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal Overlap = svalBuilder.evalBinOpLL(state, BO_GT, 513c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek *FirstEndLoc, *secondLoc, cmpTy); 514ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose DefinedOrUnknownSVal *OverlapTest = dyn_cast<DefinedOrUnknownSVal>(&Overlap); 515ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (!OverlapTest) 516ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return state; 517ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 51828f47b92e760ccf641ac91cb0fe1c12d9ca89795Ted Kremenek llvm::tie(stateTrue, stateFalse) = state->assume(*OverlapTest); 519ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 520ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (stateTrue && !stateFalse) { 521ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Overlap! 522c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek emitOverlapBug(C, stateTrue, First, Second); 523ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return NULL; 524ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose } 525ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 52628f47b92e760ccf641ac91cb0fe1c12d9ca89795Ted Kremenek // assume the two expressions don't overlap. 527ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose assert(stateFalse); 528ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return stateFalse; 529ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose} 530ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 5318bef8238181a30e52dea380789a7e2d760eac532Ted Kremenekvoid CStringChecker::emitOverlapBug(CheckerContext &C, ProgramStateRef state, 532183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis const Stmt *First, const Stmt *Second) const { 533d048c6ef5b6cfaa0cecb8cc1d4bdace32ed21d07Ted Kremenek ExplodedNode *N = C.generateSink(state); 534ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (!N) 535ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return; 536ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 537ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose if (!BT_Overlap) 538183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis BT_Overlap.reset(new BugType("Unix API", "Improper arguments")); 539ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 540ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // Generate a report for this bug. 541e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks BugReport *report = 542e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks new BugReport(*BT_Overlap, 543ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose "Arguments must not be overlapping buffers", N); 544ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose report->addRange(First->getSourceRange()); 545ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose report->addRange(Second->getSourceRange()); 546ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 547ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose C.EmitReport(report); 548ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose} 549ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 5508bef8238181a30e52dea380789a7e2d760eac532Ted KremenekProgramStateRef CStringChecker::checkAdditionOverflow(CheckerContext &C, 5518bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state, 552d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose NonLoc left, 553d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose NonLoc right) const { 55457300760964904cc022a175643342f29f46b7e6bAnna Zaks // If out-of-bounds checking is turned off, skip the rest. 55557300760964904cc022a175643342f29f46b7e6bAnna Zaks if (!Filter.CheckCStringOutOfBounds) 55657300760964904cc022a175643342f29f46b7e6bAnna Zaks return state; 55757300760964904cc022a175643342f29f46b7e6bAnna Zaks 558d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // If a previous check has failed, propagate the failure. 559d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose if (!state) 560d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose return NULL; 561d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 562d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose SValBuilder &svalBuilder = C.getSValBuilder(); 563d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose BasicValueFactory &BVF = svalBuilder.getBasicValueFactory(); 564d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 565d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose QualType sizeTy = svalBuilder.getContext().getSizeType(); 566d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose const llvm::APSInt &maxValInt = BVF.getMaxValue(sizeTy); 567d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose NonLoc maxVal = svalBuilder.makeIntVal(maxValInt); 568d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 569e3d250e488241cbfe71a592df4d07d03ad89434aAnna Zaks SVal maxMinusRight; 570e3d250e488241cbfe71a592df4d07d03ad89434aAnna Zaks if (isa<nonloc::ConcreteInt>(right)) { 571e3d250e488241cbfe71a592df4d07d03ad89434aAnna Zaks maxMinusRight = svalBuilder.evalBinOpNN(state, BO_Sub, maxVal, right, 572e3d250e488241cbfe71a592df4d07d03ad89434aAnna Zaks sizeTy); 573e3d250e488241cbfe71a592df4d07d03ad89434aAnna Zaks } else { 574d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // Try switching the operands. (The order of these two assignments is 575d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // important!) 576d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose maxMinusRight = svalBuilder.evalBinOpNN(state, BO_Sub, maxVal, left, 577d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose sizeTy); 578d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose left = right; 579d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose } 580d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 581d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose if (NonLoc *maxMinusRightNL = dyn_cast<NonLoc>(&maxMinusRight)) { 582d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose QualType cmpTy = svalBuilder.getConditionType(); 583d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // If left > max - right, we have an overflow. 584d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose SVal willOverflow = svalBuilder.evalBinOpNN(state, BO_GT, left, 585d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose *maxMinusRightNL, cmpTy); 586d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 5878bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef stateOverflow, stateOkay; 588d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose llvm::tie(stateOverflow, stateOkay) = 589d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose state->assume(cast<DefinedOrUnknownSVal>(willOverflow)); 590d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 591d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose if (stateOverflow && !stateOkay) { 592d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // We have an overflow. Emit a bug report. 593d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose ExplodedNode *N = C.generateSink(stateOverflow); 594d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose if (!N) 595d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose return NULL; 596d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 597d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose if (!BT_AdditionOverflow) 598d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose BT_AdditionOverflow.reset(new BuiltinBug("API", 599d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose "Sum of expressions causes overflow")); 600d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 601d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // This isn't a great error message, but this should never occur in real 602d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // code anyway -- you'd have to create a buffer longer than a size_t can 603d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // represent, which is sort of a contradiction. 6048cc2491239f0b9de35985a1650fffc05c1ca8242Jordy Rose const char *warning = 6058cc2491239f0b9de35985a1650fffc05c1ca8242Jordy Rose "This expression will create a string whose length is too big to " 6068cc2491239f0b9de35985a1650fffc05c1ca8242Jordy Rose "be represented as a size_t"; 607d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 608d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // Generate a report for this bug. 6098cc2491239f0b9de35985a1650fffc05c1ca8242Jordy Rose BugReport *report = new BugReport(*BT_AdditionOverflow, warning, N); 610d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose C.EmitReport(report); 611d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 612d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose return NULL; 613d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose } 614d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 615d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // From now on, assume an overflow didn't occur. 616d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose assert(stateOkay); 617d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose state = stateOkay; 618d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose } 619d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 620d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose return state; 621d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose} 622d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 6238bef8238181a30e52dea380789a7e2d760eac532Ted KremenekProgramStateRef CStringChecker::setCStringLength(ProgramStateRef state, 624e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose const MemRegion *MR, 625c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal strLength) { 626c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek assert(!strLength.isUndef() && "Attempt to set an undefined string length"); 627e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 628e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose MR = MR->StripCasts(); 629e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 630e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose switch (MR->getKind()) { 631e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose case MemRegion::StringRegionKind: 632e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // FIXME: This can happen if we strcpy() into a string region. This is 633e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // undefined [C99 6.4.5p6], but we should still warn about it. 634e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose return state; 635e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 636e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose case MemRegion::SymbolicRegionKind: 637e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose case MemRegion::AllocaRegionKind: 638e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose case MemRegion::VarRegionKind: 639e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose case MemRegion::FieldRegionKind: 640e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose case MemRegion::ObjCIvarRegionKind: 641210c05b10317a11971f87e474ffa4c30bb8e4df9Jordy Rose // These are the types we can currently track string lengths for. 642210c05b10317a11971f87e474ffa4c30bb8e4df9Jordy Rose break; 643e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 644e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose case MemRegion::ElementRegionKind: 645e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // FIXME: Handle element regions by upper-bounding the parent region's 646e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // string length. 647e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose return state; 648e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 649e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose default: 650e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // Other regions (mostly non-data) can't have a reliable C string length. 651e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // For now, just ignore the change. 652e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // FIXME: These are rare but not impossible. We should output some kind of 653e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // warning for things like strcpy((char[]){'a', 0}, "b"); 654e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose return state; 655e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose } 656210c05b10317a11971f87e474ffa4c30bb8e4df9Jordy Rose 657210c05b10317a11971f87e474ffa4c30bb8e4df9Jordy Rose if (strLength.isUnknown()) 658210c05b10317a11971f87e474ffa4c30bb8e4df9Jordy Rose return state->remove<CStringLength>(MR); 659210c05b10317a11971f87e474ffa4c30bb8e4df9Jordy Rose 660210c05b10317a11971f87e474ffa4c30bb8e4df9Jordy Rose return state->set<CStringLength>(MR, strLength); 661e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose} 662e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 663c8413fd03f73084a5c93028f8b4db619fc388087Ted KremenekSVal CStringChecker::getCStringLengthForRegion(CheckerContext &C, 6648bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef &state, 665a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose const Expr *Ex, 666d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose const MemRegion *MR, 667d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose bool hypothetical) { 668d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose if (!hypothetical) { 669d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // If there's a recorded length, go ahead and return it. 670d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose const SVal *Recorded = state->get<CStringLength>(MR); 671d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose if (Recorded) 672d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose return *Recorded; 673d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose } 674a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 675a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // Otherwise, get a new symbol and update the state. 676c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SValBuilder &svalBuilder = C.getSValBuilder(); 677c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek QualType sizeTy = svalBuilder.getContext().getSizeType(); 678183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis SVal strLength = svalBuilder.getMetadataSymbolVal(CStringChecker::getTag(), 67966c486f275531df6362b3511fc3af6563561801bTed Kremenek MR, Ex, sizeTy, 68066c486f275531df6362b3511fc3af6563561801bTed Kremenek C.blockCount()); 681d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 682d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose if (!hypothetical) 683d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose state = state->set<CStringLength>(MR, strLength); 684d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 685c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek return strLength; 686a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose} 687a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 6888bef8238181a30e52dea380789a7e2d760eac532Ted KremenekSVal CStringChecker::getCStringLength(CheckerContext &C, ProgramStateRef &state, 689d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose const Expr *Ex, SVal Buf, 690d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose bool hypothetical) const { 69119c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose const MemRegion *MR = Buf.getAsRegion(); 69219c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose if (!MR) { 69319c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose // If we can't get a region, see if it's something we /know/ isn't a 69419c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose // C string. In the context of locations, the only time we can issue such 69519c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose // a warning is for labels. 69619c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose if (loc::GotoLabel *Label = dyn_cast<loc::GotoLabel>(&Buf)) { 69757300760964904cc022a175643342f29f46b7e6bAnna Zaks if (!Filter.CheckCStringNotNullTerm) 69857300760964904cc022a175643342f29f46b7e6bAnna Zaks return UndefinedVal(); 69957300760964904cc022a175643342f29f46b7e6bAnna Zaks 7000bd6b110e908892d4b5c8671a9f435a1d72ad16aAnna Zaks if (ExplodedNode *N = C.addTransition(state)) { 70119c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose if (!BT_NotCString) 70257300760964904cc022a175643342f29f46b7e6bAnna Zaks BT_NotCString.reset(new BuiltinBug("Unix API", 703183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis "Argument is not a null-terminated string.")); 70419c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 705f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith SmallString<120> buf; 70619c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose llvm::raw_svector_ostream os(buf); 7079e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose assert(CurrentFunctionDescription); 7089e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose os << "Argument to " << CurrentFunctionDescription 7099e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose << " is the address of the label '" << Label->getLabel()->getName() 71019c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose << "', which is not a null-terminated string"; 71119c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 71219c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose // Generate a report for this bug. 713e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks BugReport *report = new BugReport(*BT_NotCString, 71419c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose os.str(), N); 71519c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 71619c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose report->addRange(Ex->getSourceRange()); 71719c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose C.EmitReport(report); 71819c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose } 71919c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose return UndefinedVal(); 72057300760964904cc022a175643342f29f46b7e6bAnna Zaks 72119c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose } 72219c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 723a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // If it's not a region and not a label, give up. 724a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose return UnknownVal(); 725a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose } 72619c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 727a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // If we have a region, strip casts from it and see if we can figure out 728a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // its length. For anything we can't figure out, just return UnknownVal. 729a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose MR = MR->StripCasts(); 730a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 731a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose switch (MR->getKind()) { 732a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose case MemRegion::StringRegionKind: { 733a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // Modifying the contents of string regions is undefined [C99 6.4.5p6], 734a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // so we can assume that the byte length is the correct C string length. 735c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SValBuilder &svalBuilder = C.getSValBuilder(); 736c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek QualType sizeTy = svalBuilder.getContext().getSizeType(); 737c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek const StringLiteral *strLit = cast<StringRegion>(MR)->getStringLiteral(); 738c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek return svalBuilder.makeIntVal(strLit->getByteLength(), sizeTy); 739a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose } 740a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose case MemRegion::SymbolicRegionKind: 741a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose case MemRegion::AllocaRegionKind: 742a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose case MemRegion::VarRegionKind: 743a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose case MemRegion::FieldRegionKind: 744a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose case MemRegion::ObjCIvarRegionKind: 745d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose return getCStringLengthForRegion(C, state, Ex, MR, hypothetical); 746a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose case MemRegion::CompoundLiteralRegionKind: 747a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // FIXME: Can we track this? Is it necessary? 748a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose return UnknownVal(); 749a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose case MemRegion::ElementRegionKind: 750a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // FIXME: How can we handle this? It's not good enough to subtract the 751a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // offset from the base string length; consider "123\x00567" and &a[5]. 752a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose return UnknownVal(); 753a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose default: 754a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // Other regions (mostly non-data) can't have a reliable C string length. 755a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // In this case, an error is emitted and UndefinedVal is returned. 756a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // The caller should always be prepared to handle this case. 75757300760964904cc022a175643342f29f46b7e6bAnna Zaks if (!Filter.CheckCStringNotNullTerm) 75857300760964904cc022a175643342f29f46b7e6bAnna Zaks return UndefinedVal(); 75957300760964904cc022a175643342f29f46b7e6bAnna Zaks 7600bd6b110e908892d4b5c8671a9f435a1d72ad16aAnna Zaks if (ExplodedNode *N = C.addTransition(state)) { 761a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (!BT_NotCString) 76257300760964904cc022a175643342f29f46b7e6bAnna Zaks BT_NotCString.reset(new BuiltinBug("Unix API", 763183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis "Argument is not a null-terminated string.")); 764a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 765f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith SmallString<120> buf; 766a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose llvm::raw_svector_ostream os(buf); 767a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 7689e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose assert(CurrentFunctionDescription); 7699e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose os << "Argument to " << CurrentFunctionDescription << " is "; 770a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 771a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (SummarizeRegion(os, C.getASTContext(), MR)) 772a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose os << ", which is not a null-terminated string"; 773a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose else 774a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose os << "not a null-terminated string"; 775a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 776a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // Generate a report for this bug. 777e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks BugReport *report = new BugReport(*BT_NotCString, 778a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose os.str(), N); 779a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 780a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose report->addRange(Ex->getSourceRange()); 781a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose C.EmitReport(report); 78219c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose } 78319c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 784a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose return UndefinedVal(); 78519c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose } 78619c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose} 78719c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 788318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maioraniconst StringLiteral *CStringChecker::getCStringLiteral(CheckerContext &C, 7898bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef &state, const Expr *expr, SVal val) const { 790318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani 791318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani // Get the memory region pointed to by the val. 792318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani const MemRegion *bufRegion = val.getAsRegion(); 793318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani if (!bufRegion) 794318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani return NULL; 795318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani 796318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani // Strip casts off the memory region. 797318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani bufRegion = bufRegion->StripCasts(); 798318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani 799318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani // Cast the memory region to a string region. 800318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani const StringRegion *strRegion= dyn_cast<StringRegion>(bufRegion); 801318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani if (!strRegion) 802318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani return NULL; 803318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani 804318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani // Return the actual string in the string region. 805318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani return strRegion->getStringLiteral(); 806318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani} 807318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani 8088bef8238181a30e52dea380789a7e2d760eac532Ted KremenekProgramStateRef CStringChecker::InvalidateBuffer(CheckerContext &C, 8098bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state, 810e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose const Expr *E, SVal V) { 811e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose Loc *L = dyn_cast<Loc>(&V); 812e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose if (!L) 813e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose return state; 814e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 815e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // FIXME: This is a simplified version of what's in CFRefCount.cpp -- it makes 816e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // some assumptions about the value that CFRefCount can't. Even so, it should 817e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // probably be refactored. 818e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose if (loc::MemRegionVal* MR = dyn_cast<loc::MemRegionVal>(L)) { 819e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose const MemRegion *R = MR->getRegion()->StripCasts(); 820e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 821e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // Are we dealing with an ElementRegion? If so, we should be invalidating 822e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // the super-region. 823e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) { 824e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose R = ER->getSuperRegion(); 825e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // FIXME: What about layers of ElementRegions? 826e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose } 827e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 828e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // Invalidate this region. 8293133f79cf451e6302dd05262b4bb53a3e4fd6300Ted Kremenek const LocationContext *LCtx = C.getPredecessor()->getLocationContext(); 83066c486f275531df6362b3511fc3af6563561801bTed Kremenek return state->invalidateRegions(R, E, C.blockCount(), LCtx); 831e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose } 832e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 833e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // If we have a non-region value by chance, just remove the binding. 834e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // FIXME: is this necessary or correct? This handles the non-Region 835e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // cases. Is it ever valid to store to these? 83656a46b51df691f857f7120aaf2d4deeff0b014deTed Kremenek return state->killBinding(*L); 837e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose} 838e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 8399c378f705405d37f49795d5e915989de774fe11fTed Kremenekbool CStringChecker::SummarizeRegion(raw_ostream &os, ASTContext &Ctx, 84019c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose const MemRegion *MR) { 8419697934650354bed2e509d8e7e44f21a1fb00f76Ted Kremenek const TypedValueRegion *TVR = dyn_cast<TypedValueRegion>(MR); 84219c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 843096aef9597b263b4cd6a0feaacf9e7214fa9c75aJordy Rose switch (MR->getKind()) { 84419c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose case MemRegion::FunctionTextRegionKind: { 845096aef9597b263b4cd6a0feaacf9e7214fa9c75aJordy Rose const FunctionDecl *FD = cast<FunctionTextRegion>(MR)->getDecl(); 84619c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose if (FD) 847b8989f27f116ff2400e92a52c067a69846119eb5Benjamin Kramer os << "the address of the function '" << *FD << '\''; 84819c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose else 84919c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose os << "the address of a function"; 85019c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose return true; 85119c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose } 85219c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose case MemRegion::BlockTextRegionKind: 85319c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose os << "block text"; 85419c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose return true; 85519c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose case MemRegion::BlockDataRegionKind: 85619c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose os << "a block"; 85719c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose return true; 85819c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose case MemRegion::CXXThisRegionKind: 85902fe28c8a6da29d4ad88d0900c133dcf22d24a75Zhongxing Xu case MemRegion::CXXTempObjectRegionKind: 8609697934650354bed2e509d8e7e44f21a1fb00f76Ted Kremenek os << "a C++ temp object of type " << TVR->getValueType().getAsString(); 86119c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose return true; 86219c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose case MemRegion::VarRegionKind: 8639697934650354bed2e509d8e7e44f21a1fb00f76Ted Kremenek os << "a variable of type" << TVR->getValueType().getAsString(); 86419c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose return true; 86519c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose case MemRegion::FieldRegionKind: 8669697934650354bed2e509d8e7e44f21a1fb00f76Ted Kremenek os << "a field of type " << TVR->getValueType().getAsString(); 86719c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose return true; 86819c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose case MemRegion::ObjCIvarRegionKind: 8699697934650354bed2e509d8e7e44f21a1fb00f76Ted Kremenek os << "an instance variable of type " << TVR->getValueType().getAsString(); 87019c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose return true; 87119c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose default: 87219c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose return false; 87319c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose } 87419c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose} 87519c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 876d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose//===----------------------------------------------------------------------===// 8779c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek// evaluation of individual function calls. 878d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose//===----------------------------------------------------------------------===// 879ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 880b8b875be7b2d177d755641c6212111859372d611Lenny Maioranivoid CStringChecker::evalCopyCommon(CheckerContext &C, 881b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani const CallExpr *CE, 8828bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state, 883d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose const Expr *Size, const Expr *Dest, 884b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani const Expr *Source, bool Restricted, 885b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani bool IsMempcpy) const { 8869e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose CurrentFunctionDescription = "memory copy function"; 8879e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose 888d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // See if the size argument is zero. 8895eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek const LocationContext *LCtx = C.getLocationContext(); 8905eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek SVal sizeVal = state->getSVal(Size, LCtx); 891c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek QualType sizeTy = Size->getType(); 892d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 8938bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef stateZeroSize, stateNonZeroSize; 8941e022415b9a66c84a9005b4e0bb2d4becb76d189Jordy Rose llvm::tie(stateZeroSize, stateNonZeroSize) = 8951e022415b9a66c84a9005b4e0bb2d4becb76d189Jordy Rose assumeZero(C, state, sizeVal, sizeTy); 896d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 897b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani // Get the value of the Dest. 8985eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek SVal destVal = state->getSVal(Dest, LCtx); 899b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani 900b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani // If the size is zero, there won't be any actual memory access, so 901b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani // just bind the return value to the destination buffer and return. 902dd160f3ed50def10765ed823bf4ce2a56b2cd035Anna Zaks if (stateZeroSize && !stateNonZeroSize) { 9035eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek stateZeroSize = stateZeroSize->BindExpr(CE, LCtx, destVal); 9040bd6b110e908892d4b5c8671a9f435a1d72ad16aAnna Zaks C.addTransition(stateZeroSize); 905dd160f3ed50def10765ed823bf4ce2a56b2cd035Anna Zaks return; 906b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani } 907d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 908d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // If the size can be nonzero, we have to check the other arguments. 909c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek if (stateNonZeroSize) { 91022d27178bf795145439b9588e260ccceab79a088Jordy Rose state = stateNonZeroSize; 911b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani 912b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani // Ensure the destination is not null. If it is NULL there will be a 913b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani // NULL pointer dereference. 914b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani state = checkNonNull(C, state, Dest, destVal); 915b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani if (!state) 916b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani return; 917b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani 918b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani // Get the value of the Src. 9195eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek SVal srcVal = state->getSVal(Source, LCtx); 920b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani 921b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani // Ensure the source is not null. If it is NULL there will be a 922b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani // NULL pointer dereference. 923b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani state = checkNonNull(C, state, Source, srcVal); 924b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani if (!state) 925b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani return; 926b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani 9277182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose // Ensure the accesses are valid and that the buffers do not overlap. 9289e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose const char * const writeWarning = 9299e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose "Memory copy function overflows destination buffer"; 930e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose state = CheckBufferAccess(C, state, Size, Dest, Source, 9319e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose writeWarning, /* sourceWarning = */ NULL); 932d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (Restricted) 933d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose state = CheckOverlap(C, state, Size, Dest, Source); 934e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 9357182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose if (!state) 9367182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose return; 9373f8bb2fa289c956a66613b0f09e3df5e25d27c66Jordy Rose 9387182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose // If this is mempcpy, get the byte after the last byte copied and 9397182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose // bind the expr. 9407182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose if (IsMempcpy) { 9417182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose loc::MemRegionVal *destRegVal = dyn_cast<loc::MemRegionVal>(&destVal); 9427182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose assert(destRegVal && "Destination should be a known MemRegionVal here"); 9437182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose 9447182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose // Get the length to copy. 9457182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose NonLoc *lenValNonLoc = dyn_cast<NonLoc>(&sizeVal); 9467182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose 9477182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose if (lenValNonLoc) { 9487182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose // Get the byte after the last byte copied. 9497182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose SVal lastElement = C.getSValBuilder().evalBinOpLN(state, BO_Add, 9507182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose *destRegVal, 9517182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose *lenValNonLoc, 9527182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose Dest->getType()); 9537182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose 9547182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose // The byte after the last byte copied is the return value. 9555eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek state = state->BindExpr(CE, LCtx, lastElement); 9563f8bb2fa289c956a66613b0f09e3df5e25d27c66Jordy Rose } else { 9577182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose // If we don't know how much we copied, we can at least 9587182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose // conjure a return value for later. 95966c486f275531df6362b3511fc3af6563561801bTed Kremenek SVal result = C.getSValBuilder().conjureSymbolVal(0, CE, LCtx, 96066c486f275531df6362b3511fc3af6563561801bTed Kremenek C.blockCount()); 9615eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek state = state->BindExpr(CE, LCtx, result); 962b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani } 963b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani 9647182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose } else { 9657182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose // All other copies return the destination buffer. 9667182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose // (Well, bcopy() has a void return type, but this won't hurt.) 9675eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek state = state->BindExpr(CE, LCtx, destVal); 968e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose } 9697182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose 9707182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose // Invalidate the destination. 9717182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose // FIXME: Even if we can't perfectly model the copy, we should see if we 9727182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose // can use LazyCompoundVals to copy the source values into the destination. 9737182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose // This would probably remove any existing bindings past the end of the 9747182b9652f20c122d261d9255e11bf3a1bf871ecJordy Rose // copied region, but that's still an improvement over blank invalidation. 9755eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek state = InvalidateBuffer(C, state, Dest, 9765eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek state->getSVal(Dest, C.getLocationContext())); 9770bd6b110e908892d4b5c8671a9f435a1d72ad16aAnna Zaks C.addTransition(state); 978d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose } 979ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose} 980ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 981ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 982183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidisvoid CStringChecker::evalMemcpy(CheckerContext &C, const CallExpr *CE) const { 983259052d8c819d101f6f627f960f56e582ecbcebcAnna Zaks if (CE->getNumArgs() < 3) 984259052d8c819d101f6f627f960f56e582ecbcebcAnna Zaks return; 985259052d8c819d101f6f627f960f56e582ecbcebcAnna Zaks 986d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // void *memcpy(void *restrict dst, const void *restrict src, size_t n); 987d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // The return value is the address of the destination buffer. 988d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose const Expr *Dest = CE->getArg(0); 9898bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state = C.getState(); 9903f8bb2fa289c956a66613b0f09e3df5e25d27c66Jordy Rose 991b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani evalCopyCommon(C, CE, state, CE->getArg(2), Dest, CE->getArg(1), true); 992b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani} 993b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani 994b8b875be7b2d177d755641c6212111859372d611Lenny Maioranivoid CStringChecker::evalMempcpy(CheckerContext &C, const CallExpr *CE) const { 995259052d8c819d101f6f627f960f56e582ecbcebcAnna Zaks if (CE->getNumArgs() < 3) 996259052d8c819d101f6f627f960f56e582ecbcebcAnna Zaks return; 997259052d8c819d101f6f627f960f56e582ecbcebcAnna Zaks 998b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani // void *mempcpy(void *restrict dst, const void *restrict src, size_t n); 999b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani // The return value is a pointer to the byte following the last written byte. 1000b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani const Expr *Dest = CE->getArg(0); 10018bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state = C.getState(); 1002b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani 1003b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani evalCopyCommon(C, CE, state, CE->getArg(2), Dest, CE->getArg(1), true, true); 1004d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose} 1005ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 1006183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidisvoid CStringChecker::evalMemmove(CheckerContext &C, const CallExpr *CE) const { 1007259052d8c819d101f6f627f960f56e582ecbcebcAnna Zaks if (CE->getNumArgs() < 3) 1008259052d8c819d101f6f627f960f56e582ecbcebcAnna Zaks return; 1009259052d8c819d101f6f627f960f56e582ecbcebcAnna Zaks 1010d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // void *memmove(void *dst, const void *src, size_t n); 1011ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose // The return value is the address of the destination buffer. 1012d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose const Expr *Dest = CE->getArg(0); 10138bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state = C.getState(); 10143f8bb2fa289c956a66613b0f09e3df5e25d27c66Jordy Rose 1015b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani evalCopyCommon(C, CE, state, CE->getArg(2), Dest, CE->getArg(1)); 1016ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose} 1017ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 1018183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidisvoid CStringChecker::evalBcopy(CheckerContext &C, const CallExpr *CE) const { 1019259052d8c819d101f6f627f960f56e582ecbcebcAnna Zaks if (CE->getNumArgs() < 3) 1020259052d8c819d101f6f627f960f56e582ecbcebcAnna Zaks return; 1021259052d8c819d101f6f627f960f56e582ecbcebcAnna Zaks 1022d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // void bcopy(const void *src, void *dst, size_t n); 1023b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani evalCopyCommon(C, CE, C.getState(), 1024b8b875be7b2d177d755641c6212111859372d611Lenny Maiorani CE->getArg(2), CE->getArg(1), CE->getArg(0)); 1025d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose} 1026d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 1027183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidisvoid CStringChecker::evalMemcmp(CheckerContext &C, const CallExpr *CE) const { 1028259052d8c819d101f6f627f960f56e582ecbcebcAnna Zaks if (CE->getNumArgs() < 3) 1029259052d8c819d101f6f627f960f56e582ecbcebcAnna Zaks return; 1030259052d8c819d101f6f627f960f56e582ecbcebcAnna Zaks 1031bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose // int memcmp(const void *s1, const void *s2, size_t n); 10329e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose CurrentFunctionDescription = "memory comparison function"; 10339e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose 1034bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose const Expr *Left = CE->getArg(0); 1035bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose const Expr *Right = CE->getArg(1); 1036bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose const Expr *Size = CE->getArg(2); 1037bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose 10388bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state = C.getState(); 1039c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SValBuilder &svalBuilder = C.getSValBuilder(); 1040bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose 1041d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // See if the size argument is zero. 10425eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek const LocationContext *LCtx = C.getLocationContext(); 10435eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek SVal sizeVal = state->getSVal(Size, LCtx); 1044c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek QualType sizeTy = Size->getType(); 1045bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose 10468bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef stateZeroSize, stateNonZeroSize; 1047c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek llvm::tie(stateZeroSize, stateNonZeroSize) = 1048c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek assumeZero(C, state, sizeVal, sizeTy); 1049bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose 1050d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // If the size can be zero, the result will be 0 in that case, and we don't 1051d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // have to check either of the buffers. 1052c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek if (stateZeroSize) { 1053c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek state = stateZeroSize; 10545eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek state = state->BindExpr(CE, LCtx, 10555eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek svalBuilder.makeZeroVal(CE->getType())); 10560bd6b110e908892d4b5c8671a9f435a1d72ad16aAnna Zaks C.addTransition(state); 1057bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose } 1058bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose 1059d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // If the size can be nonzero, we have to check the other arguments. 1060c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek if (stateNonZeroSize) { 1061c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek state = stateNonZeroSize; 1062d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // If we know the two buffers are the same, we know the result is 0. 1063d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // First, get the two buffers' addresses. Another checker will have already 1064d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // made sure they're not undefined. 10655eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek DefinedOrUnknownSVal LV = 10665eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek cast<DefinedOrUnknownSVal>(state->getSVal(Left, LCtx)); 10675eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek DefinedOrUnknownSVal RV = 10685eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek cast<DefinedOrUnknownSVal>(state->getSVal(Right, LCtx)); 1069d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 1070d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // See if they are the same. 1071c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek DefinedOrUnknownSVal SameBuf = svalBuilder.evalEQ(state, LV, RV); 10728bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef StSameBuf, StNotSameBuf; 107328f47b92e760ccf641ac91cb0fe1c12d9ca89795Ted Kremenek llvm::tie(StSameBuf, StNotSameBuf) = state->assume(SameBuf); 1074d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose 10751e022415b9a66c84a9005b4e0bb2d4becb76d189Jordy Rose // If the two arguments might be the same buffer, we know the result is 0, 1076d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // and we only need to check one size. 1077d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (StSameBuf) { 1078d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose state = StSameBuf; 1079d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose state = CheckBufferAccess(C, state, Size, Left); 1080d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (state) { 10815eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek state = StSameBuf->BindExpr(CE, LCtx, 10825eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek svalBuilder.makeZeroVal(CE->getType())); 10830bd6b110e908892d4b5c8671a9f435a1d72ad16aAnna Zaks C.addTransition(state); 1084d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose } 1085d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose } 1086bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose 1087d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // If the two arguments might be different buffers, we have to check the 1088d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // size of both of them. 1089d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (StNotSameBuf) { 1090d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose state = StNotSameBuf; 1091d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose state = CheckBufferAccess(C, state, Size, Left, Right); 1092d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose if (state) { 1093d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // The return value is the comparison result, which we don't know. 109466c486f275531df6362b3511fc3af6563561801bTed Kremenek SVal CmpV = svalBuilder.conjureSymbolVal(0, CE, LCtx, C.blockCount()); 10955eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek state = state->BindExpr(CE, LCtx, CmpV); 10960bd6b110e908892d4b5c8671a9f435a1d72ad16aAnna Zaks C.addTransition(state); 1097d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose } 1098d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose } 1099d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose } 1100bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose} 1101bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose 1102183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidisvoid CStringChecker::evalstrLength(CheckerContext &C, 1103183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis const CallExpr *CE) const { 1104259052d8c819d101f6f627f960f56e582ecbcebcAnna Zaks if (CE->getNumArgs() < 1) 1105259052d8c819d101f6f627f960f56e582ecbcebcAnna Zaks return; 1106259052d8c819d101f6f627f960f56e582ecbcebcAnna Zaks 110719c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose // size_t strlen(const char *s); 1108be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek evalstrLengthCommon(C, CE, /* IsStrnlen = */ false); 1109be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek} 1110be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek 1111183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidisvoid CStringChecker::evalstrnLength(CheckerContext &C, 1112183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis const CallExpr *CE) const { 1113259052d8c819d101f6f627f960f56e582ecbcebcAnna Zaks if (CE->getNumArgs() < 2) 1114259052d8c819d101f6f627f960f56e582ecbcebcAnna Zaks return; 1115259052d8c819d101f6f627f960f56e582ecbcebcAnna Zaks 1116be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek // size_t strnlen(const char *s, size_t maxlen); 1117be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek evalstrLengthCommon(C, CE, /* IsStrnlen = */ true); 1118be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek} 1119be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek 1120be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenekvoid CStringChecker::evalstrLengthCommon(CheckerContext &C, const CallExpr *CE, 1121183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis bool IsStrnlen) const { 11229e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose CurrentFunctionDescription = "string length function"; 11238bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state = C.getState(); 11245eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek const LocationContext *LCtx = C.getLocationContext(); 1125793bff3fb7ca2a31e81aa7f4f3f21f921459010bJordy Rose 1126793bff3fb7ca2a31e81aa7f4f3f21f921459010bJordy Rose if (IsStrnlen) { 1127793bff3fb7ca2a31e81aa7f4f3f21f921459010bJordy Rose const Expr *maxlenExpr = CE->getArg(1); 11285eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek SVal maxlenVal = state->getSVal(maxlenExpr, LCtx); 1129793bff3fb7ca2a31e81aa7f4f3f21f921459010bJordy Rose 11308bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef stateZeroSize, stateNonZeroSize; 1131793bff3fb7ca2a31e81aa7f4f3f21f921459010bJordy Rose llvm::tie(stateZeroSize, stateNonZeroSize) = 1132793bff3fb7ca2a31e81aa7f4f3f21f921459010bJordy Rose assumeZero(C, state, maxlenVal, maxlenExpr->getType()); 1133793bff3fb7ca2a31e81aa7f4f3f21f921459010bJordy Rose 1134793bff3fb7ca2a31e81aa7f4f3f21f921459010bJordy Rose // If the size can be zero, the result will be 0 in that case, and we don't 1135793bff3fb7ca2a31e81aa7f4f3f21f921459010bJordy Rose // have to check the string itself. 1136793bff3fb7ca2a31e81aa7f4f3f21f921459010bJordy Rose if (stateZeroSize) { 1137793bff3fb7ca2a31e81aa7f4f3f21f921459010bJordy Rose SVal zero = C.getSValBuilder().makeZeroVal(CE->getType()); 11385eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek stateZeroSize = stateZeroSize->BindExpr(CE, LCtx, zero); 11390bd6b110e908892d4b5c8671a9f435a1d72ad16aAnna Zaks C.addTransition(stateZeroSize); 1140793bff3fb7ca2a31e81aa7f4f3f21f921459010bJordy Rose } 1141793bff3fb7ca2a31e81aa7f4f3f21f921459010bJordy Rose 1142793bff3fb7ca2a31e81aa7f4f3f21f921459010bJordy Rose // If the size is GUARANTEED to be zero, we're done! 1143793bff3fb7ca2a31e81aa7f4f3f21f921459010bJordy Rose if (!stateNonZeroSize) 1144793bff3fb7ca2a31e81aa7f4f3f21f921459010bJordy Rose return; 1145793bff3fb7ca2a31e81aa7f4f3f21f921459010bJordy Rose 1146793bff3fb7ca2a31e81aa7f4f3f21f921459010bJordy Rose // Otherwise, record the assumption that the size is nonzero. 1147793bff3fb7ca2a31e81aa7f4f3f21f921459010bJordy Rose state = stateNonZeroSize; 1148793bff3fb7ca2a31e81aa7f4f3f21f921459010bJordy Rose } 1149793bff3fb7ca2a31e81aa7f4f3f21f921459010bJordy Rose 1150793bff3fb7ca2a31e81aa7f4f3f21f921459010bJordy Rose // Check that the string argument is non-null. 115119c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose const Expr *Arg = CE->getArg(0); 11525eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek SVal ArgVal = state->getSVal(Arg, LCtx); 115319c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 1154c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek state = checkNonNull(C, state, Arg, ArgVal); 115519c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 1156bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose if (!state) 1157bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose return; 1158a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1159bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose SVal strLength = getCStringLength(C, state, Arg, ArgVal); 1160a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1161bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose // If the argument isn't a valid C string, there's no valid state to 1162bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose // transition to. 1163bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose if (strLength.isUndef()) 1164bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose return; 1165be4242ce039f0542ea0dd5f234aa0ee698f90c53Ted Kremenek 1166bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose DefinedOrUnknownSVal result = UnknownVal(); 1167793bff3fb7ca2a31e81aa7f4f3f21f921459010bJordy Rose 1168bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose // If the check is for strnlen() then bind the return value to no more than 1169bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose // the maxlen value. 1170bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose if (IsStrnlen) { 1171ee2fde12934c0b11a71db286d1dc9ee8341802a5Jordy Rose QualType cmpTy = C.getSValBuilder().getConditionType(); 1172793bff3fb7ca2a31e81aa7f4f3f21f921459010bJordy Rose 1173bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose // It's a little unfortunate to be getting this again, 1174bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose // but it's not that expensive... 1175bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose const Expr *maxlenExpr = CE->getArg(1); 11765eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek SVal maxlenVal = state->getSVal(maxlenExpr, LCtx); 1177bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose 1178bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose NonLoc *strLengthNL = dyn_cast<NonLoc>(&strLength); 1179bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose NonLoc *maxlenValNL = dyn_cast<NonLoc>(&maxlenVal); 1180bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose 1181bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose if (strLengthNL && maxlenValNL) { 11828bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef stateStringTooLong, stateStringNotTooLong; 1183bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose 1184bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose // Check if the strLength is greater than the maxlen. 1185bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose llvm::tie(stateStringTooLong, stateStringNotTooLong) = 1186bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose state->assume(cast<DefinedOrUnknownSVal> 1187bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose (C.getSValBuilder().evalBinOpNN(state, BO_GT, 1188bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose *strLengthNL, 1189bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose *maxlenValNL, 1190bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose cmpTy))); 1191bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose 1192bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose if (stateStringTooLong && !stateStringNotTooLong) { 1193bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose // If the string is longer than maxlen, return maxlen. 1194bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose result = *maxlenValNL; 1195bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose } else if (stateStringNotTooLong && !stateStringTooLong) { 1196bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose // If the string is shorter than maxlen, return its length. 1197bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose result = *strLengthNL; 1198793bff3fb7ca2a31e81aa7f4f3f21f921459010bJordy Rose } 119919c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose } 1200a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1201bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose if (result.isUnknown()) { 1202bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose // If we don't have enough information for a comparison, there's 1203bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose // no guarantee the full string length will actually be returned. 1204bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose // All we know is the return value is the min of the string length 1205bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose // and the limit. This is better than nothing. 120666c486f275531df6362b3511fc3af6563561801bTed Kremenek result = C.getSValBuilder().conjureSymbolVal(0, CE, LCtx, C.blockCount()); 1207bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose NonLoc *resultNL = cast<NonLoc>(&result); 1208bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose 1209bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose if (strLengthNL) { 1210bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose state = state->assume(cast<DefinedOrUnknownSVal> 1211bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose (C.getSValBuilder().evalBinOpNN(state, BO_LE, 1212bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose *resultNL, 1213bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose *strLengthNL, 1214bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose cmpTy)), true); 1215bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose } 1216bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose 1217bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose if (maxlenValNL) { 1218bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose state = state->assume(cast<DefinedOrUnknownSVal> 1219bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose (C.getSValBuilder().evalBinOpNN(state, BO_LE, 1220bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose *resultNL, 1221bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose *maxlenValNL, 1222bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose cmpTy)), true); 1223bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose } 1224bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose } 1225bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose 1226bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose } else { 1227bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose // This is a plain strlen(), not strnlen(). 1228bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose result = cast<DefinedOrUnknownSVal>(strLength); 1229bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose 1230bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose // If we don't know the length of the string, conjure a return 1231bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose // value, so it can be used in constraints, at least. 1232bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose if (result.isUnknown()) { 123366c486f275531df6362b3511fc3af6563561801bTed Kremenek result = C.getSValBuilder().conjureSymbolVal(0, CE, LCtx, C.blockCount()); 1234bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose } 123519c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose } 1236bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose 1237bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose // Bind the return value. 1238bd32beee8a0f22e1d5245112f5e34ad4669994aeJordy Rose assert(!result.isUnknown() && "Should have conjured a value by now"); 12395eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek state = state->BindExpr(CE, LCtx, result); 12400bd6b110e908892d4b5c8671a9f435a1d72ad16aAnna Zaks C.addTransition(state); 124119c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose} 124219c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose 1243183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidisvoid CStringChecker::evalStrcpy(CheckerContext &C, const CallExpr *CE) const { 1244259052d8c819d101f6f627f960f56e582ecbcebcAnna Zaks if (CE->getNumArgs() < 2) 1245259052d8c819d101f6f627f960f56e582ecbcebcAnna Zaks return; 1246259052d8c819d101f6f627f960f56e582ecbcebcAnna Zaks 1247e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // char *strcpy(char *restrict dst, const char *restrict src); 1248067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani evalStrcpyCommon(C, CE, 1249067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani /* returnEnd = */ false, 1250067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani /* isBounded = */ false, 1251067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani /* isAppending = */ false); 12520ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek} 12530ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek 1254183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidisvoid CStringChecker::evalStrncpy(CheckerContext &C, const CallExpr *CE) const { 1255259052d8c819d101f6f627f960f56e582ecbcebcAnna Zaks if (CE->getNumArgs() < 3) 1256259052d8c819d101f6f627f960f56e582ecbcebcAnna Zaks return; 1257259052d8c819d101f6f627f960f56e582ecbcebcAnna Zaks 1258c152586baf0fcdfd4c660e5dcd7b6857f13203d6Jordy Rose // char *strncpy(char *restrict dst, const char *restrict src, size_t n); 1259067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani evalStrcpyCommon(C, CE, 1260067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani /* returnEnd = */ false, 1261067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani /* isBounded = */ true, 1262067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani /* isAppending = */ false); 1263e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose} 1264e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 1265183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidisvoid CStringChecker::evalStpcpy(CheckerContext &C, const CallExpr *CE) const { 1266259052d8c819d101f6f627f960f56e582ecbcebcAnna Zaks if (CE->getNumArgs() < 2) 1267259052d8c819d101f6f627f960f56e582ecbcebcAnna Zaks return; 1268259052d8c819d101f6f627f960f56e582ecbcebcAnna Zaks 1269e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // char *stpcpy(char *restrict dst, const char *restrict src); 1270067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani evalStrcpyCommon(C, CE, 1271067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani /* returnEnd = */ true, 1272067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani /* isBounded = */ false, 1273067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani /* isAppending = */ false); 1274067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani} 1275067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani 1276067bbd0e11c71a33b51832532e836971be697699Lenny Maioranivoid CStringChecker::evalStrcat(CheckerContext &C, const CallExpr *CE) const { 1277259052d8c819d101f6f627f960f56e582ecbcebcAnna Zaks if (CE->getNumArgs() < 2) 1278259052d8c819d101f6f627f960f56e582ecbcebcAnna Zaks return; 1279259052d8c819d101f6f627f960f56e582ecbcebcAnna Zaks 1280067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani //char *strcat(char *restrict s1, const char *restrict s2); 1281067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani evalStrcpyCommon(C, CE, 1282067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani /* returnEnd = */ false, 1283067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani /* isBounded = */ false, 1284067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani /* isAppending = */ true); 1285067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani} 1286067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani 1287067bbd0e11c71a33b51832532e836971be697699Lenny Maioranivoid CStringChecker::evalStrncat(CheckerContext &C, const CallExpr *CE) const { 1288259052d8c819d101f6f627f960f56e582ecbcebcAnna Zaks if (CE->getNumArgs() < 3) 1289259052d8c819d101f6f627f960f56e582ecbcebcAnna Zaks return; 1290259052d8c819d101f6f627f960f56e582ecbcebcAnna Zaks 1291067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani //char *strncat(char *restrict s1, const char *restrict s2, size_t n); 1292067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani evalStrcpyCommon(C, CE, 1293067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani /* returnEnd = */ false, 1294067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani /* isBounded = */ true, 1295067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani /* isAppending = */ true); 1296e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose} 1297e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 12989c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenekvoid CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE, 1299067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani bool returnEnd, bool isBounded, 1300067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani bool isAppending) const { 13019e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose CurrentFunctionDescription = "string copy function"; 13028bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state = C.getState(); 13035eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek const LocationContext *LCtx = C.getLocationContext(); 1304e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 1305067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani // Check that the destination is non-null. 1306e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose const Expr *Dst = CE->getArg(0); 13075eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek SVal DstVal = state->getSVal(Dst, LCtx); 1308e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 1309c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek state = checkNonNull(C, state, Dst, DstVal); 1310e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose if (!state) 1311e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose return; 1312e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 1313e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // Check that the source is non-null. 1314c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek const Expr *srcExpr = CE->getArg(1); 13155eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek SVal srcVal = state->getSVal(srcExpr, LCtx); 1316c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek state = checkNonNull(C, state, srcExpr, srcVal); 1317e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose if (!state) 1318e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose return; 1319e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 1320e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // Get the string length of the source. 1321c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal strLength = getCStringLength(C, state, srcExpr, srcVal); 1322e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 1323e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // If the source isn't a valid C string, give up. 1324c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek if (strLength.isUndef()) 1325e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose return; 1326e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 1327d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose SValBuilder &svalBuilder = C.getSValBuilder(); 1328d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose QualType cmpTy = svalBuilder.getConditionType(); 13298912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose QualType sizeTy = svalBuilder.getContext().getSizeType(); 1330d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 13318912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose // These two values allow checking two kinds of errors: 13328912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose // - actual overflows caused by a source that doesn't fit in the destination 13338912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose // - potential overflows caused by a bound that could exceed the destination 1334d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose SVal amountCopied = UnknownVal(); 13358912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose SVal maxLastElementIndex = UnknownVal(); 13368912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose const char *boundWarning = NULL; 1337d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 1338067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani // If the function is strncpy, strncat, etc... it is bounded. 1339067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani if (isBounded) { 1340067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani // Get the max number of characters to copy. 13410ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek const Expr *lenExpr = CE->getArg(2); 13425eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek SVal lenVal = state->getSVal(lenExpr, LCtx); 13430ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek 1344d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // Protect against misdeclared strncpy(). 13458912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose lenVal = svalBuilder.evalCast(lenVal, sizeTy, lenExpr->getType()); 1346508c627db67ea4b53439fbcd688145f24d9c0400Lenny Maiorani 1347d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose NonLoc *strLengthNL = dyn_cast<NonLoc>(&strLength); 13480ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek NonLoc *lenValNL = dyn_cast<NonLoc>(&lenVal); 13490ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek 1350d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // If we know both values, we might be able to figure out how much 1351d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // we're copying. 1352d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose if (strLengthNL && lenValNL) { 13538bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef stateSourceTooLong, stateSourceNotTooLong; 1354d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 1355d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // Check if the max number to copy is less than the length of the src. 13568912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose // If the bound is equal to the source length, strncpy won't null- 13578912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose // terminate the result! 1358d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose llvm::tie(stateSourceTooLong, stateSourceNotTooLong) = 1359d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose state->assume(cast<DefinedOrUnknownSVal> 13608912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose (svalBuilder.evalBinOpNN(state, BO_GE, *strLengthNL, 1361d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose *lenValNL, cmpTy))); 1362d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 1363d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose if (stateSourceTooLong && !stateSourceNotTooLong) { 1364d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // Max number to copy is less than the length of the src, so the actual 1365d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // strLength copied is the max number arg. 1366d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose state = stateSourceTooLong; 1367d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose amountCopied = lenVal; 1368d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 1369d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose } else if (!stateSourceTooLong && stateSourceNotTooLong) { 1370d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // The source buffer entirely fits in the bound. 1371d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose state = stateSourceNotTooLong; 1372d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose amountCopied = strLength; 1373d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose } 1374d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose } 1375d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 13765e5f15062bcf4b62fda9062b453178f8b9bd0c2dJordy Rose // We still want to know if the bound is known to be too large. 13778912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose if (lenValNL) { 13788912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose if (isAppending) { 13798912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose // For strncat, the check is strlen(dst) + lenVal < sizeof(dst) 13808912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose 13818912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose // Get the string length of the destination. If the destination is 13828912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose // memory that can't have a string length, we shouldn't be copying 13838912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose // into it anyway. 13848912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose SVal dstStrLength = getCStringLength(C, state, Dst, DstVal); 13858912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose if (dstStrLength.isUndef()) 13868912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose return; 13878912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose 13888912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose if (NonLoc *dstStrLengthNL = dyn_cast<NonLoc>(&dstStrLength)) { 13898912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose maxLastElementIndex = svalBuilder.evalBinOpNN(state, BO_Add, 13908912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose *lenValNL, 13918912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose *dstStrLengthNL, 13928912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose sizeTy); 13938912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose boundWarning = "Size argument is greater than the free space in the " 13948912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose "destination buffer"; 13958912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose } 13968912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose 13978912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose } else { 13988912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose // For strncpy, this is just checking that lenVal <= sizeof(dst) 13998912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose // (Yes, strncpy and strncat differ in how they treat termination. 14008912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose // strncat ALWAYS terminates, but strncpy doesn't.) 14016e4244ee86a2d71af4eac791808f2dc50c7484e6Jordy Rose 14026e4244ee86a2d71af4eac791808f2dc50c7484e6Jordy Rose // We need a special case for when the copy size is zero, in which 14036e4244ee86a2d71af4eac791808f2dc50c7484e6Jordy Rose // case strncpy will do no work at all. Our bounds check uses n-1 14046e4244ee86a2d71af4eac791808f2dc50c7484e6Jordy Rose // as the last element accessed, so n == 0 is problematic. 14056e4244ee86a2d71af4eac791808f2dc50c7484e6Jordy Rose ProgramStateRef StateZeroSize, StateNonZeroSize; 14066e4244ee86a2d71af4eac791808f2dc50c7484e6Jordy Rose llvm::tie(StateZeroSize, StateNonZeroSize) = 14076e4244ee86a2d71af4eac791808f2dc50c7484e6Jordy Rose assumeZero(C, state, *lenValNL, sizeTy); 14086e4244ee86a2d71af4eac791808f2dc50c7484e6Jordy Rose 14096e4244ee86a2d71af4eac791808f2dc50c7484e6Jordy Rose // If the size is known to be zero, we're done. 14106e4244ee86a2d71af4eac791808f2dc50c7484e6Jordy Rose if (StateZeroSize && !StateNonZeroSize) { 14116e4244ee86a2d71af4eac791808f2dc50c7484e6Jordy Rose StateZeroSize = StateZeroSize->BindExpr(CE, LCtx, DstVal); 14126e4244ee86a2d71af4eac791808f2dc50c7484e6Jordy Rose C.addTransition(StateZeroSize); 14136e4244ee86a2d71af4eac791808f2dc50c7484e6Jordy Rose return; 14146e4244ee86a2d71af4eac791808f2dc50c7484e6Jordy Rose } 14156e4244ee86a2d71af4eac791808f2dc50c7484e6Jordy Rose 14166e4244ee86a2d71af4eac791808f2dc50c7484e6Jordy Rose // Otherwise, go ahead and figure out the last element we'll touch. 14176e4244ee86a2d71af4eac791808f2dc50c7484e6Jordy Rose // We don't record the non-zero assumption here because we can't 14186e4244ee86a2d71af4eac791808f2dc50c7484e6Jordy Rose // be sure. We won't warn on a possible zero. 14198912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose NonLoc one = cast<NonLoc>(svalBuilder.makeIntVal(1, sizeTy)); 14208912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose maxLastElementIndex = svalBuilder.evalBinOpNN(state, BO_Sub, *lenValNL, 14218912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose one, sizeTy); 14228912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose boundWarning = "Size argument is greater than the length of the " 14238912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose "destination buffer"; 14248912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose } 14258912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose } 14265e5f15062bcf4b62fda9062b453178f8b9bd0c2dJordy Rose 1427d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // If we couldn't pin down the copy length, at least bound it. 14288912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose // FIXME: We should actually run this code path for append as well, but 14298912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose // right now it creates problems with constraints (since we can end up 14308912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose // trying to pass constraints from symbol to symbol). 14318912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose if (amountCopied.isUnknown() && !isAppending) { 1432d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // Try to get a "hypothetical" string length symbol, which we can later 1433d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // set as a real value if that turns out to be the case. 1434d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose amountCopied = getCStringLength(C, state, lenExpr, srcVal, true); 1435d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose assert(!amountCopied.isUndef()); 1436d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 1437d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose if (NonLoc *amountCopiedNL = dyn_cast<NonLoc>(&amountCopied)) { 1438d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose if (lenValNL) { 1439d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // amountCopied <= lenVal 1440d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose SVal copiedLessThanBound = svalBuilder.evalBinOpNN(state, BO_LE, 1441d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose *amountCopiedNL, 1442d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose *lenValNL, 1443d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose cmpTy); 1444d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose state = state->assume(cast<DefinedOrUnknownSVal>(copiedLessThanBound), 1445d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose true); 1446d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose if (!state) 1447d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose return; 1448d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose } 1449d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 1450d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose if (strLengthNL) { 1451d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // amountCopied <= strlen(source) 1452d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose SVal copiedLessThanSrc = svalBuilder.evalBinOpNN(state, BO_LE, 1453d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose *amountCopiedNL, 1454d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose *strLengthNL, 1455d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose cmpTy); 1456d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose state = state->assume(cast<DefinedOrUnknownSVal>(copiedLessThanSrc), 1457d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose true); 1458d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose if (!state) 1459d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose return; 1460d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose } 1461d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose } 1462d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose } 1463d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 1464d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose } else { 1465d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // The function isn't bounded. The amount copied should match the length 1466d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // of the source buffer. 1467d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose amountCopied = strLength; 14680ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek } 14690ef473f75426f0a95635d0a9dd567d27b07dbd5bTed Kremenek 1470d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose assert(state); 1471d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 1472d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // This represents the number of characters copied into the destination 1473d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // buffer. (It may not actually be the strlen if the destination buffer 1474d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // is not terminated.) 1475d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose SVal finalStrLength = UnknownVal(); 1476d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 1477067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani // If this is an appending function (strcat, strncat...) then set the 1478067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani // string length to strlen(src) + strlen(dst) since the buffer will 1479067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani // ultimately contain both. 1480067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani if (isAppending) { 14811e022415b9a66c84a9005b4e0bb2d4becb76d189Jordy Rose // Get the string length of the destination. If the destination is memory 14821e022415b9a66c84a9005b4e0bb2d4becb76d189Jordy Rose // that can't have a string length, we shouldn't be copying into it anyway. 1483067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani SVal dstStrLength = getCStringLength(C, state, Dst, DstVal); 1484067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani if (dstStrLength.isUndef()) 1485067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani return; 1486067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani 1487d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose NonLoc *srcStrLengthNL = dyn_cast<NonLoc>(&amountCopied); 1488067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani NonLoc *dstStrLengthNL = dyn_cast<NonLoc>(&dstStrLength); 1489067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani 1490d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // If we know both string lengths, we might know the final string length. 1491d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose if (srcStrLengthNL && dstStrLengthNL) { 1492d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // Make sure the two lengths together don't overflow a size_t. 1493d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose state = checkAdditionOverflow(C, state, *srcStrLengthNL, *dstStrLengthNL); 1494d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose if (!state) 1495d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose return; 1496d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 1497d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose finalStrLength = svalBuilder.evalBinOpNN(state, BO_Add, *srcStrLengthNL, 1498d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose *dstStrLengthNL, sizeTy); 1499d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose } 1500067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani 1501d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // If we couldn't get a single value for the final string length, 1502d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // we can at least bound it by the individual lengths. 1503d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose if (finalStrLength.isUnknown()) { 1504d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // Try to get a "hypothetical" string length symbol, which we can later 1505d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // set as a real value if that turns out to be the case. 1506d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose finalStrLength = getCStringLength(C, state, CE, DstVal, true); 1507d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose assert(!finalStrLength.isUndef()); 1508d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 1509d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose if (NonLoc *finalStrLengthNL = dyn_cast<NonLoc>(&finalStrLength)) { 1510d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose if (srcStrLengthNL) { 1511d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // finalStrLength >= srcStrLength 1512d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose SVal sourceInResult = svalBuilder.evalBinOpNN(state, BO_GE, 1513d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose *finalStrLengthNL, 1514d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose *srcStrLengthNL, 1515d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose cmpTy); 1516d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose state = state->assume(cast<DefinedOrUnknownSVal>(sourceInResult), 1517d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose true); 1518d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose if (!state) 1519d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose return; 1520d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose } 1521d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 1522d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose if (dstStrLengthNL) { 1523d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // finalStrLength >= dstStrLength 1524d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose SVal destInResult = svalBuilder.evalBinOpNN(state, BO_GE, 1525d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose *finalStrLengthNL, 1526d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose *dstStrLengthNL, 1527d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose cmpTy); 1528d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose state = state->assume(cast<DefinedOrUnknownSVal>(destInResult), 1529d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose true); 1530d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose if (!state) 1531d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose return; 1532d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose } 1533d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose } 1534d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose } 1535067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani 1536d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose } else { 1537d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // Otherwise, this is a copy-over function (strcpy, strncpy, ...), and 1538d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // the final string length will match the input string length. 1539d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose finalStrLength = amountCopied; 1540067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani } 1541067bbd0e11c71a33b51832532e836971be697699Lenny Maiorani 1542d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // The final result of the function will either be a pointer past the last 1543d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose // copied element, or a pointer to the start of the destination buffer. 1544c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SVal Result = (returnEnd ? UnknownVal() : DstVal); 1545e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 1546d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose assert(state); 1547d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 1548e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // If the destination is a MemRegion, try to check for a buffer overflow and 1549e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // record the new string length. 1550c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek if (loc::MemRegionVal *dstRegVal = dyn_cast<loc::MemRegionVal>(&DstVal)) { 15518912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose QualType ptrTy = Dst->getType(); 15528912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose 15538912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose // If we have an exact value on a bounded copy, use that to check for 15548912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose // overflows, rather than our estimate about how much is actually copied. 15558912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose if (boundWarning) { 15568912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose if (NonLoc *maxLastNL = dyn_cast<NonLoc>(&maxLastElementIndex)) { 15578912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose SVal maxLastElement = svalBuilder.evalBinOpLN(state, BO_Add, *dstRegVal, 15588912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose *maxLastNL, ptrTy); 15598912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose state = CheckLocation(C, state, CE->getArg(2), maxLastElement, 15608912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose boundWarning); 15618912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose if (!state) 15628912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose return; 15638912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose } 15648912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose } 15658912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose 15668912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose // Then, if the final length is known... 1567d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose if (NonLoc *knownStrLength = dyn_cast<NonLoc>(&finalStrLength)) { 1568d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose SVal lastElement = svalBuilder.evalBinOpLN(state, BO_Add, *dstRegVal, 15698912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose *knownStrLength, ptrTy); 15708912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose 15718912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose // ...and we haven't checked the bound, we'll check the actual copy. 15728912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose if (!boundWarning) { 15738912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose const char * const warningMsg = 15748912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose "String copy function overflows destination buffer"; 15758912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose state = CheckLocation(C, state, Dst, lastElement, warningMsg); 15768912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose if (!state) 15778912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose return; 15788912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose } 1579e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 1580e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // If this is a stpcpy-style copy, the last element is the return value. 1581c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek if (returnEnd) 1582c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek Result = lastElement; 1583e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose } 1584e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 1585e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // Invalidate the destination. This must happen before we set the C string 1586e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // length because invalidation will clear the length. 1587e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // FIXME: Even if we can't perfectly model the copy, we should see if we 1588e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // can use LazyCompoundVals to copy the source values into the destination. 1589e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // This would probably remove any existing bindings past the end of the 1590e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // string, but that's still an improvement over blank invalidation. 1591c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek state = InvalidateBuffer(C, state, Dst, *dstRegVal); 1592e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 15935e5f15062bcf4b62fda9062b453178f8b9bd0c2dJordy Rose // Set the C string length of the destination, if we know it. 15948912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose if (isBounded && !isAppending) { 15958912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose // strncpy is annoying in that it doesn't guarantee to null-terminate 15968912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose // the result string. If the original string didn't fit entirely inside 15978912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose // the bound (including the null-terminator), we don't know how long the 15988912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose // result is. 15998912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose if (amountCopied != strLength) 16008912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose finalStrLength = UnknownVal(); 16018912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose } 16028912aaedb413b15f6dd1d8997d80e1d505f7d52fJordy Rose state = setCStringLength(state, dstRegVal->getRegion(), finalStrLength); 1603e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose } 1604e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 1605d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose assert(state); 1606d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 1607e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // If this is a stpcpy-style copy, but we were unable to check for a buffer 1608e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // overflow, we still need a result. Conjure a return value. 1609c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek if (returnEnd && Result.isUnknown()) { 161066c486f275531df6362b3511fc3af6563561801bTed Kremenek Result = svalBuilder.conjureSymbolVal(0, CE, LCtx, C.blockCount()); 1611e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose } 1612e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 1613e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose // Set the return value. 16145eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek state = state->BindExpr(CE, LCtx, Result); 16150bd6b110e908892d4b5c8671a9f435a1d72ad16aAnna Zaks C.addTransition(state); 1616e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose} 1617e64f311c11a8751867c2538807054f4817c1f5cbJordy Rose 1618318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maioranivoid CStringChecker::evalStrcmp(CheckerContext &C, const CallExpr *CE) const { 1619259052d8c819d101f6f627f960f56e582ecbcebcAnna Zaks if (CE->getNumArgs() < 2) 1620259052d8c819d101f6f627f960f56e582ecbcebcAnna Zaks return; 1621259052d8c819d101f6f627f960f56e582ecbcebcAnna Zaks 1622adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose //int strcmp(const char *s1, const char *s2); 1623bd1d16a1792cd6ea5ede9869e18d781e3fc1a8c3Lenny Maiorani evalStrcmpCommon(C, CE, /* isBounded = */ false, /* ignoreCase = */ false); 1624357f6ee9f1f6f8e5027377cb3e5907c62c4fe3dfLenny Maiorani} 1625357f6ee9f1f6f8e5027377cb3e5907c62c4fe3dfLenny Maiorani 1626357f6ee9f1f6f8e5027377cb3e5907c62c4fe3dfLenny Maioranivoid CStringChecker::evalStrncmp(CheckerContext &C, const CallExpr *CE) const { 1627259052d8c819d101f6f627f960f56e582ecbcebcAnna Zaks if (CE->getNumArgs() < 3) 1628259052d8c819d101f6f627f960f56e582ecbcebcAnna Zaks return; 1629259052d8c819d101f6f627f960f56e582ecbcebcAnna Zaks 1630adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose //int strncmp(const char *s1, const char *s2, size_t n); 1631bd1d16a1792cd6ea5ede9869e18d781e3fc1a8c3Lenny Maiorani evalStrcmpCommon(C, CE, /* isBounded = */ true, /* ignoreCase = */ false); 1632bd1d16a1792cd6ea5ede9869e18d781e3fc1a8c3Lenny Maiorani} 1633bd1d16a1792cd6ea5ede9869e18d781e3fc1a8c3Lenny Maiorani 1634bd1d16a1792cd6ea5ede9869e18d781e3fc1a8c3Lenny Maioranivoid CStringChecker::evalStrcasecmp(CheckerContext &C, 1635bd1d16a1792cd6ea5ede9869e18d781e3fc1a8c3Lenny Maiorani const CallExpr *CE) const { 1636259052d8c819d101f6f627f960f56e582ecbcebcAnna Zaks if (CE->getNumArgs() < 2) 1637259052d8c819d101f6f627f960f56e582ecbcebcAnna Zaks return; 1638259052d8c819d101f6f627f960f56e582ecbcebcAnna Zaks 1639adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose //int strcasecmp(const char *s1, const char *s2); 1640bd1d16a1792cd6ea5ede9869e18d781e3fc1a8c3Lenny Maiorani evalStrcmpCommon(C, CE, /* isBounded = */ false, /* ignoreCase = */ true); 1641357f6ee9f1f6f8e5027377cb3e5907c62c4fe3dfLenny Maiorani} 1642318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani 1643454fd2d3a1b6d0ef225c5d3927c1ad3b97510d1aLenny Maioranivoid CStringChecker::evalStrncasecmp(CheckerContext &C, 1644454fd2d3a1b6d0ef225c5d3927c1ad3b97510d1aLenny Maiorani const CallExpr *CE) const { 1645259052d8c819d101f6f627f960f56e582ecbcebcAnna Zaks if (CE->getNumArgs() < 3) 1646259052d8c819d101f6f627f960f56e582ecbcebcAnna Zaks return; 1647259052d8c819d101f6f627f960f56e582ecbcebcAnna Zaks 1648adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose //int strncasecmp(const char *s1, const char *s2, size_t n); 1649454fd2d3a1b6d0ef225c5d3927c1ad3b97510d1aLenny Maiorani evalStrcmpCommon(C, CE, /* isBounded = */ true, /* ignoreCase = */ true); 1650454fd2d3a1b6d0ef225c5d3927c1ad3b97510d1aLenny Maiorani} 1651454fd2d3a1b6d0ef225c5d3927c1ad3b97510d1aLenny Maiorani 1652357f6ee9f1f6f8e5027377cb3e5907c62c4fe3dfLenny Maioranivoid CStringChecker::evalStrcmpCommon(CheckerContext &C, const CallExpr *CE, 1653bd1d16a1792cd6ea5ede9869e18d781e3fc1a8c3Lenny Maiorani bool isBounded, bool ignoreCase) const { 16549e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose CurrentFunctionDescription = "string comparison function"; 16558bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state = C.getState(); 16565eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek const LocationContext *LCtx = C.getLocationContext(); 1657318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani 1658318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani // Check that the first string is non-null 1659318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani const Expr *s1 = CE->getArg(0); 16605eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek SVal s1Val = state->getSVal(s1, LCtx); 1661318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani state = checkNonNull(C, state, s1, s1Val); 1662318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani if (!state) 1663318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani return; 1664318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani 1665318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani // Check that the second string is non-null. 1666318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani const Expr *s2 = CE->getArg(1); 16675eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek SVal s2Val = state->getSVal(s2, LCtx); 1668318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani state = checkNonNull(C, state, s2, s2Val); 1669318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani if (!state) 1670318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani return; 1671318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani 1672318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani // Get the string length of the first string or give up. 1673318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani SVal s1Length = getCStringLength(C, state, s1, s1Val); 1674318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani if (s1Length.isUndef()) 1675318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani return; 1676318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani 1677318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani // Get the string length of the second string or give up. 1678318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani SVal s2Length = getCStringLength(C, state, s2, s2Val); 1679318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani if (s2Length.isUndef()) 1680318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani return; 1681318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani 1682adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose // If we know the two buffers are the same, we know the result is 0. 1683adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose // First, get the two buffers' addresses. Another checker will have already 1684adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose // made sure they're not undefined. 1685adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose DefinedOrUnknownSVal LV = cast<DefinedOrUnknownSVal>(s1Val); 1686adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose DefinedOrUnknownSVal RV = cast<DefinedOrUnknownSVal>(s2Val); 1687adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose 1688adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose // See if they are the same. 1689adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose SValBuilder &svalBuilder = C.getSValBuilder(); 1690adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose DefinedOrUnknownSVal SameBuf = svalBuilder.evalEQ(state, LV, RV); 16918bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef StSameBuf, StNotSameBuf; 1692adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose llvm::tie(StSameBuf, StNotSameBuf) = state->assume(SameBuf); 1693adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose 1694adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose // If the two arguments might be the same buffer, we know the result is 0, 1695adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose // and we only need to check one size. 1696adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose if (StSameBuf) { 16975eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek StSameBuf = StSameBuf->BindExpr(CE, LCtx, 16985eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek svalBuilder.makeZeroVal(CE->getType())); 16990bd6b110e908892d4b5c8671a9f435a1d72ad16aAnna Zaks C.addTransition(StSameBuf); 1700adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose 1701adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose // If the two arguments are GUARANTEED to be the same, we're done! 1702adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose if (!StNotSameBuf) 1703adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose return; 1704adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose } 1705adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose 1706adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose assert(StNotSameBuf); 1707adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose state = StNotSameBuf; 1708318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani 1709adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose // At this point we can go about comparing the two buffers. 1710adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose // For now, we only do this if they're both known string literals. 1711adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose 1712adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose // Attempt to extract string literals from both expressions. 1713adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose const StringLiteral *s1StrLiteral = getCStringLiteral(C, state, s1, s1Val); 1714318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani const StringLiteral *s2StrLiteral = getCStringLiteral(C, state, s2, s2Val); 1715adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose bool canComputeResult = false; 1716adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose 1717adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose if (s1StrLiteral && s2StrLiteral) { 17185f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef s1StrRef = s1StrLiteral->getString(); 17195f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef s2StrRef = s2StrLiteral->getString(); 1720adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose 1721adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose if (isBounded) { 1722adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose // Get the max number of characters to compare. 1723adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose const Expr *lenExpr = CE->getArg(2); 17245eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek SVal lenVal = state->getSVal(lenExpr, LCtx); 1725adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose 1726adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose // If the length is known, we can get the right substrings. 1727adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose if (const llvm::APSInt *len = svalBuilder.getKnownValue(state, lenVal)) { 1728adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose // Create substrings of each to compare the prefix. 1729adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose s1StrRef = s1StrRef.substr(0, (size_t)len->getZExtValue()); 1730adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose s2StrRef = s2StrRef.substr(0, (size_t)len->getZExtValue()); 1731adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose canComputeResult = true; 1732adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose } 1733adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose } else { 1734adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose // This is a normal, unbounded strcmp. 1735adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose canComputeResult = true; 1736adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose } 1737318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani 1738adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose if (canComputeResult) { 1739adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose // Real strcmp stops at null characters. 1740adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose size_t s1Term = s1StrRef.find('\0'); 17415f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner if (s1Term != StringRef::npos) 1742adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose s1StrRef = s1StrRef.substr(0, s1Term); 1743357f6ee9f1f6f8e5027377cb3e5907c62c4fe3dfLenny Maiorani 1744adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose size_t s2Term = s2StrRef.find('\0'); 17455f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner if (s2Term != StringRef::npos) 1746adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose s2StrRef = s2StrRef.substr(0, s2Term); 1747adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose 1748adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose // Use StringRef's comparison methods to compute the actual result. 1749adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose int result; 1750adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose 1751adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose if (ignoreCase) { 1752adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose // Compare string 1 to string 2 the same way strcasecmp() does. 1753adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose result = s1StrRef.compare_lower(s2StrRef); 1754adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose } else { 1755adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose // Compare string 1 to string 2 the same way strcmp() does. 1756adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose result = s1StrRef.compare(s2StrRef); 1757adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose } 1758357f6ee9f1f6f8e5027377cb3e5907c62c4fe3dfLenny Maiorani 1759adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose // Build the SVal of the comparison and bind the return value. 1760adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose SVal resultVal = svalBuilder.makeIntVal(result, CE->getType()); 17615eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek state = state->BindExpr(CE, LCtx, resultVal); 1762adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose } 1763454fd2d3a1b6d0ef225c5d3927c1ad3b97510d1aLenny Maiorani } 1764bd1d16a1792cd6ea5ede9869e18d781e3fc1a8c3Lenny Maiorani 1765adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose if (!canComputeResult) { 1766adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose // Conjure a symbolic value. It's the best we can do. 176766c486f275531df6362b3511fc3af6563561801bTed Kremenek SVal resultVal = svalBuilder.conjureSymbolVal(0, CE, LCtx, C.blockCount()); 17685eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek state = state->BindExpr(CE, LCtx, resultVal); 1769357f6ee9f1f6f8e5027377cb3e5907c62c4fe3dfLenny Maiorani } 1770318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani 1771adc42d412d747391dbcee234610f00b0f087cf7bJordy Rose // Record this as a possible path. 17720bd6b110e908892d4b5c8671a9f435a1d72ad16aAnna Zaks C.addTransition(state); 1773318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani} 1774318dd92ad834857ea5bb91de288c1eb56cdbec1aLenny Maiorani 1775d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose//===----------------------------------------------------------------------===// 1776a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose// The driver method, and other Checker callbacks. 1777d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose//===----------------------------------------------------------------------===// 1778ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 1779183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidisbool CStringChecker::evalCall(const CallExpr *CE, CheckerContext &C) const { 1780998e2754281b19bb1db19299ae16c2fd5947bcc0Anna Zaks const FunctionDecl *FDecl = C.getCalleeDecl(CE); 1781998e2754281b19bb1db19299ae16c2fd5947bcc0Anna Zaks 1782998e2754281b19bb1db19299ae16c2fd5947bcc0Anna Zaks if (!FDecl) 178390d26a4afdbf6d917a5241ef3b316e1c8337c9b8Douglas Gregor return false; 1784ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 1785998e2754281b19bb1db19299ae16c2fd5947bcc0Anna Zaks FnCheck evalFunction = 0; 1786998e2754281b19bb1db19299ae16c2fd5947bcc0Anna Zaks if (C.isCLibraryFunction(FDecl, "memcpy")) 1787998e2754281b19bb1db19299ae16c2fd5947bcc0Anna Zaks evalFunction = &CStringChecker::evalMemcpy; 1788998e2754281b19bb1db19299ae16c2fd5947bcc0Anna Zaks else if (C.isCLibraryFunction(FDecl, "mempcpy")) 1789998e2754281b19bb1db19299ae16c2fd5947bcc0Anna Zaks evalFunction = &CStringChecker::evalMempcpy; 1790998e2754281b19bb1db19299ae16c2fd5947bcc0Anna Zaks else if (C.isCLibraryFunction(FDecl, "memcmp")) 1791998e2754281b19bb1db19299ae16c2fd5947bcc0Anna Zaks evalFunction = &CStringChecker::evalMemcmp; 1792998e2754281b19bb1db19299ae16c2fd5947bcc0Anna Zaks else if (C.isCLibraryFunction(FDecl, "memmove")) 1793998e2754281b19bb1db19299ae16c2fd5947bcc0Anna Zaks evalFunction = &CStringChecker::evalMemmove; 1794998e2754281b19bb1db19299ae16c2fd5947bcc0Anna Zaks else if (C.isCLibraryFunction(FDecl, "strcpy")) 1795998e2754281b19bb1db19299ae16c2fd5947bcc0Anna Zaks evalFunction = &CStringChecker::evalStrcpy; 1796998e2754281b19bb1db19299ae16c2fd5947bcc0Anna Zaks else if (C.isCLibraryFunction(FDecl, "strncpy")) 1797998e2754281b19bb1db19299ae16c2fd5947bcc0Anna Zaks evalFunction = &CStringChecker::evalStrncpy; 1798998e2754281b19bb1db19299ae16c2fd5947bcc0Anna Zaks else if (C.isCLibraryFunction(FDecl, "stpcpy")) 1799998e2754281b19bb1db19299ae16c2fd5947bcc0Anna Zaks evalFunction = &CStringChecker::evalStpcpy; 1800998e2754281b19bb1db19299ae16c2fd5947bcc0Anna Zaks else if (C.isCLibraryFunction(FDecl, "strcat")) 1801998e2754281b19bb1db19299ae16c2fd5947bcc0Anna Zaks evalFunction = &CStringChecker::evalStrcat; 1802998e2754281b19bb1db19299ae16c2fd5947bcc0Anna Zaks else if (C.isCLibraryFunction(FDecl, "strncat")) 1803998e2754281b19bb1db19299ae16c2fd5947bcc0Anna Zaks evalFunction = &CStringChecker::evalStrncat; 1804998e2754281b19bb1db19299ae16c2fd5947bcc0Anna Zaks else if (C.isCLibraryFunction(FDecl, "strlen")) 1805998e2754281b19bb1db19299ae16c2fd5947bcc0Anna Zaks evalFunction = &CStringChecker::evalstrLength; 1806998e2754281b19bb1db19299ae16c2fd5947bcc0Anna Zaks else if (C.isCLibraryFunction(FDecl, "strnlen")) 1807998e2754281b19bb1db19299ae16c2fd5947bcc0Anna Zaks evalFunction = &CStringChecker::evalstrnLength; 1808998e2754281b19bb1db19299ae16c2fd5947bcc0Anna Zaks else if (C.isCLibraryFunction(FDecl, "strcmp")) 1809998e2754281b19bb1db19299ae16c2fd5947bcc0Anna Zaks evalFunction = &CStringChecker::evalStrcmp; 1810998e2754281b19bb1db19299ae16c2fd5947bcc0Anna Zaks else if (C.isCLibraryFunction(FDecl, "strncmp")) 1811998e2754281b19bb1db19299ae16c2fd5947bcc0Anna Zaks evalFunction = &CStringChecker::evalStrncmp; 1812998e2754281b19bb1db19299ae16c2fd5947bcc0Anna Zaks else if (C.isCLibraryFunction(FDecl, "strcasecmp")) 1813998e2754281b19bb1db19299ae16c2fd5947bcc0Anna Zaks evalFunction = &CStringChecker::evalStrcasecmp; 1814998e2754281b19bb1db19299ae16c2fd5947bcc0Anna Zaks else if (C.isCLibraryFunction(FDecl, "strncasecmp")) 1815998e2754281b19bb1db19299ae16c2fd5947bcc0Anna Zaks evalFunction = &CStringChecker::evalStrncasecmp; 1816998e2754281b19bb1db19299ae16c2fd5947bcc0Anna Zaks else if (C.isCLibraryFunction(FDecl, "bcopy")) 1817998e2754281b19bb1db19299ae16c2fd5947bcc0Anna Zaks evalFunction = &CStringChecker::evalBcopy; 1818998e2754281b19bb1db19299ae16c2fd5947bcc0Anna Zaks else if (C.isCLibraryFunction(FDecl, "bcmp")) 1819998e2754281b19bb1db19299ae16c2fd5947bcc0Anna Zaks evalFunction = &CStringChecker::evalMemcmp; 1820998e2754281b19bb1db19299ae16c2fd5947bcc0Anna Zaks 1821d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // If the callee isn't a string function, let another checker handle it. 18229c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek if (!evalFunction) 1823ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return false; 1824ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose 18259e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose // Make sure each function sets its own description. 18269e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose // (But don't bother in a release build.) 18279e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose assert(!(CurrentFunctionDescription = NULL)); 18289e49d9fbdc861c25c2480233147dee07f5fa9660Jordy Rose 1829d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose // Check and evaluate the call. 18309c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek (this->*evalFunction)(C, CE); 183157300760964904cc022a175643342f29f46b7e6bAnna Zaks 183257300760964904cc022a175643342f29f46b7e6bAnna Zaks // If the evaluate call resulted in no change, chain to the next eval call 183357300760964904cc022a175643342f29f46b7e6bAnna Zaks // handler. 183457300760964904cc022a175643342f29f46b7e6bAnna Zaks // Note, the custom CString evaluation calls assume that basic safety 183557300760964904cc022a175643342f29f46b7e6bAnna Zaks // properties are held. However, if the user chooses to turn off some of these 183657300760964904cc022a175643342f29f46b7e6bAnna Zaks // checks, we ignore the issues and leave the call evaluation to a generic 183757300760964904cc022a175643342f29f46b7e6bAnna Zaks // handler. 183857300760964904cc022a175643342f29f46b7e6bAnna Zaks if (!C.isDifferent()) 183957300760964904cc022a175643342f29f46b7e6bAnna Zaks return false; 184057300760964904cc022a175643342f29f46b7e6bAnna Zaks 1841ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose return true; 1842ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose} 1843a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1844183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidisvoid CStringChecker::checkPreStmt(const DeclStmt *DS, CheckerContext &C) const { 1845a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // Record string length for char a[] = "abc"; 18468bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state = C.getState(); 1847a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1848a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose for (DeclStmt::const_decl_iterator I = DS->decl_begin(), E = DS->decl_end(); 1849a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose I != E; ++I) { 1850a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose const VarDecl *D = dyn_cast<VarDecl>(*I); 1851a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (!D) 1852a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose continue; 1853a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1854a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // FIXME: Handle array fields of structs. 1855a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (!D->getType()->isArrayType()) 1856a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose continue; 1857a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1858a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose const Expr *Init = D->getInit(); 1859a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (!Init) 1860a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose continue; 1861a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (!isa<StringLiteral>(Init)) 1862a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose continue; 1863a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 186439ac1876f6f9a1a8e0070f0df61036c7ba05202bAnna Zaks Loc VarLoc = state->getLValue(D, C.getLocationContext()); 1865a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose const MemRegion *MR = VarLoc.getAsRegion(); 1866a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (!MR) 1867a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose continue; 1868a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 18695eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek SVal StrVal = state->getSVal(Init, C.getLocationContext()); 1870a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose assert(StrVal.isValid() && "Initializer string is unknown or undefined"); 1871c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek DefinedOrUnknownSVal strLength 1872c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek = cast<DefinedOrUnknownSVal>(getCStringLength(C, state, Init, StrVal)); 1873a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1874c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek state = state->set<CStringLength>(MR, strLength); 1875a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose } 1876a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 18770bd6b110e908892d4b5c8671a9f435a1d72ad16aAnna Zaks C.addTransition(state); 1878a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose} 1879a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 18808bef8238181a30e52dea380789a7e2d760eac532Ted Kremenekbool CStringChecker::wantsRegionChangeUpdate(ProgramStateRef state) const { 1881a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose CStringLength::EntryMap Entries = state->get<CStringLength>(); 1882a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose return !Entries.isEmpty(); 1883a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose} 1884a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 18858bef8238181a30e52dea380789a7e2d760eac532Ted KremenekProgramStateRef 18868bef8238181a30e52dea380789a7e2d760eac532Ted KremenekCStringChecker::checkRegionChanges(ProgramStateRef state, 188735bdbf40624beba3fc00cb72ab444659939c1a6bTed Kremenek const StoreManager::InvalidatedSymbols *, 1888537716ad8dd10f984b6cfe6985afade1185c5e3cJordy Rose ArrayRef<const MemRegion *> ExplicitRegions, 188966c40400e7d6272b0cd675ada18dd62c1f0362c7Anna Zaks ArrayRef<const MemRegion *> Regions, 1890740d490593e0de8732a697c9f77b90ddd463863bJordan Rose const CallEvent *Call) const { 1891a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose CStringLength::EntryMap Entries = state->get<CStringLength>(); 1892a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (Entries.isEmpty()) 1893a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose return state; 1894a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1895a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose llvm::SmallPtrSet<const MemRegion *, 8> Invalidated; 1896a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose llvm::SmallPtrSet<const MemRegion *, 32> SuperRegions; 1897a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1898a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // First build sets for the changed regions and their super-regions. 1899537716ad8dd10f984b6cfe6985afade1185c5e3cJordy Rose for (ArrayRef<const MemRegion *>::iterator 1900537716ad8dd10f984b6cfe6985afade1185c5e3cJordy Rose I = Regions.begin(), E = Regions.end(); I != E; ++I) { 1901537716ad8dd10f984b6cfe6985afade1185c5e3cJordy Rose const MemRegion *MR = *I; 1902a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose Invalidated.insert(MR); 1903a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1904a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose SuperRegions.insert(MR); 1905a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose while (const SubRegion *SR = dyn_cast<SubRegion>(MR)) { 1906a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose MR = SR->getSuperRegion(); 1907a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose SuperRegions.insert(MR); 1908a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose } 1909a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose } 1910a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1911a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose CStringLength::EntryMap::Factory &F = state->get_context<CStringLength>(); 1912a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1913a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // Then loop over the entries in the current state. 1914a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose for (CStringLength::EntryMap::iterator I = Entries.begin(), 1915a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose E = Entries.end(); I != E; ++I) { 1916a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose const MemRegion *MR = I.getKey(); 1917a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1918a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // Is this entry for a super-region of a changed region? 1919a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (SuperRegions.count(MR)) { 19203baf672378f105602d2b12f03f00277ae1936fe9Ted Kremenek Entries = F.remove(Entries, MR); 1921a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose continue; 1922a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose } 1923a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1924a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // Is this entry for a sub-region of a changed region? 1925a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose const MemRegion *Super = MR; 1926a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose while (const SubRegion *SR = dyn_cast<SubRegion>(Super)) { 1927a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose Super = SR->getSuperRegion(); 1928a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (Invalidated.count(Super)) { 19293baf672378f105602d2b12f03f00277ae1936fe9Ted Kremenek Entries = F.remove(Entries, MR); 1930a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose break; 1931a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose } 1932a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose } 1933a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose } 1934a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1935a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose return state->set<CStringLength>(Entries); 1936a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose} 1937a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 19388bef8238181a30e52dea380789a7e2d760eac532Ted Kremenekvoid CStringChecker::checkLiveSymbols(ProgramStateRef state, 1939183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis SymbolReaper &SR) const { 1940a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose // Mark all symbols in our string length map as valid. 1941a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose CStringLength::EntryMap Entries = state->get<CStringLength>(); 1942a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1943a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose for (CStringLength::EntryMap::iterator I = Entries.begin(), E = Entries.end(); 1944a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose I != E; ++I) { 1945a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose SVal Len = I.getData(); 1946d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose 19471d1d515b2bafb59d624883d8fdda97d4b7dba0cbAnna Zaks for (SymExpr::symbol_iterator si = Len.symbol_begin(), 19481d1d515b2bafb59d624883d8fdda97d4b7dba0cbAnna Zaks se = Len.symbol_end(); si != se; ++si) 1949d5af0e17b00ab2ee6a8c1f352bb9eeb1cc5b2d07Jordy Rose SR.markInUse(*si); 1950a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose } 1951a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose} 1952a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1953183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidisvoid CStringChecker::checkDeadSymbols(SymbolReaper &SR, 1954183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis CheckerContext &C) const { 1955a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (!SR.hasDeadSymbols()) 1956a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose return; 1957a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 19588bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state = C.getState(); 1959a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose CStringLength::EntryMap Entries = state->get<CStringLength>(); 1960a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (Entries.isEmpty()) 1961a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose return; 1962a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1963a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose CStringLength::EntryMap::Factory &F = state->get_context<CStringLength>(); 1964a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose for (CStringLength::EntryMap::iterator I = Entries.begin(), E = Entries.end(); 1965a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose I != E; ++I) { 1966a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose SVal Len = I.getData(); 1967a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (SymbolRef Sym = Len.getAsSymbol()) { 1968a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose if (SR.isDead(Sym)) 19693baf672378f105602d2b12f03f00277ae1936fe9Ted Kremenek Entries = F.remove(Entries, I.getKey()); 1970a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose } 1971a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose } 1972a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose 1973a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose state = state->set<CStringLength>(Entries); 19740bd6b110e908892d4b5c8671a9f435a1d72ad16aAnna Zaks C.addTransition(state); 1975a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose} 1976183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis 197757300760964904cc022a175643342f29f46b7e6bAnna Zaks#define REGISTER_CHECKER(name) \ 197857300760964904cc022a175643342f29f46b7e6bAnna Zaksvoid ento::register##name(CheckerManager &mgr) {\ 197957300760964904cc022a175643342f29f46b7e6bAnna Zaks static CStringChecker *TheChecker = 0; \ 198057300760964904cc022a175643342f29f46b7e6bAnna Zaks if (TheChecker == 0) \ 198157300760964904cc022a175643342f29f46b7e6bAnna Zaks TheChecker = mgr.registerChecker<CStringChecker>(); \ 198257300760964904cc022a175643342f29f46b7e6bAnna Zaks TheChecker->Filter.Check##name = true; \ 1983183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis} 198457300760964904cc022a175643342f29f46b7e6bAnna Zaks 198557300760964904cc022a175643342f29f46b7e6bAnna ZaksREGISTER_CHECKER(CStringNullArg) 198657300760964904cc022a175643342f29f46b7e6bAnna ZaksREGISTER_CHECKER(CStringOutOfBounds) 198757300760964904cc022a175643342f29f46b7e6bAnna ZaksREGISTER_CHECKER(CStringBufferOverlap) 198857300760964904cc022a175643342f29f46b7e6bAnna ZaksREGISTER_CHECKER(CStringNotNullTerm) 1989f0dfc9c0f29fd82552896558c04043731d30b851Anna Zaks 1990f0dfc9c0f29fd82552896558c04043731d30b851Anna Zaksvoid ento::registerCStringCheckerBasic(CheckerManager &Mgr) { 1991f0dfc9c0f29fd82552896558c04043731d30b851Anna Zaks registerCStringNullArg(Mgr); 1992f0dfc9c0f29fd82552896558c04043731d30b851Anna Zaks} 1993