@@ -5471,6 +5471,100 @@ void Executor::executeFree(ExecutionState &state, ref<Expr> address,
54715471 }
54725472}
54735473
5474+ ExecutionState *Executor::handleNullPointerException (ExecutionState &state,
5475+ ref<Expr> base) {
5476+ StatePair branches =
5477+ forkInternal (state, Expr::createIsZero (base), BranchType::MemOp);
5478+ ExecutionState *bound = branches.first ;
5479+ if (!bound) {
5480+ return branches.second ;
5481+ }
5482+
5483+ // If there are no markers on `malloc` returning nullptr,
5484+ // then `confidence` depends on presence of `unbound` state.
5485+ if (!bound->outOfMemoryMarkers .empty ()) {
5486+ // bound constraints already contain `Expr::createIsZero()`
5487+ std::vector<const Array *> markersArrays;
5488+ markersArrays.reserve (bound->outOfMemoryMarkers .size ());
5489+ findSymbolicObjects (bound->outOfMemoryMarkers .begin (),
5490+ bound->outOfMemoryMarkers .end (), markersArrays);
5491+
5492+ // Do some iterations (2-3) to figure out if error is confident.
5493+ ref<Expr> allExcludedVectorsOfMarkers = Expr::createTrue ();
5494+
5495+ bool convinced = false ;
5496+ for (int tpCheckIteration = 0 ; tpCheckIteration < 2 ; ++tpCheckIteration) {
5497+ ref<SolverResponse> isConfidentResponse;
5498+ if (!solver->getResponse (bound->constraints .cs (),
5499+ allExcludedVectorsOfMarkers, isConfidentResponse,
5500+ bound->queryMetaData )) {
5501+ terminateStateOnSolverError (*bound, " Query timeout" );
5502+ }
5503+
5504+ if (isa<ValidResponse>(isConfidentResponse)) {
5505+ reportStateOnTargetError (*bound,
5506+ ReachWithError::MustBeNullPointerException);
5507+
5508+ terminateStateOnProgramError (
5509+ *bound,
5510+ new ErrorEvent (locationOf (*bound), StateTerminationType::Ptr,
5511+ " memory error: null pointer exception" ),
5512+ StateTerminationConfidenceCategory::CONFIDENT);
5513+ convinced = true ;
5514+ break ;
5515+ }
5516+
5517+ // Receive current values of markers
5518+ std::vector<SparseStorage<unsigned char >> boundSetSolution;
5519+ isConfidentResponse->tryGetInitialValuesFor (markersArrays,
5520+ boundSetSolution);
5521+ Assignment nonConfidentResponseAssignment (markersArrays,
5522+ boundSetSolution);
5523+
5524+ // Exclude this combinations of markers
5525+
5526+ ref<Expr> conjExcludedVectorOfMarkers = Expr::createTrue ();
5527+ for (ref<Expr> marker : bound->outOfMemoryMarkers ) {
5528+ conjExcludedVectorOfMarkers = AndExpr::create (
5529+ conjExcludedVectorOfMarkers,
5530+ EqExpr::create (marker,
5531+ nonConfidentResponseAssignment.evaluate (marker)));
5532+ }
5533+
5534+ allExcludedVectorsOfMarkers =
5535+ OrExpr::create (allExcludedVectorsOfMarkers,
5536+ NotExpr::create (conjExcludedVectorOfMarkers));
5537+ }
5538+
5539+ if (!convinced) {
5540+ reportStateOnTargetError (*bound,
5541+ ReachWithError::MayBeNullPointerException);
5542+
5543+ terminateStateOnProgramError (
5544+ *bound,
5545+ new ErrorEvent (locationOf (*bound), StateTerminationType::Ptr,
5546+ " memory error: null pointer exception" ),
5547+ StateTerminationConfidenceCategory::PROBABLY);
5548+ }
5549+
5550+ } else {
5551+ auto error = branches.second != nullptr
5552+ ? ReachWithError::MayBeNullPointerException
5553+ : ReachWithError::MustBeNullPointerException;
5554+ reportStateOnTargetError (*bound, error);
5555+
5556+ terminateStateOnProgramError (
5557+ *bound,
5558+ new ErrorEvent (locationOf (*bound), StateTerminationType::Ptr,
5559+ " memory error: null pointer exception" ),
5560+ branches.second != nullptr
5561+ ? StateTerminationConfidenceCategory::PROBABLY
5562+ : StateTerminationConfidenceCategory::CONFIDENT);
5563+ }
5564+
5565+ return branches.second ;
5566+ }
5567+
54745568bool Executor::resolveExact (ExecutionState &estate, ref<Expr> address,
54755569 KType *type, ExactResolutionList &results,
54765570 const std::string &name) {
@@ -5496,20 +5590,12 @@ bool Executor::resolveExact(ExecutionState &estate, ref<Expr> address,
54965590 Simplificator::simplifyExpr (estate.constraints .cs (), base).simplified ;
54975591 uniqueBase = toUnique (estate, uniqueBase);
54985592
5499- StatePair branches =
5500- forkInternal (estate, Expr::createIsZero (base), BranchType::MemOp);
5501- ExecutionState *bound = branches.first ;
5502- if (bound) {
5503- auto error = isReadFromSymbolicArray (uniqueBase)
5504- ? ReachWithError::MayBeNullPointerException
5505- : ReachWithError::MustBeNullPointerException;
5506- terminateStateOnTargetError (*bound, error);
5507- }
5508- if (!branches.second ) {
5509- address = Expr::createPointer (0 );
5593+ ExecutionState *handledNPEState = handleNullPointerException (estate, base);
5594+ if (!handledNPEState) {
5595+ return false ;
55105596 }
55115597
5512- ExecutionState &state = *branches. second ;
5598+ ExecutionState &state = *handledNPEState ;
55135599
55145600 ResolutionList rl;
55155601 bool mayBeOutOfBound = true ;
@@ -6266,97 +6352,9 @@ void Executor::executeMemoryOperation(
62666352
62676353 ref<Expr> uniqueBase = toUnique (estate, base);
62686354
6269- StatePair branches =
6270- forkInternal (estate, Expr::createIsZero (base), BranchType::MemOp);
6271- ExecutionState *bound = branches.first ;
6272-
6273- if (bound) {
6274- // If there are no markers on `malloc` returning nullptr,
6275- // then `confidence` depends on presence of `unbound` state.
6276- if (!bound->outOfMemoryMarkers .empty ()) {
6277- // bound constraints already contain `Expr::createIsZero()`
6278- std::vector<const Array *> markersArrays;
6279- markersArrays.reserve (bound->outOfMemoryMarkers .size ());
6280- findSymbolicObjects (bound->outOfMemoryMarkers .begin (),
6281- bound->outOfMemoryMarkers .end (), markersArrays);
6282-
6283- // Do some iterations (2-3) to figure out if error is confident.
6284- ref<Expr> allExcludedVectorsOfMarkers = Expr::createTrue ();
6285-
6286- bool convinced = false ;
6287- for (int tpCheckIteration = 0 ; tpCheckIteration < 2 ; ++tpCheckIteration) {
6288- ref<SolverResponse> isConfidentResponse;
6289- if (!solver->getResponse (bound->constraints .cs (),
6290- allExcludedVectorsOfMarkers,
6291- isConfidentResponse, bound->queryMetaData )) {
6292- terminateStateOnSolverError (*bound, " Query timeout" );
6293- }
6294-
6295- if (isa<ValidResponse>(isConfidentResponse)) {
6296- reportStateOnTargetError (*bound,
6297- ReachWithError::MustBeNullPointerException);
6298-
6299- terminateStateOnProgramError (
6300- *bound,
6301- new ErrorEvent (locationOf (*bound), StateTerminationType::Ptr,
6302- " memory error: null pointer exception" ),
6303- StateTerminationConfidenceCategory::CONFIDENT);
6304- convinced = true ;
6305- break ;
6306- }
6307-
6308- // Receive current values of markers
6309- std::vector<SparseStorage<unsigned char >> boundSetSolution;
6310- isConfidentResponse->tryGetInitialValuesFor (markersArrays,
6311- boundSetSolution);
6312- Assignment nonConfidentResponseAssignment (markersArrays,
6313- boundSetSolution);
6314-
6315- // Exclude this combinations of markers
6316-
6317- ref<Expr> conjExcludedVectorOfMarkers = Expr::createTrue ();
6318- for (ref<Expr> marker : bound->outOfMemoryMarkers ) {
6319- conjExcludedVectorOfMarkers = AndExpr::create (
6320- conjExcludedVectorOfMarkers,
6321- EqExpr::create (marker,
6322- nonConfidentResponseAssignment.evaluate (marker)));
6323- }
6324-
6325- allExcludedVectorsOfMarkers =
6326- OrExpr::create (allExcludedVectorsOfMarkers,
6327- NotExpr::create (conjExcludedVectorOfMarkers));
6328- }
6329-
6330- if (!convinced) {
6331- reportStateOnTargetError (*bound,
6332- ReachWithError::MayBeNullPointerException);
6333-
6334- terminateStateOnProgramError (
6335- *bound,
6336- new ErrorEvent (locationOf (*bound), StateTerminationType::Ptr,
6337- " memory error: null pointer exception" ),
6338- StateTerminationConfidenceCategory::PROBABLY);
6339- }
6340-
6341- } else {
6342- auto error = branches.second != nullptr
6343- ? ReachWithError::MayBeNullPointerException
6344- : ReachWithError::MustBeNullPointerException;
6345- reportStateOnTargetError (*bound, error);
6346-
6347- terminateStateOnProgramError (
6348- *bound,
6349- new ErrorEvent (locationOf (*bound), StateTerminationType::Ptr,
6350- " memory error: null pointer exception" ),
6351- branches.second != nullptr
6352- ? StateTerminationConfidenceCategory::PROBABLY
6353- : StateTerminationConfidenceCategory::CONFIDENT);
6354- }
6355- }
6356-
6357- if (!branches.second )
6355+ ExecutionState *state = handleNullPointerException (estate, base);
6356+ if (!state)
63586357 return ;
6359- ExecutionState *state = branches.second ;
63606358
63616359 // fast path: single in-bounds resolution
63626360 IDType idFastResult;
@@ -6542,7 +6540,7 @@ void Executor::executeMemoryOperation(
65426540 maxNewWriteableOSSize =
65436541 std::max (maxNewWriteableOSSize, wos->getSparseStorageEntries ());
65446542 if (wos->readOnly ) {
6545- branches =
6543+ StatePair branches =
65466544 forkInternal (*state, Expr::createIsZero (unboundConditions[i]),
65476545 BranchType::MemOp);
65486546 assert (branches.first );
0 commit comments