diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h index a6005ffd96..8c541efd6f 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h @@ -143,30 +143,17 @@ class SVal { void dumpToStream(raw_ostream &OS) const; void dump() const; - // Iterators. - class symbol_iterator { - SmallVector itr; - void expand(); - public: - symbol_iterator() {} - symbol_iterator(const SymExpr *SE); - - symbol_iterator &operator++(); - SymbolRef operator*(); - - bool operator==(const symbol_iterator &X) const; - bool operator!=(const symbol_iterator &X) const; - }; - - symbol_iterator symbol_begin() const { + SymExpr::symbol_iterator symbol_begin() const { const SymExpr *SE = getAsSymbolicExpression(); if (SE) - return symbol_iterator(SE); + return SE->symbol_begin(); else - return symbol_iterator(); + return SymExpr::symbol_iterator(); } - symbol_iterator symbol_end() const { return symbol_iterator(); } + SymExpr::symbol_iterator symbol_end() const { + return SymExpr::symbol_end(); + } // Implement isa support. static inline bool classof(const SVal*) { return true; } diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h index addc0d3988..d47363cc10 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h @@ -69,6 +69,26 @@ class SymExpr : public llvm::FoldingSetNode { // Implement isa support. static inline bool classof(const SymExpr*) { return true; } + + class symbol_iterator { + SmallVector itr; + void expand(); + public: + symbol_iterator() {} + symbol_iterator(const SymExpr *SE); + + symbol_iterator &operator++(); + const SymExpr* operator*(); + + bool operator==(const symbol_iterator &X) const; + bool operator!=(const symbol_iterator &X) const; + }; + + symbol_iterator symbol_begin() const { + return symbol_iterator(this); + } + + static symbol_iterator symbol_end() { return symbol_iterator(); } }; typedef const SymExpr* SymbolRef; diff --git a/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/lib/StaticAnalyzer/Checkers/CStringChecker.cpp index 6ab98b4187..ff9d8689f6 100644 --- a/lib/StaticAnalyzer/Checkers/CStringChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/CStringChecker.cpp @@ -1804,8 +1804,8 @@ void CStringChecker::checkLiveSymbols(const ProgramState *state, I != E; ++I) { SVal Len = I.getData(); - for (SVal::symbol_iterator si = Len.symbol_begin(), se = Len.symbol_end(); - si != se; ++si) + for (SymExpr::symbol_iterator si = Len.symbol_begin(), + se = Len.symbol_end(); si != se; ++si) SR.markInUse(*si); } } diff --git a/lib/StaticAnalyzer/Core/ProgramState.cpp b/lib/StaticAnalyzer/Core/ProgramState.cpp index 2dafeeee00..a725d38192 100644 --- a/lib/StaticAnalyzer/Core/ProgramState.cpp +++ b/lib/StaticAnalyzer/Core/ProgramState.cpp @@ -673,29 +673,21 @@ bool ProgramState::isTainted(SVal V, TaintTagType Kind) const { bool ProgramState::isTainted(const SymExpr* Sym, TaintTagType Kind) const { if (!Sym) return false; - - // TODO: Can we use symbol_iterator (like removeDeadBindingsWorker) here? - - // Check taint on derived symbols. - if (const SymbolDerived *SD = dyn_cast(Sym)) - return isTainted(SD->getParentSymbol(), Kind); - - if (const SymbolCast *SC = dyn_cast(Sym)) - return (isTainted(SC->getOperand(), Kind)); - - if (const SymIntExpr *SIE = dyn_cast(Sym)) - return isTainted(SIE->getLHS(), Kind); - - if (const SymSymExpr *SSE = dyn_cast(Sym)) - return (isTainted(SSE->getLHS(), Kind) || isTainted(SSE->getRHS(), Kind)); - - // Check taint on the current symbol. - if (const SymbolData *SymR = dyn_cast(Sym)) { - const TaintTagType *Tag = get(SymR); - return (Tag && *Tag == Kind); + + // Travese all the symbols this symbol depends on to see if any are tainted. + bool Tainted = false; + for (SymExpr::symbol_iterator SI = Sym->symbol_begin(), SE =Sym->symbol_end(); + SI != SE; ++SI) { + assert(isa(*SI)); + const TaintTagType *Tag = get(*SI); + Tainted = (Tag && *Tag == Kind); + + // If this is a SymbolDerived with a tainted parent, it's also tainted. + if (const SymbolDerived *SD = dyn_cast(*SI)) + Tainted = Tainted || isTainted(SD->getParentSymbol(), Kind); + if (Tainted) + return true; } - - // TODO: Remove llvm unreachable. - llvm_unreachable("We do not know show to check taint on this symbol."); - return false; + + return Tainted; } diff --git a/lib/StaticAnalyzer/Core/RegionStore.cpp b/lib/StaticAnalyzer/Core/RegionStore.cpp index 4f811dfa73..56ce0e13a9 100644 --- a/lib/StaticAnalyzer/Core/RegionStore.cpp +++ b/lib/StaticAnalyzer/Core/RegionStore.cpp @@ -1721,8 +1721,8 @@ void removeDeadBindingsWorker::VisitBinding(SVal V) { AddToWorkList(R); // Update the set of live symbols. - for (SVal::symbol_iterator SI=V.symbol_begin(), SE=V.symbol_end(); - SI!=SE;++SI) + for (SymExpr::symbol_iterator SI = V.symbol_begin(), SE = V.symbol_end(); + SI!=SE; ++SI) SymReaper.markLive(*SI); } @@ -1810,7 +1810,7 @@ StoreRef RegionStoreManager::removeDeadBindings(Store store, SymReaper.maybeDead(SymR->getSymbol()); SVal X = I.getData(); - SVal::symbol_iterator SI = X.symbol_begin(), SE = X.symbol_end(); + SymExpr::symbol_iterator SI = X.symbol_begin(), SE = X.symbol_end(); for (; SI != SE; ++SI) SymReaper.maybeDead(*SI); } diff --git a/lib/StaticAnalyzer/Core/SVals.cpp b/lib/StaticAnalyzer/Core/SVals.cpp index 97e5a1be4c..27d6e3eed1 100644 --- a/lib/StaticAnalyzer/Core/SVals.cpp +++ b/lib/StaticAnalyzer/Core/SVals.cpp @@ -138,54 +138,6 @@ const MemRegion *loc::MemRegionVal::stripCasts() const { return R ? R->StripCasts() : NULL; } -bool SVal::symbol_iterator::operator==(const symbol_iterator &X) const { - return itr == X.itr; -} - -bool SVal::symbol_iterator::operator!=(const symbol_iterator &X) const { - return itr != X.itr; -} - -SVal::symbol_iterator::symbol_iterator(const SymExpr *SE) { - itr.push_back(SE); - while (!isa(itr.back())) expand(); -} - -SVal::symbol_iterator &SVal::symbol_iterator::operator++() { - assert(!itr.empty() && "attempting to iterate on an 'end' iterator"); - assert(isa(itr.back())); - itr.pop_back(); - if (!itr.empty()) - while (!isa(itr.back())) expand(); - return *this; -} - -SymbolRef SVal::symbol_iterator::operator*() { - assert(!itr.empty() && "attempting to dereference an 'end' iterator"); - return cast(itr.back()); -} - -void SVal::symbol_iterator::expand() { - const SymExpr *SE = itr.back(); - itr.pop_back(); - - if (const SymbolCast *SC = dyn_cast(SE)) { - itr.push_back(SC->getOperand()); - return; - } - if (const SymIntExpr *SIE = dyn_cast(SE)) { - itr.push_back(SIE->getLHS()); - return; - } - else if (const SymSymExpr *SSE = dyn_cast(SE)) { - itr.push_back(SSE->getLHS()); - itr.push_back(SSE->getRHS()); - return; - } - - llvm_unreachable("unhandled expansion case"); -} - const void *nonloc::LazyCompoundVal::getStore() const { return static_cast(Data)->getStore(); } diff --git a/lib/StaticAnalyzer/Core/SymbolManager.cpp b/lib/StaticAnalyzer/Core/SymbolManager.cpp index 02c0a9e36d..e79075f412 100644 --- a/lib/StaticAnalyzer/Core/SymbolManager.cpp +++ b/lib/StaticAnalyzer/Core/SymbolManager.cpp @@ -94,6 +94,54 @@ void SymbolRegionValue::dumpToStream(raw_ostream &os) const { os << "reg_$" << getSymbolID() << "<" << R << ">"; } +bool SymExpr::symbol_iterator::operator==(const symbol_iterator &X) const { + return itr == X.itr; +} + +bool SymExpr::symbol_iterator::operator!=(const symbol_iterator &X) const { + return itr != X.itr; +} + +SymExpr::symbol_iterator::symbol_iterator(const SymExpr *SE) { + itr.push_back(SE); + while (!isa(itr.back())) expand(); +} + +SymExpr::symbol_iterator &SymExpr::symbol_iterator::operator++() { + assert(!itr.empty() && "attempting to iterate on an 'end' iterator"); + assert(isa(itr.back())); + itr.pop_back(); + if (!itr.empty()) + while (!isa(itr.back())) expand(); + return *this; +} + +SymbolRef SymExpr::symbol_iterator::operator*() { + assert(!itr.empty() && "attempting to dereference an 'end' iterator"); + return cast(itr.back()); +} + +void SymExpr::symbol_iterator::expand() { + const SymExpr *SE = itr.back(); + itr.pop_back(); + + if (const SymbolCast *SC = dyn_cast(SE)) { + itr.push_back(SC->getOperand()); + return; + } + if (const SymIntExpr *SIE = dyn_cast(SE)) { + itr.push_back(SIE->getLHS()); + return; + } + else if (const SymSymExpr *SSE = dyn_cast(SE)) { + itr.push_back(SSE->getLHS()); + itr.push_back(SSE->getRHS()); + return; + } + + llvm_unreachable("unhandled expansion case"); +} + const SymbolRegionValue* SymbolManager::getRegionValueSymbol(const TypedValueRegion* R) { llvm::FoldingSetNodeID profile;