clang API Documentation
00001 //= ProgramState.cpp - Path-Sensitive "State" for tracking values --*- C++ -*--= 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file implements ProgramState and ProgramStateManager. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #include "clang/Analysis/CFG.h" 00015 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h" 00016 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" 00017 #include "clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h" 00018 #include "clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h" 00019 #include "llvm/Support/raw_ostream.h" 00020 00021 using namespace clang; 00022 using namespace ento; 00023 00024 // Give the vtable for ConstraintManager somewhere to live. 00025 // FIXME: Move this elsewhere. 00026 ConstraintManager::~ConstraintManager() {} 00027 00028 namespace clang { namespace ento { 00029 /// Increments the number of times this state is referenced. 00030 00031 void ProgramStateRetain(const ProgramState *state) { 00032 ++const_cast<ProgramState*>(state)->refCount; 00033 } 00034 00035 /// Decrement the number of times this state is referenced. 00036 void ProgramStateRelease(const ProgramState *state) { 00037 assert(state->refCount > 0); 00038 ProgramState *s = const_cast<ProgramState*>(state); 00039 if (--s->refCount == 0) { 00040 ProgramStateManager &Mgr = s->getStateManager(); 00041 Mgr.StateSet.RemoveNode(s); 00042 s->~ProgramState(); 00043 Mgr.freeStates.push_back(s); 00044 } 00045 } 00046 }} 00047 00048 ProgramState::ProgramState(ProgramStateManager *mgr, const Environment& env, 00049 StoreRef st, GenericDataMap gdm) 00050 : stateMgr(mgr), 00051 Env(env), 00052 store(st.getStore()), 00053 GDM(gdm), 00054 refCount(0) { 00055 stateMgr->getStoreManager().incrementReferenceCount(store); 00056 } 00057 00058 ProgramState::ProgramState(const ProgramState &RHS) 00059 : llvm::FoldingSetNode(), 00060 stateMgr(RHS.stateMgr), 00061 Env(RHS.Env), 00062 store(RHS.store), 00063 GDM(RHS.GDM), 00064 refCount(0) { 00065 stateMgr->getStoreManager().incrementReferenceCount(store); 00066 } 00067 00068 ProgramState::~ProgramState() { 00069 if (store) 00070 stateMgr->getStoreManager().decrementReferenceCount(store); 00071 } 00072 00073 ProgramStateManager::~ProgramStateManager() { 00074 for (GDMContextsTy::iterator I=GDMContexts.begin(), E=GDMContexts.end(); 00075 I!=E; ++I) 00076 I->second.second(I->second.first); 00077 } 00078 00079 ProgramStateRef 00080 ProgramStateManager::removeDeadBindings(ProgramStateRef state, 00081 const StackFrameContext *LCtx, 00082 SymbolReaper& SymReaper) { 00083 00084 // This code essentially performs a "mark-and-sweep" of the VariableBindings. 00085 // The roots are any Block-level exprs and Decls that our liveness algorithm 00086 // tells us are live. We then see what Decls they may reference, and keep 00087 // those around. This code more than likely can be made faster, and the 00088 // frequency of which this method is called should be experimented with 00089 // for optimum performance. 00090 ProgramState NewState = *state; 00091 00092 NewState.Env = EnvMgr.removeDeadBindings(NewState.Env, SymReaper, state); 00093 00094 // Clean up the store. 00095 StoreRef newStore = StoreMgr->removeDeadBindings(NewState.getStore(), LCtx, 00096 SymReaper); 00097 NewState.setStore(newStore); 00098 SymReaper.setReapedStore(newStore); 00099 00100 return getPersistentState(NewState); 00101 } 00102 00103 ProgramStateRef ProgramStateManager::MarshalState(ProgramStateRef state, 00104 const StackFrameContext *InitLoc) { 00105 // make up an empty state for now. 00106 ProgramState State(this, 00107 EnvMgr.getInitialEnvironment(), 00108 StoreMgr->getInitialStore(InitLoc), 00109 GDMFactory.getEmptyMap()); 00110 00111 return getPersistentState(State); 00112 } 00113 00114 ProgramStateRef ProgramState::bindCompoundLiteral(const CompoundLiteralExpr *CL, 00115 const LocationContext *LC, 00116 SVal V) const { 00117 const StoreRef &newStore = 00118 getStateManager().StoreMgr->BindCompoundLiteral(getStore(), CL, LC, V); 00119 return makeWithStore(newStore); 00120 } 00121 00122 ProgramStateRef ProgramState::bindDecl(const VarRegion* VR, SVal IVal) const { 00123 const StoreRef &newStore = 00124 getStateManager().StoreMgr->BindDecl(getStore(), VR, IVal); 00125 return makeWithStore(newStore); 00126 } 00127 00128 ProgramStateRef ProgramState::bindDeclWithNoInit(const VarRegion* VR) const { 00129 const StoreRef &newStore = 00130 getStateManager().StoreMgr->BindDeclWithNoInit(getStore(), VR); 00131 return makeWithStore(newStore); 00132 } 00133 00134 ProgramStateRef ProgramState::bindLoc(Loc LV, SVal V) const { 00135 ProgramStateManager &Mgr = getStateManager(); 00136 ProgramStateRef newState = makeWithStore(Mgr.StoreMgr->Bind(getStore(), 00137 LV, V)); 00138 const MemRegion *MR = LV.getAsRegion(); 00139 if (MR && Mgr.getOwningEngine()) 00140 return Mgr.getOwningEngine()->processRegionChange(newState, MR); 00141 00142 return newState; 00143 } 00144 00145 ProgramStateRef ProgramState::bindDefault(SVal loc, SVal V) const { 00146 ProgramStateManager &Mgr = getStateManager(); 00147 const MemRegion *R = cast<loc::MemRegionVal>(loc).getRegion(); 00148 const StoreRef &newStore = Mgr.StoreMgr->BindDefault(getStore(), R, V); 00149 ProgramStateRef new_state = makeWithStore(newStore); 00150 return Mgr.getOwningEngine() ? 00151 Mgr.getOwningEngine()->processRegionChange(new_state, R) : 00152 new_state; 00153 } 00154 00155 ProgramStateRef 00156 ProgramState::invalidateRegions(ArrayRef<const MemRegion *> Regions, 00157 const Expr *E, unsigned Count, 00158 const LocationContext *LCtx, 00159 StoreManager::InvalidatedSymbols *IS, 00160 const CallOrObjCMessage *Call) const { 00161 if (!IS) { 00162 StoreManager::InvalidatedSymbols invalidated; 00163 return invalidateRegionsImpl(Regions, E, Count, LCtx, 00164 invalidated, Call); 00165 } 00166 return invalidateRegionsImpl(Regions, E, Count, LCtx, *IS, Call); 00167 } 00168 00169 ProgramStateRef 00170 ProgramState::invalidateRegionsImpl(ArrayRef<const MemRegion *> Regions, 00171 const Expr *E, unsigned Count, 00172 const LocationContext *LCtx, 00173 StoreManager::InvalidatedSymbols &IS, 00174 const CallOrObjCMessage *Call) const { 00175 ProgramStateManager &Mgr = getStateManager(); 00176 SubEngine* Eng = Mgr.getOwningEngine(); 00177 00178 if (Eng && Eng->wantsRegionChangeUpdate(this)) { 00179 StoreManager::InvalidatedRegions Invalidated; 00180 const StoreRef &newStore 00181 = Mgr.StoreMgr->invalidateRegions(getStore(), Regions, E, Count, LCtx, IS, 00182 Call, &Invalidated); 00183 ProgramStateRef newState = makeWithStore(newStore); 00184 return Eng->processRegionChanges(newState, &IS, Regions, Invalidated, Call); 00185 } 00186 00187 const StoreRef &newStore = 00188 Mgr.StoreMgr->invalidateRegions(getStore(), Regions, E, Count, LCtx, IS, 00189 Call, NULL); 00190 return makeWithStore(newStore); 00191 } 00192 00193 ProgramStateRef ProgramState::unbindLoc(Loc LV) const { 00194 assert(!isa<loc::MemRegionVal>(LV) && "Use invalidateRegion instead."); 00195 00196 Store OldStore = getStore(); 00197 const StoreRef &newStore = getStateManager().StoreMgr->Remove(OldStore, LV); 00198 00199 if (newStore.getStore() == OldStore) 00200 return this; 00201 00202 return makeWithStore(newStore); 00203 } 00204 00205 ProgramStateRef 00206 ProgramState::enterStackFrame(const LocationContext *callerCtx, 00207 const StackFrameContext *calleeCtx) const { 00208 const StoreRef &new_store = 00209 getStateManager().StoreMgr->enterStackFrame(this, callerCtx, calleeCtx); 00210 return makeWithStore(new_store); 00211 } 00212 00213 SVal ProgramState::getSValAsScalarOrLoc(const MemRegion *R) const { 00214 // We only want to do fetches from regions that we can actually bind 00215 // values. For example, SymbolicRegions of type 'id<...>' cannot 00216 // have direct bindings (but their can be bindings on their subregions). 00217 if (!R->isBoundable()) 00218 return UnknownVal(); 00219 00220 if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) { 00221 QualType T = TR->getValueType(); 00222 if (Loc::isLocType(T) || T->isIntegerType()) 00223 return getSVal(R); 00224 } 00225 00226 return UnknownVal(); 00227 } 00228 00229 SVal ProgramState::getSVal(Loc location, QualType T) const { 00230 SVal V = getRawSVal(cast<Loc>(location), T); 00231 00232 // If 'V' is a symbolic value that is *perfectly* constrained to 00233 // be a constant value, use that value instead to lessen the burden 00234 // on later analysis stages (so we have less symbolic values to reason 00235 // about). 00236 if (!T.isNull()) { 00237 if (SymbolRef sym = V.getAsSymbol()) { 00238 if (const llvm::APSInt *Int = getSymVal(sym)) { 00239 // FIXME: Because we don't correctly model (yet) sign-extension 00240 // and truncation of symbolic values, we need to convert 00241 // the integer value to the correct signedness and bitwidth. 00242 // 00243 // This shows up in the following: 00244 // 00245 // char foo(); 00246 // unsigned x = foo(); 00247 // if (x == 54) 00248 // ... 00249 // 00250 // The symbolic value stored to 'x' is actually the conjured 00251 // symbol for the call to foo(); the type of that symbol is 'char', 00252 // not unsigned. 00253 const llvm::APSInt &NewV = getBasicVals().Convert(T, *Int); 00254 00255 if (isa<Loc>(V)) 00256 return loc::ConcreteInt(NewV); 00257 else 00258 return nonloc::ConcreteInt(NewV); 00259 } 00260 } 00261 } 00262 00263 return V; 00264 } 00265 00266 ProgramStateRef ProgramState::BindExpr(const Stmt *S, 00267 const LocationContext *LCtx, 00268 SVal V, bool Invalidate) const{ 00269 Environment NewEnv = 00270 getStateManager().EnvMgr.bindExpr(Env, EnvironmentEntry(S, LCtx), V, 00271 Invalidate); 00272 if (NewEnv == Env) 00273 return this; 00274 00275 ProgramState NewSt = *this; 00276 NewSt.Env = NewEnv; 00277 return getStateManager().getPersistentState(NewSt); 00278 } 00279 00280 ProgramStateRef 00281 ProgramState::bindExprAndLocation(const Stmt *S, const LocationContext *LCtx, 00282 SVal location, 00283 SVal V) const { 00284 Environment NewEnv = 00285 getStateManager().EnvMgr.bindExprAndLocation(Env, 00286 EnvironmentEntry(S, LCtx), 00287 location, V); 00288 00289 if (NewEnv == Env) 00290 return this; 00291 00292 ProgramState NewSt = *this; 00293 NewSt.Env = NewEnv; 00294 return getStateManager().getPersistentState(NewSt); 00295 } 00296 00297 ProgramStateRef ProgramState::assumeInBound(DefinedOrUnknownSVal Idx, 00298 DefinedOrUnknownSVal UpperBound, 00299 bool Assumption, 00300 QualType indexTy) const { 00301 if (Idx.isUnknown() || UpperBound.isUnknown()) 00302 return this; 00303 00304 // Build an expression for 0 <= Idx < UpperBound. 00305 // This is the same as Idx + MIN < UpperBound + MIN, if overflow is allowed. 00306 // FIXME: This should probably be part of SValBuilder. 00307 ProgramStateManager &SM = getStateManager(); 00308 SValBuilder &svalBuilder = SM.getSValBuilder(); 00309 ASTContext &Ctx = svalBuilder.getContext(); 00310 00311 // Get the offset: the minimum value of the array index type. 00312 BasicValueFactory &BVF = svalBuilder.getBasicValueFactory(); 00313 // FIXME: This should be using ValueManager::ArrayindexTy...somehow. 00314 if (indexTy.isNull()) 00315 indexTy = Ctx.IntTy; 00316 nonloc::ConcreteInt Min(BVF.getMinValue(indexTy)); 00317 00318 // Adjust the index. 00319 SVal newIdx = svalBuilder.evalBinOpNN(this, BO_Add, 00320 cast<NonLoc>(Idx), Min, indexTy); 00321 if (newIdx.isUnknownOrUndef()) 00322 return this; 00323 00324 // Adjust the upper bound. 00325 SVal newBound = 00326 svalBuilder.evalBinOpNN(this, BO_Add, cast<NonLoc>(UpperBound), 00327 Min, indexTy); 00328 00329 if (newBound.isUnknownOrUndef()) 00330 return this; 00331 00332 // Build the actual comparison. 00333 SVal inBound = svalBuilder.evalBinOpNN(this, BO_LT, 00334 cast<NonLoc>(newIdx), cast<NonLoc>(newBound), 00335 Ctx.IntTy); 00336 if (inBound.isUnknownOrUndef()) 00337 return this; 00338 00339 // Finally, let the constraint manager take care of it. 00340 ConstraintManager &CM = SM.getConstraintManager(); 00341 return CM.assume(this, cast<DefinedSVal>(inBound), Assumption); 00342 } 00343 00344 ProgramStateRef ProgramStateManager::getInitialState(const LocationContext *InitLoc) { 00345 ProgramState State(this, 00346 EnvMgr.getInitialEnvironment(), 00347 StoreMgr->getInitialStore(InitLoc), 00348 GDMFactory.getEmptyMap()); 00349 00350 return getPersistentState(State); 00351 } 00352 00353 ProgramStateRef ProgramStateManager::getPersistentStateWithGDM( 00354 ProgramStateRef FromState, 00355 ProgramStateRef GDMState) { 00356 ProgramState NewState(*FromState); 00357 NewState.GDM = GDMState->GDM; 00358 return getPersistentState(NewState); 00359 } 00360 00361 ProgramStateRef ProgramStateManager::getPersistentState(ProgramState &State) { 00362 00363 llvm::FoldingSetNodeID ID; 00364 State.Profile(ID); 00365 void *InsertPos; 00366 00367 if (ProgramState *I = StateSet.FindNodeOrInsertPos(ID, InsertPos)) 00368 return I; 00369 00370 ProgramState *newState = 0; 00371 if (!freeStates.empty()) { 00372 newState = freeStates.back(); 00373 freeStates.pop_back(); 00374 } 00375 else { 00376 newState = (ProgramState*) Alloc.Allocate<ProgramState>(); 00377 } 00378 new (newState) ProgramState(State); 00379 StateSet.InsertNode(newState, InsertPos); 00380 return newState; 00381 } 00382 00383 ProgramStateRef ProgramState::makeWithStore(const StoreRef &store) const { 00384 ProgramState NewSt(*this); 00385 NewSt.setStore(store); 00386 return getStateManager().getPersistentState(NewSt); 00387 } 00388 00389 void ProgramState::setStore(const StoreRef &newStore) { 00390 Store newStoreStore = newStore.getStore(); 00391 if (newStoreStore) 00392 stateMgr->getStoreManager().incrementReferenceCount(newStoreStore); 00393 if (store) 00394 stateMgr->getStoreManager().decrementReferenceCount(store); 00395 store = newStoreStore; 00396 } 00397 00398 //===----------------------------------------------------------------------===// 00399 // State pretty-printing. 00400 //===----------------------------------------------------------------------===// 00401 00402 void ProgramState::print(raw_ostream &Out, 00403 const char *NL, const char *Sep) const { 00404 // Print the store. 00405 ProgramStateManager &Mgr = getStateManager(); 00406 Mgr.getStoreManager().print(getStore(), Out, NL, Sep); 00407 00408 // Print out the environment. 00409 Env.print(Out, NL, Sep); 00410 00411 // Print out the constraints. 00412 Mgr.getConstraintManager().print(this, Out, NL, Sep); 00413 00414 // Print checker-specific data. 00415 Mgr.getOwningEngine()->printState(Out, this, NL, Sep); 00416 } 00417 00418 void ProgramState::printDOT(raw_ostream &Out) const { 00419 print(Out, "\\l", "\\|"); 00420 } 00421 00422 void ProgramState::dump() const { 00423 print(llvm::errs()); 00424 } 00425 00426 void ProgramState::printTaint(raw_ostream &Out, 00427 const char *NL, const char *Sep) const { 00428 TaintMapImpl TM = get<TaintMap>(); 00429 00430 if (!TM.isEmpty()) 00431 Out <<"Tainted Symbols:" << NL; 00432 00433 for (TaintMapImpl::iterator I = TM.begin(), E = TM.end(); I != E; ++I) { 00434 Out << I->first << " : " << I->second << NL; 00435 } 00436 } 00437 00438 void ProgramState::dumpTaint() const { 00439 printTaint(llvm::errs()); 00440 } 00441 00442 //===----------------------------------------------------------------------===// 00443 // Generic Data Map. 00444 //===----------------------------------------------------------------------===// 00445 00446 void *const* ProgramState::FindGDM(void *K) const { 00447 return GDM.lookup(K); 00448 } 00449 00450 void* 00451 ProgramStateManager::FindGDMContext(void *K, 00452 void *(*CreateContext)(llvm::BumpPtrAllocator&), 00453 void (*DeleteContext)(void*)) { 00454 00455 std::pair<void*, void (*)(void*)>& p = GDMContexts[K]; 00456 if (!p.first) { 00457 p.first = CreateContext(Alloc); 00458 p.second = DeleteContext; 00459 } 00460 00461 return p.first; 00462 } 00463 00464 ProgramStateRef ProgramStateManager::addGDM(ProgramStateRef St, void *Key, void *Data){ 00465 ProgramState::GenericDataMap M1 = St->getGDM(); 00466 ProgramState::GenericDataMap M2 = GDMFactory.add(M1, Key, Data); 00467 00468 if (M1 == M2) 00469 return St; 00470 00471 ProgramState NewSt = *St; 00472 NewSt.GDM = M2; 00473 return getPersistentState(NewSt); 00474 } 00475 00476 ProgramStateRef ProgramStateManager::removeGDM(ProgramStateRef state, void *Key) { 00477 ProgramState::GenericDataMap OldM = state->getGDM(); 00478 ProgramState::GenericDataMap NewM = GDMFactory.remove(OldM, Key); 00479 00480 if (NewM == OldM) 00481 return state; 00482 00483 ProgramState NewState = *state; 00484 NewState.GDM = NewM; 00485 return getPersistentState(NewState); 00486 } 00487 00488 void ScanReachableSymbols::anchor() { } 00489 00490 bool ScanReachableSymbols::scan(nonloc::CompoundVal val) { 00491 for (nonloc::CompoundVal::iterator I=val.begin(), E=val.end(); I!=E; ++I) 00492 if (!scan(*I)) 00493 return false; 00494 00495 return true; 00496 } 00497 00498 bool ScanReachableSymbols::scan(const SymExpr *sym) { 00499 unsigned &isVisited = visited[sym]; 00500 if (isVisited) 00501 return true; 00502 isVisited = 1; 00503 00504 if (!visitor.VisitSymbol(sym)) 00505 return false; 00506 00507 // TODO: should be rewritten using SymExpr::symbol_iterator. 00508 switch (sym->getKind()) { 00509 case SymExpr::RegionValueKind: 00510 case SymExpr::ConjuredKind: 00511 case SymExpr::DerivedKind: 00512 case SymExpr::ExtentKind: 00513 case SymExpr::MetadataKind: 00514 break; 00515 case SymExpr::CastSymbolKind: 00516 return scan(cast<SymbolCast>(sym)->getOperand()); 00517 case SymExpr::SymIntKind: 00518 return scan(cast<SymIntExpr>(sym)->getLHS()); 00519 case SymExpr::IntSymKind: 00520 return scan(cast<IntSymExpr>(sym)->getRHS()); 00521 case SymExpr::SymSymKind: { 00522 const SymSymExpr *x = cast<SymSymExpr>(sym); 00523 return scan(x->getLHS()) && scan(x->getRHS()); 00524 } 00525 } 00526 return true; 00527 } 00528 00529 bool ScanReachableSymbols::scan(SVal val) { 00530 if (loc::MemRegionVal *X = dyn_cast<loc::MemRegionVal>(&val)) 00531 return scan(X->getRegion()); 00532 00533 if (nonloc::LocAsInteger *X = dyn_cast<nonloc::LocAsInteger>(&val)) 00534 return scan(X->getLoc()); 00535 00536 if (SymbolRef Sym = val.getAsSymbol()) 00537 return scan(Sym); 00538 00539 if (const SymExpr *Sym = val.getAsSymbolicExpression()) 00540 return scan(Sym); 00541 00542 if (nonloc::CompoundVal *X = dyn_cast<nonloc::CompoundVal>(&val)) 00543 return scan(*X); 00544 00545 return true; 00546 } 00547 00548 bool ScanReachableSymbols::scan(const MemRegion *R) { 00549 if (isa<MemSpaceRegion>(R)) 00550 return true; 00551 00552 unsigned &isVisited = visited[R]; 00553 if (isVisited) 00554 return true; 00555 isVisited = 1; 00556 00557 00558 if (!visitor.VisitMemRegion(R)) 00559 return false; 00560 00561 // If this is a symbolic region, visit the symbol for the region. 00562 if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R)) 00563 if (!visitor.VisitSymbol(SR->getSymbol())) 00564 return false; 00565 00566 // If this is a subregion, also visit the parent regions. 00567 if (const SubRegion *SR = dyn_cast<SubRegion>(R)) 00568 if (!scan(SR->getSuperRegion())) 00569 return false; 00570 00571 // Now look at the binding to this region (if any). 00572 if (!scan(state->getSValAsScalarOrLoc(R))) 00573 return false; 00574 00575 // Now look at the subregions. 00576 if (!SRM.get()) 00577 SRM.reset(state->getStateManager().getStoreManager(). 00578 getSubRegionMap(state->getStore())); 00579 00580 return SRM->iterSubRegions(R, *this); 00581 } 00582 00583 bool ProgramState::scanReachableSymbols(SVal val, SymbolVisitor& visitor) const { 00584 ScanReachableSymbols S(this, visitor); 00585 return S.scan(val); 00586 } 00587 00588 bool ProgramState::scanReachableSymbols(const SVal *I, const SVal *E, 00589 SymbolVisitor &visitor) const { 00590 ScanReachableSymbols S(this, visitor); 00591 for ( ; I != E; ++I) { 00592 if (!S.scan(*I)) 00593 return false; 00594 } 00595 return true; 00596 } 00597 00598 bool ProgramState::scanReachableSymbols(const MemRegion * const *I, 00599 const MemRegion * const *E, 00600 SymbolVisitor &visitor) const { 00601 ScanReachableSymbols S(this, visitor); 00602 for ( ; I != E; ++I) { 00603 if (!S.scan(*I)) 00604 return false; 00605 } 00606 return true; 00607 } 00608 00609 ProgramStateRef ProgramState::addTaint(const Stmt *S, 00610 const LocationContext *LCtx, 00611 TaintTagType Kind) const { 00612 if (const Expr *E = dyn_cast_or_null<Expr>(S)) 00613 S = E->IgnoreParens(); 00614 00615 SymbolRef Sym = getSVal(S, LCtx).getAsSymbol(); 00616 if (Sym) 00617 return addTaint(Sym, Kind); 00618 00619 const MemRegion *R = getSVal(S, LCtx).getAsRegion(); 00620 addTaint(R, Kind); 00621 00622 // Cannot add taint, so just return the state. 00623 return this; 00624 } 00625 00626 ProgramStateRef ProgramState::addTaint(const MemRegion *R, 00627 TaintTagType Kind) const { 00628 if (const SymbolicRegion *SR = dyn_cast_or_null<SymbolicRegion>(R)) 00629 return addTaint(SR->getSymbol(), Kind); 00630 return this; 00631 } 00632 00633 ProgramStateRef ProgramState::addTaint(SymbolRef Sym, 00634 TaintTagType Kind) const { 00635 // If this is a symbol cast, remove the cast before adding the taint. Taint 00636 // is cast agnostic. 00637 while (const SymbolCast *SC = dyn_cast<SymbolCast>(Sym)) 00638 Sym = SC->getOperand(); 00639 00640 ProgramStateRef NewState = set<TaintMap>(Sym, Kind); 00641 assert(NewState); 00642 return NewState; 00643 } 00644 00645 bool ProgramState::isTainted(const Stmt *S, const LocationContext *LCtx, 00646 TaintTagType Kind) const { 00647 if (const Expr *E = dyn_cast_or_null<Expr>(S)) 00648 S = E->IgnoreParens(); 00649 00650 SVal val = getSVal(S, LCtx); 00651 return isTainted(val, Kind); 00652 } 00653 00654 bool ProgramState::isTainted(SVal V, TaintTagType Kind) const { 00655 if (const SymExpr *Sym = V.getAsSymExpr()) 00656 return isTainted(Sym, Kind); 00657 if (const MemRegion *Reg = V.getAsRegion()) 00658 return isTainted(Reg, Kind); 00659 return false; 00660 } 00661 00662 bool ProgramState::isTainted(const MemRegion *Reg, TaintTagType K) const { 00663 if (!Reg) 00664 return false; 00665 00666 // Element region (array element) is tainted if either the base or the offset 00667 // are tainted. 00668 if (const ElementRegion *ER = dyn_cast<ElementRegion>(Reg)) 00669 return isTainted(ER->getSuperRegion(), K) || isTainted(ER->getIndex(), K); 00670 00671 if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(Reg)) 00672 return isTainted(SR->getSymbol(), K); 00673 00674 if (const SubRegion *ER = dyn_cast<SubRegion>(Reg)) 00675 return isTainted(ER->getSuperRegion(), K); 00676 00677 return false; 00678 } 00679 00680 bool ProgramState::isTainted(SymbolRef Sym, TaintTagType Kind) const { 00681 if (!Sym) 00682 return false; 00683 00684 // Traverse all the symbols this symbol depends on to see if any are tainted. 00685 bool Tainted = false; 00686 for (SymExpr::symbol_iterator SI = Sym->symbol_begin(), SE =Sym->symbol_end(); 00687 SI != SE; ++SI) { 00688 assert(isa<SymbolData>(*SI)); 00689 const TaintTagType *Tag = get<TaintMap>(*SI); 00690 Tainted = (Tag && *Tag == Kind); 00691 00692 // If this is a SymbolDerived with a tainted parent, it's also tainted. 00693 if (const SymbolDerived *SD = dyn_cast<SymbolDerived>(*SI)) 00694 Tainted = Tainted || isTainted(SD->getParentSymbol(), Kind); 00695 00696 // If memory region is tainted, data is also tainted. 00697 if (const SymbolRegionValue *SRV = dyn_cast<SymbolRegionValue>(*SI)) 00698 Tainted = Tainted || isTainted(SRV->getRegion(), Kind); 00699 00700 // If If this is a SymbolCast from a tainted value, it's also tainted. 00701 if (const SymbolCast *SC = dyn_cast<SymbolCast>(*SI)) 00702 Tainted = Tainted || isTainted(SC->getOperand(), Kind); 00703 00704 if (Tainted) 00705 return true; 00706 } 00707 00708 return Tainted; 00709 }