CStringChecker.cpp revision a5261549754fab80e30e893d8fa706bfb31e430a
1ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose//= CStringChecker.h - Checks calls to C string functions ----------*- C++ -*-//
2ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose//
3ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose//                     The LLVM Compiler Infrastructure
4ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose//
5ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose// This file is distributed under the University of Illinois Open Source
6ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose// License. See LICENSE.TXT for details.
7ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose//
8ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose//===----------------------------------------------------------------------===//
9ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose//
10ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose// This defines CStringChecker, which is an assortment of checks on calls
11ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose// to functions in <string.h>.
12ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose//
13ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose//===----------------------------------------------------------------------===//
14ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose
15ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose#include "GRExprEngineExperimentalChecks.h"
16ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose#include "clang/Checker/BugReporter/BugType.h"
17ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose#include "clang/Checker/PathSensitive/CheckerVisitor.h"
18a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose#include "clang/Checker/PathSensitive/GRStateTrait.h"
19ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose#include "llvm/ADT/StringSwitch.h"
20ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose
21ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Roseusing namespace clang;
22ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose
23ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rosenamespace {
24ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Roseclass CStringChecker : public CheckerVisitor<CStringChecker> {
2519c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose  BugType *BT_Null, *BT_Bounds, *BT_Overlap, *BT_NotCString;
26ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rosepublic:
27ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  CStringChecker()
2819c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose  : BT_Null(0), BT_Bounds(0), BT_Overlap(0), BT_NotCString(0) {}
29ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  static void *getTag() { static int tag; return &tag; }
30ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose
31ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  bool EvalCallExpr(CheckerContext &C, const CallExpr *CE);
32a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  void PreVisitDeclStmt(CheckerContext &C, const DeclStmt *DS);
33a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  void MarkLiveSymbols(const GRState *state, SymbolReaper &SR);
34a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  void EvalDeadSymbols(CheckerContext &C, SymbolReaper &SR);
35a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  bool WantsRegionChangeUpdate(const GRState *state);
36a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose
37a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  const GRState *EvalRegionChanges(const GRState *state,
38a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose                                   const MemRegion * const *Begin,
39a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose                                   const MemRegion * const *End,
40a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose                                   bool*);
41ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose
42d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  typedef void (CStringChecker::*FnCheck)(CheckerContext &, const CallExpr *);
43ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose
44d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  void EvalMemcpy(CheckerContext &C, const CallExpr *CE);
45d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  void EvalMemmove(CheckerContext &C, const CallExpr *CE);
46d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  void EvalBcopy(CheckerContext &C, const CallExpr *CE);
47d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  void EvalCopyCommon(CheckerContext &C, const GRState *state,
48d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose                      const Expr *Size, const Expr *Source, const Expr *Dest,
49d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose                      bool Restricted = false);
50d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose
51d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  void EvalMemcmp(CheckerContext &C, const CallExpr *CE);
52ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose
5319c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose  void EvalStrlen(CheckerContext &C, const CallExpr *CE);
5419c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose
55ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  // Utility methods
56d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  std::pair<const GRState*, const GRState*>
57d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  AssumeZero(CheckerContext &C, const GRState *state, SVal V, QualType Ty);
58d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose
59a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  SVal GetCStringLengthForRegion(CheckerContext &C, const GRState *&state,
60a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose                                 const Expr *Ex, const MemRegion *MR);
61a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  SVal GetCStringLength(CheckerContext &C, const GRState *&state,
6219c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose                        const Expr *Ex, SVal Buf);
6319c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose
6419c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose  bool SummarizeRegion(llvm::raw_ostream& os, ASTContext& Ctx,
6519c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose                       const MemRegion *MR);
6619c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose
6719c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose  // Re-usable checks
68a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose  const GRState *CheckNonNull(CheckerContext &C, const GRState *state,
69d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose                               const Expr *S, SVal l);
70ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  const GRState *CheckLocation(CheckerContext &C, const GRState *state,
71d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose                               const Expr *S, SVal l);
72ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  const GRState *CheckBufferAccess(CheckerContext &C, const GRState *state,
73ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose                                   const Expr *Size,
74ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose                                   const Expr *FirstBuf,
75ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose                                   const Expr *SecondBuf = NULL);
76ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  const GRState *CheckOverlap(CheckerContext &C, const GRState *state,
77d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose                              const Expr *Size, const Expr *First,
78d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose                              const Expr *Second);
79ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  void EmitOverlapBug(CheckerContext &C, const GRState *state,
80ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose                      const Stmt *First, const Stmt *Second);
81ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose};
82a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose
83a5261549754fab80e30e893d8fa706bfb31e430aJordy Roseclass CStringLength {
84a5261549754fab80e30e893d8fa706bfb31e430aJordy Rosepublic:
85a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  typedef llvm::ImmutableMap<const MemRegion *, SVal> EntryMap;
86a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose};
87ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose} //end anonymous namespace
88ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose
89a5261549754fab80e30e893d8fa706bfb31e430aJordy Rosenamespace clang {
90a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  template <>
91a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  struct GRStateTrait<CStringLength>
92a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    : public GRStatePartialTrait<CStringLength::EntryMap> {
93a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    static void *GDMIndex() { return CStringChecker::getTag(); }
94a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  };
95a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose}
96a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose
97ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rosevoid clang::RegisterCStringChecker(GRExprEngine &Eng) {
98ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  Eng.registerCheck(new CStringChecker());
99ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose}
100ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose
101d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose//===----------------------------------------------------------------------===//
102d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose// Individual checks and utility methods.
103d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose//===----------------------------------------------------------------------===//
104d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose
105d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rosestd::pair<const GRState*, const GRState*>
106d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy RoseCStringChecker::AssumeZero(CheckerContext &C, const GRState *state, SVal V,
107d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose                           QualType Ty) {
108d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  DefinedSVal *Val = dyn_cast<DefinedSVal>(&V);
109d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  if (!Val)
110d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose    return std::pair<const GRState*, const GRState *>(state, state);
111a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose
112a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose  ValueManager &ValMgr = C.getValueManager();
113a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose  SValuator &SV = ValMgr.getSValuator();
114a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose
115d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  DefinedOrUnknownSVal Zero = ValMgr.makeZeroVal(Ty);
116d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  DefinedOrUnknownSVal ValIsZero = SV.EvalEQ(state, *Val, Zero);
117d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose
118d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  return state->Assume(ValIsZero);
119d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose}
120d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose
121d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Roseconst GRState *CStringChecker::CheckNonNull(CheckerContext &C,
122d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose                                            const GRState *state,
123d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose                                            const Expr *S, SVal l) {
124d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  // If a previous check has failed, propagate the failure.
125d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  if (!state)
126d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose    return NULL;
127a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose
128d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  const GRState *stateNull, *stateNonNull;
129d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  llvm::tie(stateNull, stateNonNull) = AssumeZero(C, state, l, S->getType());
130a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose
131d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  if (stateNull && !stateNonNull) {
132d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose    ExplodedNode *N = C.GenerateSink(stateNull);
133a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose    if (!N)
134a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose      return NULL;
135a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose
136d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose    if (!BT_Null)
137d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose      BT_Null = new BuiltinBug("API",
138a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose        "Null pointer argument in call to byte string function");
139a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose
140a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose    // Generate a report for this bug.
141d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose    BuiltinBug *BT = static_cast<BuiltinBug*>(BT_Null);
142a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose    EnhancedBugReport *report = new EnhancedBugReport(*BT,
143a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose                                                      BT->getDescription(), N);
144a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose
145a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose    report->addRange(S->getSourceRange());
146a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose    report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, S);
147a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose    C.EmitReport(report);
148a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose    return NULL;
149a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose  }
150a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose
151a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose  // From here on, assume that the value is non-null.
152d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  assert(stateNonNull);
153d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  return stateNonNull;
154a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose}
155a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose
156ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose// FIXME: This was originally copied from ArrayBoundChecker.cpp. Refactor?
157ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Roseconst GRState *CStringChecker::CheckLocation(CheckerContext &C,
158ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose                                             const GRState *state,
159d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose                                             const Expr *S, SVal l) {
160d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  // If a previous check has failed, propagate the failure.
161d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  if (!state)
162d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose    return NULL;
163d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose
164ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  // Check for out of bound array element access.
165ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  const MemRegion *R = l.getAsRegion();
166ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  if (!R)
167ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose    return state;
168ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose
169ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  const ElementRegion *ER = dyn_cast<ElementRegion>(R);
170ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  if (!ER)
171ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose    return state;
172ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose
173018220c343c103b7dfaa117a7a474c7a7fd6d068Zhongxing Xu  assert(ER->getValueType() == C.getASTContext().CharTy &&
174ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose    "CheckLocation should only be called with char* ElementRegions");
175ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose
176ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  // Get the size of the array.
177ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  const SubRegion *Super = cast<SubRegion>(ER->getSuperRegion());
178ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  ValueManager &ValMgr = C.getValueManager();
179ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  SVal Extent = ValMgr.convertToArrayIndex(Super->getExtent(ValMgr));
180ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  DefinedOrUnknownSVal Size = cast<DefinedOrUnknownSVal>(Extent);
181ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose
182ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  // Get the index of the accessed element.
183ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  DefinedOrUnknownSVal &Idx = cast<DefinedOrUnknownSVal>(ER->getIndex());
184ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose
185ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  const GRState *StInBound = state->AssumeInBound(Idx, Size, true);
186ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  const GRState *StOutBound = state->AssumeInBound(Idx, Size, false);
187ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  if (StOutBound && !StInBound) {
188ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose    ExplodedNode *N = C.GenerateSink(StOutBound);
189ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose    if (!N)
190ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose      return NULL;
191ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose
192ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose    if (!BT_Bounds)
193ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose      BT_Bounds = new BuiltinBug("Out-of-bound array access",
194ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose        "Byte string function accesses out-of-bound array element "
195ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose        "(buffer overflow)");
196ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose
197ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose    // FIXME: It would be nice to eventually make this diagnostic more clear,
198ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose    // e.g., by referencing the original declaration or by saying *why* this
199ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose    // reference is outside the range.
200ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose
201ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose    // Generate a report for this bug.
202ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose    BuiltinBug *BT = static_cast<BuiltinBug*>(BT_Bounds);
203ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose    RangedBugReport *report = new RangedBugReport(*BT, BT->getDescription(), N);
204ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose
205ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose    report->addRange(S->getSourceRange());
206ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose    C.EmitReport(report);
207ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose    return NULL;
208ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  }
209ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose
210ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  // Array bound check succeeded.  From this point forward the array bound
211ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  // should always succeed.
212ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  return StInBound;
213ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose}
214ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose
215ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Roseconst GRState *CStringChecker::CheckBufferAccess(CheckerContext &C,
216ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose                                                 const GRState *state,
217ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose                                                 const Expr *Size,
218ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose                                                 const Expr *FirstBuf,
219ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose                                                 const Expr *SecondBuf) {
220d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  // If a previous check has failed, propagate the failure.
221d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  if (!state)
222d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose    return NULL;
223d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose
224ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  ValueManager &VM = C.getValueManager();
225ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  SValuator &SV = VM.getSValuator();
226ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  ASTContext &Ctx = C.getASTContext();
227ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose
228ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  QualType SizeTy = Ctx.getSizeType();
229ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  QualType PtrTy = Ctx.getPointerType(Ctx.CharTy);
230ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose
231a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose  // Check that the first buffer is non-null.
232a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose  SVal BufVal = state->getSVal(FirstBuf);
233a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose  state = CheckNonNull(C, state, FirstBuf, BufVal);
234a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose  if (!state)
235a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose    return NULL;
236a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose
237d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  // Get the access length and make sure it is known.
238d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  SVal LengthVal = state->getSVal(Size);
239d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  NonLoc *Length = dyn_cast<NonLoc>(&LengthVal);
240d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  if (!Length)
241d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose    return state;
242d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose
243ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  // Compute the offset of the last element to be accessed: size-1.
244ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  NonLoc One = cast<NonLoc>(VM.makeIntVal(1, SizeTy));
245ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  NonLoc LastOffset = cast<NonLoc>(SV.EvalBinOpNN(state, BinaryOperator::Sub,
246ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose                                                  *Length, One, SizeTy));
247ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose
248a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose  // Check that the first buffer is sufficently long.
249b6a4026de13909c2b145166ae0b7d96cf1948f64Jordy Rose  SVal BufStart = SV.EvalCast(BufVal, PtrTy, FirstBuf->getType());
250b6a4026de13909c2b145166ae0b7d96cf1948f64Jordy Rose  if (Loc *BufLoc = dyn_cast<Loc>(&BufStart)) {
251b6a4026de13909c2b145166ae0b7d96cf1948f64Jordy Rose    SVal BufEnd = SV.EvalBinOpLN(state, BinaryOperator::Add, *BufLoc,
252b6a4026de13909c2b145166ae0b7d96cf1948f64Jordy Rose                                 LastOffset, PtrTy);
253b6a4026de13909c2b145166ae0b7d96cf1948f64Jordy Rose    state = CheckLocation(C, state, FirstBuf, BufEnd);
254ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose
255b6a4026de13909c2b145166ae0b7d96cf1948f64Jordy Rose    // If the buffer isn't large enough, abort.
256b6a4026de13909c2b145166ae0b7d96cf1948f64Jordy Rose    if (!state)
257b6a4026de13909c2b145166ae0b7d96cf1948f64Jordy Rose      return NULL;
258b6a4026de13909c2b145166ae0b7d96cf1948f64Jordy Rose  }
259ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose
260ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  // If there's a second buffer, check it as well.
261ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  if (SecondBuf) {
262ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose    BufVal = state->getSVal(SecondBuf);
263a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose    state = CheckNonNull(C, state, SecondBuf, BufVal);
264a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose    if (!state)
265a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose      return NULL;
266a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose
267b6a4026de13909c2b145166ae0b7d96cf1948f64Jordy Rose    BufStart = SV.EvalCast(BufVal, PtrTy, SecondBuf->getType());
268b6a4026de13909c2b145166ae0b7d96cf1948f64Jordy Rose    if (Loc *BufLoc = dyn_cast<Loc>(&BufStart)) {
269b6a4026de13909c2b145166ae0b7d96cf1948f64Jordy Rose      SVal BufEnd = SV.EvalBinOpLN(state, BinaryOperator::Add, *BufLoc,
270b6a4026de13909c2b145166ae0b7d96cf1948f64Jordy Rose                                   LastOffset, PtrTy);
271b6a4026de13909c2b145166ae0b7d96cf1948f64Jordy Rose      state = CheckLocation(C, state, SecondBuf, BufEnd);
272b6a4026de13909c2b145166ae0b7d96cf1948f64Jordy Rose    }
273ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  }
274ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose
275ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  // Large enough or not, return this state!
276ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  return state;
277ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose}
278ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose
279ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Roseconst GRState *CStringChecker::CheckOverlap(CheckerContext &C,
280ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose                                            const GRState *state,
281d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose                                            const Expr *Size,
282ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose                                            const Expr *First,
283d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose                                            const Expr *Second) {
284ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  // Do a simple check for overlap: if the two arguments are from the same
285ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  // buffer, see if the end of the first is greater than the start of the second
286ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  // or vice versa.
287ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose
288d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  // If a previous check has failed, propagate the failure.
289d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  if (!state)
290d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose    return NULL;
291d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose
292ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  ValueManager &VM = state->getStateManager().getValueManager();
293ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  SValuator &SV = VM.getSValuator();
294ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  ASTContext &Ctx = VM.getContext();
295ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  const GRState *stateTrue, *stateFalse;
296ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose
297ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  // Get the buffer values and make sure they're known locations.
298ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  SVal FirstVal = state->getSVal(First);
299ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  SVal SecondVal = state->getSVal(Second);
300ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose
301ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  Loc *FirstLoc = dyn_cast<Loc>(&FirstVal);
302ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  if (!FirstLoc)
303ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose    return state;
304ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose
305ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  Loc *SecondLoc = dyn_cast<Loc>(&SecondVal);
306ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  if (!SecondLoc)
307ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose    return state;
308ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose
309ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  // Are the two values the same?
310ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  DefinedOrUnknownSVal EqualTest = SV.EvalEQ(state, *FirstLoc, *SecondLoc);
311ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  llvm::tie(stateTrue, stateFalse) = state->Assume(EqualTest);
312ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose
313ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  if (stateTrue && !stateFalse) {
314ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose    // If the values are known to be equal, that's automatically an overlap.
315ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose    EmitOverlapBug(C, stateTrue, First, Second);
316ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose    return NULL;
317ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  }
318ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose
319ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  // Assume the two expressions are not equal.
320ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  assert(stateFalse);
321ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  state = stateFalse;
322ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose
323ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  // Which value comes first?
324ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  QualType CmpTy = Ctx.IntTy;
325ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  SVal Reverse = SV.EvalBinOpLL(state, BinaryOperator::GT,
326ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose                                *FirstLoc, *SecondLoc, CmpTy);
327ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  DefinedOrUnknownSVal *ReverseTest = dyn_cast<DefinedOrUnknownSVal>(&Reverse);
328ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  if (!ReverseTest)
329ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose    return state;
330ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose
331ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  llvm::tie(stateTrue, stateFalse) = state->Assume(*ReverseTest);
332ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose
333ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  if (stateTrue) {
334ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose    if (stateFalse) {
335ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose      // If we don't know which one comes first, we can't perform this test.
336ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose      return state;
337ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose    } else {
338ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose      // Switch the values so that FirstVal is before SecondVal.
339ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose      Loc *tmpLoc = FirstLoc;
340ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose      FirstLoc = SecondLoc;
341ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose      SecondLoc = tmpLoc;
342ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose
343ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose      // Switch the Exprs as well, so that they still correspond.
344ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose      const Expr *tmpExpr = First;
345ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose      First = Second;
346ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose      Second = tmpExpr;
347ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose    }
348ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  }
349ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose
350ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  // Get the length, and make sure it too is known.
351ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  SVal LengthVal = state->getSVal(Size);
352ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  NonLoc *Length = dyn_cast<NonLoc>(&LengthVal);
353ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  if (!Length)
354ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose    return state;
355ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose
356ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  // Convert the first buffer's start address to char*.
357ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  // Bail out if the cast fails.
358ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  QualType CharPtrTy = Ctx.getPointerType(Ctx.CharTy);
359ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  SVal FirstStart = SV.EvalCast(*FirstLoc, CharPtrTy, First->getType());
360ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  Loc *FirstStartLoc = dyn_cast<Loc>(&FirstStart);
361ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  if (!FirstStartLoc)
362ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose    return state;
363ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose
364ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  // Compute the end of the first buffer. Bail out if THAT fails.
365ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  SVal FirstEnd = SV.EvalBinOpLN(state, BinaryOperator::Add,
366ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose                                 *FirstStartLoc, *Length, CharPtrTy);
367ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  Loc *FirstEndLoc = dyn_cast<Loc>(&FirstEnd);
368ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  if (!FirstEndLoc)
369ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose    return state;
370ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose
371ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  // Is the end of the first buffer past the start of the second buffer?
372ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  SVal Overlap = SV.EvalBinOpLL(state, BinaryOperator::GT,
373ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose                                *FirstEndLoc, *SecondLoc, CmpTy);
374ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  DefinedOrUnknownSVal *OverlapTest = dyn_cast<DefinedOrUnknownSVal>(&Overlap);
375ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  if (!OverlapTest)
376ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose    return state;
377ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose
378ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  llvm::tie(stateTrue, stateFalse) = state->Assume(*OverlapTest);
379ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose
380ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  if (stateTrue && !stateFalse) {
381ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose    // Overlap!
382ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose    EmitOverlapBug(C, stateTrue, First, Second);
383ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose    return NULL;
384ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  }
385ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose
386ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  // Assume the two expressions don't overlap.
387ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  assert(stateFalse);
388ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  return stateFalse;
389ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose}
390ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose
391ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rosevoid CStringChecker::EmitOverlapBug(CheckerContext &C, const GRState *state,
392ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose                                    const Stmt *First, const Stmt *Second) {
393ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  ExplodedNode *N = C.GenerateSink(state);
394ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  if (!N)
395ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose    return;
396ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose
397ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  if (!BT_Overlap)
398ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose    BT_Overlap = new BugType("Unix API", "Improper arguments");
399ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose
400ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  // Generate a report for this bug.
401ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  RangedBugReport *report =
402ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose    new RangedBugReport(*BT_Overlap,
403ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose      "Arguments must not be overlapping buffers", N);
404ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  report->addRange(First->getSourceRange());
405ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  report->addRange(Second->getSourceRange());
406ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose
407ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  C.EmitReport(report);
408ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose}
409ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose
410a5261549754fab80e30e893d8fa706bfb31e430aJordy RoseSVal CStringChecker::GetCStringLengthForRegion(CheckerContext &C,
411a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose                                               const GRState *&state,
412a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose                                               const Expr *Ex,
413a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose                                               const MemRegion *MR) {
414a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  // If there's a recorded length, go ahead and return it.
415a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  const SVal *Recorded = state->get<CStringLength>(MR);
416a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  if (Recorded)
417a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    return *Recorded;
418a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose
419a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  // Otherwise, get a new symbol and update the state.
420a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  unsigned Count = C.getNodeBuilder().getCurrentBlockCount();
421a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  ValueManager &ValMgr = C.getValueManager();
422a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  QualType SizeTy = ValMgr.getContext().getSizeType();
423a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  SVal Strlen = ValMgr.getMetadataSymbolVal(getTag(), MR, Ex, SizeTy, Count);
424a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose
425a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  state = state->set<CStringLength>(MR, Strlen);
426a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  return Strlen;
427a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose}
428a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose
429a5261549754fab80e30e893d8fa706bfb31e430aJordy RoseSVal CStringChecker::GetCStringLength(CheckerContext &C, const GRState *&state,
43019c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose                                      const Expr *Ex, SVal Buf) {
43119c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose  const MemRegion *MR = Buf.getAsRegion();
43219c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose  if (!MR) {
43319c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose    // If we can't get a region, see if it's something we /know/ isn't a
43419c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose    // C string. In the context of locations, the only time we can issue such
43519c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose    // a warning is for labels.
43619c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose    if (loc::GotoLabel *Label = dyn_cast<loc::GotoLabel>(&Buf)) {
437a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose      if (ExplodedNode *N = C.GenerateNode(state)) {
43819c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose        if (!BT_NotCString)
43919c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose          BT_NotCString = new BuiltinBug("API",
44019c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose            "Argument is not a null-terminated string.");
44119c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose
44219c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose        llvm::SmallString<120> buf;
44319c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose        llvm::raw_svector_ostream os(buf);
44419c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose        os << "Argument to byte string function is the address of the label '"
44519c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose           << Label->getLabel()->getID()->getName()
44619c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose           << "', which is not a null-terminated string";
44719c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose
44819c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose        // Generate a report for this bug.
44919c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose        EnhancedBugReport *report = new EnhancedBugReport(*BT_NotCString,
45019c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose                                                          os.str(), N);
45119c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose
45219c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose        report->addRange(Ex->getSourceRange());
45319c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose        C.EmitReport(report);
45419c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose      }
45519c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose
45619c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose      return UndefinedVal();
45719c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose    }
45819c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose
459a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    // If it's not a region and not a label, give up.
460a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    return UnknownVal();
461a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  }
46219c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose
463a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  // If we have a region, strip casts from it and see if we can figure out
464a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  // its length. For anything we can't figure out, just return UnknownVal.
465a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  MR = MR->StripCasts();
466a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose
467a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  switch (MR->getKind()) {
468a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  case MemRegion::StringRegionKind: {
469a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    // Modifying the contents of string regions is undefined [C99 6.4.5p6],
470a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    // so we can assume that the byte length is the correct C string length.
471a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    ValueManager &ValMgr = C.getValueManager();
472a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    QualType SizeTy = ValMgr.getContext().getSizeType();
473a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    const StringLiteral *Str = cast<StringRegion>(MR)->getStringLiteral();
474a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    return ValMgr.makeIntVal(Str->getByteLength(), SizeTy);
475a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  }
476a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  case MemRegion::SymbolicRegionKind:
477a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  case MemRegion::AllocaRegionKind:
478a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  case MemRegion::VarRegionKind:
479a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  case MemRegion::FieldRegionKind:
480a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  case MemRegion::ObjCIvarRegionKind:
481a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    return GetCStringLengthForRegion(C, state, Ex, MR);
482a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  case MemRegion::CompoundLiteralRegionKind:
483a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    // FIXME: Can we track this? Is it necessary?
484a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    return UnknownVal();
485a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  case MemRegion::ElementRegionKind:
486a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    // FIXME: How can we handle this? It's not good enough to subtract the
487a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    // offset from the base string length; consider "123\x00567" and &a[5].
488a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    return UnknownVal();
489a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  default:
490a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    // Other regions (mostly non-data) can't have a reliable C string length.
491a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    // In this case, an error is emitted and UndefinedVal is returned.
492a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    // The caller should always be prepared to handle this case.
493a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    if (ExplodedNode *N = C.GenerateNode(state)) {
494a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose      if (!BT_NotCString)
495a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose        BT_NotCString = new BuiltinBug("API",
496a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose          "Argument is not a null-terminated string.");
497a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose
498a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose      llvm::SmallString<120> buf;
499a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose      llvm::raw_svector_ostream os(buf);
500a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose
501a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose      os << "Argument to byte string function is ";
502a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose
503a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose      if (SummarizeRegion(os, C.getASTContext(), MR))
504a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose        os << ", which is not a null-terminated string";
505a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose      else
506a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose        os << "not a null-terminated string";
507a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose
508a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose      // Generate a report for this bug.
509a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose      EnhancedBugReport *report = new EnhancedBugReport(*BT_NotCString,
510a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose                                                        os.str(), N);
511a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose
512a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose      report->addRange(Ex->getSourceRange());
513a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose      C.EmitReport(report);
51419c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose    }
51519c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose
516a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    return UndefinedVal();
51719c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose  }
51819c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose}
51919c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose
52019c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rosebool CStringChecker::SummarizeRegion(llvm::raw_ostream& os, ASTContext& Ctx,
52119c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose                                     const MemRegion *MR) {
52219c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose  const TypedRegion *TR = dyn_cast<TypedRegion>(MR);
52319c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose  if (!TR)
52419c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose    return false;
52519c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose
52619c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose  switch (TR->getKind()) {
52719c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose  case MemRegion::FunctionTextRegionKind: {
52819c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose    const FunctionDecl *FD = cast<FunctionTextRegion>(TR)->getDecl();
52919c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose    if (FD)
53019c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose      os << "the address of the function '" << FD << "'";
53119c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose    else
53219c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose      os << "the address of a function";
53319c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose    return true;
53419c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose  }
53519c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose  case MemRegion::BlockTextRegionKind:
53619c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose    os << "block text";
53719c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose    return true;
53819c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose  case MemRegion::BlockDataRegionKind:
53919c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose    os << "a block";
54019c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose    return true;
54119c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose  case MemRegion::CXXThisRegionKind:
54219c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose  case MemRegion::CXXObjectRegionKind:
543018220c343c103b7dfaa117a7a474c7a7fd6d068Zhongxing Xu    os << "a C++ object of type " << TR->getValueType().getAsString();
54419c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose    return true;
54519c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose  case MemRegion::VarRegionKind:
546018220c343c103b7dfaa117a7a474c7a7fd6d068Zhongxing Xu    os << "a variable of type" << TR->getValueType().getAsString();
54719c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose    return true;
54819c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose  case MemRegion::FieldRegionKind:
549018220c343c103b7dfaa117a7a474c7a7fd6d068Zhongxing Xu    os << "a field of type " << TR->getValueType().getAsString();
55019c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose    return true;
55119c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose  case MemRegion::ObjCIvarRegionKind:
552018220c343c103b7dfaa117a7a474c7a7fd6d068Zhongxing Xu    os << "an instance variable of type " << TR->getValueType().getAsString();
55319c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose    return true;
55419c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose  default:
55519c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose    return false;
55619c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose  }
55719c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose}
55819c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose
559d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose//===----------------------------------------------------------------------===//
560d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose// Evaluation of individual function calls.
561d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose//===----------------------------------------------------------------------===//
562ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose
563d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rosevoid CStringChecker::EvalCopyCommon(CheckerContext &C, const GRState *state,
564d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose                                    const Expr *Size, const Expr *Dest,
565d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose                                    const Expr *Source, bool Restricted) {
566d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  // See if the size argument is zero.
567d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  SVal SizeVal = state->getSVal(Size);
568d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  QualType SizeTy = Size->getType();
569d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose
570d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  const GRState *StZeroSize, *StNonZeroSize;
571d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  llvm::tie(StZeroSize, StNonZeroSize) = AssumeZero(C, state, SizeVal, SizeTy);
572d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose
573d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  // If the size is zero, there won't be any actual memory access.
574d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  if (StZeroSize)
575d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose    C.addTransition(StZeroSize);
576d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose
577d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  // If the size can be nonzero, we have to check the other arguments.
578d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  if (StNonZeroSize) {
579d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose    state = StNonZeroSize;
580d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose    state = CheckBufferAccess(C, state, Size, Dest, Source);
581d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose    if (Restricted)
582d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose      state = CheckOverlap(C, state, Size, Dest, Source);
583d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose    if (state)
584d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose      C.addTransition(state);
585d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  }
586ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose}
587ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose
588ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose
589d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rosevoid CStringChecker::EvalMemcpy(CheckerContext &C, const CallExpr *CE) {
590d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  // void *memcpy(void *restrict dst, const void *restrict src, size_t n);
591d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  // The return value is the address of the destination buffer.
592d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  const Expr *Dest = CE->getArg(0);
593ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  const GRState *state = C.getState();
594d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  state = state->BindExpr(CE, state->getSVal(Dest));
595d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  EvalCopyCommon(C, state, CE->getArg(2), Dest, CE->getArg(1), true);
596d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose}
597ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose
598d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rosevoid CStringChecker::EvalMemmove(CheckerContext &C, const CallExpr *CE) {
599d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  // void *memmove(void *dst, const void *src, size_t n);
600ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  // The return value is the address of the destination buffer.
601d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  const Expr *Dest = CE->getArg(0);
602d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  const GRState *state = C.getState();
603d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  state = state->BindExpr(CE, state->getSVal(Dest));
604d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  EvalCopyCommon(C, state, CE->getArg(2), Dest, CE->getArg(1));
605ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose}
606ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose
607d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rosevoid CStringChecker::EvalBcopy(CheckerContext &C, const CallExpr *CE) {
608d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  // void bcopy(const void *src, void *dst, size_t n);
609d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  EvalCopyCommon(C, C.getState(), CE->getArg(2), CE->getArg(1), CE->getArg(0));
610d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose}
611d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose
612d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rosevoid CStringChecker::EvalMemcmp(CheckerContext &C, const CallExpr *CE) {
613bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose  // int memcmp(const void *s1, const void *s2, size_t n);
614bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose  const Expr *Left = CE->getArg(0);
615bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose  const Expr *Right = CE->getArg(1);
616bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose  const Expr *Size = CE->getArg(2);
617bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose
618bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose  const GRState *state = C.getState();
619bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose  ValueManager &ValMgr = C.getValueManager();
620bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose  SValuator &SV = ValMgr.getSValuator();
621bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose
622d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  // See if the size argument is zero.
623d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  SVal SizeVal = state->getSVal(Size);
624d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  QualType SizeTy = Size->getType();
625bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose
626d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  const GRState *StZeroSize, *StNonZeroSize;
627d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  llvm::tie(StZeroSize, StNonZeroSize) = AssumeZero(C, state, SizeVal, SizeTy);
628bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose
629d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  // If the size can be zero, the result will be 0 in that case, and we don't
630d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  // have to check either of the buffers.
631d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  if (StZeroSize) {
632d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose    state = StZeroSize;
633d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose    state = state->BindExpr(CE, ValMgr.makeZeroVal(CE->getType()));
634d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose    C.addTransition(state);
635bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose  }
636bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose
637d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  // If the size can be nonzero, we have to check the other arguments.
638d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  if (StNonZeroSize) {
639d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose    state = StNonZeroSize;
640d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose
641d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose    // If we know the two buffers are the same, we know the result is 0.
642d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose    // First, get the two buffers' addresses. Another checker will have already
643d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose    // made sure they're not undefined.
644d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose    DefinedOrUnknownSVal LV = cast<DefinedOrUnknownSVal>(state->getSVal(Left));
645d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose    DefinedOrUnknownSVal RV = cast<DefinedOrUnknownSVal>(state->getSVal(Right));
646d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose
647d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose    // See if they are the same.
648d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose    DefinedOrUnknownSVal SameBuf = SV.EvalEQ(state, LV, RV);
649d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose    const GRState *StSameBuf, *StNotSameBuf;
650d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose    llvm::tie(StSameBuf, StNotSameBuf) = state->Assume(SameBuf);
651d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose
652d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose    // If the two arguments might be the same buffer, we know the result is zero,
653d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose    // and we only need to check one size.
654d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose    if (StSameBuf) {
655d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose      state = StSameBuf;
656d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose      state = CheckBufferAccess(C, state, Size, Left);
657d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose      if (state) {
658d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose        state = StSameBuf->BindExpr(CE, ValMgr.makeZeroVal(CE->getType()));
659d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose        C.addTransition(state);
660d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose      }
661d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose    }
662bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose
663d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose    // If the two arguments might be different buffers, we have to check the
664d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose    // size of both of them.
665d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose    if (StNotSameBuf) {
666d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose      state = StNotSameBuf;
667d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose      state = CheckBufferAccess(C, state, Size, Left, Right);
668d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose      if (state) {
669d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose        // The return value is the comparison result, which we don't know.
670d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose        unsigned Count = C.getNodeBuilder().getCurrentBlockCount();
671d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose        SVal CmpV = ValMgr.getConjuredSymbolVal(NULL, CE, CE->getType(), Count);
672d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose        state = state->BindExpr(CE, CmpV);
673d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose        C.addTransition(state);
674d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose      }
675d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose    }
676d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  }
677bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose}
678bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose
67919c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rosevoid CStringChecker::EvalStrlen(CheckerContext &C, const CallExpr *CE) {
68019c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose  // size_t strlen(const char *s);
68119c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose  const GRState *state = C.getState();
68219c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose  const Expr *Arg = CE->getArg(0);
68319c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose  SVal ArgVal = state->getSVal(Arg);
68419c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose
68519c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose  // Check that the argument is non-null.
68619c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose  state = CheckNonNull(C, state, Arg, ArgVal);
68719c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose
68819c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose  if (state) {
68919c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose    SVal StrLen = GetCStringLength(C, state, Arg, ArgVal);
690a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose
691a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    // If the argument isn't a valid C string, there's no valid state to
692a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    // transition to.
693a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    if (StrLen.isUndef())
694a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose      return;
695a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose
696a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    // If GetCStringLength couldn't figure out the length, conjure a return
697a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    // value, so it can be used in constraints, at least.
698a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    if (StrLen.isUnknown()) {
699a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose      ValueManager &ValMgr = C.getValueManager();
700a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose      unsigned Count = C.getNodeBuilder().getCurrentBlockCount();
701a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose      StrLen = ValMgr.getConjuredSymbolVal(NULL, CE, CE->getType(), Count);
70219c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose    }
703a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose
704a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    // Bind the return value.
705a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    state = state->BindExpr(CE, StrLen);
706a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    C.addTransition(state);
70719c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose  }
70819c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose}
70919c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose
710d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose//===----------------------------------------------------------------------===//
711a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose// The driver method, and other Checker callbacks.
712d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose//===----------------------------------------------------------------------===//
713ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose
714ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rosebool CStringChecker::EvalCallExpr(CheckerContext &C, const CallExpr *CE) {
715ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  // Get the callee.  All the functions we care about are C functions
716ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  // with simple identifiers.
717ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  const GRState *state = C.getState();
718ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  const Expr *Callee = CE->getCallee();
719ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  const FunctionDecl *FD = state->getSVal(Callee).getAsFunctionDecl();
720ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose
721ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  if (!FD)
722ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose    return false;
723ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose
724ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  // Get the name of the callee. If it's a builtin, strip off the prefix.
725ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  llvm::StringRef Name = FD->getName();
726ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  if (Name.startswith("__builtin_"))
727ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose    Name = Name.substr(10);
728ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose
729ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  FnCheck EvalFunction = llvm::StringSwitch<FnCheck>(Name)
730a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose    .Cases("memcpy", "__memcpy_chk", &CStringChecker::EvalMemcpy)
731bc56d1f6e2288aea9546b2380c71288939d688caJordy Rose    .Cases("memcmp", "bcmp", &CStringChecker::EvalMemcmp)
732a6b808c6ba57723b997da2ef7a4a8cf48fbc2ba8Jordy Rose    .Cases("memmove", "__memmove_chk", &CStringChecker::EvalMemmove)
73319c5dd120e42b1ba0642309a185c70f4a41aadbdJordy Rose    .Case("strlen", &CStringChecker::EvalStrlen)
734ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose    .Case("bcopy", &CStringChecker::EvalBcopy)
735ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose    .Default(NULL);
736ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose
737d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  // If the callee isn't a string function, let another checker handle it.
738ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  if (!EvalFunction)
739ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose    return false;
740ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose
741d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  // Check and evaluate the call.
742d325ffb9cbd26b6a3f219d115191d9a00b6dea8cJordy Rose  (this->*EvalFunction)(C, CE);
743ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose  return true;
744ccbf7eebc8425429e8fd9f9124770f86a74864ebJordy Rose}
745a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose
746a5261549754fab80e30e893d8fa706bfb31e430aJordy Rosevoid CStringChecker::PreVisitDeclStmt(CheckerContext &C, const DeclStmt *DS) {
747a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  // Record string length for char a[] = "abc";
748a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  const GRState *state = C.getState();
749a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose
750a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  for (DeclStmt::const_decl_iterator I = DS->decl_begin(), E = DS->decl_end();
751a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose       I != E; ++I) {
752a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    const VarDecl *D = dyn_cast<VarDecl>(*I);
753a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    if (!D)
754a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose      continue;
755a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose
756a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    // FIXME: Handle array fields of structs.
757a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    if (!D->getType()->isArrayType())
758a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose      continue;
759a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose
760a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    const Expr *Init = D->getInit();
761a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    if (!Init)
762a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose      continue;
763a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    if (!isa<StringLiteral>(Init))
764a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose      continue;
765a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose
766a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    Loc VarLoc = state->getLValue(D, C.getPredecessor()->getLocationContext());
767a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    const MemRegion *MR = VarLoc.getAsRegion();
768a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    if (!MR)
769a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose      continue;
770a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose
771a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    SVal StrVal = state->getSVal(Init);
772a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    assert(StrVal.isValid() && "Initializer string is unknown or undefined");
773a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    DefinedOrUnknownSVal StrLen
774a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose      = cast<DefinedOrUnknownSVal>(GetCStringLength(C, state, Init, StrVal));
775a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose
776a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    state = state->set<CStringLength>(MR, StrLen);
777a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  }
778a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose
779a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  C.addTransition(state);
780a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose}
781a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose
782a5261549754fab80e30e893d8fa706bfb31e430aJordy Rosebool CStringChecker::WantsRegionChangeUpdate(const GRState *state) {
783a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  CStringLength::EntryMap Entries = state->get<CStringLength>();
784a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  return !Entries.isEmpty();
785a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose}
786a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose
787a5261549754fab80e30e893d8fa706bfb31e430aJordy Roseconst GRState *CStringChecker::EvalRegionChanges(const GRState *state,
788a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose                                                 const MemRegion * const *Begin,
789a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose                                                 const MemRegion * const *End,
790a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose                                                 bool *) {
791a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  CStringLength::EntryMap Entries = state->get<CStringLength>();
792a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  if (Entries.isEmpty())
793a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    return state;
794a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose
795a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  llvm::SmallPtrSet<const MemRegion *, 8> Invalidated;
796a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  llvm::SmallPtrSet<const MemRegion *, 32> SuperRegions;
797a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose
798a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  // First build sets for the changed regions and their super-regions.
799a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  for ( ; Begin != End; ++Begin) {
800a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    const MemRegion *MR = *Begin;
801a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    Invalidated.insert(MR);
802a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose
803a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    SuperRegions.insert(MR);
804a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    while (const SubRegion *SR = dyn_cast<SubRegion>(MR)) {
805a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose      MR = SR->getSuperRegion();
806a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose      SuperRegions.insert(MR);
807a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    }
808a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  }
809a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose
810a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  CStringLength::EntryMap::Factory &F = state->get_context<CStringLength>();
811a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose
812a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  // Then loop over the entries in the current state.
813a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  for (CStringLength::EntryMap::iterator I = Entries.begin(),
814a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose       E = Entries.end(); I != E; ++I) {
815a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    const MemRegion *MR = I.getKey();
816a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose
817a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    // Is this entry for a super-region of a changed region?
818a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    if (SuperRegions.count(MR)) {
819a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose      Entries = F.Remove(Entries, MR);
820a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose      continue;
821a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    }
822a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose
823a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    // Is this entry for a sub-region of a changed region?
824a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    const MemRegion *Super = MR;
825a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    while (const SubRegion *SR = dyn_cast<SubRegion>(Super)) {
826a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose      Super = SR->getSuperRegion();
827a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose      if (Invalidated.count(Super)) {
828a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose        Entries = F.Remove(Entries, MR);
829a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose        break;
830a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose      }
831a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    }
832a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  }
833a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose
834a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  return state->set<CStringLength>(Entries);
835a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose}
836a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose
837a5261549754fab80e30e893d8fa706bfb31e430aJordy Rosevoid CStringChecker::MarkLiveSymbols(const GRState *state, SymbolReaper &SR) {
838a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  // Mark all symbols in our string length map as valid.
839a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  CStringLength::EntryMap Entries = state->get<CStringLength>();
840a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose
841a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  for (CStringLength::EntryMap::iterator I = Entries.begin(), E = Entries.end();
842a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose       I != E; ++I) {
843a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    SVal Len = I.getData();
844a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    if (SymbolRef Sym = Len.getAsSymbol())
845a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose      SR.markInUse(Sym);
846a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  }
847a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose}
848a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose
849a5261549754fab80e30e893d8fa706bfb31e430aJordy Rosevoid CStringChecker::EvalDeadSymbols(CheckerContext &C, SymbolReaper &SR) {
850a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  if (!SR.hasDeadSymbols())
851a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    return;
852a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose
853a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  const GRState *state = C.getState();
854a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  CStringLength::EntryMap Entries = state->get<CStringLength>();
855a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  if (Entries.isEmpty())
856a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    return;
857a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose
858a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  CStringLength::EntryMap::Factory &F = state->get_context<CStringLength>();
859a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  for (CStringLength::EntryMap::iterator I = Entries.begin(), E = Entries.end();
860a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose       I != E; ++I) {
861a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    SVal Len = I.getData();
862a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    if (SymbolRef Sym = Len.getAsSymbol()) {
863a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose      if (SR.isDead(Sym))
864a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose        Entries = F.Remove(Entries, I.getKey());
865a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose    }
866a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  }
867a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose
868a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  state = state->set<CStringLength>(Entries);
869a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose  C.GenerateNode(state);
870a5261549754fab80e30e893d8fa706bfb31e430aJordy Rose}
871