@@ -5497,6 +5497,100 @@ void Executor::executeFree(ExecutionState &state, ref<Expr> address,
54975497 }
54985498}
54995499
5500+ ExecutionState *Executor::handleNullPointerException (ExecutionState &state,
5501+ ref<Expr> base) {
5502+ StatePair branches =
5503+ forkInternal (state, Expr::createIsZero (base), BranchType::MemOp);
5504+ ExecutionState *bound = branches.first ;
5505+ if (!bound) {
5506+ return branches.second ;
5507+ }
5508+
5509+ // If there are no markers on `malloc` returning nullptr,
5510+ // then `confidence` depends on presence of `unbound` state.
5511+ if (!bound->outOfMemoryMarkers .empty ()) {
5512+ // bound constraints already contain `Expr::createIsZero()`
5513+ std::vector<const Array *> markersArrays;
5514+ markersArrays.reserve (bound->outOfMemoryMarkers .size ());
5515+ findSymbolicObjects (bound->outOfMemoryMarkers .begin (),
5516+ bound->outOfMemoryMarkers .end (), markersArrays);
5517+
5518+ // Do some iterations (2-3) to figure out if error is confident.
5519+ ref<Expr> allExcludedVectorsOfMarkers = Expr::createTrue ();
5520+
5521+ bool convinced = false ;
5522+ for (int tpCheckIteration = 0 ; tpCheckIteration < 2 ; ++tpCheckIteration) {
5523+ ref<SolverResponse> isConfidentResponse;
5524+ if (!solver->getResponse (bound->constraints .cs (),
5525+ allExcludedVectorsOfMarkers, isConfidentResponse,
5526+ bound->queryMetaData )) {
5527+ terminateStateOnSolverError (*bound, " Query timeout" );
5528+ }
5529+
5530+ if (isa<ValidResponse>(isConfidentResponse)) {
5531+ reportStateOnTargetError (*bound,
5532+ ReachWithError::MustBeNullPointerException);
5533+
5534+ terminateStateOnProgramError (
5535+ *bound,
5536+ new ErrorEvent (locationOf (*bound), StateTerminationType::Ptr,
5537+ " memory error: null pointer exception" ),
5538+ StateTerminationConfidenceCategory::CONFIDENT);
5539+ convinced = true ;
5540+ break ;
5541+ }
5542+
5543+ // Receive current values of markers
5544+ std::vector<SparseStorage<unsigned char >> boundSetSolution;
5545+ isConfidentResponse->tryGetInitialValuesFor (markersArrays,
5546+ boundSetSolution);
5547+ Assignment nonConfidentResponseAssignment (markersArrays,
5548+ boundSetSolution);
5549+
5550+ // Exclude this combinations of markers
5551+
5552+ ref<Expr> conjExcludedVectorOfMarkers = Expr::createTrue ();
5553+ for (ref<Expr> marker : bound->outOfMemoryMarkers ) {
5554+ conjExcludedVectorOfMarkers = AndExpr::create (
5555+ conjExcludedVectorOfMarkers,
5556+ EqExpr::create (marker,
5557+ nonConfidentResponseAssignment.evaluate (marker)));
5558+ }
5559+
5560+ allExcludedVectorsOfMarkers =
5561+ OrExpr::create (allExcludedVectorsOfMarkers,
5562+ NotExpr::create (conjExcludedVectorOfMarkers));
5563+ }
5564+
5565+ if (!convinced) {
5566+ reportStateOnTargetError (*bound,
5567+ ReachWithError::MayBeNullPointerException);
5568+
5569+ terminateStateOnProgramError (
5570+ *bound,
5571+ new ErrorEvent (locationOf (*bound), StateTerminationType::Ptr,
5572+ " memory error: null pointer exception" ),
5573+ StateTerminationConfidenceCategory::PROBABLY);
5574+ }
5575+
5576+ } else {
5577+ auto error = branches.second != nullptr
5578+ ? ReachWithError::MayBeNullPointerException
5579+ : ReachWithError::MustBeNullPointerException;
5580+ reportStateOnTargetError (*bound, error);
5581+
5582+ terminateStateOnProgramError (
5583+ *bound,
5584+ new ErrorEvent (locationOf (*bound), StateTerminationType::Ptr,
5585+ " memory error: null pointer exception" ),
5586+ branches.second != nullptr
5587+ ? StateTerminationConfidenceCategory::PROBABLY
5588+ : StateTerminationConfidenceCategory::CONFIDENT);
5589+ }
5590+
5591+ return branches.second ;
5592+ }
5593+
55005594bool Executor::resolveExact (ExecutionState &estate, ref<Expr> address,
55015595 KType *type, ExactResolutionList &results,
55025596 const std::string &name) {
@@ -5522,20 +5616,12 @@ bool Executor::resolveExact(ExecutionState &estate, ref<Expr> address,
55225616 Simplificator::simplifyExpr (estate.constraints .cs (), base).simplified ;
55235617 uniqueBase = toUnique (estate, uniqueBase);
55245618
5525- StatePair branches =
5526- forkInternal (estate, Expr::createIsZero (base), BranchType::MemOp);
5527- ExecutionState *bound = branches.first ;
5528- if (bound) {
5529- auto error = isReadFromSymbolicArray (uniqueBase)
5530- ? ReachWithError::MayBeNullPointerException
5531- : ReachWithError::MustBeNullPointerException;
5532- terminateStateOnTargetError (*bound, error);
5533- }
5534- if (!branches.second ) {
5535- address = Expr::createPointer (0 );
5619+ ExecutionState *handledNPEState = handleNullPointerException (estate, base);
5620+ if (!handledNPEState) {
5621+ return false ;
55365622 }
55375623
5538- ExecutionState &state = *branches. second ;
5624+ ExecutionState &state = *handledNPEState ;
55395625
55405626 ResolutionList rl;
55415627 bool mayBeOutOfBound = true ;
@@ -6316,97 +6402,9 @@ void Executor::executeMemoryOperation(
63166402
63176403 ref<Expr> uniqueBase = toUnique (estate, base);
63186404
6319- StatePair branches =
6320- forkInternal (estate, Expr::createIsZero (base), BranchType::MemOp);
6321- ExecutionState *bound = branches.first ;
6322-
6323- if (bound) {
6324- // If there are no markers on `malloc` returning nullptr,
6325- // then `confidence` depends on presence of `unbound` state.
6326- if (!bound->outOfMemoryMarkers .empty ()) {
6327- // bound constraints already contain `Expr::createIsZero()`
6328- std::vector<const Array *> markersArrays;
6329- markersArrays.reserve (bound->outOfMemoryMarkers .size ());
6330- findSymbolicObjects (bound->outOfMemoryMarkers .begin (),
6331- bound->outOfMemoryMarkers .end (), markersArrays);
6332-
6333- // Do some iterations (2-3) to figure out if error is confident.
6334- ref<Expr> allExcludedVectorsOfMarkers = Expr::createTrue ();
6335-
6336- bool convinced = false ;
6337- for (int tpCheckIteration = 0 ; tpCheckIteration < 2 ; ++tpCheckIteration) {
6338- ref<SolverResponse> isConfidentResponse;
6339- if (!solver->getResponse (bound->constraints .cs (),
6340- allExcludedVectorsOfMarkers,
6341- isConfidentResponse, bound->queryMetaData )) {
6342- terminateStateOnSolverError (*bound, " Query timeout" );
6343- }
6344-
6345- if (isa<ValidResponse>(isConfidentResponse)) {
6346- reportStateOnTargetError (*bound,
6347- ReachWithError::MustBeNullPointerException);
6348-
6349- terminateStateOnProgramError (
6350- *bound,
6351- new ErrorEvent (locationOf (*bound), StateTerminationType::Ptr,
6352- " memory error: null pointer exception" ),
6353- StateTerminationConfidenceCategory::CONFIDENT);
6354- convinced = true ;
6355- break ;
6356- }
6357-
6358- // Receive current values of markers
6359- std::vector<SparseStorage<unsigned char >> boundSetSolution;
6360- isConfidentResponse->tryGetInitialValuesFor (markersArrays,
6361- boundSetSolution);
6362- Assignment nonConfidentResponseAssignment (markersArrays,
6363- boundSetSolution);
6364-
6365- // Exclude this combinations of markers
6366-
6367- ref<Expr> conjExcludedVectorOfMarkers = Expr::createTrue ();
6368- for (ref<Expr> marker : bound->outOfMemoryMarkers ) {
6369- conjExcludedVectorOfMarkers = AndExpr::create (
6370- conjExcludedVectorOfMarkers,
6371- EqExpr::create (marker,
6372- nonConfidentResponseAssignment.evaluate (marker)));
6373- }
6374-
6375- allExcludedVectorsOfMarkers =
6376- OrExpr::create (allExcludedVectorsOfMarkers,
6377- NotExpr::create (conjExcludedVectorOfMarkers));
6378- }
6379-
6380- if (!convinced) {
6381- reportStateOnTargetError (*bound,
6382- ReachWithError::MayBeNullPointerException);
6383-
6384- terminateStateOnProgramError (
6385- *bound,
6386- new ErrorEvent (locationOf (*bound), StateTerminationType::Ptr,
6387- " memory error: null pointer exception" ),
6388- StateTerminationConfidenceCategory::PROBABLY);
6389- }
6390-
6391- } else {
6392- auto error = branches.second != nullptr
6393- ? ReachWithError::MayBeNullPointerException
6394- : ReachWithError::MustBeNullPointerException;
6395- reportStateOnTargetError (*bound, error);
6396-
6397- terminateStateOnProgramError (
6398- *bound,
6399- new ErrorEvent (locationOf (*bound), StateTerminationType::Ptr,
6400- " memory error: null pointer exception" ),
6401- branches.second != nullptr
6402- ? StateTerminationConfidenceCategory::PROBABLY
6403- : StateTerminationConfidenceCategory::CONFIDENT);
6404- }
6405- }
6406-
6407- if (!branches.second )
6405+ ExecutionState *state = handleNullPointerException (estate, base);
6406+ if (!state)
64086407 return ;
6409- ExecutionState *state = branches.second ;
64106408
64116409 // fast path: single in-bounds resolution
64126410 IDType idFastResult;
@@ -6602,7 +6600,7 @@ void Executor::executeMemoryOperation(
66026600 maxNewWriteableOSSize =
66036601 std::max (maxNewWriteableOSSize, wos->getSparseStorageEntries ());
66046602 if (wos->readOnly ) {
6605- branches =
6603+ StatePair branches =
66066604 forkInternal (*state, Expr::createIsZero (unboundConditions[i]),
66076605 BranchType::MemOp);
66086606 assert (branches.first );
0 commit comments