Skip to content

Commit 2d82e28

Browse files
committed
[feat] Added error classification on 'confident' and 'possible'.
1 parent 8bfceae commit 2d82e28

File tree

6 files changed

+135
-51
lines changed

6 files changed

+135
-51
lines changed

include/klee/Core/TerminationTypes.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ enum class StateTerminationType : std::uint8_t {
8585
/// \endcond
8686
};
8787

88+
enum StateTerminationConfidenceCategory { CONFIDENT, PROBABLY };
89+
8890
namespace HaltExecution {
8991
enum Reason {
9092
NotHalt = 0,

lib/Core/ExecutionState.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,9 @@ class ExecutionState {
317317

318318
// Overall state of the state - Data specific
319319

320+
/// @brief: TODO:
321+
bool lastBrConfidently = true;
322+
320323
/// @brief Exploration depth, i.e., number of times KLEE branched for this
321324
/// state
322325
std::uint32_t depth = 0;

lib/Core/Executor.cpp

Lines changed: 87 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#include "klee/Config/Version.h"
4141
#include "klee/Config/config.h"
4242
#include "klee/Core/Interpreter.h"
43+
#include "klee/Core/TerminationTypes.h"
4344
#include "klee/Expr/ArrayExprOptimizer.h"
4445
#include "klee/Expr/ArrayExprVisitor.h"
4546
#include "klee/Expr/Assignment.h"
@@ -519,9 +520,9 @@ Executor::Executor(LLVMContext &ctx, const InterpreterOptions &opts,
519520
InterpreterHandler *ih)
520521
: Interpreter(opts), interpreterHandler(ih), searcher(nullptr),
521522
externalDispatcher(new ExternalDispatcher(ctx)), statsTracker(0),
522-
pathWriter(0), symPathWriter(0),
523-
specialFunctionHandler(0), timers{time::Span(TimerInterval)},
524-
guidanceKind(opts.Guidance), codeGraphInfo(new CodeGraphInfo()),
523+
pathWriter(0), symPathWriter(0), specialFunctionHandler(0),
524+
timers{time::Span(TimerInterval)}, guidanceKind(opts.Guidance),
525+
codeGraphInfo(new CodeGraphInfo()),
525526
distanceCalculator(new DistanceCalculator(*codeGraphInfo)),
526527
targetCalculator(new TargetCalculator(*codeGraphInfo)),
527528
targetManager(new TargetManager(guidanceKind, *distanceCalculator,
@@ -2728,6 +2729,7 @@ void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) {
27282729
if (bi->getMetadata("md.ret")) {
27292730
state.stack.forceReturnLocation(locationOf(state));
27302731
}
2732+
state.lastBrConfidently = true;
27312733

27322734
transferToBasicBlock(bi->getSuccessor(0), bi->getParent(), state);
27332735
} else {
@@ -2747,6 +2749,11 @@ void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) {
27472749
maxNewStateStackSize =
27482750
std::max(maxNewStateStackSize,
27492751
branches.first->stack.stackRegisterSize() * 8);
2752+
branches.first->lastBrConfidently = false;
2753+
branches.second->lastBrConfidently = false;
2754+
} else {
2755+
(branches.first ? branches.first : branches.second)->lastBrConfidently =
2756+
true;
27502757
}
27512758

27522759
// NOTE: There is a hidden dependency here, markBranchVisited
@@ -4018,9 +4025,11 @@ void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) {
40184025
if (iIdx >= vt->getNumElements()) {
40194026
// Out of bounds write
40204027
terminateStateOnProgramError(
4021-
state, new ErrorEvent(locationOf(state),
4022-
StateTerminationType::BadVectorAccess,
4023-
"Out of bounds write when inserting element"));
4028+
state,
4029+
new ErrorEvent(locationOf(state),
4030+
StateTerminationType::BadVectorAccess,
4031+
"Out of bounds write when inserting element"),
4032+
StateTerminationConfidenceCategory::CONFIDENT);
40244033
return;
40254034
}
40264035

@@ -4061,9 +4070,11 @@ void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) {
40614070
if (iIdx >= vt->getNumElements()) {
40624071
// Out of bounds read
40634072
terminateStateOnProgramError(
4064-
state, new ErrorEvent(locationOf(state),
4065-
StateTerminationType::BadVectorAccess,
4066-
"Out of bounds read when extracting element"));
4073+
state,
4074+
new ErrorEvent(locationOf(state),
4075+
StateTerminationType::BadVectorAccess,
4076+
"Out of bounds read when extracting element"),
4077+
StateTerminationConfidenceCategory::CONFIDENT);
40674078
return;
40684079
}
40694080

@@ -4967,28 +4978,41 @@ void Executor::terminateStateOnTargetError(ExecutionState &state,
49674978
terminationType = StateTerminationType::User;
49684979
}
49694980
terminateStateOnProgramError(
4970-
state, new ErrorEvent(locationOf(state), terminationType, messaget));
4981+
state, new ErrorEvent(locationOf(state), terminationType, messaget),
4982+
StateTerminationConfidenceCategory::CONFIDENT);
49714983
}
49724984

