diff options
author | Anna Zaks <ganna@apple.com> | 2011-12-06 23:12:27 +0000 |
---|---|---|
committer | Anna Zaks <ganna@apple.com> | 2011-12-06 23:12:27 +0000 |
commit | aace9ef279be3dadd53b481aee568bd7701178b4 (patch) | |
tree | 9da5657b9b4926b62e1e8fe095d0b844ae4ab923 /lib | |
parent | e5ee70d08e62cb6c96a736163204c12c6ef8147a (diff) |
[analyzer] Propagate taint through NonLoc to NonLoc casts.
- Created a new SymExpr type - SymbolCast.
- SymbolCast is created when we don't know how to simplify a NonLoc to
NonLoc casts.
- A bit of code refactoring: introduced dispatchCast to have better
code reuse, remove a goto.
- Updated the test case to showcase the new taint flow.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@145985 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/StaticAnalyzer/Core/ProgramState.cpp | 7 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/RegionStore.cpp | 2 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/SValBuilder.cpp | 31 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/SVals.cpp | 5 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp | 8 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/Store.cpp | 10 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/SymbolManager.cpp | 22 |
7 files changed, 58 insertions, 27 deletions
diff --git a/lib/StaticAnalyzer/Core/ProgramState.cpp b/lib/StaticAnalyzer/Core/ProgramState.cpp index 79f4348b7c..2dafeeee00 100644 --- a/lib/StaticAnalyzer/Core/ProgramState.cpp +++ b/lib/StaticAnalyzer/Core/ProgramState.cpp @@ -560,6 +560,8 @@ bool ScanReachableSymbols::scan(const SymExpr *sym) { case SymExpr::ExtentKind: case SymExpr::MetadataKind: break; + case SymExpr::CastSymbolKind: + return scan(cast<SymbolCast>(sym)->getOperand()); case SymExpr::SymIntKind: return scan(cast<SymIntExpr>(sym)->getLHS()); case SymExpr::SymSymKind: { @@ -672,10 +674,15 @@ 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<SymbolDerived>(Sym)) return isTainted(SD->getParentSymbol(), Kind); + if (const SymbolCast *SC = dyn_cast<SymbolCast>(Sym)) + return (isTainted(SC->getOperand(), Kind)); + if (const SymIntExpr *SIE = dyn_cast<SymIntExpr>(Sym)) return isTainted(SIE->getLHS(), Kind); diff --git a/lib/StaticAnalyzer/Core/RegionStore.cpp b/lib/StaticAnalyzer/Core/RegionStore.cpp index 27077afada..4f811dfa73 100644 --- a/lib/StaticAnalyzer/Core/RegionStore.cpp +++ b/lib/StaticAnalyzer/Core/RegionStore.cpp @@ -1720,7 +1720,7 @@ void removeDeadBindingsWorker::VisitBinding(SVal V) { if (const MemRegion *R = V.getAsRegion()) AddToWorkList(R); - // Update the set of live symbols. + // Update the set of live symbols. for (SVal::symbol_iterator SI=V.symbol_begin(), SE=V.symbol_end(); SI!=SE;++SI) SymReaper.markLive(*SI); diff --git a/lib/StaticAnalyzer/Core/SValBuilder.cpp b/lib/StaticAnalyzer/Core/SValBuilder.cpp index 617e0ddc72..ff0a85a572 100644 --- a/lib/StaticAnalyzer/Core/SValBuilder.cpp +++ b/lib/StaticAnalyzer/Core/SValBuilder.cpp @@ -56,6 +56,12 @@ NonLoc SValBuilder::makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op, return nonloc::SymbolVal(SymMgr.getSymSymExpr(lhs, op, rhs, type)); } +NonLoc SValBuilder::makeNonLoc(const SymExpr *operand, + QualType fromTy, QualType toTy) { + assert(operand); + assert(!Loc::isLocType(toTy)); + return nonloc::SymbolVal(SymMgr.getCastSymbol(operand, fromTy, toTy)); +} SVal SValBuilder::convertToArrayIndex(SVal val) { if (val.isUnknownOrUndef()) @@ -220,21 +226,7 @@ SVal SValBuilder::evalCast(SVal val, QualType castTy, QualType originalTy) { if (!castTy->isVariableArrayType() && !originalTy->isVariableArrayType()) if (Context.hasSameUnqualifiedType(castTy, originalTy)) return val; - - // Check for casts to real or complex numbers. We don't handle these at all - // right now. - if (castTy->isFloatingType() || castTy->isAnyComplexType()) - return UnknownVal(); - // Check for casts from integers to integers. - if (castTy->isIntegerType() && originalTy->isIntegerType()) { - if (isa<Loc>(val)) - // This can be a cast to ObjC property of type int. - return evalCastFromLoc(cast<Loc>(val), castTy); - else - return evalCastFromNonLoc(cast<NonLoc>(val), castTy); - } - // Check for casts from pointers to integers. if (castTy->isIntegerType() && Loc::isLocType(originalTy)) return evalCastFromLoc(cast<Loc>(val), castTy); @@ -249,7 +241,7 @@ SVal SValBuilder::evalCast(SVal val, QualType castTy, QualType originalTy) { } return LV->getLoc(); } - goto DispatchCast; + return dispatchCast(val, castTy); } // Just pass through function and block pointers. @@ -323,8 +315,9 @@ SVal SValBuilder::evalCast(SVal val, QualType castTy, QualType originalTy) { return R ? SVal(loc::MemRegionVal(R)) : UnknownVal(); } -DispatchCast: - // All other cases. - return isa<Loc>(val) ? evalCastFromLoc(cast<Loc>(val), castTy) - : evalCastFromNonLoc(cast<NonLoc>(val), castTy); + // Check for casts from integers to integers. + if (castTy->isIntegerType() && originalTy->isIntegerType()) + return dispatchCast(val, castTy); + + return dispatchCast(val, castTy); } diff --git a/lib/StaticAnalyzer/Core/SVals.cpp b/lib/StaticAnalyzer/Core/SVals.cpp index 4bdea1d9e1..97e5a1be4c 100644 --- a/lib/StaticAnalyzer/Core/SVals.cpp +++ b/lib/StaticAnalyzer/Core/SVals.cpp @@ -91,6 +91,7 @@ SymbolRef SVal::getLocSymbolInBase() const { return 0; } +// TODO: The next 3 functions have to be simplified. /// getAsSymbol - If this Sval wraps a symbol return that SymbolRef. /// Otherwise return 0. // FIXME: should we consider SymbolRef wrapped in CodeTextRegion? @@ -168,6 +169,10 @@ void SVal::symbol_iterator::expand() { const SymExpr *SE = itr.back(); itr.pop_back(); + if (const SymbolCast *SC = dyn_cast<SymbolCast>(SE)) { + itr.push_back(SC->getOperand()); + return; + } if (const SymIntExpr *SIE = dyn_cast<SymIntExpr>(SE)) { itr.push_back(SIE->getLHS()); return; diff --git a/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp b/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp index 495f6f20b6..da07d8ad0f 100644 --- a/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp +++ b/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp @@ -20,6 +20,7 @@ using namespace ento; namespace { class SimpleSValBuilder : public SValBuilder { protected: + virtual SVal dispatchCast(SVal val, QualType castTy); virtual SVal evalCastFromNonLoc(NonLoc val, QualType castTy); virtual SVal evalCastFromLoc(Loc val, QualType castTy); @@ -57,6 +58,11 @@ SValBuilder *ento::createSimpleSValBuilder(llvm::BumpPtrAllocator &alloc, // Transfer function for Casts. //===----------------------------------------------------------------------===// +SVal SimpleSValBuilder::dispatchCast(SVal val, QualType castTy) { + return isa<Loc>(val) ? evalCastFromLoc(cast<Loc>(val), castTy) + : evalCastFromNonLoc(cast<NonLoc>(val), castTy); +} + SVal SimpleSValBuilder::evalCastFromNonLoc(NonLoc val, QualType castTy) { bool isLocType = Loc::isLocType(castTy); @@ -86,6 +92,8 @@ SVal SimpleSValBuilder::evalCastFromNonLoc(NonLoc val, QualType castTy) { if (T->isIntegerType() && castTy->isIntegerType()) return val; + if (!isLocType) + return makeNonLoc(se, T, castTy); return UnknownVal(); } diff --git a/lib/StaticAnalyzer/Core/Store.cpp b/lib/StaticAnalyzer/Core/Store.cpp index 48a6f4f60f..5d152d4d53 100644 --- a/lib/StaticAnalyzer/Core/Store.cpp +++ b/lib/StaticAnalyzer/Core/Store.cpp @@ -212,7 +212,7 @@ const MemRegion *StoreManager::castRegion(const MemRegion *R, QualType CastToTy) SVal StoreManager::CastRetrievedVal(SVal V, const TypedValueRegion *R, QualType castTy, bool performTestOnly) { - if (castTy.isNull()) + if (castTy.isNull() || V.isUnknownOrUndef()) return V; ASTContext &Ctx = svalBuilder.getContext(); @@ -227,12 +227,8 @@ SVal StoreManager::CastRetrievedVal(SVal V, const TypedValueRegion *R, return V; } - if (const Loc *L = dyn_cast<Loc>(&V)) - return svalBuilder.evalCastFromLoc(*L, castTy); - else if (const NonLoc *NL = dyn_cast<NonLoc>(&V)) - return svalBuilder.evalCastFromNonLoc(*NL, castTy); - - return V; + assert(isa<Loc>(&V) || isa<NonLoc>(&V)); + return svalBuilder.dispatchCast(V, castTy); } SVal StoreManager::getLValueFieldOrIvar(const Decl *D, SVal Base) { diff --git a/lib/StaticAnalyzer/Core/SymbolManager.cpp b/lib/StaticAnalyzer/Core/SymbolManager.cpp index b843ab1a90..02c0a9e36d 100644 --- a/lib/StaticAnalyzer/Core/SymbolManager.cpp +++ b/lib/StaticAnalyzer/Core/SymbolManager.cpp @@ -66,6 +66,12 @@ void SymSymExpr::dumpToStream(raw_ostream &os) const { os << ')'; } +void SymbolCast::dumpToStream(raw_ostream &os) const { + os << '(' << ToTy.getAsString() << ") ("; + Operand->dumpToStream(os); + os << ')'; +} + void SymbolConjured::dumpToStream(raw_ostream &os) const { os << "conj_$" << getSymbolID() << '{' << T.getAsString() << '}'; } @@ -174,6 +180,22 @@ SymbolManager::getMetadataSymbol(const MemRegion* R, const Stmt *S, QualType T, return cast<SymbolMetadata>(SD); } +const SymbolCast* +SymbolManager::getCastSymbol(const SymExpr *Op, + QualType From, QualType To) { + llvm::FoldingSetNodeID ID; + SymbolCast::Profile(ID, Op, From, To); + void *InsertPos; + SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos); + if (!data) { + data = (SymbolCast*) BPAlloc.Allocate<SymbolCast>(); + new (data) SymbolCast(Op, From, To); + DataSet.InsertNode(data, InsertPos); + } + + return cast<SymbolCast>(data); +} + const SymIntExpr *SymbolManager::getSymIntExpr(const SymExpr *lhs, BinaryOperator::Opcode op, const llvm::APSInt& v, |