Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion configs/options.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
"--use-lazy-initialization=only",
"--min-number-elements-li=${minNumberElements}",
"--use-sym-size-li=${useSymbolicSizeLI}",
"--max-cycles=${maxCycles}",
"--max-cycles-before-stuck=${maxCycles}",
"--rewrite-equalities=simple",
"--symbolic-allocation-threshold=${SymbolicAllocationThreshold}",
"--analysis-reproduce=${sarifTracesFilePath}",
Expand Down
4 changes: 2 additions & 2 deletions include/klee/Core/Interpreter.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ class InterpreterHandler {
virtual void incPathsCompleted() = 0;
virtual void incPathsExplored(std::uint32_t num = 1) = 0;

virtual void processTestCase(const ExecutionState &state, const char *err,
const char *suffix) = 0;
virtual void processTestCase(const ExecutionState &state, const char *message,
const char *suffix, bool isError = false) = 0;
};

class Interpreter {
Expand Down
2 changes: 1 addition & 1 deletion include/klee/Core/TargetedExecutionReporter.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ ty min(ty left, ty right);
}; // namespace confidence

void reportFalsePositive(confidence::ty confidence,
const std::set<ReachWithError> &errors,
const std::vector<ReachWithError> &errors,
const std::string &id, std::string whatToIncrease);

} // namespace klee
Expand Down
5 changes: 3 additions & 2 deletions include/klee/Core/TerminationTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ enum class StateTerminationClass : std::uint8_t {
TTYPE(MaxDepth, 11U, "early") \
TTYPE(OutOfMemory, 12U, "early") \
TTYPE(OutOfStackMemory, 13U, "early") \
TTMARK(EARLY, 13U) \
TTYPE(MaxCycles, 14U, "early") \
TTMARK(EARLY, 14U) \
TTYPE(Solver, 20U, "solver.err") \
TTMARK(SOLVERERR, 20U) \
TTYPE(Abort, 30U, "abort.err") \
Expand Down Expand Up @@ -68,7 +69,7 @@ enum class StateTerminationClass : std::uint8_t {
TTYPE(External, 61U, "external.err") \
TTMARK(EXECERR, 61U) \
TTYPE(Replay, 70U, "") \
TTYPE(MissedAllTargets, 71U, "") \
TTYPE(MissedAllTargets, 71U, "miss_all_targets.early") \
TTMARK(EARLYALGORITHM, 71U) \
TTYPE(SilentExit, 80U, "") \
TTMARK(EARLYUSER, 80U) \
Expand Down
1 change: 1 addition & 0 deletions include/klee/Expr/Assignment.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ class Assignment {

bindings_ty::const_iterator begin() const { return bindings.begin(); }
bindings_ty::const_iterator end() const { return bindings.end(); }
bool isEmpty() { return begin() == end(); }

std::vector<const Array *> keys() const;
std::vector<SparseStorage<unsigned char>> values() const;
Expand Down
2 changes: 1 addition & 1 deletion include/klee/Expr/Expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ class Expr {
};

static ExprCacheSet cachedExpressions;
static ref<Expr> createCachedExpr(const ref<Expr> &e);
static ref<Expr> createCachedExpr(ref<Expr> e);
bool isCached = false;
bool toBeCleared = false;

Expand Down
3 changes: 3 additions & 0 deletions include/klee/Module/CodeGraphDistance.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ class CodeGraphDistance {
getSortedDistance(KFunction *kf);
const std::vector<std::pair<KFunction *, unsigned int>> &
getSortedBackwardDistance(KFunction *kf);

void getNearestPredicateSatisfying(KBlock *from, KBlockPredicate predicate,
std::set<KBlock *> &result);
};

} // namespace klee
Expand Down
4 changes: 3 additions & 1 deletion include/klee/Module/KModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ struct KBlock {
std::string toString() const;
};

typedef std::function<bool(KBlock *)> KBlockPredicate;

struct KCallBlock : KBlock {
KInstruction *kcallInstruction;
std::set<llvm::Function *> calledFunctions;
Expand Down Expand Up @@ -287,7 +289,7 @@ class KModule {

KBlock *getKBlock(llvm::BasicBlock *bb);

bool inMainModule(llvm::Function *f);
bool inMainModule(const llvm::Function &f);

bool inMainModule(const llvm::GlobalVariable &v);

Expand Down
4 changes: 2 additions & 2 deletions include/klee/Module/SarifReport.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ enum ReachWithError {
};

const char *getErrorString(ReachWithError error);
std::string getErrorsString(const std::set<ReachWithError> &errors);
std::string getErrorsString(const std::vector<ReachWithError> &errors);

struct FunctionInfo;
struct KBlock;
Expand Down Expand Up @@ -264,7 +264,7 @@ struct Result {
std::vector<ref<Location>> locations;
std::vector<optional<json>> metadatas;
std::string id;
std::set<ReachWithError> errors;
std::vector<ReachWithError> errors;
};

struct SarifReport {
Expand Down
176 changes: 138 additions & 38 deletions include/klee/Module/Target.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
#ifndef KLEE_TARGET_H
#define KLEE_TARGET_H

#include "klee/Module/TargetHash.h"

#include "klee/ADT/RNG.h"
#include "klee/ADT/Ref.h"
#include "klee/Module/KModule.h"
Expand All @@ -32,10 +34,6 @@ DISABLE_WARNING_POP
#include <vector>

namespace klee {
struct EquivTargetCmp;
struct TargetHash;
struct TargetCmp;

using nonstd::optional;

struct ErrorLocation {
Expand All @@ -45,35 +43,63 @@ struct ErrorLocation {
optional<unsigned int> endColumn;
};

struct Target {
class ReproduceErrorTarget;

class Target {
private:
typedef std::unordered_set<Target *, TargetHash, EquivTargetCmp>
EquivTargetHashSet;
typedef std::unordered_set<Target *, TargetHash, TargetCmp> TargetHashSet;
static EquivTargetHashSet cachedTargets;
static TargetHashSet targets;
protected:
friend class ref<Target>;
friend class ref<const Target>;

struct TargetHash {
unsigned operator()(Target *const t) const { return t->hash(); }
};

struct TargetCmp {
bool operator()(Target *const a, Target *const b) const {
return a->equals(*b);
}
};

typedef std::unordered_set<Target *, TargetHash, TargetCmp> CacheType;

struct TargetCacheSet {
CacheType cache;
~TargetCacheSet() {
while (cache.size() != 0) {
ref<Target> tmp = *cache.begin();
tmp->isCached = false;
cache.erase(cache.begin());
}
}
};

KBlock *block;
std::set<ReachWithError>
errors; // None - if it is not terminated in error trace
std::string id; // "" - if it is not terminated in error trace
optional<ErrorLocation> loc; // TODO(): only for check in reportTruePositive
static TargetCacheSet cachedTargets;
bool isCached = false;
bool toBeCleared = false;

/// @brief Required by klee::ref-managed objects
mutable class ReferenceCounter _refCount;

explicit Target(const std::set<ReachWithError> &_errors,
const std::string &_id, optional<ErrorLocation> _loc,
KBlock *_block)
: block(_block), errors(_errors), id(_id), loc(_loc) {}
explicit Target(KBlock *_block) : block(_block) {}

static ref<Target> getFromCacheOrReturn(Target *target);
static ref<Target> createCachedTarget(ref<Target> target);

public:
bool isReported = false;
/// @brief Required by klee::ref-managed objects
class ReferenceCounter _refCount;
static const unsigned MAGIC_HASH_CONSTANT = 39;

static ref<Target> create(const std::set<ReachWithError> &_errors,
const std::string &_id,
optional<ErrorLocation> _loc, KBlock *_block);
static ref<Target> create(KBlock *_block);
enum Kind {
CoverBranch = 3,
ReproduceError,
ReachBlock,
};

virtual ~Target();
virtual Kind getKind() const = 0;
virtual int internalCompare(const Target &b) const = 0;
static bool classof(const Target *) { return true; }
virtual std::string toString() const = 0;

int compare(const Target &other) const;

Expand All @@ -83,8 +109,6 @@ struct Target {

bool operator==(const Target &other) const;

bool atReturn() const { return isa<KReturnBlock>(block); }

KBlock *getBlock() const { return block; }

bool isNull() const { return block == nullptr; }
Expand All @@ -93,23 +117,99 @@ struct Target {

unsigned hash() const { return reinterpret_cast<uintptr_t>(block); }

const std::set<ReachWithError> &getErrors() const { return errors; }
bool isThatError(ReachWithError err) const;
bool shouldFailOnThisTarget() const {
return errors.count(ReachWithError::None) == 0;
return isa<ReproduceErrorTarget>(this);
}
};

class ReachBlockTarget : public Target {
protected:
bool atEnd;

explicit ReachBlockTarget(KBlock *_block, bool _atEnd)
: Target(_block), atEnd(_atEnd) {}

public:
static ref<Target> create(KBlock *_block, bool _atEnd);
static ref<Target> create(KBlock *_block);

Kind getKind() const override { return Kind::ReachBlock; }

static bool classof(const Target *S) {
return S->getKind() == Kind::ReachBlock;
}
static bool classof(const ReachBlockTarget *) { return true; }

bool isAtEnd() const { return atEnd; }

virtual int internalCompare(const Target &other) const override;
virtual std::string toString() const override;
};

class CoverBranchTarget : public Target {
protected:
unsigned branchCase;

explicit CoverBranchTarget(KBlock *_block, unsigned _branchCase)
: Target(_block), branchCase(_branchCase) {}

public:
static ref<Target> create(KBlock *_block, unsigned _branchCase);

Kind getKind() const override { return Kind::CoverBranch; }

static bool classof(const Target *S) {
return S->getKind() == Kind::CoverBranch;
}
static bool classof(const CoverBranchTarget *) { return true; }

virtual int internalCompare(const Target &other) const override;
virtual std::string toString() const override;

unsigned getBranchCase() const { return branchCase; }
};

class ReproduceErrorTarget : public Target {
private:
std::vector<ReachWithError>
errors; // None - if it is not terminated in error trace
std::string id; // "" - if it is not terminated in error trace
ErrorLocation loc; // TODO(): only for check in reportTruePositive

protected:
explicit ReproduceErrorTarget(const std::vector<ReachWithError> &_errors,
const std::string &_id, ErrorLocation _loc,
KBlock *_block)
: Target(_block), errors(_errors), id(_id), loc(_loc) {
assert(errors.size() > 0);
std::sort(errors.begin(), errors.end());
}

bool isTheSameAsIn(KInstruction *instr) const;
public:
static ref<Target> create(const std::vector<ReachWithError> &_errors,
const std::string &_id, ErrorLocation _loc,
KBlock *_block);

Kind getKind() const override { return Kind::ReproduceError; }

/// returns true if we cannot use CFG reachability checks
/// from instr children to this target
/// to avoid solver calls
bool mustVisitForkBranches(KInstruction *instr) const;
static bool classof(const Target *S) {
return S->getKind() == Kind::ReproduceError;
}
static bool classof(const ReproduceErrorTarget *) { return true; }

virtual int internalCompare(const Target &other) const override;
virtual std::string toString() const override;

std::string getId() const { return id; }

std::string toString() const;
~Target();
bool isReported = false;

const std::vector<ReachWithError> &getErrors() const { return errors; }
bool isThatError(ReachWithError err) const {
return std::find(errors.begin(), errors.end(), err) != errors.end();
}

bool isTheSameAsIn(const KInstruction *instr) const;
};
} // namespace klee

Expand Down
Loading