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