1226633Sdim//= CStringChecker.cpp - Checks calls to C string functions --------*- C++ -*-//
2218887Sdim//
3218887Sdim//                     The LLVM Compiler Infrastructure
4218887Sdim//
5218887Sdim// This file is distributed under the University of Illinois Open Source
6218887Sdim// License. See LICENSE.TXT for details.
7218887Sdim//
8218887Sdim//===----------------------------------------------------------------------===//
9218887Sdim//
10218887Sdim// This defines CStringChecker, which is an assortment of checks on calls
11218887Sdim// to functions in <string.h>.
12218887Sdim//
13218887Sdim//===----------------------------------------------------------------------===//
14218887Sdim
15218887Sdim#include "ClangSACheckers.h"
16234353Sdim#include "InterCheckerAPI.h"
17249423Sdim#include "clang/Basic/CharInfo.h"
18249423Sdim#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
19221345Sdim#include "clang/StaticAnalyzer/Core/Checker.h"
20218887Sdim#include "clang/StaticAnalyzer/Core/CheckerManager.h"
21219077Sdim#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
22226633Sdim#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
23249423Sdim#include "llvm/ADT/STLExtras.h"
24234353Sdim#include "llvm/ADT/SmallString.h"
25218887Sdim#include "llvm/ADT/StringSwitch.h"
26249423Sdim#include "llvm/Support/raw_ostream.h"
27218887Sdim
28218887Sdimusing namespace clang;
29218887Sdimusing namespace ento;
30218887Sdim
31218887Sdimnamespace {
32221345Sdimclass CStringChecker : public Checker< eval::Call,
33219077Sdim                                         check::PreStmt<DeclStmt>,
34219077Sdim                                         check::LiveSymbols,
35219077Sdim                                         check::DeadSymbols,
36219077Sdim                                         check::RegionChanges
37219077Sdim                                         > {
38234353Sdim  mutable OwningPtr<BugType> BT_Null,
39234353Sdim                             BT_Bounds,
40234353Sdim                             BT_Overlap,
41234353Sdim                             BT_NotCString,
42234353Sdim                             BT_AdditionOverflow;
43234353Sdim
44224145Sdim  mutable const char *CurrentFunctionDescription;
45224145Sdim
46218887Sdimpublic:
47234353Sdim  /// The filter is used to filter out the diagnostics which are not enabled by
48234353Sdim  /// the user.
49234353Sdim  struct CStringChecksFilter {
50234353Sdim    DefaultBool CheckCStringNullArg;
51234353Sdim    DefaultBool CheckCStringOutOfBounds;
52234353Sdim    DefaultBool CheckCStringBufferOverlap;
53234353Sdim    DefaultBool CheckCStringNotNullTerm;
54234353Sdim  };
55234353Sdim
56234353Sdim  CStringChecksFilter Filter;
57234353Sdim
58218887Sdim  static void *getTag() { static int tag; return &tag; }
59218887Sdim
60219077Sdim  bool evalCall(const CallExpr *CE, CheckerContext &C) const;
61219077Sdim  void checkPreStmt(const DeclStmt *DS, CheckerContext &C) const;
62234353Sdim  void checkLiveSymbols(ProgramStateRef state, SymbolReaper &SR) const;
63219077Sdim  void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const;
64234353Sdim  bool wantsRegionChangeUpdate(ProgramStateRef state) const;
65218887Sdim
66234353Sdim  ProgramStateRef
67234353Sdim    checkRegionChanges(ProgramStateRef state,
68249423Sdim                       const InvalidatedSymbols *,
69226633Sdim                       ArrayRef<const MemRegion *> ExplicitRegions,
70234353Sdim                       ArrayRef<const MemRegion *> Regions,
71239462Sdim                       const CallEvent *Call) const;
72218887Sdim
73219077Sdim  typedef void (CStringChecker::*FnCheck)(CheckerContext &,
74219077Sdim                                          const CallExpr *) const;
75218887Sdim
76219077Sdim  void evalMemcpy(CheckerContext &C, const CallExpr *CE) const;
77221345Sdim  void evalMempcpy(CheckerContext &C, const CallExpr *CE) const;
78219077Sdim  void evalMemmove(CheckerContext &C, const CallExpr *CE) const;
79219077Sdim  void evalBcopy(CheckerContext &C, const CallExpr *CE) const;
80221345Sdim  void evalCopyCommon(CheckerContext &C, const CallExpr *CE,
81234353Sdim                      ProgramStateRef state,
82226633Sdim                      const Expr *Size,
83226633Sdim                      const Expr *Source,
84226633Sdim                      const Expr *Dest,
85221345Sdim                      bool Restricted = false,
86221345Sdim                      bool IsMempcpy = false) const;
87218887Sdim
88219077Sdim  void evalMemcmp(CheckerContext &C, const CallExpr *CE) const;
89218887Sdim
90219077Sdim  void evalstrLength(CheckerContext &C, const CallExpr *CE) const;
91219077Sdim  void evalstrnLength(CheckerContext &C, const CallExpr *CE) const;
92226633Sdim  void evalstrLengthCommon(CheckerContext &C,
93226633Sdim                           const CallExpr *CE,
94219077Sdim                           bool IsStrnlen = false) const;
95218887Sdim
96219077Sdim  void evalStrcpy(CheckerContext &C, const CallExpr *CE) const;
97219077Sdim  void evalStrncpy(CheckerContext &C, const CallExpr *CE) const;
98219077Sdim  void evalStpcpy(CheckerContext &C, const CallExpr *CE) const;
99226633Sdim  void evalStrcpyCommon(CheckerContext &C,
100226633Sdim                        const CallExpr *CE,
101226633Sdim                        bool returnEnd,
102226633Sdim                        bool isBounded,
103226633Sdim                        bool isAppending) const;
104218887Sdim
105221345Sdim  void evalStrcat(CheckerContext &C, const CallExpr *CE) const;
106221345Sdim  void evalStrncat(CheckerContext &C, const CallExpr *CE) const;
107221345Sdim
108221345Sdim  void evalStrcmp(CheckerContext &C, const CallExpr *CE) const;
109221345Sdim  void evalStrncmp(CheckerContext &C, const CallExpr *CE) const;
110221345Sdim  void evalStrcasecmp(CheckerContext &C, const CallExpr *CE) const;
111223017Sdim  void evalStrncasecmp(CheckerContext &C, const CallExpr *CE) const;
112226633Sdim  void evalStrcmpCommon(CheckerContext &C,
113226633Sdim                        const CallExpr *CE,
114226633Sdim                        bool isBounded = false,
115226633Sdim                        bool ignoreCase = false) const;
116221345Sdim
117251662Sdim  void evalStrsep(CheckerContext &C, const CallExpr *CE) const;
118251662Sdim
119218887Sdim  // Utility methods
120234353Sdim  std::pair<ProgramStateRef , ProgramStateRef >
121219077Sdim  static assumeZero(CheckerContext &C,
122234353Sdim                    ProgramStateRef state, SVal V, QualType Ty);
123218887Sdim
124234353Sdim  static ProgramStateRef setCStringLength(ProgramStateRef state,
125226633Sdim                                              const MemRegion *MR,
126226633Sdim                                              SVal strLength);
127219077Sdim  static SVal getCStringLengthForRegion(CheckerContext &C,
128234353Sdim                                        ProgramStateRef &state,
129226633Sdim                                        const Expr *Ex,
130226633Sdim                                        const MemRegion *MR,
131224145Sdim                                        bool hypothetical);
132226633Sdim  SVal getCStringLength(CheckerContext &C,
133234353Sdim                        ProgramStateRef &state,
134226633Sdim                        const Expr *Ex,
135226633Sdim                        SVal Buf,
136224145Sdim                        bool hypothetical = false) const;
137218887Sdim
138221345Sdim  const StringLiteral *getCStringLiteral(CheckerContext &C,
139234353Sdim                                         ProgramStateRef &state,
140221345Sdim                                         const Expr *expr,
141221345Sdim                                         SVal val) const;
142221345Sdim
143234353Sdim  static ProgramStateRef InvalidateBuffer(CheckerContext &C,
144263508Sdim                                          ProgramStateRef state,
145263508Sdim                                          const Expr *Ex, SVal V,
146263508Sdim                                          bool IsSourceBuffer);
147218887Sdim
148226633Sdim  static bool SummarizeRegion(raw_ostream &os, ASTContext &Ctx,
149219077Sdim                              const MemRegion *MR);
150218887Sdim
151218887Sdim  // Re-usable checks
152234353Sdim  ProgramStateRef checkNonNull(CheckerContext &C,
153234353Sdim                                   ProgramStateRef state,
154226633Sdim                                   const Expr *S,
155226633Sdim                                   SVal l) const;
156234353Sdim  ProgramStateRef CheckLocation(CheckerContext &C,
157234353Sdim                                    ProgramStateRef state,
158226633Sdim                                    const Expr *S,
159226633Sdim                                    SVal l,
160226633Sdim                                    const char *message = NULL) const;
161234353Sdim  ProgramStateRef CheckBufferAccess(CheckerContext &C,
162234353Sdim                                        ProgramStateRef state,
163226633Sdim                                        const Expr *Size,
164226633Sdim                                        const Expr *FirstBuf,
165226633Sdim                                        const Expr *SecondBuf,
166226633Sdim                                        const char *firstMessage = NULL,
167226633Sdim                                        const char *secondMessage = NULL,
168226633Sdim                                        bool WarnAboutSize = false) const;
169226633Sdim
170234353Sdim  ProgramStateRef CheckBufferAccess(CheckerContext &C,
171234353Sdim                                        ProgramStateRef state,
172226633Sdim                                        const Expr *Size,
173226633Sdim                                        const Expr *Buf,
174226633Sdim                                        const char *message = NULL,
175226633Sdim                                        bool WarnAboutSize = false) const {
176224145Sdim    // This is a convenience override.
177224145Sdim    return CheckBufferAccess(C, state, Size, Buf, NULL, message, NULL,
178224145Sdim                             WarnAboutSize);
179224145Sdim  }
180234353Sdim  ProgramStateRef CheckOverlap(CheckerContext &C,
181234353Sdim                                   ProgramStateRef state,
182226633Sdim                                   const Expr *Size,
183226633Sdim                                   const Expr *First,
184226633Sdim                                   const Expr *Second) const;
185226633Sdim  void emitOverlapBug(CheckerContext &C,
186234353Sdim                      ProgramStateRef state,
187226633Sdim                      const Stmt *First,
188226633Sdim                      const Stmt *Second) const;
189226633Sdim
190234353Sdim  ProgramStateRef checkAdditionOverflow(CheckerContext &C,
191234353Sdim                                            ProgramStateRef state,
192226633Sdim                                            NonLoc left,
193226633Sdim                                            NonLoc right) const;
194218887Sdim};
195218887Sdim
196218887Sdim} //end anonymous namespace
197218887Sdim
198243830SdimREGISTER_MAP_WITH_PROGRAMSTATE(CStringLength, const MemRegion *, SVal)
199218887Sdim
200218887Sdim//===----------------------------------------------------------------------===//
201218887Sdim// Individual checks and utility methods.
202218887Sdim//===----------------------------------------------------------------------===//
203218887Sdim
204234353Sdimstd::pair<ProgramStateRef , ProgramStateRef >
205234353SdimCStringChecker::assumeZero(CheckerContext &C, ProgramStateRef state, SVal V,
206218887Sdim                           QualType Ty) {
207249423Sdim  Optional<DefinedSVal> val = V.getAs<DefinedSVal>();
208218887Sdim  if (!val)
209234353Sdim    return std::pair<ProgramStateRef , ProgramStateRef >(state, state);
210218887Sdim
211218887Sdim  SValBuilder &svalBuilder = C.getSValBuilder();
212218887Sdim  DefinedOrUnknownSVal zero = svalBuilder.makeZeroVal(Ty);
213218887Sdim  return state->assume(svalBuilder.evalEQ(state, *val, zero));
214218887Sdim}
215218887Sdim
216234353SdimProgramStateRef CStringChecker::checkNonNull(CheckerContext &C,
217234353Sdim                                            ProgramStateRef state,
218219077Sdim                                            const Expr *S, SVal l) const {
219218887Sdim  // If a previous check has failed, propagate the failure.
220218887Sdim  if (!state)
221218887Sdim    return NULL;
222218887Sdim
223234353Sdim  ProgramStateRef stateNull, stateNonNull;
224218887Sdim  llvm::tie(stateNull, stateNonNull) = assumeZero(C, state, l, S->getType());
225218887Sdim
226218887Sdim  if (stateNull && !stateNonNull) {
227234353Sdim    if (!Filter.CheckCStringNullArg)
228234353Sdim      return NULL;
229234353Sdim
230218887Sdim    ExplodedNode *N = C.generateSink(stateNull);
231218887Sdim    if (!N)
232218887Sdim      return NULL;
233218887Sdim
234218887Sdim    if (!BT_Null)
235263508Sdim      BT_Null.reset(new BuiltinBug(categories::UnixAPI,
236219077Sdim        "Null pointer argument in call to byte string function"));
237218887Sdim
238234353Sdim    SmallString<80> buf;
239224145Sdim    llvm::raw_svector_ostream os(buf);
240224145Sdim    assert(CurrentFunctionDescription);
241224145Sdim    os << "Null pointer argument in call to " << CurrentFunctionDescription;
242224145Sdim
243218887Sdim    // Generate a report for this bug.
244219077Sdim    BuiltinBug *BT = static_cast<BuiltinBug*>(BT_Null.get());
245226633Sdim    BugReport *report = new BugReport(*BT, os.str(), N);
246218887Sdim
247218887Sdim    report->addRange(S->getSourceRange());
248243830Sdim    bugreporter::trackNullOrUndefValue(N, S, *report);
249243830Sdim    C.emitReport(report);
250218887Sdim    return NULL;
251218887Sdim  }
252218887Sdim
253218887Sdim  // From here on, assume that the value is non-null.
254218887Sdim  assert(stateNonNull);
255218887Sdim  return stateNonNull;
256218887Sdim}
257218887Sdim
258218887Sdim// FIXME: This was originally copied from ArrayBoundChecker.cpp. Refactor?
259234353SdimProgramStateRef CStringChecker::CheckLocation(CheckerContext &C,
260234353Sdim                                             ProgramStateRef state,
261218887Sdim                                             const Expr *S, SVal l,
262224145Sdim                                             const char *warningMsg) const {
263218887Sdim  // If a previous check has failed, propagate the failure.
264218887Sdim  if (!state)
265218887Sdim    return NULL;
266218887Sdim
267218887Sdim  // Check for out of bound array element access.
268218887Sdim  const MemRegion *R = l.getAsRegion();
269218887Sdim  if (!R)
270218887Sdim    return state;
271218887Sdim
272218887Sdim  const ElementRegion *ER = dyn_cast<ElementRegion>(R);
273218887Sdim  if (!ER)
274218887Sdim    return state;
275218887Sdim
276218887Sdim  assert(ER->getValueType() == C.getASTContext().CharTy &&
277218887Sdim    "CheckLocation should only be called with char* ElementRegions");
278218887Sdim
279218887Sdim  // Get the size of the array.
280218887Sdim  const SubRegion *superReg = cast<SubRegion>(ER->getSuperRegion());
281218887Sdim  SValBuilder &svalBuilder = C.getSValBuilder();
282224145Sdim  SVal Extent =
283224145Sdim    svalBuilder.convertToArrayIndex(superReg->getExtent(svalBuilder));
284249423Sdim  DefinedOrUnknownSVal Size = Extent.castAs<DefinedOrUnknownSVal>();
285218887Sdim
286218887Sdim  // Get the index of the accessed element.
287249423Sdim  DefinedOrUnknownSVal Idx = ER->getIndex().castAs<DefinedOrUnknownSVal>();
288218887Sdim
289234353Sdim  ProgramStateRef StInBound = state->assumeInBound(Idx, Size, true);
290234353Sdim  ProgramStateRef StOutBound = state->assumeInBound(Idx, Size, false);
291218887Sdim  if (StOutBound && !StInBound) {
292218887Sdim    ExplodedNode *N = C.generateSink(StOutBound);
293218887Sdim    if (!N)
294218887Sdim      return NULL;
295218887Sdim
296224145Sdim    if (!BT_Bounds) {
297224145Sdim      BT_Bounds.reset(new BuiltinBug("Out-of-bound array access",
298224145Sdim        "Byte string function accesses out-of-bound array element"));
299224145Sdim    }
300224145Sdim    BuiltinBug *BT = static_cast<BuiltinBug*>(BT_Bounds.get());
301224145Sdim
302224145Sdim    // Generate a report for this bug.
303226633Sdim    BugReport *report;
304224145Sdim    if (warningMsg) {
305226633Sdim      report = new BugReport(*BT, warningMsg, N);
306218887Sdim    } else {
307224145Sdim      assert(CurrentFunctionDescription);
308224145Sdim      assert(CurrentFunctionDescription[0] != '\0');
309224145Sdim
310234353Sdim      SmallString<80> buf;
311224145Sdim      llvm::raw_svector_ostream os(buf);
312249423Sdim      os << toUppercase(CurrentFunctionDescription[0])
313224145Sdim         << &CurrentFunctionDescription[1]
314224145Sdim         << " accesses out-of-bound array element";
315226633Sdim      report = new BugReport(*BT, os.str(), N);
316218887Sdim    }
317218887Sdim
318218887Sdim    // FIXME: It would be nice to eventually make this diagnostic more clear,
319218887Sdim    // e.g., by referencing the original declaration or by saying *why* this
320218887Sdim    // reference is outside the range.
321218887Sdim
322218887Sdim    report->addRange(S->getSourceRange());
323243830Sdim    C.emitReport(report);
324218887Sdim    return NULL;
325218887Sdim  }
326218887Sdim
327218887Sdim  // Array bound check succeeded.  From this point forward the array bound
328218887Sdim  // should always succeed.
329218887Sdim  return StInBound;
330218887Sdim}
331218887Sdim
332234353SdimProgramStateRef CStringChecker::CheckBufferAccess(CheckerContext &C,
333234353Sdim                                                 ProgramStateRef state,
334218887Sdim                                                 const Expr *Size,
335218887Sdim                                                 const Expr *FirstBuf,
336218887Sdim                                                 const Expr *SecondBuf,
337224145Sdim                                                 const char *firstMessage,
338224145Sdim                                                 const char *secondMessage,
339224145Sdim                                                 bool WarnAboutSize) const {
340218887Sdim  // If a previous check has failed, propagate the failure.
341218887Sdim  if (!state)
342218887Sdim    return NULL;
343218887Sdim
344218887Sdim  SValBuilder &svalBuilder = C.getSValBuilder();
345224145Sdim  ASTContext &Ctx = svalBuilder.getContext();
346234353Sdim  const LocationContext *LCtx = C.getLocationContext();
347218887Sdim
348218887Sdim  QualType sizeTy = Size->getType();
349218887Sdim  QualType PtrTy = Ctx.getPointerType(Ctx.CharTy);
350218887Sdim
351218887Sdim  // Check that the first buffer is non-null.
352234353Sdim  SVal BufVal = state->getSVal(FirstBuf, LCtx);
353218887Sdim  state = checkNonNull(C, state, FirstBuf, BufVal);
354218887Sdim  if (!state)
355218887Sdim    return NULL;
356218887Sdim
357234353Sdim  // If out-of-bounds checking is turned off, skip the rest.
358234353Sdim  if (!Filter.CheckCStringOutOfBounds)
359234353Sdim    return state;
360234353Sdim
361218887Sdim  // Get the access length and make sure it is known.
362224145Sdim  // FIXME: This assumes the caller has already checked that the access length
363224145Sdim  // is positive. And that it's unsigned.
364234353Sdim  SVal LengthVal = state->getSVal(Size, LCtx);
365249423Sdim  Optional<NonLoc> Length = LengthVal.getAs<NonLoc>();
366218887Sdim  if (!Length)
367218887Sdim    return state;
368218887Sdim
369218887Sdim  // Compute the offset of the last element to be accessed: size-1.
370249423Sdim  NonLoc One = svalBuilder.makeIntVal(1, sizeTy).castAs<NonLoc>();
371249423Sdim  NonLoc LastOffset = svalBuilder
372249423Sdim      .evalBinOpNN(state, BO_Sub, *Length, One, sizeTy).castAs<NonLoc>();
373218887Sdim
374221345Sdim  // Check that the first buffer is sufficiently long.
375218887Sdim  SVal BufStart = svalBuilder.evalCast(BufVal, PtrTy, FirstBuf->getType());
376249423Sdim  if (Optional<Loc> BufLoc = BufStart.getAs<Loc>()) {
377224145Sdim    const Expr *warningExpr = (WarnAboutSize ? Size : FirstBuf);
378224145Sdim
379218887Sdim    SVal BufEnd = svalBuilder.evalBinOpLN(state, BO_Add, *BufLoc,
380218887Sdim                                          LastOffset, PtrTy);
381224145Sdim    state = CheckLocation(C, state, warningExpr, BufEnd, firstMessage);
382218887Sdim
383218887Sdim    // If the buffer isn't large enough, abort.
384218887Sdim    if (!state)
385218887Sdim      return NULL;
386218887Sdim  }
387218887Sdim
388218887Sdim  // If there's a second buffer, check it as well.
389218887Sdim  if (SecondBuf) {
390234353Sdim    BufVal = state->getSVal(SecondBuf, LCtx);
391218887Sdim    state = checkNonNull(C, state, SecondBuf, BufVal);
392218887Sdim    if (!state)
393218887Sdim      return NULL;
394218887Sdim
395218887Sdim    BufStart = svalBuilder.evalCast(BufVal, PtrTy, SecondBuf->getType());
396249423Sdim    if (Optional<Loc> BufLoc = BufStart.getAs<Loc>()) {
397224145Sdim      const Expr *warningExpr = (WarnAboutSize ? Size : SecondBuf);
398224145Sdim
399218887Sdim      SVal BufEnd = svalBuilder.evalBinOpLN(state, BO_Add, *BufLoc,
400218887Sdim                                            LastOffset, PtrTy);
401224145Sdim      state = CheckLocation(C, state, warningExpr, BufEnd, secondMessage);
402218887Sdim    }
403218887Sdim  }
404218887Sdim
405218887Sdim  // Large enough or not, return this state!
406218887Sdim  return state;
407218887Sdim}
408218887Sdim
409234353SdimProgramStateRef CStringChecker::CheckOverlap(CheckerContext &C,
410234353Sdim                                            ProgramStateRef state,
411218887Sdim                                            const Expr *Size,
412218887Sdim                                            const Expr *First,
413219077Sdim                                            const Expr *Second) const {
414234353Sdim  if (!Filter.CheckCStringBufferOverlap)
415234353Sdim    return state;
416234353Sdim
417218887Sdim  // Do a simple check for overlap: if the two arguments are from the same
418218887Sdim  // buffer, see if the end of the first is greater than the start of the second
419218887Sdim  // or vice versa.
420218887Sdim
421218887Sdim  // If a previous check has failed, propagate the failure.
422218887Sdim  if (!state)
423218887Sdim    return NULL;
424218887Sdim
425234353Sdim  ProgramStateRef stateTrue, stateFalse;
426218887Sdim
427218887Sdim  // Get the buffer values and make sure they're known locations.
428234353Sdim  const LocationContext *LCtx = C.getLocationContext();
429234353Sdim  SVal firstVal = state->getSVal(First, LCtx);
430234353Sdim  SVal secondVal = state->getSVal(Second, LCtx);
431218887Sdim
432249423Sdim  Optional<Loc> firstLoc = firstVal.getAs<Loc>();
433218887Sdim  if (!firstLoc)
434218887Sdim    return state;
435218887Sdim
436249423Sdim  Optional<Loc> secondLoc = secondVal.getAs<Loc>();
437218887Sdim  if (!secondLoc)
438218887Sdim    return state;
439218887Sdim
440218887Sdim  // Are the two values the same?
441218887Sdim  SValBuilder &svalBuilder = C.getSValBuilder();
442218887Sdim  llvm::tie(stateTrue, stateFalse) =
443218887Sdim    state->assume(svalBuilder.evalEQ(state, *firstLoc, *secondLoc));
444218887Sdim
445218887Sdim  if (stateTrue && !stateFalse) {
446218887Sdim    // If the values are known to be equal, that's automatically an overlap.
447218887Sdim    emitOverlapBug(C, stateTrue, First, Second);
448218887Sdim    return NULL;
449218887Sdim  }
450218887Sdim
451218887Sdim  // assume the two expressions are not equal.
452218887Sdim  assert(stateFalse);
453218887Sdim  state = stateFalse;
454218887Sdim
455218887Sdim  // Which value comes first?
456224145Sdim  QualType cmpTy = svalBuilder.getConditionType();
457218887Sdim  SVal reverse = svalBuilder.evalBinOpLL(state, BO_GT,
458218887Sdim                                         *firstLoc, *secondLoc, cmpTy);
459249423Sdim  Optional<DefinedOrUnknownSVal> reverseTest =
460249423Sdim      reverse.getAs<DefinedOrUnknownSVal>();
461218887Sdim  if (!reverseTest)
462218887Sdim    return state;
463218887Sdim
464218887Sdim  llvm::tie(stateTrue, stateFalse) = state->assume(*reverseTest);
465218887Sdim  if (stateTrue) {
466218887Sdim    if (stateFalse) {
467218887Sdim      // If we don't know which one comes first, we can't perform this test.
468218887Sdim      return state;
469218887Sdim    } else {
470218887Sdim      // Switch the values so that firstVal is before secondVal.
471249423Sdim      std::swap(firstLoc, secondLoc);
472218887Sdim
473218887Sdim      // Switch the Exprs as well, so that they still correspond.
474249423Sdim      std::swap(First, Second);
475218887Sdim    }
476218887Sdim  }
477218887Sdim
478218887Sdim  // Get the length, and make sure it too is known.
479234353Sdim  SVal LengthVal = state->getSVal(Size, LCtx);
480249423Sdim  Optional<NonLoc> Length = LengthVal.getAs<NonLoc>();
481218887Sdim  if (!Length)
482218887Sdim    return state;
483218887Sdim
484218887Sdim  // Convert the first buffer's start address to char*.
485218887Sdim  // Bail out if the cast fails.
486224145Sdim  ASTContext &Ctx = svalBuilder.getContext();
487218887Sdim  QualType CharPtrTy = Ctx.getPointerType(Ctx.CharTy);
488224145Sdim  SVal FirstStart = svalBuilder.evalCast(*firstLoc, CharPtrTy,
489224145Sdim                                         First->getType());
490249423Sdim  Optional<Loc> FirstStartLoc = FirstStart.getAs<Loc>();
491218887Sdim  if (!FirstStartLoc)
492218887Sdim    return state;
493218887Sdim
494218887Sdim  // Compute the end of the first buffer. Bail out if THAT fails.
495218887Sdim  SVal FirstEnd = svalBuilder.evalBinOpLN(state, BO_Add,
496218887Sdim                                 *FirstStartLoc, *Length, CharPtrTy);
497249423Sdim  Optional<Loc> FirstEndLoc = FirstEnd.getAs<Loc>();
498218887Sdim  if (!FirstEndLoc)
499218887Sdim    return state;
500218887Sdim
501218887Sdim  // Is the end of the first buffer past the start of the second buffer?
502218887Sdim  SVal Overlap = svalBuilder.evalBinOpLL(state, BO_GT,
503218887Sdim                                *FirstEndLoc, *secondLoc, cmpTy);
504249423Sdim  Optional<DefinedOrUnknownSVal> OverlapTest =
505249423Sdim      Overlap.getAs<DefinedOrUnknownSVal>();
506218887Sdim  if (!OverlapTest)
507218887Sdim    return state;
508218887Sdim
509218887Sdim  llvm::tie(stateTrue, stateFalse) = state->assume(*OverlapTest);
510218887Sdim
511218887Sdim  if (stateTrue && !stateFalse) {
512218887Sdim    // Overlap!
513218887Sdim    emitOverlapBug(C, stateTrue, First, Second);
514218887Sdim    return NULL;
515218887Sdim  }
516218887Sdim
517218887Sdim  // assume the two expressions don't overlap.
518218887Sdim  assert(stateFalse);
519218887Sdim  return stateFalse;
520218887Sdim}
521218887Sdim
522234353Sdimvoid CStringChecker::emitOverlapBug(CheckerContext &C, ProgramStateRef state,
523219077Sdim                                  const Stmt *First, const Stmt *Second) const {
524218887Sdim  ExplodedNode *N = C.generateSink(state);
525218887Sdim  if (!N)
526218887Sdim    return;
527218887Sdim
528218887Sdim  if (!BT_Overlap)
529263508Sdim    BT_Overlap.reset(new BugType(categories::UnixAPI, "Improper arguments"));
530218887Sdim
531218887Sdim  // Generate a report for this bug.
532226633Sdim  BugReport *report =
533226633Sdim    new BugReport(*BT_Overlap,
534218887Sdim      "Arguments must not be overlapping buffers", N);
535218887Sdim  report->addRange(First->getSourceRange());
536218887Sdim  report->addRange(Second->getSourceRange());
537218887Sdim
538243830Sdim  C.emitReport(report);
539218887Sdim}
540218887Sdim
541234353SdimProgramStateRef CStringChecker::checkAdditionOverflow(CheckerContext &C,
542234353Sdim                                                     ProgramStateRef state,
543224145Sdim                                                     NonLoc left,
544224145Sdim                                                     NonLoc right) const {
545234353Sdim  // If out-of-bounds checking is turned off, skip the rest.
546234353Sdim  if (!Filter.CheckCStringOutOfBounds)
547234353Sdim    return state;
548234353Sdim
549224145Sdim  // If a previous check has failed, propagate the failure.
550224145Sdim  if (!state)
551224145Sdim    return NULL;
552224145Sdim
553224145Sdim  SValBuilder &svalBuilder = C.getSValBuilder();
554224145Sdim  BasicValueFactory &BVF = svalBuilder.getBasicValueFactory();
555224145Sdim
556224145Sdim  QualType sizeTy = svalBuilder.getContext().getSizeType();
557224145Sdim  const llvm::APSInt &maxValInt = BVF.getMaxValue(sizeTy);
558224145Sdim  NonLoc maxVal = svalBuilder.makeIntVal(maxValInt);
559224145Sdim
560234353Sdim  SVal maxMinusRight;
561249423Sdim  if (right.getAs<nonloc::ConcreteInt>()) {
562234353Sdim    maxMinusRight = svalBuilder.evalBinOpNN(state, BO_Sub, maxVal, right,
563234353Sdim                                                 sizeTy);
564234353Sdim  } else {
565224145Sdim    // Try switching the operands. (The order of these two assignments is
566224145Sdim    // important!)
567224145Sdim    maxMinusRight = svalBuilder.evalBinOpNN(state, BO_Sub, maxVal, left,
568224145Sdim                                            sizeTy);
569224145Sdim    left = right;
570224145Sdim  }
571224145Sdim
572249423Sdim  if (Optional<NonLoc> maxMinusRightNL = maxMinusRight.getAs<NonLoc>()) {
573224145Sdim    QualType cmpTy = svalBuilder.getConditionType();
574224145Sdim    // If left > max - right, we have an overflow.
575224145Sdim    SVal willOverflow = svalBuilder.evalBinOpNN(state, BO_GT, left,
576224145Sdim                                                *maxMinusRightNL, cmpTy);
577224145Sdim
578234353Sdim    ProgramStateRef stateOverflow, stateOkay;
579224145Sdim    llvm::tie(stateOverflow, stateOkay) =
580249423Sdim      state->assume(willOverflow.castAs<DefinedOrUnknownSVal>());
581224145Sdim
582224145Sdim    if (stateOverflow && !stateOkay) {
583224145Sdim      // We have an overflow. Emit a bug report.
584224145Sdim      ExplodedNode *N = C.generateSink(stateOverflow);
585224145Sdim      if (!N)
586224145Sdim        return NULL;
587224145Sdim
588224145Sdim      if (!BT_AdditionOverflow)
589224145Sdim        BT_AdditionOverflow.reset(new BuiltinBug("API",
590224145Sdim          "Sum of expressions causes overflow"));
591224145Sdim
592224145Sdim      // This isn't a great error message, but this should never occur in real
593224145Sdim      // code anyway -- you'd have to create a buffer longer than a size_t can
594224145Sdim      // represent, which is sort of a contradiction.
595224145Sdim      const char *warning =
596224145Sdim        "This expression will create a string whose length is too big to "
597224145Sdim        "be represented as a size_t";
598224145Sdim
599224145Sdim      // Generate a report for this bug.
600224145Sdim      BugReport *report = new BugReport(*BT_AdditionOverflow, warning, N);
601243830Sdim      C.emitReport(report);
602224145Sdim
603224145Sdim      return NULL;
604224145Sdim    }
605224145Sdim
606224145Sdim    // From now on, assume an overflow didn't occur.
607224145Sdim    assert(stateOkay);
608224145Sdim    state = stateOkay;
609224145Sdim  }
610224145Sdim
611224145Sdim  return state;
612224145Sdim}
613224145Sdim
614234353SdimProgramStateRef CStringChecker::setCStringLength(ProgramStateRef state,
615218887Sdim                                                const MemRegion *MR,
616218887Sdim                                                SVal strLength) {
617218887Sdim  assert(!strLength.isUndef() && "Attempt to set an undefined string length");
618218887Sdim
619218887Sdim  MR = MR->StripCasts();
620218887Sdim
621218887Sdim  switch (MR->getKind()) {
622218887Sdim  case MemRegion::StringRegionKind:
623218887Sdim    // FIXME: This can happen if we strcpy() into a string region. This is
624218887Sdim    // undefined [C99 6.4.5p6], but we should still warn about it.
625218887Sdim    return state;
626218887Sdim
627218887Sdim  case MemRegion::SymbolicRegionKind:
628218887Sdim  case MemRegion::AllocaRegionKind:
629218887Sdim  case MemRegion::VarRegionKind:
630218887Sdim  case MemRegion::FieldRegionKind:
631218887Sdim  case MemRegion::ObjCIvarRegionKind:
632224145Sdim    // These are the types we can currently track string lengths for.
633224145Sdim    break;
634218887Sdim
635218887Sdim  case MemRegion::ElementRegionKind:
636218887Sdim    // FIXME: Handle element regions by upper-bounding the parent region's
637218887Sdim    // string length.
638218887Sdim    return state;
639218887Sdim
640218887Sdim  default:
641218887Sdim    // Other regions (mostly non-data) can't have a reliable C string length.
642218887Sdim    // For now, just ignore the change.
643218887Sdim    // FIXME: These are rare but not impossible. We should output some kind of
644218887Sdim    // warning for things like strcpy((char[]){'a', 0}, "b");
645218887Sdim    return state;
646218887Sdim  }
647224145Sdim
648224145Sdim  if (strLength.isUnknown())
649224145Sdim    return state->remove<CStringLength>(MR);
650224145Sdim
651224145Sdim  return state->set<CStringLength>(MR, strLength);
652218887Sdim}
653218887Sdim
654218887SdimSVal CStringChecker::getCStringLengthForRegion(CheckerContext &C,
655234353Sdim                                               ProgramStateRef &state,
656218887Sdim                                               const Expr *Ex,
657224145Sdim                                               const MemRegion *MR,
658224145Sdim                                               bool hypothetical) {
659224145Sdim  if (!hypothetical) {
660224145Sdim    // If there's a recorded length, go ahead and return it.
661224145Sdim    const SVal *Recorded = state->get<CStringLength>(MR);
662224145Sdim    if (Recorded)
663224145Sdim      return *Recorded;
664224145Sdim  }
665263508Sdim
666218887Sdim  // Otherwise, get a new symbol and update the state.
667218887Sdim  SValBuilder &svalBuilder = C.getSValBuilder();
668218887Sdim  QualType sizeTy = svalBuilder.getContext().getSizeType();
669219077Sdim  SVal strLength = svalBuilder.getMetadataSymbolVal(CStringChecker::getTag(),
670243830Sdim                                                    MR, Ex, sizeTy,
671243830Sdim                                                    C.blockCount());
672224145Sdim
673263508Sdim  if (!hypothetical) {
674263508Sdim    if (Optional<NonLoc> strLn = strLength.getAs<NonLoc>()) {
675263508Sdim      // In case of unbounded calls strlen etc bound the range to SIZE_MAX/4
676263508Sdim      BasicValueFactory &BVF = svalBuilder.getBasicValueFactory();
677263508Sdim      const llvm::APSInt &maxValInt = BVF.getMaxValue(sizeTy);
678263508Sdim      llvm::APSInt fourInt = APSIntType(maxValInt).getValue(4);
679263508Sdim      const llvm::APSInt *maxLengthInt = BVF.evalAPSInt(BO_Div, maxValInt,
680263508Sdim                                                        fourInt);
681263508Sdim      NonLoc maxLength = svalBuilder.makeIntVal(*maxLengthInt);
682263508Sdim      SVal evalLength = svalBuilder.evalBinOpNN(state, BO_LE, *strLn,
683263508Sdim                                                maxLength, sizeTy);
684263508Sdim      state = state->assume(evalLength.castAs<DefinedOrUnknownSVal>(), true);
685263508Sdim    }
686224145Sdim    state = state->set<CStringLength>(MR, strLength);
687263508Sdim  }
688224145Sdim
689218887Sdim  return strLength;
690218887Sdim}
691218887Sdim
692234353SdimSVal CStringChecker::getCStringLength(CheckerContext &C, ProgramStateRef &state,
693224145Sdim                                      const Expr *Ex, SVal Buf,
694224145Sdim                                      bool hypothetical) const {
695218887Sdim  const MemRegion *MR = Buf.getAsRegion();
696218887Sdim  if (!MR) {
697218887Sdim    // If we can't get a region, see if it's something we /know/ isn't a
698218887Sdim    // C string. In the context of locations, the only time we can issue such
699218887Sdim    // a warning is for labels.
700249423Sdim    if (Optional<loc::GotoLabel> Label = Buf.getAs<loc::GotoLabel>()) {
701234353Sdim      if (!Filter.CheckCStringNotNullTerm)
702234353Sdim        return UndefinedVal();
703234353Sdim
704234353Sdim      if (ExplodedNode *N = C.addTransition(state)) {
705218887Sdim        if (!BT_NotCString)
706263508Sdim          BT_NotCString.reset(new BuiltinBug(categories::UnixAPI,
707219077Sdim            "Argument is not a null-terminated string."));
708218887Sdim
709234353Sdim        SmallString<120> buf;
710218887Sdim        llvm::raw_svector_ostream os(buf);
711224145Sdim        assert(CurrentFunctionDescription);
712224145Sdim        os << "Argument to " << CurrentFunctionDescription
713224145Sdim           << " is the address of the label '" << Label->getLabel()->getName()
714218887Sdim           << "', which is not a null-terminated string";
715218887Sdim
716218887Sdim        // Generate a report for this bug.
717226633Sdim        BugReport *report = new BugReport(*BT_NotCString,
718218887Sdim                                                          os.str(), N);
719218887Sdim
720218887Sdim        report->addRange(Ex->getSourceRange());
721243830Sdim        C.emitReport(report);
722218887Sdim      }
723234353Sdim      return UndefinedVal();
724218887Sdim
725218887Sdim    }
726218887Sdim
727218887Sdim    // If it's not a region and not a label, give up.
728218887Sdim    return UnknownVal();
729218887Sdim  }
730218887Sdim
731218887Sdim  // If we have a region, strip casts from it and see if we can figure out
732218887Sdim  // its length. For anything we can't figure out, just return UnknownVal.
733218887Sdim  MR = MR->StripCasts();
734218887Sdim
735218887Sdim  switch (MR->getKind()) {
736218887Sdim  case MemRegion::StringRegionKind: {
737218887Sdim    // Modifying the contents of string regions is undefined [C99 6.4.5p6],
738218887Sdim    // so we can assume that the byte length is the correct C string length.
739218887Sdim    SValBuilder &svalBuilder = C.getSValBuilder();
740218887Sdim    QualType sizeTy = svalBuilder.getContext().getSizeType();
741218887Sdim    const StringLiteral *strLit = cast<StringRegion>(MR)->getStringLiteral();
742218887Sdim    return svalBuilder.makeIntVal(strLit->getByteLength(), sizeTy);
743218887Sdim  }
744218887Sdim  case MemRegion::SymbolicRegionKind:
745218887Sdim  case MemRegion::AllocaRegionKind:
746218887Sdim  case MemRegion::VarRegionKind:
747218887Sdim  case MemRegion::FieldRegionKind:
748218887Sdim  case MemRegion::ObjCIvarRegionKind:
749224145Sdim    return getCStringLengthForRegion(C, state, Ex, MR, hypothetical);
750218887Sdim  case MemRegion::CompoundLiteralRegionKind:
751218887Sdim    // FIXME: Can we track this? Is it necessary?
752218887Sdim    return UnknownVal();
753218887Sdim  case MemRegion::ElementRegionKind:
754218887Sdim    // FIXME: How can we handle this? It's not good enough to subtract the
755218887Sdim    // offset from the base string length; consider "123\x00567" and &a[5].
756218887Sdim    return UnknownVal();
757218887Sdim  default:
758218887Sdim    // Other regions (mostly non-data) can't have a reliable C string length.
759218887Sdim    // In this case, an error is emitted and UndefinedVal is returned.
760218887Sdim    // The caller should always be prepared to handle this case.
761234353Sdim    if (!Filter.CheckCStringNotNullTerm)
762234353Sdim      return UndefinedVal();
763234353Sdim
764234353Sdim    if (ExplodedNode *N = C.addTransition(state)) {
765218887Sdim      if (!BT_NotCString)
766263508Sdim        BT_NotCString.reset(new BuiltinBug(categories::UnixAPI,
767219077Sdim          "Argument is not a null-terminated string."));
768218887Sdim
769234353Sdim      SmallString<120> buf;
770218887Sdim      llvm::raw_svector_ostream os(buf);
771218887Sdim
772224145Sdim      assert(CurrentFunctionDescription);
773224145Sdim      os << "Argument to " << CurrentFunctionDescription << " is ";
774218887Sdim
775218887Sdim      if (SummarizeRegion(os, C.getASTContext(), MR))
776218887Sdim        os << ", which is not a null-terminated string";
777218887Sdim      else
778218887Sdim        os << "not a null-terminated string";
779218887Sdim
780218887Sdim      // Generate a report for this bug.
781226633Sdim      BugReport *report = new BugReport(*BT_NotCString,
782218887Sdim                                                        os.str(), N);
783218887Sdim
784218887Sdim      report->addRange(Ex->getSourceRange());
785243830Sdim      C.emitReport(report);
786218887Sdim    }
787218887Sdim
788218887Sdim    return UndefinedVal();
789218887Sdim  }
790218887Sdim}
791218887Sdim
792221345Sdimconst StringLiteral *CStringChecker::getCStringLiteral(CheckerContext &C,
793234353Sdim  ProgramStateRef &state, const Expr *expr, SVal val) const {
794221345Sdim
795221345Sdim  // Get the memory region pointed to by the val.
796221345Sdim  const MemRegion *bufRegion = val.getAsRegion();
797221345Sdim  if (!bufRegion)
798221345Sdim    return NULL;
799221345Sdim
800221345Sdim  // Strip casts off the memory region.
801221345Sdim  bufRegion = bufRegion->StripCasts();
802221345Sdim
803221345Sdim  // Cast the memory region to a string region.
804221345Sdim  const StringRegion *strRegion= dyn_cast<StringRegion>(bufRegion);
805221345Sdim  if (!strRegion)
806221345Sdim    return NULL;
807221345Sdim
808221345Sdim  // Return the actual string in the string region.
809221345Sdim  return strRegion->getStringLiteral();
810221345Sdim}
811221345Sdim
812234353SdimProgramStateRef CStringChecker::InvalidateBuffer(CheckerContext &C,
813263508Sdim                                                 ProgramStateRef state,
814263508Sdim                                                 const Expr *E, SVal V,
815263508Sdim                                                 bool IsSourceBuffer) {
816249423Sdim  Optional<Loc> L = V.getAs<Loc>();
817218887Sdim  if (!L)
818218887Sdim    return state;
819218887Sdim
820218887Sdim  // FIXME: This is a simplified version of what's in CFRefCount.cpp -- it makes
821218887Sdim  // some assumptions about the value that CFRefCount can't. Even so, it should
822218887Sdim  // probably be refactored.
823249423Sdim  if (Optional<loc::MemRegionVal> MR = L->getAs<loc::MemRegionVal>()) {
824218887Sdim    const MemRegion *R = MR->getRegion()->StripCasts();
825218887Sdim
826218887Sdim    // Are we dealing with an ElementRegion?  If so, we should be invalidating
827218887Sdim    // the super-region.
828218887Sdim    if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
829218887Sdim      R = ER->getSuperRegion();
830218887Sdim      // FIXME: What about layers of ElementRegions?
831218887Sdim    }
832218887Sdim
833218887Sdim    // Invalidate this region.
834234353Sdim    const LocationContext *LCtx = C.getPredecessor()->getLocationContext();
835263508Sdim
836263508Sdim    bool CausesPointerEscape = false;
837263508Sdim    RegionAndSymbolInvalidationTraits ITraits;
838263508Sdim    // Invalidate and escape only indirect regions accessible through the source
839263508Sdim    // buffer.
840263508Sdim    if (IsSourceBuffer) {
841263508Sdim      ITraits.setTrait(R,
842263508Sdim                       RegionAndSymbolInvalidationTraits::TK_PreserveContents);
843263508Sdim      ITraits.setTrait(R, RegionAndSymbolInvalidationTraits::TK_SuppressEscape);
844263508Sdim      CausesPointerEscape = true;
845263508Sdim    }
846263508Sdim
847263508Sdim    return state->invalidateRegions(R, E, C.blockCount(), LCtx,
848263508Sdim                                    CausesPointerEscape, 0, 0, &ITraits);
849218887Sdim  }
850218887Sdim
851218887Sdim  // If we have a non-region value by chance, just remove the binding.
852218887Sdim  // FIXME: is this necessary or correct? This handles the non-Region
853218887Sdim  //  cases.  Is it ever valid to store to these?
854243830Sdim  return state->killBinding(*L);
855218887Sdim}
856218887Sdim
857226633Sdimbool CStringChecker::SummarizeRegion(raw_ostream &os, ASTContext &Ctx,
858218887Sdim                                     const MemRegion *MR) {
859226633Sdim  const TypedValueRegion *TVR = dyn_cast<TypedValueRegion>(MR);
860218887Sdim
861226633Sdim  switch (MR->getKind()) {
862218887Sdim  case MemRegion::FunctionTextRegionKind: {
863243830Sdim    const NamedDecl *FD = cast<FunctionTextRegion>(MR)->getDecl();
864218887Sdim    if (FD)
865226633Sdim      os << "the address of the function '" << *FD << '\'';
866218887Sdim    else
867218887Sdim      os << "the address of a function";
868218887Sdim    return true;
869218887Sdim  }
870218887Sdim  case MemRegion::BlockTextRegionKind:
871218887Sdim    os << "block text";
872218887Sdim    return true;
873218887Sdim  case MemRegion::BlockDataRegionKind:
874218887Sdim    os << "a block";
875218887Sdim    return true;
876218887Sdim  case MemRegion::CXXThisRegionKind:
877218887Sdim  case MemRegion::CXXTempObjectRegionKind:
878226633Sdim    os << "a C++ temp object of type " << TVR->getValueType().getAsString();
879218887Sdim    return true;
880218887Sdim  case MemRegion::VarRegionKind:
881226633Sdim    os << "a variable of type" << TVR->getValueType().getAsString();
882218887Sdim    return true;
883218887Sdim  case MemRegion::FieldRegionKind:
884226633Sdim    os << "a field of type " << TVR->getValueType().getAsString();
885218887Sdim    return true;
886218887Sdim  case MemRegion::ObjCIvarRegionKind:
887226633Sdim    os << "an instance variable of type " << TVR->getValueType().getAsString();
888218887Sdim    return true;
889218887Sdim  default:
890218887Sdim    return false;
891218887Sdim  }
892218887Sdim}
893218887Sdim
894218887Sdim//===----------------------------------------------------------------------===//
895218887Sdim// evaluation of individual function calls.
896218887Sdim//===----------------------------------------------------------------------===//
897218887Sdim
898221345Sdimvoid CStringChecker::evalCopyCommon(CheckerContext &C,
899221345Sdim                                    const CallExpr *CE,
900234353Sdim                                    ProgramStateRef state,
901218887Sdim                                    const Expr *Size, const Expr *Dest,
902221345Sdim                                    const Expr *Source, bool Restricted,
903221345Sdim                                    bool IsMempcpy) const {
904224145Sdim  CurrentFunctionDescription = "memory copy function";
905224145Sdim
906218887Sdim  // See if the size argument is zero.
907234353Sdim  const LocationContext *LCtx = C.getLocationContext();
908234353Sdim  SVal sizeVal = state->getSVal(Size, LCtx);
909218887Sdim  QualType sizeTy = Size->getType();
910218887Sdim
911234353Sdim  ProgramStateRef stateZeroSize, stateNonZeroSize;
912224145Sdim  llvm::tie(stateZeroSize, stateNonZeroSize) =
913224145Sdim    assumeZero(C, state, sizeVal, sizeTy);
914218887Sdim
915221345Sdim  // Get the value of the Dest.
916234353Sdim  SVal destVal = state->getSVal(Dest, LCtx);
917221345Sdim
918221345Sdim  // If the size is zero, there won't be any actual memory access, so
919221345Sdim  // just bind the return value to the destination buffer and return.
920239462Sdim  if (stateZeroSize && !stateNonZeroSize) {
921234353Sdim    stateZeroSize = stateZeroSize->BindExpr(CE, LCtx, destVal);
922218887Sdim    C.addTransition(stateZeroSize);
923239462Sdim    return;
924221345Sdim  }
925218887Sdim
926218887Sdim  // If the size can be nonzero, we have to check the other arguments.
927218887Sdim  if (stateNonZeroSize) {
928223017Sdim    state = stateNonZeroSize;
929221345Sdim
930221345Sdim    // Ensure the destination is not null. If it is NULL there will be a
931221345Sdim    // NULL pointer dereference.
932221345Sdim    state = checkNonNull(C, state, Dest, destVal);
933221345Sdim    if (!state)
934221345Sdim      return;
935221345Sdim
936221345Sdim    // Get the value of the Src.
937234353Sdim    SVal srcVal = state->getSVal(Source, LCtx);
938221345Sdim
939221345Sdim    // Ensure the source is not null. If it is NULL there will be a
940221345Sdim    // NULL pointer dereference.
941221345Sdim    state = checkNonNull(C, state, Source, srcVal);
942221345Sdim    if (!state)
943221345Sdim      return;
944221345Sdim
945223017Sdim    // Ensure the accesses are valid and that the buffers do not overlap.
946224145Sdim    const char * const writeWarning =
947224145Sdim      "Memory copy function overflows destination buffer";
948218887Sdim    state = CheckBufferAccess(C, state, Size, Dest, Source,
949224145Sdim                              writeWarning, /* sourceWarning = */ NULL);
950218887Sdim    if (Restricted)
951218887Sdim      state = CheckOverlap(C, state, Size, Dest, Source);
952218887Sdim
953223017Sdim    if (!state)
954223017Sdim      return;
955221345Sdim
956223017Sdim    // If this is mempcpy, get the byte after the last byte copied and
957223017Sdim    // bind the expr.
958223017Sdim    if (IsMempcpy) {
959249423Sdim      loc::MemRegionVal destRegVal = destVal.castAs<loc::MemRegionVal>();
960223017Sdim
961223017Sdim      // Get the length to copy.
962249423Sdim      if (Optional<NonLoc> lenValNonLoc = sizeVal.getAs<NonLoc>()) {
963221345Sdim        // Get the byte after the last byte copied.
964221345Sdim        SVal lastElement = C.getSValBuilder().evalBinOpLN(state, BO_Add,
965249423Sdim                                                          destRegVal,
966221345Sdim                                                          *lenValNonLoc,
967221345Sdim                                                          Dest->getType());
968223017Sdim
969221345Sdim        // The byte after the last byte copied is the return value.
970234353Sdim        state = state->BindExpr(CE, LCtx, lastElement);
971223017Sdim      } else {
972223017Sdim        // If we don't know how much we copied, we can at least
973223017Sdim        // conjure a return value for later.
974243830Sdim        SVal result = C.getSValBuilder().conjureSymbolVal(0, CE, LCtx,
975243830Sdim                                                          C.blockCount());
976234353Sdim        state = state->BindExpr(CE, LCtx, result);
977221345Sdim      }
978221345Sdim
979223017Sdim    } else {
980223017Sdim      // All other copies return the destination buffer.
981223017Sdim      // (Well, bcopy() has a void return type, but this won't hurt.)
982234353Sdim      state = state->BindExpr(CE, LCtx, destVal);
983218887Sdim    }
984223017Sdim
985263508Sdim    // Invalidate the destination (regular invalidation without pointer-escaping
986263508Sdim    // the address of the top-level region).
987223017Sdim    // FIXME: Even if we can't perfectly model the copy, we should see if we
988223017Sdim    // can use LazyCompoundVals to copy the source values into the destination.
989223017Sdim    // This would probably remove any existing bindings past the end of the
990223017Sdim    // copied region, but that's still an improvement over blank invalidation.
991263508Sdim    state = InvalidateBuffer(C, state, Dest, C.getSVal(Dest),
992263508Sdim                             /*IsSourceBuffer*/false);
993263508Sdim
994263508Sdim    // Invalidate the source (const-invalidation without const-pointer-escaping
995263508Sdim    // the address of the top-level region).
996263508Sdim    state = InvalidateBuffer(C, state, Source, C.getSVal(Source),
997263508Sdim                             /*IsSourceBuffer*/true);
998263508Sdim
999223017Sdim    C.addTransition(state);
1000218887Sdim  }
1001218887Sdim}
1002218887Sdim
1003218887Sdim
1004219077Sdimvoid CStringChecker::evalMemcpy(CheckerContext &C, const CallExpr *CE) const {
1005234353Sdim  if (CE->getNumArgs() < 3)
1006234353Sdim    return;
1007234353Sdim
1008218887Sdim  // void *memcpy(void *restrict dst, const void *restrict src, size_t n);
1009218887Sdim  // The return value is the address of the destination buffer.
1010218887Sdim  const Expr *Dest = CE->getArg(0);
1011234353Sdim  ProgramStateRef state = C.getState();
1012223017Sdim
1013221345Sdim  evalCopyCommon(C, CE, state, CE->getArg(2), Dest, CE->getArg(1), true);
1014218887Sdim}
1015218887Sdim
1016221345Sdimvoid CStringChecker::evalMempcpy(CheckerContext &C, const CallExpr *CE) const {
1017234353Sdim  if (CE->getNumArgs() < 3)
1018234353Sdim    return;
1019234353Sdim
1020221345Sdim  // void *mempcpy(void *restrict dst, const void *restrict src, size_t n);
1021221345Sdim  // The return value is a pointer to the byte following the last written byte.
1022221345Sdim  const Expr *Dest = CE->getArg(0);
1023234353Sdim  ProgramStateRef state = C.getState();
1024221345Sdim
1025221345Sdim  evalCopyCommon(C, CE, state, CE->getArg(2), Dest, CE->getArg(1), true, true);
1026221345Sdim}
1027221345Sdim
1028219077Sdimvoid CStringChecker::evalMemmove(CheckerContext &C, const CallExpr *CE) const {
1029234353Sdim  if (CE->getNumArgs() < 3)
1030234353Sdim    return;
1031234353Sdim
1032218887Sdim  // void *memmove(void *dst, const void *src, size_t n);
1033218887Sdim  // The return value is the address of the destination buffer.
1034218887Sdim  const Expr *Dest = CE->getArg(0);
1035234353Sdim  ProgramStateRef state = C.getState();
1036223017Sdim
1037221345Sdim  evalCopyCommon(C, CE, state, CE->getArg(2), Dest, CE->getArg(1));
1038218887Sdim}
1039218887Sdim
1040219077Sdimvoid CStringChecker::evalBcopy(CheckerContext &C, const CallExpr *CE) const {
1041234353Sdim  if (CE->getNumArgs() < 3)
1042234353Sdim    return;
1043234353Sdim
1044218887Sdim  // void bcopy(const void *src, void *dst, size_t n);
1045221345Sdim  evalCopyCommon(C, CE, C.getState(),
1046221345Sdim                 CE->getArg(2), CE->getArg(1), CE->getArg(0));
1047218887Sdim}
1048218887Sdim
1049219077Sdimvoid CStringChecker::evalMemcmp(CheckerContext &C, const CallExpr *CE) const {
1050234353Sdim  if (CE->getNumArgs() < 3)
1051234353Sdim    return;
1052234353Sdim
1053218887Sdim  // int memcmp(const void *s1, const void *s2, size_t n);
1054224145Sdim  CurrentFunctionDescription = "memory comparison function";
1055224145Sdim
1056218887Sdim  const Expr *Left = CE->getArg(0);
1057218887Sdim  const Expr *Right = CE->getArg(1);
1058218887Sdim  const Expr *Size = CE->getArg(2);
1059218887Sdim
1060234353Sdim  ProgramStateRef state = C.getState();
1061218887Sdim  SValBuilder &svalBuilder = C.getSValBuilder();
1062218887Sdim
1063218887Sdim  // See if the size argument is zero.
1064234353Sdim  const LocationContext *LCtx = C.getLocationContext();
1065234353Sdim  SVal sizeVal = state->getSVal(Size, LCtx);
1066218887Sdim  QualType sizeTy = Size->getType();
1067218887Sdim
1068234353Sdim  ProgramStateRef stateZeroSize, stateNonZeroSize;
1069218887Sdim  llvm::tie(stateZeroSize, stateNonZeroSize) =
1070218887Sdim    assumeZero(C, state, sizeVal, sizeTy);
1071218887Sdim
1072218887Sdim  // If the size can be zero, the result will be 0 in that case, and we don't
1073218887Sdim  // have to check either of the buffers.
1074218887Sdim  if (stateZeroSize) {
1075218887Sdim    state = stateZeroSize;
1076234353Sdim    state = state->BindExpr(CE, LCtx,
1077234353Sdim                            svalBuilder.makeZeroVal(CE->getType()));
1078218887Sdim    C.addTransition(state);
1079218887Sdim  }
1080218887Sdim
1081218887Sdim  // If the size can be nonzero, we have to check the other arguments.
1082218887Sdim  if (stateNonZeroSize) {
1083218887Sdim    state = stateNonZeroSize;
1084218887Sdim    // If we know the two buffers are the same, we know the result is 0.
1085218887Sdim    // First, get the two buffers' addresses. Another checker will have already
1086218887Sdim    // made sure they're not undefined.
1087234353Sdim    DefinedOrUnknownSVal LV =
1088249423Sdim        state->getSVal(Left, LCtx).castAs<DefinedOrUnknownSVal>();
1089234353Sdim    DefinedOrUnknownSVal RV =
1090249423Sdim        state->getSVal(Right, LCtx).castAs<DefinedOrUnknownSVal>();
1091218887Sdim
1092218887Sdim    // See if they are the same.
1093218887Sdim    DefinedOrUnknownSVal SameBuf = svalBuilder.evalEQ(state, LV, RV);
1094234353Sdim    ProgramStateRef StSameBuf, StNotSameBuf;
1095218887Sdim    llvm::tie(StSameBuf, StNotSameBuf) = state->assume(SameBuf);
1096218887Sdim
1097224145Sdim    // If the two arguments might be the same buffer, we know the result is 0,
1098218887Sdim    // and we only need to check one size.
1099218887Sdim    if (StSameBuf) {
1100218887Sdim      state = StSameBuf;
1101218887Sdim      state = CheckBufferAccess(C, state, Size, Left);
1102218887Sdim      if (state) {
1103234353Sdim        state = StSameBuf->BindExpr(CE, LCtx,
1104234353Sdim                                    svalBuilder.makeZeroVal(CE->getType()));
1105234353Sdim        C.addTransition(state);
1106218887Sdim      }
1107218887Sdim    }
1108218887Sdim
1109218887Sdim    // If the two arguments might be different buffers, we have to check the
1110218887Sdim    // size of both of them.
1111218887Sdim    if (StNotSameBuf) {
1112218887Sdim      state = StNotSameBuf;
1113218887Sdim      state = CheckBufferAccess(C, state, Size, Left, Right);
1114218887Sdim      if (state) {
1115218887Sdim        // The return value is the comparison result, which we don't know.
1116243830Sdim        SVal CmpV = svalBuilder.conjureSymbolVal(0, CE, LCtx, C.blockCount());
1117234353Sdim        state = state->BindExpr(CE, LCtx, CmpV);
1118218887Sdim        C.addTransition(state);
1119218887Sdim      }
1120218887Sdim    }
1121218887Sdim  }
1122218887Sdim}
1123218887Sdim
1124219077Sdimvoid CStringChecker::evalstrLength(CheckerContext &C,
1125219077Sdim                                   const CallExpr *CE) const {
1126234353Sdim  if (CE->getNumArgs() < 1)
1127234353Sdim    return;
1128234353Sdim
1129218887Sdim  // size_t strlen(const char *s);
1130219077Sdim  evalstrLengthCommon(C, CE, /* IsStrnlen = */ false);
1131219077Sdim}
1132219077Sdim
1133219077Sdimvoid CStringChecker::evalstrnLength(CheckerContext &C,
1134219077Sdim                                    const CallExpr *CE) const {
1135234353Sdim  if (CE->getNumArgs() < 2)
1136234353Sdim    return;
1137234353Sdim
1138219077Sdim  // size_t strnlen(const char *s, size_t maxlen);
1139219077Sdim  evalstrLengthCommon(C, CE, /* IsStrnlen = */ true);
1140219077Sdim}
1141219077Sdim
1142219077Sdimvoid CStringChecker::evalstrLengthCommon(CheckerContext &C, const CallExpr *CE,
1143219077Sdim                                         bool IsStrnlen) const {
1144224145Sdim  CurrentFunctionDescription = "string length function";
1145234353Sdim  ProgramStateRef state = C.getState();
1146234353Sdim  const LocationContext *LCtx = C.getLocationContext();
1147224145Sdim
1148224145Sdim  if (IsStrnlen) {
1149224145Sdim    const Expr *maxlenExpr = CE->getArg(1);
1150234353Sdim    SVal maxlenVal = state->getSVal(maxlenExpr, LCtx);
1151224145Sdim
1152234353Sdim    ProgramStateRef stateZeroSize, stateNonZeroSize;
1153224145Sdim    llvm::tie(stateZeroSize, stateNonZeroSize) =
1154224145Sdim      assumeZero(C, state, maxlenVal, maxlenExpr->getType());
1155224145Sdim
1156224145Sdim    // If the size can be zero, the result will be 0 in that case, and we don't
1157224145Sdim    // have to check the string itself.
1158224145Sdim    if (stateZeroSize) {
1159224145Sdim      SVal zero = C.getSValBuilder().makeZeroVal(CE->getType());
1160234353Sdim      stateZeroSize = stateZeroSize->BindExpr(CE, LCtx, zero);
1161224145Sdim      C.addTransition(stateZeroSize);
1162224145Sdim    }
1163224145Sdim
1164224145Sdim    // If the size is GUARANTEED to be zero, we're done!
1165224145Sdim    if (!stateNonZeroSize)
1166224145Sdim      return;
1167224145Sdim
1168224145Sdim    // Otherwise, record the assumption that the size is nonzero.
1169224145Sdim    state = stateNonZeroSize;
1170224145Sdim  }
1171224145Sdim
1172224145Sdim  // Check that the string argument is non-null.
1173218887Sdim  const Expr *Arg = CE->getArg(0);
1174234353Sdim  SVal ArgVal = state->getSVal(Arg, LCtx);
1175218887Sdim
1176218887Sdim  state = checkNonNull(C, state, Arg, ArgVal);
1177218887Sdim
1178224145Sdim  if (!state)
1179224145Sdim    return;
1180218887Sdim
1181224145Sdim  SVal strLength = getCStringLength(C, state, Arg, ArgVal);
1182218887Sdim
1183224145Sdim  // If the argument isn't a valid C string, there's no valid state to
1184224145Sdim  // transition to.
1185224145Sdim  if (strLength.isUndef())
1186224145Sdim    return;
1187219077Sdim
1188224145Sdim  DefinedOrUnknownSVal result = UnknownVal();
1189224145Sdim
1190224145Sdim  // If the check is for strnlen() then bind the return value to no more than
1191224145Sdim  // the maxlen value.
1192224145Sdim  if (IsStrnlen) {
1193224145Sdim    QualType cmpTy = C.getSValBuilder().getConditionType();
1194224145Sdim
1195224145Sdim    // It's a little unfortunate to be getting this again,
1196224145Sdim    // but it's not that expensive...
1197224145Sdim    const Expr *maxlenExpr = CE->getArg(1);
1198234353Sdim    SVal maxlenVal = state->getSVal(maxlenExpr, LCtx);
1199224145Sdim
1200249423Sdim    Optional<NonLoc> strLengthNL = strLength.getAs<NonLoc>();
1201249423Sdim    Optional<NonLoc> maxlenValNL = maxlenVal.getAs<NonLoc>();
1202224145Sdim
1203224145Sdim    if (strLengthNL && maxlenValNL) {
1204234353Sdim      ProgramStateRef stateStringTooLong, stateStringNotTooLong;
1205224145Sdim
1206224145Sdim      // Check if the strLength is greater than the maxlen.
1207224145Sdim      llvm::tie(stateStringTooLong, stateStringNotTooLong) =
1208249423Sdim          state->assume(C.getSValBuilder().evalBinOpNN(
1209249423Sdim              state, BO_GT, *strLengthNL, *maxlenValNL, cmpTy)
1210249423Sdim                            .castAs<DefinedOrUnknownSVal>());
1211219077Sdim
1212224145Sdim      if (stateStringTooLong && !stateStringNotTooLong) {
1213224145Sdim        // If the string is longer than maxlen, return maxlen.
1214224145Sdim        result = *maxlenValNL;
1215224145Sdim      } else if (stateStringNotTooLong && !stateStringTooLong) {
1216224145Sdim        // If the string is shorter than maxlen, return its length.
1217224145Sdim        result = *strLengthNL;
1218219077Sdim      }
1219219077Sdim    }
1220219077Sdim
1221224145Sdim    if (result.isUnknown()) {
1222224145Sdim      // If we don't have enough information for a comparison, there's
1223224145Sdim      // no guarantee the full string length will actually be returned.
1224224145Sdim      // All we know is the return value is the min of the string length
1225224145Sdim      // and the limit. This is better than nothing.
1226243830Sdim      result = C.getSValBuilder().conjureSymbolVal(0, CE, LCtx, C.blockCount());
1227249423Sdim      NonLoc resultNL = result.castAs<NonLoc>();
1228224145Sdim
1229224145Sdim      if (strLengthNL) {
1230249423Sdim        state = state->assume(C.getSValBuilder().evalBinOpNN(
1231249423Sdim                                  state, BO_LE, resultNL, *strLengthNL, cmpTy)
1232249423Sdim                                  .castAs<DefinedOrUnknownSVal>(), true);
1233224145Sdim      }
1234224145Sdim
1235224145Sdim      if (maxlenValNL) {
1236249423Sdim        state = state->assume(C.getSValBuilder().evalBinOpNN(
1237249423Sdim                                  state, BO_LE, resultNL, *maxlenValNL, cmpTy)
1238249423Sdim                                  .castAs<DefinedOrUnknownSVal>(), true);
1239224145Sdim      }
1240224145Sdim    }
1241224145Sdim
1242224145Sdim  } else {
1243224145Sdim    // This is a plain strlen(), not strnlen().
1244249423Sdim    result = strLength.castAs<DefinedOrUnknownSVal>();
1245224145Sdim
1246224145Sdim    // If we don't know the length of the string, conjure a return
1247218887Sdim    // value, so it can be used in constraints, at least.
1248224145Sdim    if (result.isUnknown()) {
1249243830Sdim      result = C.getSValBuilder().conjureSymbolVal(0, CE, LCtx, C.blockCount());
1250218887Sdim    }
1251224145Sdim  }
1252218887Sdim
1253224145Sdim  // Bind the return value.
1254224145Sdim  assert(!result.isUnknown() && "Should have conjured a value by now");
1255234353Sdim  state = state->BindExpr(CE, LCtx, result);
1256224145Sdim  C.addTransition(state);
1257218887Sdim}
1258218887Sdim
1259219077Sdimvoid CStringChecker::evalStrcpy(CheckerContext &C, const CallExpr *CE) const {
1260234353Sdim  if (CE->getNumArgs() < 2)
1261234353Sdim    return;
1262234353Sdim
1263218887Sdim  // char *strcpy(char *restrict dst, const char *restrict src);
1264221345Sdim  evalStrcpyCommon(C, CE,
1265221345Sdim                   /* returnEnd = */ false,
1266221345Sdim                   /* isBounded = */ false,
1267221345Sdim                   /* isAppending = */ false);
1268218887Sdim}
1269218887Sdim
1270219077Sdimvoid CStringChecker::evalStrncpy(CheckerContext &C, const CallExpr *CE) const {
1271234353Sdim  if (CE->getNumArgs() < 3)
1272234353Sdim    return;
1273234353Sdim
1274223017Sdim  // char *strncpy(char *restrict dst, const char *restrict src, size_t n);
1275221345Sdim  evalStrcpyCommon(C, CE,
1276221345Sdim                   /* returnEnd = */ false,
1277221345Sdim                   /* isBounded = */ true,
1278221345Sdim                   /* isAppending = */ false);
1279219077Sdim}
1280219077Sdim
1281219077Sdimvoid CStringChecker::evalStpcpy(CheckerContext &C, const CallExpr *CE) const {
1282234353Sdim  if (CE->getNumArgs() < 2)
1283234353Sdim    return;
1284234353Sdim
1285218887Sdim  // char *stpcpy(char *restrict dst, const char *restrict src);
1286221345Sdim  evalStrcpyCommon(C, CE,
1287221345Sdim                   /* returnEnd = */ true,
1288221345Sdim                   /* isBounded = */ false,
1289221345Sdim                   /* isAppending = */ false);
1290218887Sdim}
1291218887Sdim
1292221345Sdimvoid CStringChecker::evalStrcat(CheckerContext &C, const CallExpr *CE) const {
1293234353Sdim  if (CE->getNumArgs() < 2)
1294234353Sdim    return;
1295234353Sdim
1296221345Sdim  //char *strcat(char *restrict s1, const char *restrict s2);
1297221345Sdim  evalStrcpyCommon(C, CE,
1298221345Sdim                   /* returnEnd = */ false,
1299221345Sdim                   /* isBounded = */ false,
1300221345Sdim                   /* isAppending = */ true);
1301221345Sdim}
1302221345Sdim
1303221345Sdimvoid CStringChecker::evalStrncat(CheckerContext &C, const CallExpr *CE) const {
1304234353Sdim  if (CE->getNumArgs() < 3)
1305234353Sdim    return;
1306234353Sdim
1307221345Sdim  //char *strncat(char *restrict s1, const char *restrict s2, size_t n);
1308221345Sdim  evalStrcpyCommon(C, CE,
1309221345Sdim                   /* returnEnd = */ false,
1310221345Sdim                   /* isBounded = */ true,
1311221345Sdim                   /* isAppending = */ true);
1312221345Sdim}
1313221345Sdim
1314218887Sdimvoid CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE,
1315221345Sdim                                      bool returnEnd, bool isBounded,
1316221345Sdim                                      bool isAppending) const {
1317224145Sdim  CurrentFunctionDescription = "string copy function";
1318234353Sdim  ProgramStateRef state = C.getState();
1319234353Sdim  const LocationContext *LCtx = C.getLocationContext();
1320218887Sdim
1321221345Sdim  // Check that the destination is non-null.
1322218887Sdim  const Expr *Dst = CE->getArg(0);
1323234353Sdim  SVal DstVal = state->getSVal(Dst, LCtx);
1324218887Sdim
1325218887Sdim  state = checkNonNull(C, state, Dst, DstVal);
1326218887Sdim  if (!state)
1327218887Sdim    return;
1328218887Sdim
1329218887Sdim  // Check that the source is non-null.
1330218887Sdim  const Expr *srcExpr = CE->getArg(1);
1331234353Sdim  SVal srcVal = state->getSVal(srcExpr, LCtx);
1332218887Sdim  state = checkNonNull(C, state, srcExpr, srcVal);
1333218887Sdim  if (!state)
1334218887Sdim    return;
1335218887Sdim
1336218887Sdim  // Get the string length of the source.
1337218887Sdim  SVal strLength = getCStringLength(C, state, srcExpr, srcVal);
1338218887Sdim
1339218887Sdim  // If the source isn't a valid C string, give up.
1340218887Sdim  if (strLength.isUndef())
1341218887Sdim    return;
1342218887Sdim
1343224145Sdim  SValBuilder &svalBuilder = C.getSValBuilder();
1344224145Sdim  QualType cmpTy = svalBuilder.getConditionType();
1345224145Sdim  QualType sizeTy = svalBuilder.getContext().getSizeType();
1346224145Sdim
1347224145Sdim  // These two values allow checking two kinds of errors:
1348224145Sdim  // - actual overflows caused by a source that doesn't fit in the destination
1349224145Sdim  // - potential overflows caused by a bound that could exceed the destination
1350224145Sdim  SVal amountCopied = UnknownVal();
1351224145Sdim  SVal maxLastElementIndex = UnknownVal();
1352224145Sdim  const char *boundWarning = NULL;
1353224145Sdim
1354221345Sdim  // If the function is strncpy, strncat, etc... it is bounded.
1355221345Sdim  if (isBounded) {
1356221345Sdim    // Get the max number of characters to copy.
1357219077Sdim    const Expr *lenExpr = CE->getArg(2);
1358234353Sdim    SVal lenVal = state->getSVal(lenExpr, LCtx);
1359219077Sdim
1360224145Sdim    // Protect against misdeclared strncpy().
1361224145Sdim    lenVal = svalBuilder.evalCast(lenVal, sizeTy, lenExpr->getType());
1362224145Sdim
1363249423Sdim    Optional<NonLoc> strLengthNL = strLength.getAs<NonLoc>();
1364249423Sdim    Optional<NonLoc> lenValNL = lenVal.getAs<NonLoc>();
1365219077Sdim
1366224145Sdim    // If we know both values, we might be able to figure out how much
1367224145Sdim    // we're copying.
1368224145Sdim    if (strLengthNL && lenValNL) {
1369234353Sdim      ProgramStateRef stateSourceTooLong, stateSourceNotTooLong;
1370219077Sdim
1371224145Sdim      // Check if the max number to copy is less than the length of the src.
1372224145Sdim      // If the bound is equal to the source length, strncpy won't null-
1373224145Sdim      // terminate the result!
1374249423Sdim      llvm::tie(stateSourceTooLong, stateSourceNotTooLong) = state->assume(
1375249423Sdim          svalBuilder.evalBinOpNN(state, BO_GE, *strLengthNL, *lenValNL, cmpTy)
1376249423Sdim              .castAs<DefinedOrUnknownSVal>());
1377224145Sdim
1378224145Sdim      if (stateSourceTooLong && !stateSourceNotTooLong) {
1379224145Sdim        // Max number to copy is less than the length of the src, so the actual
1380224145Sdim        // strLength copied is the max number arg.
1381224145Sdim        state = stateSourceTooLong;
1382224145Sdim        amountCopied = lenVal;
1383224145Sdim
1384224145Sdim      } else if (!stateSourceTooLong && stateSourceNotTooLong) {
1385224145Sdim        // The source buffer entirely fits in the bound.
1386224145Sdim        state = stateSourceNotTooLong;
1387224145Sdim        amountCopied = strLength;
1388224145Sdim      }
1389224145Sdim    }
1390224145Sdim
1391224145Sdim    // We still want to know if the bound is known to be too large.
1392224145Sdim    if (lenValNL) {
1393224145Sdim      if (isAppending) {
1394224145Sdim        // For strncat, the check is strlen(dst) + lenVal < sizeof(dst)
1395224145Sdim
1396224145Sdim        // Get the string length of the destination. If the destination is
1397224145Sdim        // memory that can't have a string length, we shouldn't be copying
1398224145Sdim        // into it anyway.
1399224145Sdim        SVal dstStrLength = getCStringLength(C, state, Dst, DstVal);
1400224145Sdim        if (dstStrLength.isUndef())
1401224145Sdim          return;
1402224145Sdim
1403249423Sdim        if (Optional<NonLoc> dstStrLengthNL = dstStrLength.getAs<NonLoc>()) {
1404224145Sdim          maxLastElementIndex = svalBuilder.evalBinOpNN(state, BO_Add,
1405224145Sdim                                                        *lenValNL,
1406224145Sdim                                                        *dstStrLengthNL,
1407224145Sdim                                                        sizeTy);
1408224145Sdim          boundWarning = "Size argument is greater than the free space in the "
1409224145Sdim                         "destination buffer";
1410224145Sdim        }
1411224145Sdim
1412224145Sdim      } else {
1413224145Sdim        // For strncpy, this is just checking that lenVal <= sizeof(dst)
1414224145Sdim        // (Yes, strncpy and strncat differ in how they treat termination.
1415224145Sdim        // strncat ALWAYS terminates, but strncpy doesn't.)
1416239462Sdim
1417239462Sdim        // We need a special case for when the copy size is zero, in which
1418239462Sdim        // case strncpy will do no work at all. Our bounds check uses n-1
1419239462Sdim        // as the last element accessed, so n == 0 is problematic.
1420239462Sdim        ProgramStateRef StateZeroSize, StateNonZeroSize;
1421239462Sdim        llvm::tie(StateZeroSize, StateNonZeroSize) =
1422239462Sdim          assumeZero(C, state, *lenValNL, sizeTy);
1423239462Sdim
1424239462Sdim        // If the size is known to be zero, we're done.
1425239462Sdim        if (StateZeroSize && !StateNonZeroSize) {
1426239462Sdim          StateZeroSize = StateZeroSize->BindExpr(CE, LCtx, DstVal);
1427239462Sdim          C.addTransition(StateZeroSize);
1428239462Sdim          return;
1429239462Sdim        }
1430239462Sdim
1431239462Sdim        // Otherwise, go ahead and figure out the last element we'll touch.
1432239462Sdim        // We don't record the non-zero assumption here because we can't
1433239462Sdim        // be sure. We won't warn on a possible zero.
1434249423Sdim        NonLoc one = svalBuilder.makeIntVal(1, sizeTy).castAs<NonLoc>();
1435224145Sdim        maxLastElementIndex = svalBuilder.evalBinOpNN(state, BO_Sub, *lenValNL,
1436224145Sdim                                                      one, sizeTy);
1437224145Sdim        boundWarning = "Size argument is greater than the length of the "
1438224145Sdim                       "destination buffer";
1439224145Sdim      }
1440224145Sdim    }
1441224145Sdim
1442224145Sdim    // If we couldn't pin down the copy length, at least bound it.
1443224145Sdim    // FIXME: We should actually run this code path for append as well, but
1444224145Sdim    // right now it creates problems with constraints (since we can end up
1445224145Sdim    // trying to pass constraints from symbol to symbol).
1446224145Sdim    if (amountCopied.isUnknown() && !isAppending) {
1447224145Sdim      // Try to get a "hypothetical" string length symbol, which we can later
1448224145Sdim      // set as a real value if that turns out to be the case.
1449224145Sdim      amountCopied = getCStringLength(C, state, lenExpr, srcVal, true);
1450224145Sdim      assert(!amountCopied.isUndef());
1451224145Sdim
1452249423Sdim      if (Optional<NonLoc> amountCopiedNL = amountCopied.getAs<NonLoc>()) {
1453224145Sdim        if (lenValNL) {
1454224145Sdim          // amountCopied <= lenVal
1455224145Sdim          SVal copiedLessThanBound = svalBuilder.evalBinOpNN(state, BO_LE,
1456224145Sdim                                                             *amountCopiedNL,
1457224145Sdim                                                             *lenValNL,
1458224145Sdim                                                             cmpTy);
1459249423Sdim          state = state->assume(
1460249423Sdim              copiedLessThanBound.castAs<DefinedOrUnknownSVal>(), true);
1461224145Sdim          if (!state)
1462224145Sdim            return;
1463224145Sdim        }
1464224145Sdim
1465224145Sdim        if (strLengthNL) {
1466224145Sdim          // amountCopied <= strlen(source)
1467224145Sdim          SVal copiedLessThanSrc = svalBuilder.evalBinOpNN(state, BO_LE,
1468224145Sdim                                                           *amountCopiedNL,
1469224145Sdim                                                           *strLengthNL,
1470224145Sdim                                                           cmpTy);
1471249423Sdim          state = state->assume(
1472249423Sdim              copiedLessThanSrc.castAs<DefinedOrUnknownSVal>(), true);
1473224145Sdim          if (!state)
1474224145Sdim            return;
1475224145Sdim        }
1476224145Sdim      }
1477224145Sdim    }
1478224145Sdim
1479224145Sdim  } else {
1480224145Sdim    // The function isn't bounded. The amount copied should match the length
1481224145Sdim    // of the source buffer.
1482224145Sdim    amountCopied = strLength;
1483219077Sdim  }
1484219077Sdim
1485224145Sdim  assert(state);
1486224145Sdim
1487224145Sdim  // This represents the number of characters copied into the destination
1488224145Sdim  // buffer. (It may not actually be the strlen if the destination buffer
1489224145Sdim  // is not terminated.)
1490224145Sdim  SVal finalStrLength = UnknownVal();
1491224145Sdim
1492221345Sdim  // If this is an appending function (strcat, strncat...) then set the
1493221345Sdim  // string length to strlen(src) + strlen(dst) since the buffer will
1494221345Sdim  // ultimately contain both.
1495221345Sdim  if (isAppending) {
1496224145Sdim    // Get the string length of the destination. If the destination is memory
1497224145Sdim    // that can't have a string length, we shouldn't be copying into it anyway.
1498221345Sdim    SVal dstStrLength = getCStringLength(C, state, Dst, DstVal);
1499221345Sdim    if (dstStrLength.isUndef())
1500221345Sdim      return;
1501221345Sdim
1502249423Sdim    Optional<NonLoc> srcStrLengthNL = amountCopied.getAs<NonLoc>();
1503249423Sdim    Optional<NonLoc> dstStrLengthNL = dstStrLength.getAs<NonLoc>();
1504221345Sdim
1505224145Sdim    // If we know both string lengths, we might know the final string length.
1506224145Sdim    if (srcStrLengthNL && dstStrLengthNL) {
1507224145Sdim      // Make sure the two lengths together don't overflow a size_t.
1508224145Sdim      state = checkAdditionOverflow(C, state, *srcStrLengthNL, *dstStrLengthNL);
1509224145Sdim      if (!state)
1510224145Sdim        return;
1511221345Sdim
1512224145Sdim      finalStrLength = svalBuilder.evalBinOpNN(state, BO_Add, *srcStrLengthNL,
1513224145Sdim                                               *dstStrLengthNL, sizeTy);
1514224145Sdim    }
1515221345Sdim
1516224145Sdim    // If we couldn't get a single value for the final string length,
1517224145Sdim    // we can at least bound it by the individual lengths.
1518224145Sdim    if (finalStrLength.isUnknown()) {
1519224145Sdim      // Try to get a "hypothetical" string length symbol, which we can later
1520224145Sdim      // set as a real value if that turns out to be the case.
1521224145Sdim      finalStrLength = getCStringLength(C, state, CE, DstVal, true);
1522224145Sdim      assert(!finalStrLength.isUndef());
1523224145Sdim
1524249423Sdim      if (Optional<NonLoc> finalStrLengthNL = finalStrLength.getAs<NonLoc>()) {
1525224145Sdim        if (srcStrLengthNL) {
1526224145Sdim          // finalStrLength >= srcStrLength
1527224145Sdim          SVal sourceInResult = svalBuilder.evalBinOpNN(state, BO_GE,
1528224145Sdim                                                        *finalStrLengthNL,
1529224145Sdim                                                        *srcStrLengthNL,
1530224145Sdim                                                        cmpTy);
1531249423Sdim          state = state->assume(sourceInResult.castAs<DefinedOrUnknownSVal>(),
1532224145Sdim                                true);
1533224145Sdim          if (!state)
1534224145Sdim            return;
1535224145Sdim        }
1536224145Sdim
1537224145Sdim        if (dstStrLengthNL) {
1538224145Sdim          // finalStrLength >= dstStrLength
1539224145Sdim          SVal destInResult = svalBuilder.evalBinOpNN(state, BO_GE,
1540224145Sdim                                                      *finalStrLengthNL,
1541224145Sdim                                                      *dstStrLengthNL,
1542224145Sdim                                                      cmpTy);
1543249423Sdim          state =
1544249423Sdim              state->assume(destInResult.castAs<DefinedOrUnknownSVal>(), true);
1545224145Sdim          if (!state)
1546224145Sdim            return;
1547224145Sdim        }
1548224145Sdim      }
1549224145Sdim    }
1550224145Sdim
1551224145Sdim  } else {
1552224145Sdim    // Otherwise, this is a copy-over function (strcpy, strncpy, ...), and
1553224145Sdim    // the final string length will match the input string length.
1554224145Sdim    finalStrLength = amountCopied;
1555221345Sdim  }
1556221345Sdim
1557224145Sdim  // The final result of the function will either be a pointer past the last
1558224145Sdim  // copied element, or a pointer to the start of the destination buffer.
1559218887Sdim  SVal Result = (returnEnd ? UnknownVal() : DstVal);
1560218887Sdim
1561224145Sdim  assert(state);
1562224145Sdim
1563218887Sdim  // If the destination is a MemRegion, try to check for a buffer overflow and
1564218887Sdim  // record the new string length.
1565249423Sdim  if (Optional<loc::MemRegionVal> dstRegVal =
1566249423Sdim          DstVal.getAs<loc::MemRegionVal>()) {
1567224145Sdim    QualType ptrTy = Dst->getType();
1568218887Sdim
1569224145Sdim    // If we have an exact value on a bounded copy, use that to check for
1570224145Sdim    // overflows, rather than our estimate about how much is actually copied.
1571224145Sdim    if (boundWarning) {
1572249423Sdim      if (Optional<NonLoc> maxLastNL = maxLastElementIndex.getAs<NonLoc>()) {
1573224145Sdim        SVal maxLastElement = svalBuilder.evalBinOpLN(state, BO_Add, *dstRegVal,
1574224145Sdim                                                      *maxLastNL, ptrTy);
1575224145Sdim        state = CheckLocation(C, state, CE->getArg(2), maxLastElement,
1576224145Sdim                              boundWarning);
1577224145Sdim        if (!state)
1578224145Sdim          return;
1579224145Sdim      }
1580224145Sdim    }
1581218887Sdim
1582224145Sdim    // Then, if the final length is known...
1583249423Sdim    if (Optional<NonLoc> knownStrLength = finalStrLength.getAs<NonLoc>()) {
1584224145Sdim      SVal lastElement = svalBuilder.evalBinOpLN(state, BO_Add, *dstRegVal,
1585224145Sdim                                                 *knownStrLength, ptrTy);
1586224145Sdim
1587224145Sdim      // ...and we haven't checked the bound, we'll check the actual copy.
1588224145Sdim      if (!boundWarning) {
1589224145Sdim        const char * const warningMsg =
1590224145Sdim          "String copy function overflows destination buffer";
1591224145Sdim        state = CheckLocation(C, state, Dst, lastElement, warningMsg);
1592224145Sdim        if (!state)
1593224145Sdim          return;
1594224145Sdim      }
1595224145Sdim
1596218887Sdim      // If this is a stpcpy-style copy, the last element is the return value.
1597218887Sdim      if (returnEnd)
1598218887Sdim        Result = lastElement;
1599218887Sdim    }
1600218887Sdim
1601263508Sdim    // Invalidate the destination (regular invalidation without pointer-escaping
1602263508Sdim    // the address of the top-level region). This must happen before we set the
1603263508Sdim    // C string length because invalidation will clear the length.
1604218887Sdim    // FIXME: Even if we can't perfectly model the copy, we should see if we
1605218887Sdim    // can use LazyCompoundVals to copy the source values into the destination.
1606218887Sdim    // This would probably remove any existing bindings past the end of the
1607218887Sdim    // string, but that's still an improvement over blank invalidation.
1608263508Sdim    state = InvalidateBuffer(C, state, Dst, *dstRegVal,
1609263508Sdim                             /*IsSourceBuffer*/false);
1610218887Sdim
1611263508Sdim    // Invalidate the source (const-invalidation without const-pointer-escaping
1612263508Sdim    // the address of the top-level region).
1613263508Sdim    state = InvalidateBuffer(C, state, srcExpr, srcVal, /*IsSourceBuffer*/true);
1614263508Sdim
1615224145Sdim    // Set the C string length of the destination, if we know it.
1616224145Sdim    if (isBounded && !isAppending) {
1617224145Sdim      // strncpy is annoying in that it doesn't guarantee to null-terminate
1618224145Sdim      // the result string. If the original string didn't fit entirely inside
1619224145Sdim      // the bound (including the null-terminator), we don't know how long the
1620224145Sdim      // result is.
1621224145Sdim      if (amountCopied != strLength)
1622224145Sdim        finalStrLength = UnknownVal();
1623224145Sdim    }
1624224145Sdim    state = setCStringLength(state, dstRegVal->getRegion(), finalStrLength);
1625218887Sdim  }
1626218887Sdim
1627224145Sdim  assert(state);
1628224145Sdim
1629218887Sdim  // If this is a stpcpy-style copy, but we were unable to check for a buffer
1630218887Sdim  // overflow, we still need a result. Conjure a return value.
1631218887Sdim  if (returnEnd && Result.isUnknown()) {
1632243830Sdim    Result = svalBuilder.conjureSymbolVal(0, CE, LCtx, C.blockCount());
1633218887Sdim  }
1634218887Sdim
1635218887Sdim  // Set the return value.
1636234353Sdim  state = state->BindExpr(CE, LCtx, Result);
1637218887Sdim  C.addTransition(state);
1638218887Sdim}
1639218887Sdim
1640221345Sdimvoid CStringChecker::evalStrcmp(CheckerContext &C, const CallExpr *CE) const {
1641234353Sdim  if (CE->getNumArgs() < 2)
1642234353Sdim    return;
1643234353Sdim
1644224145Sdim  //int strcmp(const char *s1, const char *s2);
1645221345Sdim  evalStrcmpCommon(C, CE, /* isBounded = */ false, /* ignoreCase = */ false);
1646221345Sdim}
1647221345Sdim
1648221345Sdimvoid CStringChecker::evalStrncmp(CheckerContext &C, const CallExpr *CE) const {
1649234353Sdim  if (CE->getNumArgs() < 3)
1650234353Sdim    return;
1651234353Sdim
1652224145Sdim  //int strncmp(const char *s1, const char *s2, size_t n);
1653221345Sdim  evalStrcmpCommon(C, CE, /* isBounded = */ true, /* ignoreCase = */ false);
1654221345Sdim}
1655221345Sdim
1656221345Sdimvoid CStringChecker::evalStrcasecmp(CheckerContext &C,
1657221345Sdim                                    const CallExpr *CE) const {
1658234353Sdim  if (CE->getNumArgs() < 2)
1659234353Sdim    return;
1660234353Sdim
1661224145Sdim  //int strcasecmp(const char *s1, const char *s2);
1662221345Sdim  evalStrcmpCommon(C, CE, /* isBounded = */ false, /* ignoreCase = */ true);
1663221345Sdim}
1664221345Sdim
1665223017Sdimvoid CStringChecker::evalStrncasecmp(CheckerContext &C,
1666223017Sdim                                     const CallExpr *CE) const {
1667234353Sdim  if (CE->getNumArgs() < 3)
1668234353Sdim    return;
1669234353Sdim
1670224145Sdim  //int strncasecmp(const char *s1, const char *s2, size_t n);
1671223017Sdim  evalStrcmpCommon(C, CE, /* isBounded = */ true, /* ignoreCase = */ true);
1672223017Sdim}
1673223017Sdim
1674221345Sdimvoid CStringChecker::evalStrcmpCommon(CheckerContext &C, const CallExpr *CE,
1675221345Sdim                                      bool isBounded, bool ignoreCase) const {
1676224145Sdim  CurrentFunctionDescription = "string comparison function";
1677234353Sdim  ProgramStateRef state = C.getState();
1678234353Sdim  const LocationContext *LCtx = C.getLocationContext();
1679221345Sdim
1680221345Sdim  // Check that the first string is non-null
1681221345Sdim  const Expr *s1 = CE->getArg(0);
1682234353Sdim  SVal s1Val = state->getSVal(s1, LCtx);
1683221345Sdim  state = checkNonNull(C, state, s1, s1Val);
1684221345Sdim  if (!state)
1685221345Sdim    return;
1686221345Sdim
1687221345Sdim  // Check that the second string is non-null.
1688221345Sdim  const Expr *s2 = CE->getArg(1);
1689234353Sdim  SVal s2Val = state->getSVal(s2, LCtx);
1690221345Sdim  state = checkNonNull(C, state, s2, s2Val);
1691221345Sdim  if (!state)
1692221345Sdim    return;
1693221345Sdim
1694221345Sdim  // Get the string length of the first string or give up.
1695221345Sdim  SVal s1Length = getCStringLength(C, state, s1, s1Val);
1696221345Sdim  if (s1Length.isUndef())
1697221345Sdim    return;
1698221345Sdim
1699221345Sdim  // Get the string length of the second string or give up.
1700221345Sdim  SVal s2Length = getCStringLength(C, state, s2, s2Val);
1701221345Sdim  if (s2Length.isUndef())
1702221345Sdim    return;
1703221345Sdim
1704224145Sdim  // If we know the two buffers are the same, we know the result is 0.
1705224145Sdim  // First, get the two buffers' addresses. Another checker will have already
1706224145Sdim  // made sure they're not undefined.
1707249423Sdim  DefinedOrUnknownSVal LV = s1Val.castAs<DefinedOrUnknownSVal>();
1708249423Sdim  DefinedOrUnknownSVal RV = s2Val.castAs<DefinedOrUnknownSVal>();
1709221345Sdim
1710224145Sdim  // See if they are the same.
1711224145Sdim  SValBuilder &svalBuilder = C.getSValBuilder();
1712224145Sdim  DefinedOrUnknownSVal SameBuf = svalBuilder.evalEQ(state, LV, RV);
1713234353Sdim  ProgramStateRef StSameBuf, StNotSameBuf;
1714224145Sdim  llvm::tie(StSameBuf, StNotSameBuf) = state->assume(SameBuf);
1715221345Sdim
1716224145Sdim  // If the two arguments might be the same buffer, we know the result is 0,
1717224145Sdim  // and we only need to check one size.
1718224145Sdim  if (StSameBuf) {
1719234353Sdim    StSameBuf = StSameBuf->BindExpr(CE, LCtx,
1720234353Sdim                                    svalBuilder.makeZeroVal(CE->getType()));
1721224145Sdim    C.addTransition(StSameBuf);
1722221345Sdim
1723224145Sdim    // If the two arguments are GUARANTEED to be the same, we're done!
1724224145Sdim    if (!StNotSameBuf)
1725221345Sdim      return;
1726224145Sdim  }
1727221345Sdim
1728224145Sdim  assert(StNotSameBuf);
1729224145Sdim  state = StNotSameBuf;
1730224145Sdim
1731224145Sdim  // At this point we can go about comparing the two buffers.
1732224145Sdim  // For now, we only do this if they're both known string literals.
1733224145Sdim
1734224145Sdim  // Attempt to extract string literals from both expressions.
1735224145Sdim  const StringLiteral *s1StrLiteral = getCStringLiteral(C, state, s1, s1Val);
1736224145Sdim  const StringLiteral *s2StrLiteral = getCStringLiteral(C, state, s2, s2Val);
1737224145Sdim  bool canComputeResult = false;
1738224145Sdim
1739224145Sdim  if (s1StrLiteral && s2StrLiteral) {
1740226633Sdim    StringRef s1StrRef = s1StrLiteral->getString();
1741226633Sdim    StringRef s2StrRef = s2StrLiteral->getString();
1742224145Sdim
1743224145Sdim    if (isBounded) {
1744224145Sdim      // Get the max number of characters to compare.
1745224145Sdim      const Expr *lenExpr = CE->getArg(2);
1746234353Sdim      SVal lenVal = state->getSVal(lenExpr, LCtx);
1747224145Sdim
1748224145Sdim      // If the length is known, we can get the right substrings.
1749224145Sdim      if (const llvm::APSInt *len = svalBuilder.getKnownValue(state, lenVal)) {
1750224145Sdim        // Create substrings of each to compare the prefix.
1751224145Sdim        s1StrRef = s1StrRef.substr(0, (size_t)len->getZExtValue());
1752224145Sdim        s2StrRef = s2StrRef.substr(0, (size_t)len->getZExtValue());
1753224145Sdim        canComputeResult = true;
1754224145Sdim      }
1755224145Sdim    } else {
1756224145Sdim      // This is a normal, unbounded strcmp.
1757224145Sdim      canComputeResult = true;
1758224145Sdim    }
1759224145Sdim
1760224145Sdim    if (canComputeResult) {
1761224145Sdim      // Real strcmp stops at null characters.
1762224145Sdim      size_t s1Term = s1StrRef.find('\0');
1763226633Sdim      if (s1Term != StringRef::npos)
1764224145Sdim        s1StrRef = s1StrRef.substr(0, s1Term);
1765224145Sdim
1766224145Sdim      size_t s2Term = s2StrRef.find('\0');
1767226633Sdim      if (s2Term != StringRef::npos)
1768224145Sdim        s2StrRef = s2StrRef.substr(0, s2Term);
1769224145Sdim
1770224145Sdim      // Use StringRef's comparison methods to compute the actual result.
1771224145Sdim      int result;
1772224145Sdim
1773224145Sdim      if (ignoreCase) {
1774224145Sdim        // Compare string 1 to string 2 the same way strcasecmp() does.
1775224145Sdim        result = s1StrRef.compare_lower(s2StrRef);
1776224145Sdim      } else {
1777224145Sdim        // Compare string 1 to string 2 the same way strcmp() does.
1778224145Sdim        result = s1StrRef.compare(s2StrRef);
1779224145Sdim      }
1780224145Sdim
1781224145Sdim      // Build the SVal of the comparison and bind the return value.
1782224145Sdim      SVal resultVal = svalBuilder.makeIntVal(result, CE->getType());
1783234353Sdim      state = state->BindExpr(CE, LCtx, resultVal);
1784224145Sdim    }
1785223017Sdim  }
1786221345Sdim
1787224145Sdim  if (!canComputeResult) {
1788224145Sdim    // Conjure a symbolic value. It's the best we can do.
1789243830Sdim    SVal resultVal = svalBuilder.conjureSymbolVal(0, CE, LCtx, C.blockCount());
1790234353Sdim    state = state->BindExpr(CE, LCtx, resultVal);
1791221345Sdim  }
1792221345Sdim
1793224145Sdim  // Record this as a possible path.
1794221345Sdim  C.addTransition(state);
1795221345Sdim}
1796221345Sdim
1797251662Sdimvoid CStringChecker::evalStrsep(CheckerContext &C, const CallExpr *CE) const {
1798251662Sdim  //char *strsep(char **stringp, const char *delim);
1799251662Sdim  if (CE->getNumArgs() < 2)
1800251662Sdim    return;
1801251662Sdim
1802251662Sdim  // Sanity: does the search string parameter match the return type?
1803251662Sdim  const Expr *SearchStrPtr = CE->getArg(0);
1804251662Sdim  QualType CharPtrTy = SearchStrPtr->getType()->getPointeeType();
1805251662Sdim  if (CharPtrTy.isNull() ||
1806251662Sdim      CE->getType().getUnqualifiedType() != CharPtrTy.getUnqualifiedType())
1807251662Sdim    return;
1808251662Sdim
1809251662Sdim  CurrentFunctionDescription = "strsep()";
1810251662Sdim  ProgramStateRef State = C.getState();
1811251662Sdim  const LocationContext *LCtx = C.getLocationContext();
1812251662Sdim
1813251662Sdim  // Check that the search string pointer is non-null (though it may point to
1814251662Sdim  // a null string).
1815251662Sdim  SVal SearchStrVal = State->getSVal(SearchStrPtr, LCtx);
1816251662Sdim  State = checkNonNull(C, State, SearchStrPtr, SearchStrVal);
1817251662Sdim  if (!State)
1818251662Sdim    return;
1819251662Sdim
1820251662Sdim  // Check that the delimiter string is non-null.
1821251662Sdim  const Expr *DelimStr = CE->getArg(1);
1822251662Sdim  SVal DelimStrVal = State->getSVal(DelimStr, LCtx);
1823251662Sdim  State = checkNonNull(C, State, DelimStr, DelimStrVal);
1824251662Sdim  if (!State)
1825251662Sdim    return;
1826251662Sdim
1827251662Sdim  SValBuilder &SVB = C.getSValBuilder();
1828251662Sdim  SVal Result;
1829251662Sdim  if (Optional<Loc> SearchStrLoc = SearchStrVal.getAs<Loc>()) {
1830251662Sdim    // Get the current value of the search string pointer, as a char*.
1831251662Sdim    Result = State->getSVal(*SearchStrLoc, CharPtrTy);
1832251662Sdim
1833251662Sdim    // Invalidate the search string, representing the change of one delimiter
1834251662Sdim    // character to NUL.
1835263508Sdim    State = InvalidateBuffer(C, State, SearchStrPtr, Result,
1836263508Sdim                             /*IsSourceBuffer*/false);
1837251662Sdim
1838251662Sdim    // Overwrite the search string pointer. The new value is either an address
1839251662Sdim    // further along in the same string, or NULL if there are no more tokens.
1840251662Sdim    State = State->bindLoc(*SearchStrLoc,
1841251662Sdim                           SVB.conjureSymbolVal(getTag(), CE, LCtx, CharPtrTy,
1842251662Sdim                                                C.blockCount()));
1843251662Sdim  } else {
1844251662Sdim    assert(SearchStrVal.isUnknown());
1845251662Sdim    // Conjure a symbolic value. It's the best we can do.
1846251662Sdim    Result = SVB.conjureSymbolVal(0, CE, LCtx, C.blockCount());
1847251662Sdim  }
1848251662Sdim
1849251662Sdim  // Set the return value, and finish.
1850251662Sdim  State = State->BindExpr(CE, LCtx, Result);
1851251662Sdim  C.addTransition(State);
1852251662Sdim}
1853251662Sdim
1854251662Sdim
1855218887Sdim//===----------------------------------------------------------------------===//
1856218887Sdim// The driver method, and other Checker callbacks.
1857218887Sdim//===----------------------------------------------------------------------===//
1858218887Sdim
1859219077Sdimbool CStringChecker::evalCall(const CallExpr *CE, CheckerContext &C) const {
1860234353Sdim  const FunctionDecl *FDecl = C.getCalleeDecl(CE);
1861218887Sdim
1862234353Sdim  if (!FDecl)
1863218887Sdim    return false;
1864218887Sdim
1865251662Sdim  // FIXME: Poorly-factored string switches are slow.
1866234353Sdim  FnCheck evalFunction = 0;
1867234353Sdim  if (C.isCLibraryFunction(FDecl, "memcpy"))
1868234353Sdim    evalFunction =  &CStringChecker::evalMemcpy;
1869234353Sdim  else if (C.isCLibraryFunction(FDecl, "mempcpy"))
1870234353Sdim    evalFunction =  &CStringChecker::evalMempcpy;
1871234353Sdim  else if (C.isCLibraryFunction(FDecl, "memcmp"))
1872234353Sdim    evalFunction =  &CStringChecker::evalMemcmp;
1873234353Sdim  else if (C.isCLibraryFunction(FDecl, "memmove"))
1874234353Sdim    evalFunction =  &CStringChecker::evalMemmove;
1875234353Sdim  else if (C.isCLibraryFunction(FDecl, "strcpy"))
1876234353Sdim    evalFunction =  &CStringChecker::evalStrcpy;
1877234353Sdim  else if (C.isCLibraryFunction(FDecl, "strncpy"))
1878234353Sdim    evalFunction =  &CStringChecker::evalStrncpy;
1879234353Sdim  else if (C.isCLibraryFunction(FDecl, "stpcpy"))
1880234353Sdim    evalFunction =  &CStringChecker::evalStpcpy;
1881234353Sdim  else if (C.isCLibraryFunction(FDecl, "strcat"))
1882234353Sdim    evalFunction =  &CStringChecker::evalStrcat;
1883234353Sdim  else if (C.isCLibraryFunction(FDecl, "strncat"))
1884234353Sdim    evalFunction =  &CStringChecker::evalStrncat;
1885234353Sdim  else if (C.isCLibraryFunction(FDecl, "strlen"))
1886234353Sdim    evalFunction =  &CStringChecker::evalstrLength;
1887234353Sdim  else if (C.isCLibraryFunction(FDecl, "strnlen"))
1888234353Sdim    evalFunction =  &CStringChecker::evalstrnLength;
1889234353Sdim  else if (C.isCLibraryFunction(FDecl, "strcmp"))
1890234353Sdim    evalFunction =  &CStringChecker::evalStrcmp;
1891234353Sdim  else if (C.isCLibraryFunction(FDecl, "strncmp"))
1892234353Sdim    evalFunction =  &CStringChecker::evalStrncmp;
1893234353Sdim  else if (C.isCLibraryFunction(FDecl, "strcasecmp"))
1894234353Sdim    evalFunction =  &CStringChecker::evalStrcasecmp;
1895234353Sdim  else if (C.isCLibraryFunction(FDecl, "strncasecmp"))
1896234353Sdim    evalFunction =  &CStringChecker::evalStrncasecmp;
1897251662Sdim  else if (C.isCLibraryFunction(FDecl, "strsep"))
1898251662Sdim    evalFunction =  &CStringChecker::evalStrsep;
1899234353Sdim  else if (C.isCLibraryFunction(FDecl, "bcopy"))
1900234353Sdim    evalFunction =  &CStringChecker::evalBcopy;
1901234353Sdim  else if (C.isCLibraryFunction(FDecl, "bcmp"))
1902234353Sdim    evalFunction =  &CStringChecker::evalMemcmp;
1903234353Sdim
1904218887Sdim  // If the callee isn't a string function, let another checker handle it.
1905218887Sdim  if (!evalFunction)
1906218887Sdim    return false;
1907218887Sdim
1908224145Sdim  // Make sure each function sets its own description.
1909224145Sdim  // (But don't bother in a release build.)
1910224145Sdim  assert(!(CurrentFunctionDescription = NULL));
1911224145Sdim
1912218887Sdim  // Check and evaluate the call.
1913218887Sdim  (this->*evalFunction)(C, CE);
1914234353Sdim
1915234353Sdim  // If the evaluate call resulted in no change, chain to the next eval call
1916234353Sdim  // handler.
1917234353Sdim  // Note, the custom CString evaluation calls assume that basic safety
1918234353Sdim  // properties are held. However, if the user chooses to turn off some of these
1919234353Sdim  // checks, we ignore the issues and leave the call evaluation to a generic
1920234353Sdim  // handler.
1921234353Sdim  if (!C.isDifferent())
1922234353Sdim    return false;
1923234353Sdim
1924218887Sdim  return true;
1925218887Sdim}
1926218887Sdim
1927219077Sdimvoid CStringChecker::checkPreStmt(const DeclStmt *DS, CheckerContext &C) const {
1928218887Sdim  // Record string length for char a[] = "abc";
1929234353Sdim  ProgramStateRef state = C.getState();
1930218887Sdim
1931218887Sdim  for (DeclStmt::const_decl_iterator I = DS->decl_begin(), E = DS->decl_end();
1932218887Sdim       I != E; ++I) {
1933218887Sdim    const VarDecl *D = dyn_cast<VarDecl>(*I);
1934218887Sdim    if (!D)
1935218887Sdim      continue;
1936218887Sdim
1937218887Sdim    // FIXME: Handle array fields of structs.
1938218887Sdim    if (!D->getType()->isArrayType())
1939218887Sdim      continue;
1940218887Sdim
1941218887Sdim    const Expr *Init = D->getInit();
1942218887Sdim    if (!Init)
1943218887Sdim      continue;
1944218887Sdim    if (!isa<StringLiteral>(Init))
1945218887Sdim      continue;
1946218887Sdim
1947234353Sdim    Loc VarLoc = state->getLValue(D, C.getLocationContext());
1948218887Sdim    const MemRegion *MR = VarLoc.getAsRegion();
1949218887Sdim    if (!MR)
1950218887Sdim      continue;
1951218887Sdim
1952234353Sdim    SVal StrVal = state->getSVal(Init, C.getLocationContext());
1953218887Sdim    assert(StrVal.isValid() && "Initializer string is unknown or undefined");
1954249423Sdim    DefinedOrUnknownSVal strLength =
1955249423Sdim        getCStringLength(C, state, Init, StrVal).castAs<DefinedOrUnknownSVal>();
1956218887Sdim
1957218887Sdim    state = state->set<CStringLength>(MR, strLength);
1958218887Sdim  }
1959218887Sdim
1960218887Sdim  C.addTransition(state);
1961218887Sdim}
1962218887Sdim
1963234353Sdimbool CStringChecker::wantsRegionChangeUpdate(ProgramStateRef state) const {
1964243830Sdim  CStringLengthTy Entries = state->get<CStringLength>();
1965218887Sdim  return !Entries.isEmpty();
1966218887Sdim}
1967218887Sdim
1968234353SdimProgramStateRef
1969234353SdimCStringChecker::checkRegionChanges(ProgramStateRef state,
1970249423Sdim                                   const InvalidatedSymbols *,
1971226633Sdim                                   ArrayRef<const MemRegion *> ExplicitRegions,
1972234353Sdim                                   ArrayRef<const MemRegion *> Regions,
1973239462Sdim                                   const CallEvent *Call) const {
1974243830Sdim  CStringLengthTy Entries = state->get<CStringLength>();
1975218887Sdim  if (Entries.isEmpty())
1976218887Sdim    return state;
1977218887Sdim
1978218887Sdim  llvm::SmallPtrSet<const MemRegion *, 8> Invalidated;
1979218887Sdim  llvm::SmallPtrSet<const MemRegion *, 32> SuperRegions;
1980218887Sdim
1981218887Sdim  // First build sets for the changed regions and their super-regions.
1982226633Sdim  for (ArrayRef<const MemRegion *>::iterator
1983226633Sdim       I = Regions.begin(), E = Regions.end(); I != E; ++I) {
1984226633Sdim    const MemRegion *MR = *I;
1985218887Sdim    Invalidated.insert(MR);
1986218887Sdim
1987218887Sdim    SuperRegions.insert(MR);
1988218887Sdim    while (const SubRegion *SR = dyn_cast<SubRegion>(MR)) {
1989218887Sdim      MR = SR->getSuperRegion();
1990218887Sdim      SuperRegions.insert(MR);
1991218887Sdim    }
1992218887Sdim  }
1993218887Sdim
1994243830Sdim  CStringLengthTy::Factory &F = state->get_context<CStringLength>();
1995218887Sdim
1996218887Sdim  // Then loop over the entries in the current state.
1997243830Sdim  for (CStringLengthTy::iterator I = Entries.begin(),
1998218887Sdim       E = Entries.end(); I != E; ++I) {
1999218887Sdim    const MemRegion *MR = I.getKey();
2000218887Sdim
2001218887Sdim    // Is this entry for a super-region of a changed region?
2002218887Sdim    if (SuperRegions.count(MR)) {
2003218887Sdim      Entries = F.remove(Entries, MR);
2004218887Sdim      continue;
2005218887Sdim    }
2006218887Sdim
2007218887Sdim    // Is this entry for a sub-region of a changed region?
2008218887Sdim    const MemRegion *Super = MR;
2009218887Sdim    while (const SubRegion *SR = dyn_cast<SubRegion>(Super)) {
2010218887Sdim      Super = SR->getSuperRegion();
2011218887Sdim      if (Invalidated.count(Super)) {
2012218887Sdim        Entries = F.remove(Entries, MR);
2013218887Sdim        break;
2014218887Sdim      }
2015218887Sdim    }
2016218887Sdim  }
2017218887Sdim
2018218887Sdim  return state->set<CStringLength>(Entries);
2019218887Sdim}
2020218887Sdim
2021234353Sdimvoid CStringChecker::checkLiveSymbols(ProgramStateRef state,
2022219077Sdim                                      SymbolReaper &SR) const {
2023218887Sdim  // Mark all symbols in our string length map as valid.
2024243830Sdim  CStringLengthTy Entries = state->get<CStringLength>();
2025218887Sdim
2026243830Sdim  for (CStringLengthTy::iterator I = Entries.begin(), E = Entries.end();
2027218887Sdim       I != E; ++I) {
2028218887Sdim    SVal Len = I.getData();
2029224145Sdim
2030234353Sdim    for (SymExpr::symbol_iterator si = Len.symbol_begin(),
2031234353Sdim                                  se = Len.symbol_end(); si != se; ++si)
2032224145Sdim      SR.markInUse(*si);
2033218887Sdim  }
2034218887Sdim}
2035218887Sdim
2036219077Sdimvoid CStringChecker::checkDeadSymbols(SymbolReaper &SR,
2037219077Sdim                                      CheckerContext &C) const {
2038218887Sdim  if (!SR.hasDeadSymbols())
2039218887Sdim    return;
2040218887Sdim
2041234353Sdim  ProgramStateRef state = C.getState();
2042243830Sdim  CStringLengthTy Entries = state->get<CStringLength>();
2043218887Sdim  if (Entries.isEmpty())
2044218887Sdim    return;
2045218887Sdim
2046243830Sdim  CStringLengthTy::Factory &F = state->get_context<CStringLength>();
2047243830Sdim  for (CStringLengthTy::iterator I = Entries.begin(), E = Entries.end();
2048218887Sdim       I != E; ++I) {
2049218887Sdim    SVal Len = I.getData();
2050218887Sdim    if (SymbolRef Sym = Len.getAsSymbol()) {
2051218887Sdim      if (SR.isDead(Sym))
2052218887Sdim        Entries = F.remove(Entries, I.getKey());
2053218887Sdim    }
2054218887Sdim  }
2055218887Sdim
2056218887Sdim  state = state->set<CStringLength>(Entries);
2057234353Sdim  C.addTransition(state);
2058218887Sdim}
2059219077Sdim
2060234353Sdim#define REGISTER_CHECKER(name) \
2061234353Sdimvoid ento::register##name(CheckerManager &mgr) {\
2062263508Sdim  mgr.registerChecker<CStringChecker>()->Filter.Check##name = true; \
2063219077Sdim}
2064234353Sdim
2065234353SdimREGISTER_CHECKER(CStringNullArg)
2066234353SdimREGISTER_CHECKER(CStringOutOfBounds)
2067234353SdimREGISTER_CHECKER(CStringBufferOverlap)
2068234353SdimREGISTER_CHECKER(CStringNotNullTerm)
2069234353Sdim
2070234353Sdimvoid ento::registerCStringCheckerBasic(CheckerManager &Mgr) {
2071234353Sdim  registerCStringNullArg(Mgr);
2072234353Sdim}
2073