Skip to content

Commit ae3c89e

Browse files
committed
[feat] Distinct kinds of NPE.
1 parent 2c50df5 commit ae3c89e

File tree

4 files changed

+95
-5
lines changed

4 files changed

+95
-5
lines changed

lib/Core/ExecutionState.cpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,9 @@ ExecutionState::~ExecutionState() {
160160
ExecutionState::ExecutionState(const ExecutionState &state)
161161
: initPC(state.initPC), pc(state.pc), prevPC(state.prevPC),
162162
stack(state.stack), stackBalance(state.stackBalance),
163-
incomingBBIndex(state.incomingBBIndex), depth(state.depth),
163+
incomingBBIndex(state.incomingBBIndex),
164+
lastBrConfidently(state.lastBrConfidently),
165+
outOfMemoryMarkers(state.outOfMemoryMarkers), depth(state.depth),
164166
level(state.level), addressSpace(state.addressSpace),
165167
constraints(state.constraints), eventsRecorder(state.eventsRecorder),
166168
targetForest(state.targetForest), pathOS(state.pathOS),

lib/Core/ExecutionState.h

+3
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,9 @@ class ExecutionState {
320320
/// @brief: TODO:
321321
bool lastBrConfidently = true;
322322

323+
/// @brief: TODO:
324+
ImmutableList<ref<Expr>> outOfMemoryMarkers;
325+
323326
/// @brief Exploration depth, i.e., number of times KLEE branched for this
324327
/// state
325328
std::uint32_t depth = 0;

lib/Core/Executor.cpp

+85-4
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
#include "klee/Solver/Common.h"
6363
#include "klee/Solver/Solver.h"
6464
#include "klee/Solver/SolverCmdLine.h"
65+
#include "klee/Solver/SolverUtil.h"
6566
#include "klee/Statistics/TimerStatIncrementer.h"
6667
#include "klee/Support/Casting.h"
6768
#include "klee/Support/ErrorHandling.h"
@@ -5398,6 +5399,7 @@ void Executor::executeAlloc(ExecutionState &state, ref<Expr> size, bool isLocal,
53985399
makeMockValue(state, "symCheckOutOfMemory", Expr::Bool);
53995400
address = SelectExpr::create(symCheckOutOfMemoryExpr,
54005401
Expr::createPointer(0), address);
5402+
state.outOfMemoryMarkers.push_back(symCheckOutOfMemoryExpr);
54015403
}
54025404

54035405
// state.addPointerResolution(address, mo);
@@ -6267,12 +6269,91 @@ void Executor::executeMemoryOperation(
62676269
StatePair branches =
62686270
forkInternal(estate, Expr::createIsZero(base), BranchType::MemOp);
62696271
ExecutionState *bound = branches.first;
6272+
62706273
if (bound) {
6271-
auto error = isReadFromSymbolicArray(uniqueBase)
6272-
? ReachWithError::MayBeNullPointerException
6273-
: ReachWithError::MustBeNullPointerException;
6274-
terminateStateOnTargetError(*bound, error);
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+
}
62756355
}
6356+
62766357
if (!branches.second)
62776358
return;
62786359
ExecutionState *state = branches.second;

lib/Expr/ExprUtil.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
//===----------------------------------------------------------------------===//
99

1010
#include "klee/Expr/ExprUtil.h"
11+
#include "klee/ADT/ImmutableList.h"
1112
#include "klee/Expr/Expr.h"
1213
#include "klee/Expr/ExprHashMap.h"
1314
#include "klee/Expr/ExprVisitor.h"
@@ -186,6 +187,9 @@ template void klee::findSymbolicObjects<B>(B, B, std::vector<const Array *> &);
186187
typedef ExprHashSet::iterator C;
187188
template void klee::findSymbolicObjects<C>(C, C, std::vector<const Array *> &);
188189

190+
typedef ImmutableList<ref<Expr>>::iterator D;
191+
template void klee::findSymbolicObjects<D>(D, D, std::vector<const Array *> &);
192+
189193
typedef std::vector<ref<Expr>>::iterator A;
190194
template void klee::findObjects<A>(A, A, std::vector<const Array *> &);
191195

0 commit comments

Comments
 (0)