4973-
void Executor::terminateStateOnError(ExecutionState &state,
4974-
const llvm::Twine &messaget,
4975-
StateTerminationType terminationType,
4976-
const llvm::Twine &info,
4977-
const char *suffix) {
4985+
void Executor::terminateStateOnError(
4986+
ExecutionState &state, const llvm::Twine &messaget,
4987+
StateTerminationType terminationType,
4988+
StateTerminationConfidenceCategory confidence, const llvm::Twine &info,
4989+
const char *suffix) {
49784990
std::string message = messaget.str();
4979-
static std::set<std::pair<Instruction *, std::string>> emittedErrors;
4991+
static std::set<
4992+
std::pair<Instruction *,
4993+
std::pair<StateTerminationConfidenceCategory, std::string>>>
4994+
emittedErrors;
49804995
const KInstruction *ki = getLastNonKleeInternalInstruction(state);
49814996
Instruction *lastInst = ki->inst();
49824997

4983-
if ((EmitAllErrors ||
4984-
emittedErrors.insert(std::make_pair(lastInst, message)).second) &&
4998+
if ((EmitAllErrors || emittedErrors
4999+
.insert(std::make_pair(
5000+
lastInst, std::make_pair(confidence, message)))
5001+
.second) &&
49855002
shouldWriteTest(state, true)) {
49865003
std::string filepath = ki->getSourceFilepath();
5004+
5005+
std::string prefix =
5006+
(confidence == StateTerminationConfidenceCategory::CONFIDENT
5007+
? "ERROR"
5008+
: "POSSIBLE ERROR");
5009+
49875010
if (!filepath.empty()) {
4988-
klee_message("ERROR: %s:%zu: %s", filepath.c_str(), ki->getLine(),
4989-
message.c_str());
5011+
klee_message((prefix + ": %s:%zu: %s").c_str(), filepath.c_str(),
5012+
ki->getLine(), message.c_str());
49905013
} else {
4991-
klee_message("ERROR: (location information missing) %s", message.c_str());
5014+
klee_message((prefix + ": (location information missing) %s").c_str(),
5015+
message.c_str());
49925016
}
49935017
if (!EmitAllErrors)
49945018
klee_message("NOTE: now ignoring this error at this location");
@@ -5034,13 +5058,14 @@ void Executor::terminateStateOnExecError(ExecutionState &state,
50345058
assert(reason > StateTerminationType::USERERR &&
50355059
reason <= StateTerminationType::EXECERR);
50365060
++stats::terminationExecutionError;
5037-
terminateStateOnError(state, message, reason, "");
5061+
terminateStateOnError(state, message, reason,
5062+
StateTerminationConfidenceCategory::CONFIDENT, "");
50385063
}
50395064

5040-
void Executor::terminateStateOnProgramError(ExecutionState &state,
5041-
const ref<ErrorEvent> &reason,
5042-
const llvm::Twine &info,
5043-
const char *suffix) {
5065+
void Executor::terminateStateOnProgramError(
5066+
ExecutionState &state, const ref<ErrorEvent> &reason,
5067+
StateTerminationConfidenceCategory confidence, const llvm::Twine &info,
5068+
const char *suffix) {
50445069
assert(reason->ruleID > StateTerminationType::SOLVERERR &&
50455070
reason->ruleID <= StateTerminationType::PROGERR);
50465071
++stats::terminationProgramError;
@@ -5059,19 +5084,22 @@ void Executor::terminateStateOnProgramError(ExecutionState &state,
50595084
}
50605085
state.eventsRecorder.record(reason);
50615086

5062-
terminateStateOnError(state, reason->message, reason->ruleID, info, suffix);
5087+
terminateStateOnError(state, reason->message, reason->ruleID, confidence,
5088+
info, suffix);
50635089
}
50645090

50655091
void Executor::terminateStateOnSolverError(ExecutionState &state,
50665092
const llvm::Twine &message) {
50675093
++stats::terminationSolverError;
5068-
terminateStateOnError(state, message, StateTerminationType::Solver, "");
5094+
terminateStateOnError(state, message, StateTerminationType::Solver,
5095+
StateTerminationConfidenceCategory::CONFIDENT, "");
50695096
}
50705097

50715098
void Executor::terminateStateOnUserError(ExecutionState &state,
50725099
const llvm::Twine &message) {
50735100
++stats::terminationUserError;
5074-
terminateStateOnError(state, message, StateTerminationType::User, "");
5101+
terminateStateOnError(state, message, StateTerminationType::User,
5102+
StateTerminationConfidenceCategory::CONFIDENT, "");
50755103
}
50765104

50775105
// XXX shoot me
@@ -5442,13 +5470,20 @@ void Executor::executeFree(ExecutionState &state, ref<Expr> address,
54425470
new ErrorEvent(new AllocEvent(mo->allocSite),
54435471
locationOf(*it->second), StateTerminationType::Free,
54445472
"free of alloca"),
5473+
rl.size() != 1 ? StateTerminationConfidenceCategory::PROBABLY
5474+
: StateTerminationConfidenceCategory::CONFIDENT,
54455475
getAddressInfo(*it->second, address));
54465476
} else if (mo->isGlobal) {
5477+
if (rl.size() != 1) {
5478+
klee_warning("Following error if likely false positive");
5479+
}
54475480
terminateStateOnProgramError(
54485481
*it->second,
54495482
new ErrorEvent(new AllocEvent(mo->allocSite),
54505483
locationOf(*it->second), StateTerminationType::Free,
54515484
"free of global"),
5485+
rl.size() != 1 ? StateTerminationConfidenceCategory::PROBABLY
5486+
: StateTerminationConfidenceCategory::CONFIDENT,
54525487
getAddressInfo(*it->second, address));
54535488
} else {
54545489
it->second->removePointerResolutions(mo);
@@ -5544,6 +5579,8 @@ bool Executor::resolveExact(ExecutionState &estate, ref<Expr> address,
55445579
*unbound,
55455580
new ErrorEvent(locationOf(*unbound), StateTerminationType::Ptr,
55465581
"memory error: invalid pointer: " + name),
5582+
!results.empty() ? StateTerminationConfidenceCategory::PROBABLY
5583+
: StateTerminationConfidenceCategory::CONFIDENT,
55475584
getAddressInfo(*unbound, address));
55485585
}
55495586
}
@@ -5633,7 +5670,7 @@ void Executor::concretizeSize(ExecutionState &state, ref<Expr> size,
56335670
new ErrorEvent(locationOf(*hugeSize.second),
56345671
StateTerminationType::Model,
56355672
"concretized symbolic size"),
5636-
info.str());
5673+
StateTerminationConfidenceCategory::CONFIDENT, info.str());
56375674
}
56385675
}
56395676
}
@@ -6359,7 +6396,8 @@ void Executor::executeMemoryOperation(
63596396
*state,
63606397
new ErrorEvent(new AllocEvent(mo->allocSite), locationOf(*state),
63616398
StateTerminationType::ReadOnly,
6362-
"memory error: object read only"));
6399+
"memory error: object read only"),
6400+
StateTerminationConfidenceCategory::CONFIDENT);
63636401
} else {
63646402
wos->write(mo->getOffsetExpr(address), value);
63656403
}
@@ -6431,6 +6469,10 @@ void Executor::executeMemoryOperation(
64316469
return;
64326470
}
64336471

