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); }
// TODO: Remove this after we ensure that checkDeadSymbols are always called. void MacOSKeychainAPIChecker::checkEndPath(CheckerContext &Ctx) const { const ProgramState *state = Ctx.getState(); AllocatedSetTy AS = state->get<AllocatedData>(); if (AS.isEmpty()) return; // Anything which has been allocated but not freed (nor escaped) will be // found here, so report it. bool Changed = false; AllocationPairVec Errors; for (AllocatedSetTy::iterator I = AS.begin(), E = AS.end(); I != E; ++I ) { Changed = true; state = state->remove<AllocatedData>(I->first); // If the allocated symbol is null or if error code was returned at // allocation, do not report. if (state->getSymVal(I.getKey()) || definitelyReturnedError(I->second.Region, state, Ctx.getSValBuilder())) { continue; } Errors.push_back(std::make_pair(I->first, &I->second)); } // If no change, do not generate a new state. if (!Changed) return; ExplodedNode *N = Ctx.addTransition(state); if (!N) return; // Generate the error reports. for (AllocationPairVec::iterator I = Errors.begin(), E = Errors.end(); I != E; ++I) { Ctx.EmitReport(generateAllocatedDataNotReleasedReport(*I, N)); } }
void MacOSKeychainAPIChecker::checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const { const ProgramState *State = C.getState(); AllocatedSetTy ASet = State->get<AllocatedData>(); if (ASet.isEmpty()) return; bool Changed = false; AllocationPairVec Errors; for (AllocatedSetTy::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. if (State->getSymVal(I->first) || definitelyReturnedError(I->second.Region, State, C.getSValBuilder())) continue; Errors.push_back(std::make_pair(I->first, &I->second)); } if (!Changed) return; // Generate the new, cleaned up state. ExplodedNode *N = C.addTransition(State); if (!N) return; // Generate the error reports. for (AllocationPairVec::iterator I = Errors.begin(), E = Errors.end(); I != E; ++I) { C.EmitReport(generateAllocatedDataNotReleasedReport(*I, N)); } }