static NullConstraint getNullConstraint(DefinedOrUnknownSVal Val, ProgramStateRef State) { ConditionTruthVal Nullness = State->isNull(Val); if (Nullness.isConstrainedFalse()) return NullConstraint::IsNotNull; if (Nullness.isConstrainedTrue()) return NullConstraint::IsNull; return NullConstraint::Unknown; }
static bool isLeaked(SymbolRef Sym, const StreamState &SS, bool IsSymDead, ProgramStateRef State) { if (IsSymDead && SS.isOpened()) { // If a symbol is NULL, assume that fopen failed on this path. // A symbol should only be considered leaked if it is non-null. ConstraintManager &CMgr = State->getConstraintManager(); ConditionTruthVal OpenFailed = CMgr.isNull(State, Sym); return !OpenFailed.isConstrainedTrue(); } return false; }
void MacOSKeychainAPIChecker::checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const { ProgramStateRef State = C.getState(); AllocatedDataTy ASet = State->get<AllocatedData>(); if (ASet.isEmpty()) return; bool Changed = false; AllocationPairVec Errors; for (AllocatedDataTy::iterator I = ASet.begin(), E = ASet.end(); I != E; ++I) { if (SR.isLive(I->first)) continue; Changed = true; State = State->remove<AllocatedData>(I->first); // If the allocated symbol is null or if the allocation call might have // returned an error, do not report. ConstraintManager &CMgr = State->getConstraintManager(); ConditionTruthVal AllocFailed = CMgr.isNull(State, I.getKey()); if (AllocFailed.isConstrainedTrue() || definitelyReturnedError(I->second.Region, State, C.getSValBuilder())) continue; Errors.push_back(std::make_pair(I->first, &I->second)); } if (!Changed) { // Generate the new, cleaned up state. C.addTransition(State); return; } static SimpleProgramPointTag Tag("MacOSKeychainAPIChecker : DeadSymbolsLeak"); ExplodedNode *N = C.addTransition(C.getState(), C.getPredecessor(), &Tag); // Generate the error reports. for (AllocationPairVec::iterator I = Errors.begin(), E = Errors.end(); I != E; ++I) { C.emitReport(generateAllocatedDataNotReleasedReport(*I, N, C)); } // Generate the new, cleaned up state. C.addTransition(State, N); }
// In PthreadSemantics, pthread_mutex_destroy() returns zero if the lock is // successfully destroyed and it returns a non-zero value otherwise. ProgramStateRef PthreadLockChecker::resolvePossiblyDestroyedMutex( ProgramStateRef state, const MemRegion *lockR, const SymbolRef *sym) const { const LockState *lstate = state->get<LockMap>(lockR); // Existence in DestroyRetVal ensures existence in LockMap. // Existence in Destroyed also ensures that the lock state for lockR is either // UntouchedAndPossiblyDestroyed or UnlockedAndPossiblyDestroyed. assert(lstate->isUntouchedAndPossiblyDestroyed() || lstate->isUnlockedAndPossiblyDestroyed()); ConstraintManager &CMgr = state->getConstraintManager(); ConditionTruthVal retZero = CMgr.isNull(state, *sym); if (retZero.isConstrainedFalse()) { if (lstate->isUntouchedAndPossiblyDestroyed()) state = state->remove<LockMap>(lockR); else if (lstate->isUnlockedAndPossiblyDestroyed()) state = state->set<LockMap>(lockR, LockState::getUnlocked()); } else state = state->set<LockMap>(lockR, LockState::getDestroyed()); // Removing the map entry (lockR, sym) from DestroyRetVal as the lock state is // now resolved. state = state->remove<DestroyRetVal>(lockR); return state; }