Skip to content

Commit a9c63e7

Browse files
committed
[feat] Handling of NPE moved to separate function.
1 parent 5fa61cc commit a9c63e7

File tree

2 files changed

+104
-103
lines changed

2 files changed

+104
-103
lines changed

lib/Core/Executor.cpp

Lines changed: 101 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
55005594
bool 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);

lib/Core/Executor.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,9 @@ class Executor : public Interpreter {
413413
const std::vector<Assignment> &resolveConcretizations,
414414
std::vector<ref<Expr>> &results);
415415

416+
ExecutionState *handleNullPointerException(ExecutionState &state,
417+
ref<Expr> base);
418+
416419
// do address resolution / object binding / out of bounds checking
417420
// and perform the operation
418421
void executeMemoryOperation(ExecutionState &state, bool isWrite,

0 commit comments

Comments
 (0)