ProgramState.cpp revision 341825
1//= ProgramState.cpp - Path-Sensitive "State" for tracking values --*- C++ -*--=
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10//  This file implements ProgramState and ProgramStateManager.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
15#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
16#include "clang/Analysis/CFG.h"
17#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
18#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
19#include "clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h"
20#include "clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h"
21#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h"
22#include "llvm/Support/raw_ostream.h"
23
24using namespace clang;
25using namespace ento;
26
27namespace clang { namespace  ento {
28/// Increments the number of times this state is referenced.
29
30void ProgramStateRetain(const ProgramState *state) {
31  ++const_cast<ProgramState*>(state)->refCount;
32}
33
34/// Decrement the number of times this state is referenced.
35void ProgramStateRelease(const ProgramState *state) {
36  assert(state->refCount > 0);
37  ProgramState *s = const_cast<ProgramState*>(state);
38  if (--s->refCount == 0) {
39    ProgramStateManager &Mgr = s->getStateManager();
40    Mgr.StateSet.RemoveNode(s);
41    s->~ProgramState();
42    Mgr.freeStates.push_back(s);
43  }
44}
45}}
46
47ProgramState::ProgramState(ProgramStateManager *mgr, const Environment& env,
48                 StoreRef st, GenericDataMap gdm)
49  : stateMgr(mgr),
50    Env(env),
51    store(st.getStore()),
52    GDM(gdm),
53    refCount(0) {
54  stateMgr->getStoreManager().incrementReferenceCount(store);
55}
56
57ProgramState::ProgramState(const ProgramState &RHS)
58    : llvm::FoldingSetNode(),
59      stateMgr(RHS.stateMgr),
60      Env(RHS.Env),
61      store(RHS.store),
62      GDM(RHS.GDM),
63      refCount(0) {
64  stateMgr->getStoreManager().incrementReferenceCount(store);
65}
66
67ProgramState::~ProgramState() {
68  if (store)
69    stateMgr->getStoreManager().decrementReferenceCount(store);
70}
71
72ProgramStateManager::ProgramStateManager(ASTContext &Ctx,
73                                         StoreManagerCreator CreateSMgr,
74                                         ConstraintManagerCreator CreateCMgr,
75                                         llvm::BumpPtrAllocator &alloc,
76                                         SubEngine *SubEng)
77  : Eng(SubEng), EnvMgr(alloc), GDMFactory(alloc),
78    svalBuilder(createSimpleSValBuilder(alloc, Ctx, *this)),
79    CallEventMgr(new CallEventManager(alloc)), Alloc(alloc) {
80  StoreMgr = (*CreateSMgr)(*this);
81  ConstraintMgr = (*CreateCMgr)(*this, SubEng);
82}
83
84
85ProgramStateManager::~ProgramStateManager() {
86  for (GDMContextsTy::iterator I=GDMContexts.begin(), E=GDMContexts.end();
87       I!=E; ++I)
88    I->second.second(I->second.first);
89}
90
91ProgramStateRef
92ProgramStateManager::removeDeadBindings(ProgramStateRef state,
93                                   const StackFrameContext *LCtx,
94                                   SymbolReaper& SymReaper) {
95
96  // This code essentially performs a "mark-and-sweep" of the VariableBindings.
97  // The roots are any Block-level exprs and Decls that our liveness algorithm
98  // tells us are live.  We then see what Decls they may reference, and keep
99  // those around.  This code more than likely can be made faster, and the
100  // frequency of which this method is called should be experimented with
101  // for optimum performance.
102  ProgramState NewState = *state;
103
104  NewState.Env = EnvMgr.removeDeadBindings(NewState.Env, SymReaper, state);
105
106  // Clean up the store.
107  StoreRef newStore = StoreMgr->removeDeadBindings(NewState.getStore(), LCtx,
108                                                   SymReaper);
109  NewState.setStore(newStore);
110  SymReaper.setReapedStore(newStore);
111
112  ProgramStateRef Result = getPersistentState(NewState);
113  return ConstraintMgr->removeDeadBindings(Result, SymReaper);
114}
115
116ProgramStateRef ProgramState::bindLoc(Loc LV,
117                                      SVal V,
118                                      const LocationContext *LCtx,
119                                      bool notifyChanges) const {
120  ProgramStateManager &Mgr = getStateManager();
121  ProgramStateRef newState = makeWithStore(Mgr.StoreMgr->Bind(getStore(),
122                                                             LV, V));
123  const MemRegion *MR = LV.getAsRegion();
124  if (MR && Mgr.getOwningEngine() && notifyChanges)
125    return Mgr.getOwningEngine()->processRegionChange(newState, MR, LCtx);
126
127  return newState;
128}
129
130ProgramStateRef
131ProgramState::bindDefaultInitial(SVal loc, SVal V,
132                                 const LocationContext *LCtx) const {
133  ProgramStateManager &Mgr = getStateManager();
134  const MemRegion *R = loc.castAs<loc::MemRegionVal>().getRegion();
135  const StoreRef &newStore = Mgr.StoreMgr->BindDefaultInitial(getStore(), R, V);
136  ProgramStateRef new_state = makeWithStore(newStore);
137  return Mgr.getOwningEngine()
138             ? Mgr.getOwningEngine()->processRegionChange(new_state, R, LCtx)
139             : new_state;
140}
141
142ProgramStateRef
143ProgramState::bindDefaultZero(SVal loc, const LocationContext *LCtx) const {
144  ProgramStateManager &Mgr = getStateManager();
145  const MemRegion *R = loc.castAs<loc::MemRegionVal>().getRegion();
146  const StoreRef &newStore = Mgr.StoreMgr->BindDefaultZero(getStore(), R);
147  ProgramStateRef new_state = makeWithStore(newStore);
148  return Mgr.getOwningEngine()
149             ? Mgr.getOwningEngine()->processRegionChange(new_state, R, LCtx)
150             : new_state;
151}
152
153typedef ArrayRef<const MemRegion *> RegionList;
154typedef ArrayRef<SVal> ValueList;
155
156ProgramStateRef
157ProgramState::invalidateRegions(RegionList Regions,
158                             const Expr *E, unsigned Count,
159                             const LocationContext *LCtx,
160                             bool CausedByPointerEscape,
161                             InvalidatedSymbols *IS,
162                             const CallEvent *Call,
163                             RegionAndSymbolInvalidationTraits *ITraits) const {
164  SmallVector<SVal, 8> Values;
165  for (RegionList::const_iterator I = Regions.begin(),
166                                  End = Regions.end(); I != End; ++I)
167    Values.push_back(loc::MemRegionVal(*I));
168
169  return invalidateRegionsImpl(Values, E, Count, LCtx, CausedByPointerEscape,
170                               IS, ITraits, Call);
171}
172
173ProgramStateRef
174ProgramState::invalidateRegions(ValueList Values,
175                             const Expr *E, unsigned Count,
176                             const LocationContext *LCtx,
177                             bool CausedByPointerEscape,
178                             InvalidatedSymbols *IS,
179                             const CallEvent *Call,
180                             RegionAndSymbolInvalidationTraits *ITraits) const {
181
182  return invalidateRegionsImpl(Values, E, Count, LCtx, CausedByPointerEscape,
183                               IS, ITraits, Call);
184}
185
186ProgramStateRef
187ProgramState::invalidateRegionsImpl(ValueList Values,
188                                    const Expr *E, unsigned Count,
189                                    const LocationContext *LCtx,
190                                    bool CausedByPointerEscape,
191                                    InvalidatedSymbols *IS,
192                                    RegionAndSymbolInvalidationTraits *ITraits,
193                                    const CallEvent *Call) const {
194  ProgramStateManager &Mgr = getStateManager();
195  SubEngine* Eng = Mgr.getOwningEngine();
196
197  InvalidatedSymbols Invalidated;
198  if (!IS)
199    IS = &Invalidated;
200
201  RegionAndSymbolInvalidationTraits ITraitsLocal;
202  if (!ITraits)
203    ITraits = &ITraitsLocal;
204
205  if (Eng) {
206    StoreManager::InvalidatedRegions TopLevelInvalidated;
207    StoreManager::InvalidatedRegions Invalidated;
208    const StoreRef &newStore
209    = Mgr.StoreMgr->invalidateRegions(getStore(), Values, E, Count, LCtx, Call,
210                                      *IS, *ITraits, &TopLevelInvalidated,
211                                      &Invalidated);
212
213    ProgramStateRef newState = makeWithStore(newStore);
214
215    if (CausedByPointerEscape) {
216      newState = Eng->notifyCheckersOfPointerEscape(newState, IS,
217                                                    TopLevelInvalidated,
218                                                    Invalidated, Call,
219                                                    *ITraits);
220    }
221
222    return Eng->processRegionChanges(newState, IS, TopLevelInvalidated,
223                                     Invalidated, LCtx, Call);
224  }
225
226  const StoreRef &newStore =
227  Mgr.StoreMgr->invalidateRegions(getStore(), Values, E, Count, LCtx, Call,
228                                  *IS, *ITraits, nullptr, nullptr);
229  return makeWithStore(newStore);
230}
231
232ProgramStateRef ProgramState::killBinding(Loc LV) const {
233  assert(!LV.getAs<loc::MemRegionVal>() && "Use invalidateRegion instead.");
234
235  Store OldStore = getStore();
236  const StoreRef &newStore =
237    getStateManager().StoreMgr->killBinding(OldStore, LV);
238
239  if (newStore.getStore() == OldStore)
240    return this;
241
242  return makeWithStore(newStore);
243}
244
245ProgramStateRef
246ProgramState::enterStackFrame(const CallEvent &Call,
247                              const StackFrameContext *CalleeCtx) const {
248  const StoreRef &NewStore =
249    getStateManager().StoreMgr->enterStackFrame(getStore(), Call, CalleeCtx);
250  return makeWithStore(NewStore);
251}
252
253SVal ProgramState::getSValAsScalarOrLoc(const MemRegion *R) const {
254  // We only want to do fetches from regions that we can actually bind
255  // values.  For example, SymbolicRegions of type 'id<...>' cannot
256  // have direct bindings (but their can be bindings on their subregions).
257  if (!R->isBoundable())
258    return UnknownVal();
259
260  if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) {
261    QualType T = TR->getValueType();
262    if (Loc::isLocType(T) || T->isIntegralOrEnumerationType())
263      return getSVal(R);
264  }
265
266  return UnknownVal();
267}
268
269SVal ProgramState::getSVal(Loc location, QualType T) const {
270  SVal V = getRawSVal(location, T);
271
272  // If 'V' is a symbolic value that is *perfectly* constrained to
273  // be a constant value, use that value instead to lessen the burden
274  // on later analysis stages (so we have less symbolic values to reason
275  // about).
276  // We only go into this branch if we can convert the APSInt value we have
277  // to the type of T, which is not always the case (e.g. for void).
278  if (!T.isNull() && (T->isIntegralOrEnumerationType() || Loc::isLocType(T))) {
279    if (SymbolRef sym = V.getAsSymbol()) {
280      if (const llvm::APSInt *Int = getStateManager()
281                                    .getConstraintManager()
282                                    .getSymVal(this, sym)) {
283        // FIXME: Because we don't correctly model (yet) sign-extension
284        // and truncation of symbolic values, we need to convert
285        // the integer value to the correct signedness and bitwidth.
286        //
287        // This shows up in the following:
288        //
289        //   char foo();
290        //   unsigned x = foo();
291        //   if (x == 54)
292        //     ...
293        //
294        //  The symbolic value stored to 'x' is actually the conjured
295        //  symbol for the call to foo(); the type of that symbol is 'char',
296        //  not unsigned.
297        const llvm::APSInt &NewV = getBasicVals().Convert(T, *Int);
298
299        if (V.getAs<Loc>())
300          return loc::ConcreteInt(NewV);
301        else
302          return nonloc::ConcreteInt(NewV);
303      }
304    }
305  }
306
307  return V;
308}
309
310ProgramStateRef ProgramState::BindExpr(const Stmt *S,
311                                           const LocationContext *LCtx,
312                                           SVal V, bool Invalidate) const{
313  Environment NewEnv =
314    getStateManager().EnvMgr.bindExpr(Env, EnvironmentEntry(S, LCtx), V,
315                                      Invalidate);
316  if (NewEnv == Env)
317    return this;
318
319  ProgramState NewSt = *this;
320  NewSt.Env = NewEnv;
321  return getStateManager().getPersistentState(NewSt);
322}
323
324ProgramStateRef ProgramState::assumeInBound(DefinedOrUnknownSVal Idx,
325                                      DefinedOrUnknownSVal UpperBound,
326                                      bool Assumption,
327                                      QualType indexTy) const {
328  if (Idx.isUnknown() || UpperBound.isUnknown())
329    return this;
330
331  // Build an expression for 0 <= Idx < UpperBound.
332  // This is the same as Idx + MIN < UpperBound + MIN, if overflow is allowed.
333  // FIXME: This should probably be part of SValBuilder.
334  ProgramStateManager &SM = getStateManager();
335  SValBuilder &svalBuilder = SM.getSValBuilder();
336  ASTContext &Ctx = svalBuilder.getContext();
337
338  // Get the offset: the minimum value of the array index type.
339  BasicValueFactory &BVF = svalBuilder.getBasicValueFactory();
340  if (indexTy.isNull())
341    indexTy = svalBuilder.getArrayIndexType();
342  nonloc::ConcreteInt Min(BVF.getMinValue(indexTy));
343
344  // Adjust the index.
345  SVal newIdx = svalBuilder.evalBinOpNN(this, BO_Add,
346                                        Idx.castAs<NonLoc>(), Min, indexTy);
347  if (newIdx.isUnknownOrUndef())
348    return this;
349
350  // Adjust the upper bound.
351  SVal newBound =
352    svalBuilder.evalBinOpNN(this, BO_Add, UpperBound.castAs<NonLoc>(),
353                            Min, indexTy);
354
355  if (newBound.isUnknownOrUndef())
356    return this;
357
358  // Build the actual comparison.
359  SVal inBound = svalBuilder.evalBinOpNN(this, BO_LT, newIdx.castAs<NonLoc>(),
360                                         newBound.castAs<NonLoc>(), Ctx.IntTy);
361  if (inBound.isUnknownOrUndef())
362    return this;
363
364  // Finally, let the constraint manager take care of it.
365  ConstraintManager &CM = SM.getConstraintManager();
366  return CM.assume(this, inBound.castAs<DefinedSVal>(), Assumption);
367}
368
369ConditionTruthVal ProgramState::isNonNull(SVal V) const {
370  ConditionTruthVal IsNull = isNull(V);
371  if (IsNull.isUnderconstrained())
372    return IsNull;
373  return ConditionTruthVal(!IsNull.getValue());
374}
375
376ConditionTruthVal ProgramState::areEqual(SVal Lhs, SVal Rhs) const {
377  return stateMgr->getSValBuilder().areEqual(this, Lhs, Rhs);
378}
379
380ConditionTruthVal ProgramState::isNull(SVal V) const {
381  if (V.isZeroConstant())
382    return true;
383
384  if (V.isConstant())
385    return false;
386
387  SymbolRef Sym = V.getAsSymbol(/* IncludeBaseRegion */ true);
388  if (!Sym)
389    return ConditionTruthVal();
390
391  return getStateManager().ConstraintMgr->isNull(this, Sym);
392}
393
394ProgramStateRef ProgramStateManager::getInitialState(const LocationContext *InitLoc) {
395  ProgramState State(this,
396                EnvMgr.getInitialEnvironment(),
397                StoreMgr->getInitialStore(InitLoc),
398                GDMFactory.getEmptyMap());
399
400  return getPersistentState(State);
401}
402
403ProgramStateRef ProgramStateManager::getPersistentStateWithGDM(
404                                                     ProgramStateRef FromState,
405                                                     ProgramStateRef GDMState) {
406  ProgramState NewState(*FromState);
407  NewState.GDM = GDMState->GDM;
408  return getPersistentState(NewState);
409}
410
411ProgramStateRef ProgramStateManager::getPersistentState(ProgramState &State) {
412
413  llvm::FoldingSetNodeID ID;
414  State.Profile(ID);
415  void *InsertPos;
416
417  if (ProgramState *I = StateSet.FindNodeOrInsertPos(ID, InsertPos))
418    return I;
419
420  ProgramState *newState = nullptr;
421  if (!freeStates.empty()) {
422    newState = freeStates.back();
423    freeStates.pop_back();
424  }
425  else {
426    newState = (ProgramState*) Alloc.Allocate<ProgramState>();
427  }
428  new (newState) ProgramState(State);
429  StateSet.InsertNode(newState, InsertPos);
430  return newState;
431}
432
433ProgramStateRef ProgramState::makeWithStore(const StoreRef &store) const {
434  ProgramState NewSt(*this);
435  NewSt.setStore(store);
436  return getStateManager().getPersistentState(NewSt);
437}
438
439void ProgramState::setStore(const StoreRef &newStore) {
440  Store newStoreStore = newStore.getStore();
441  if (newStoreStore)
442    stateMgr->getStoreManager().incrementReferenceCount(newStoreStore);
443  if (store)
444    stateMgr->getStoreManager().decrementReferenceCount(store);
445  store = newStoreStore;
446}
447
448//===----------------------------------------------------------------------===//
449//  State pretty-printing.
450//===----------------------------------------------------------------------===//
451
452void ProgramState::print(raw_ostream &Out, const char *NL, const char *Sep,
453                         const LocationContext *LC) const {
454  // Print the store.
455  ProgramStateManager &Mgr = getStateManager();
456  Mgr.getStoreManager().print(getStore(), Out, NL, Sep);
457
458  // Print out the environment.
459  Env.print(Out, NL, Sep, LC);
460
461  // Print out the constraints.
462  Mgr.getConstraintManager().print(this, Out, NL, Sep);
463
464  // Print out the tracked dynamic types.
465  printDynamicTypeInfo(this, Out, NL, Sep);
466
467  // Print out tainted symbols.
468  printTaint(Out, NL, Sep);
469
470  // Print checker-specific data.
471  Mgr.getOwningEngine()->printState(Out, this, NL, Sep, LC);
472}
473
474void ProgramState::printDOT(raw_ostream &Out, const LocationContext *LC) const {
475  print(Out, "\\l", "\\|", LC);
476}
477
478LLVM_DUMP_METHOD void ProgramState::dump() const {
479  print(llvm::errs());
480}
481
482void ProgramState::printTaint(raw_ostream &Out,
483                              const char *NL, const char *Sep) const {
484  TaintMapImpl TM = get<TaintMap>();
485
486  if (!TM.isEmpty())
487    Out <<"Tainted symbols:" << NL;
488
489  for (TaintMapImpl::iterator I = TM.begin(), E = TM.end(); I != E; ++I) {
490    Out << I->first << " : " << I->second << NL;
491  }
492}
493
494void ProgramState::dumpTaint() const {
495  printTaint(llvm::errs());
496}
497
498AnalysisManager& ProgramState::getAnalysisManager() const {
499  return stateMgr->getOwningEngine()->getAnalysisManager();
500}
501
502//===----------------------------------------------------------------------===//
503// Generic Data Map.
504//===----------------------------------------------------------------------===//
505
506void *const* ProgramState::FindGDM(void *K) const {
507  return GDM.lookup(K);
508}
509
510void*
511ProgramStateManager::FindGDMContext(void *K,
512                               void *(*CreateContext)(llvm::BumpPtrAllocator&),
513                               void (*DeleteContext)(void*)) {
514
515  std::pair<void*, void (*)(void*)>& p = GDMContexts[K];
516  if (!p.first) {
517    p.first = CreateContext(Alloc);
518    p.second = DeleteContext;
519  }
520
521  return p.first;
522}
523
524ProgramStateRef ProgramStateManager::addGDM(ProgramStateRef St, void *Key, void *Data){
525  ProgramState::GenericDataMap M1 = St->getGDM();
526  ProgramState::GenericDataMap M2 = GDMFactory.add(M1, Key, Data);
527
528  if (M1 == M2)
529    return St;
530
531  ProgramState NewSt = *St;
532  NewSt.GDM = M2;
533  return getPersistentState(NewSt);
534}
535
536ProgramStateRef ProgramStateManager::removeGDM(ProgramStateRef state, void *Key) {
537  ProgramState::GenericDataMap OldM = state->getGDM();
538  ProgramState::GenericDataMap NewM = GDMFactory.remove(OldM, Key);
539
540  if (NewM == OldM)
541    return state;
542
543  ProgramState NewState = *state;
544  NewState.GDM = NewM;
545  return getPersistentState(NewState);
546}
547
548bool ScanReachableSymbols::scan(nonloc::LazyCompoundVal val) {
549  bool wasVisited = !visited.insert(val.getCVData()).second;
550  if (wasVisited)
551    return true;
552
553  StoreManager &StoreMgr = state->getStateManager().getStoreManager();
554  // FIXME: We don't really want to use getBaseRegion() here because pointer
555  // arithmetic doesn't apply, but scanReachableSymbols only accepts base
556  // regions right now.
557  const MemRegion *R = val.getRegion()->getBaseRegion();
558  return StoreMgr.scanReachableSymbols(val.getStore(), R, *this);
559}
560
561bool ScanReachableSymbols::scan(nonloc::CompoundVal val) {
562  for (nonloc::CompoundVal::iterator I=val.begin(), E=val.end(); I!=E; ++I)
563    if (!scan(*I))
564      return false;
565
566  return true;
567}
568
569bool ScanReachableSymbols::scan(const SymExpr *sym) {
570  for (SymExpr::symbol_iterator SI = sym->symbol_begin(),
571                                SE = sym->symbol_end();
572       SI != SE; ++SI) {
573    bool wasVisited = !visited.insert(*SI).second;
574    if (wasVisited)
575      continue;
576
577    if (!visitor.VisitSymbol(*SI))
578      return false;
579  }
580
581  return true;
582}
583
584bool ScanReachableSymbols::scan(SVal val) {
585  if (Optional<loc::MemRegionVal> X = val.getAs<loc::MemRegionVal>())
586    return scan(X->getRegion());
587
588  if (Optional<nonloc::LazyCompoundVal> X =
589          val.getAs<nonloc::LazyCompoundVal>())
590    return scan(*X);
591
592  if (Optional<nonloc::LocAsInteger> X = val.getAs<nonloc::LocAsInteger>())
593    return scan(X->getLoc());
594
595  if (SymbolRef Sym = val.getAsSymbol())
596    return scan(Sym);
597
598  if (const SymExpr *Sym = val.getAsSymbolicExpression())
599    return scan(Sym);
600
601  if (Optional<nonloc::CompoundVal> X = val.getAs<nonloc::CompoundVal>())
602    return scan(*X);
603
604  return true;
605}
606
607bool ScanReachableSymbols::scan(const MemRegion *R) {
608  if (isa<MemSpaceRegion>(R))
609    return true;
610
611  bool wasVisited = !visited.insert(R).second;
612  if (wasVisited)
613    return true;
614
615  if (!visitor.VisitMemRegion(R))
616    return false;
617
618  // If this is a symbolic region, visit the symbol for the region.
619  if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R))
620    if (!visitor.VisitSymbol(SR->getSymbol()))
621      return false;
622
623  // If this is a subregion, also visit the parent regions.
624  if (const SubRegion *SR = dyn_cast<SubRegion>(R)) {
625    const MemRegion *Super = SR->getSuperRegion();
626    if (!scan(Super))
627      return false;
628
629    // When we reach the topmost region, scan all symbols in it.
630    if (isa<MemSpaceRegion>(Super)) {
631      StoreManager &StoreMgr = state->getStateManager().getStoreManager();
632      if (!StoreMgr.scanReachableSymbols(state->getStore(), SR, *this))
633        return false;
634    }
635  }
636
637  // Regions captured by a block are also implicitly reachable.
638  if (const BlockDataRegion *BDR = dyn_cast<BlockDataRegion>(R)) {
639    BlockDataRegion::referenced_vars_iterator I = BDR->referenced_vars_begin(),
640                                              E = BDR->referenced_vars_end();
641    for ( ; I != E; ++I) {
642      if (!scan(I.getCapturedRegion()))
643        return false;
644    }
645  }
646
647  return true;
648}
649
650bool ProgramState::scanReachableSymbols(SVal val, SymbolVisitor& visitor) const {
651  ScanReachableSymbols S(this, visitor);
652  return S.scan(val);
653}
654
655bool ProgramState::scanReachableSymbols(const SVal *I, const SVal *E,
656                                   SymbolVisitor &visitor) const {
657  ScanReachableSymbols S(this, visitor);
658  for ( ; I != E; ++I) {
659    if (!S.scan(*I))
660      return false;
661  }
662  return true;
663}
664
665bool ProgramState::scanReachableSymbols(const MemRegion * const *I,
666                                   const MemRegion * const *E,
667                                   SymbolVisitor &visitor) const {
668  ScanReachableSymbols S(this, visitor);
669  for ( ; I != E; ++I) {
670    if (!S.scan(*I))
671      return false;
672  }
673  return true;
674}
675
676ProgramStateRef ProgramState::addTaint(const Stmt *S,
677                                           const LocationContext *LCtx,
678                                           TaintTagType Kind) const {
679  if (const Expr *E = dyn_cast_or_null<Expr>(S))
680    S = E->IgnoreParens();
681
682  return addTaint(getSVal(S, LCtx), Kind);
683}
684
685ProgramStateRef ProgramState::addTaint(SVal V,
686                                       TaintTagType Kind) const {
687  SymbolRef Sym = V.getAsSymbol();
688  if (Sym)
689    return addTaint(Sym, Kind);
690
691  // If the SVal represents a structure, try to mass-taint all values within the
692  // structure. For now it only works efficiently on lazy compound values that
693  // were conjured during a conservative evaluation of a function - either as
694  // return values of functions that return structures or arrays by value, or as
695  // values of structures or arrays passed into the function by reference,
696  // directly or through pointer aliasing. Such lazy compound values are
697  // characterized by having exactly one binding in their captured store within
698  // their parent region, which is a conjured symbol default-bound to the base
699  // region of the parent region.
700  if (auto LCV = V.getAs<nonloc::LazyCompoundVal>()) {
701    if (Optional<SVal> binding = getStateManager().StoreMgr->getDefaultBinding(*LCV)) {
702      if (SymbolRef Sym = binding->getAsSymbol())
703        return addPartialTaint(Sym, LCV->getRegion(), Kind);
704    }
705  }
706
707  const MemRegion *R = V.getAsRegion();
708  return addTaint(R, Kind);
709}
710
711ProgramStateRef ProgramState::addTaint(const MemRegion *R,
712                                           TaintTagType Kind) const {
713  if (const SymbolicRegion *SR = dyn_cast_or_null<SymbolicRegion>(R))
714    return addTaint(SR->getSymbol(), Kind);
715  return this;
716}
717
718ProgramStateRef ProgramState::addTaint(SymbolRef Sym,
719                                           TaintTagType Kind) const {
720  // If this is a symbol cast, remove the cast before adding the taint. Taint
721  // is cast agnostic.
722  while (const SymbolCast *SC = dyn_cast<SymbolCast>(Sym))
723    Sym = SC->getOperand();
724
725  ProgramStateRef NewState = set<TaintMap>(Sym, Kind);
726  assert(NewState);
727  return NewState;
728}
729
730ProgramStateRef ProgramState::addPartialTaint(SymbolRef ParentSym,
731                                              const SubRegion *SubRegion,
732                                              TaintTagType Kind) const {
733  // Ignore partial taint if the entire parent symbol is already tainted.
734  if (contains<TaintMap>(ParentSym) && *get<TaintMap>(ParentSym) == Kind)
735    return this;
736
737  // Partial taint applies if only a portion of the symbol is tainted.
738  if (SubRegion == SubRegion->getBaseRegion())
739    return addTaint(ParentSym, Kind);
740
741  const TaintedSubRegions *SavedRegs = get<DerivedSymTaint>(ParentSym);
742  TaintedSubRegions Regs =
743      SavedRegs ? *SavedRegs : stateMgr->TSRFactory.getEmptyMap();
744
745  Regs = stateMgr->TSRFactory.add(Regs, SubRegion, Kind);
746  ProgramStateRef NewState = set<DerivedSymTaint>(ParentSym, Regs);
747  assert(NewState);
748  return NewState;
749}
750
751bool ProgramState::isTainted(const Stmt *S, const LocationContext *LCtx,
752                             TaintTagType Kind) const {
753  if (const Expr *E = dyn_cast_or_null<Expr>(S))
754    S = E->IgnoreParens();
755
756  SVal val = getSVal(S, LCtx);
757  return isTainted(val, Kind);
758}
759
760bool ProgramState::isTainted(SVal V, TaintTagType Kind) const {
761  if (const SymExpr *Sym = V.getAsSymExpr())
762    return isTainted(Sym, Kind);
763  if (const MemRegion *Reg = V.getAsRegion())
764    return isTainted(Reg, Kind);
765  return false;
766}
767
768bool ProgramState::isTainted(const MemRegion *Reg, TaintTagType K) const {
769  if (!Reg)
770    return false;
771
772  // Element region (array element) is tainted if either the base or the offset
773  // are tainted.
774  if (const ElementRegion *ER = dyn_cast<ElementRegion>(Reg))
775    return isTainted(ER->getSuperRegion(), K) || isTainted(ER->getIndex(), K);
776
777  if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(Reg))
778    return isTainted(SR->getSymbol(), K);
779
780  if (const SubRegion *ER = dyn_cast<SubRegion>(Reg))
781    return isTainted(ER->getSuperRegion(), K);
782
783  return false;
784}
785
786bool ProgramState::isTainted(SymbolRef Sym, TaintTagType Kind) const {
787  if (!Sym)
788    return false;
789
790  // Traverse all the symbols this symbol depends on to see if any are tainted.
791  for (SymExpr::symbol_iterator SI = Sym->symbol_begin(), SE =Sym->symbol_end();
792       SI != SE; ++SI) {
793    if (!isa<SymbolData>(*SI))
794      continue;
795
796    if (const TaintTagType *Tag = get<TaintMap>(*SI)) {
797      if (*Tag == Kind)
798        return true;
799    }
800
801    if (const SymbolDerived *SD = dyn_cast<SymbolDerived>(*SI)) {
802      // If this is a SymbolDerived with a tainted parent, it's also tainted.
803      if (isTainted(SD->getParentSymbol(), Kind))
804        return true;
805
806      // If this is a SymbolDerived with the same parent symbol as another
807      // tainted SymbolDerived and a region that's a sub-region of that tainted
808      // symbol, it's also tainted.
809      if (const TaintedSubRegions *Regs =
810              get<DerivedSymTaint>(SD->getParentSymbol())) {
811        const TypedValueRegion *R = SD->getRegion();
812        for (auto I : *Regs) {
813          // FIXME: The logic to identify tainted regions could be more
814          // complete. For example, this would not currently identify
815          // overlapping fields in a union as tainted. To identify this we can
816          // check for overlapping/nested byte offsets.
817          if (Kind == I.second && R->isSubRegionOf(I.first))
818            return true;
819        }
820      }
821    }
822
823    // If memory region is tainted, data is also tainted.
824    if (const SymbolRegionValue *SRV = dyn_cast<SymbolRegionValue>(*SI)) {
825      if (isTainted(SRV->getRegion(), Kind))
826        return true;
827    }
828
829    // If this is a SymbolCast from a tainted value, it's also tainted.
830    if (const SymbolCast *SC = dyn_cast<SymbolCast>(*SI)) {
831      if (isTainted(SC->getOperand(), Kind))
832        return true;
833    }
834  }
835
836  return false;
837}
838
839