6472+
bool mayBeFalsePositive =
6473+
resolvedMemoryObjects.size() > 1 ||
6474+
(resolvedMemoryObjects.size() == 1 && mayBeOutOfBound);
6475+
64346476
ExecutionState *unbound = nullptr;
64356477
if (MergedPointerDereference) {
64366478
ref<Expr> guard;
@@ -6488,7 +6530,10 @@ void Executor::executeMemoryOperation(
64886530
new ErrorEvent(new AllocEvent(mo->allocSite),
64896531
locationOf(*branches.first),
64906532
StateTerminationType::ReadOnly,
6491-
"memory error: object read only"));
6533+
"memory error: object read only"),
6534+
mayBeFalsePositive
6535+
? StateTerminationConfidenceCategory::PROBABLY
6536+
: StateTerminationConfidenceCategory::CONFIDENT);
64926537
state = branches.second;
64936538
} else {
64946539
ref<Expr> result = SelectExpr::create(
@@ -6560,7 +6605,10 @@ void Executor::executeMemoryOperation(
65606605
*bound,
65616606
new ErrorEvent(new AllocEvent(mo->allocSite), locationOf(*bound),
65626607
StateTerminationType::ReadOnly,
6563-
"memory error: object read only"));
6608+
"memory error: object read only"),
6609+
mayBeFalsePositive
6610+
? StateTerminationConfidenceCategory::PROBABLY
6611+
: StateTerminationConfidenceCategory::CONFIDENT);
65646612
} else {
65656613
wos->write(mo->getOffsetExpr(address), value);
65666614
}
@@ -6622,6 +6670,8 @@ void Executor::executeMemoryOperation(
66226670
new ErrorEvent(new AllocEvent(baseObjectPair.first->allocSite),
66236671
locationOf(*unbound), StateTerminationType::Ptr,
66246672
"memory error: out of bound pointer"),
6673+
mayBeFalsePositive ? StateTerminationConfidenceCategory::PROBABLY
6674+
: StateTerminationConfidenceCategory::CONFIDENT,
66256675
getAddressInfo(*unbound, address));
66266676
return;
66276677
}
@@ -6631,6 +6681,8 @@ void Executor::executeMemoryOperation(
66316681
*unbound,
66326682
new ErrorEvent(locationOf(*unbound), StateTerminationType::Ptr,
66336683
"memory error: out of bound pointer"),
6684+
mayBeFalsePositive ? StateTerminationConfidenceCategory::PROBABLY
6685+
: StateTerminationConfidenceCategory::CONFIDENT,
66346686
getAddressInfo(*unbound, address));
66356687
}
66366688
}
@@ -6864,8 +6916,7 @@ void Executor::executeMakeSymbolic(ExecutionState &state,
68646916
(!AllowSeedTruncation && obj->numBytes > mo->size))) {
68656917
std::stringstream msg;
68666918
msg << "replace size mismatch: " << mo->name << "[" << mo->size
6867-
<< "]"
6868-
<< " vs " << obj->name << "[" << obj->numBytes << "]"
6919+
<< "]" << " vs " << obj->name << "[" << obj->numBytes << "]"
68696920
<< " in test\n";
68706921

68716922
terminateStateOnUserError(state, msg.str());
@@ -7309,8 +7360,7 @@ void Executor::logState(const ExecutionState &state, int id,
73097360
*f << "Address memory object: " << object.first->address << "\n";
73107361
*f << "Memory object size: " << object.first->size << "\n";
73117362
}
7312-
*f << state.symbolics.size() << " symbolics total. "
7313-
<< "Symbolics:\n";
7363+
*f << state.symbolics.size() << " symbolics total. " << "Symbolics:\n";
73147364
size_t sc = 0;
73157365
for (const auto &symbolic : state.symbolics) {
73167366
*f << "Symbolic number " << sc++ << "\n";

lib/Core/Executor.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -618,6 +618,7 @@ class Executor : public Interpreter {
618618
/// below.
619619
void terminateStateOnError(ExecutionState &state, const llvm::Twine &message,
620620
StateTerminationType reason,
621+
StateTerminationConfidenceCategory confidence,
621622
const llvm::Twine &longMessage = "",
622623
const char *suffix = nullptr);
623624

@@ -629,10 +630,10 @@ class Executor : public Interpreter {
629630

630631
/// Call error handler and terminate state in case of program errors
631632
/// (e.g. free()ing globals, out-of-bound accesses)
632-
void terminateStateOnProgramError(ExecutionState &state,
633-
const ref<ErrorEvent> &reason,
634-
const llvm::Twine &longMessage = "",
635-
const char *suffix = nullptr);
633+
void terminateStateOnProgramError(
634+
ExecutionState &state, const ref<ErrorEvent> &reason,
635+
StateTerminationConfidenceCategory confidence,
636+
const llvm::Twine &longMessage = "", const char *suffix = nullptr);
636637

637638
void terminateStateOnTerminator(ExecutionState &state);
638639

0 commit comments

Comments
 (0)