From ffae8848712b0608ada1772a012713cc1af079a0 Mon Sep 17 00:00:00 2001 From: dim8art Date: Sun, 20 Aug 2023 16:16:19 +0300 Subject: [PATCH 001/103] Add DisjointSetUnion --- include/klee/ADT/DisjointSetUnion.h | 143 +++++++++++++++ .../klee/Expr/IndependentConstraintSetUnion.h | 46 +++++ lib/Expr/IndependentConstraintSetUnion.cpp | 166 ++++++++++++++++++ 3 files changed, 355 insertions(+) create mode 100644 include/klee/ADT/DisjointSetUnion.h create mode 100644 include/klee/Expr/IndependentConstraintSetUnion.h create mode 100644 lib/Expr/IndependentConstraintSetUnion.cpp diff --git a/include/klee/ADT/DisjointSetUnion.h b/include/klee/ADT/DisjointSetUnion.h new file mode 100644 index 0000000000..77a41353c2 --- /dev/null +++ b/include/klee/ADT/DisjointSetUnion.h @@ -0,0 +1,143 @@ +#ifndef KLEE_DISJOINEDSETUNION_H +#define KLEE_DISJOINEDSETUNION_H +#include "klee/ADT/PersistentMap.h" +#include "klee/ADT/PersistentSet.h" +#include "klee/ADT/Ref.h" +#include +#include +#include +#include + +namespace klee { + +template > +class DisjointSetUnion { +protected: + PersistentMap parent; + PersistentSet roots; + PersistentMap rank; + + PersistentSet internalStorage; + PersistentMap, CMP> disjointSets; + + ValueType find(const ValueType &v) { // findparent + assert(parent.find(v) != parent.end()); + if (v == parent.at(v)) + return v; + parent.replace({v, find(parent.at(v))}); + return parent.at(v); + } + + ValueType constFind(const ValueType &v) const { + assert(parent.find(v) != parent.end()); + ValueType v1 = parent.at(v); + if (v == v1) + return v; + return constFind(v1); + } + + void merge(ValueType a, ValueType b) { + a = find(a); + b = find(b); + if (a == b) { + return; + } + + if (rank.at(a) < rank.at(b)) { + std::swap(a, b); + } + parent.replace({b, a}); + if (rank.at(a) == rank.at(b)) { + rank.replace({a, rank.at(a) + 1}); + } + + roots.remove(b); + disjointSets.replace( + {a, SetType::merge(disjointSets.at(a), disjointSets.at(b))}); + disjointSets.replace({b, nullptr}); + } + + bool areJoined(const ValueType &i, const ValueType &j) const { + return constFind(i) == constFind(j); + } + +public: + using internalStorage_ty = PersistentSet; + using disjointSets_ty = ImmutableMap, CMP>; + using iterator = typename internalStorage_ty::iterator; + + iterator begin() const { return internalStorage.begin(); } + iterator end() const { return internalStorage.end(); } + + size_t numberOfValues() const noexcept { return internalStorage.size(); } + + size_t numberOfGroups() const noexcept { return disjointSets.size(); } + + bool empty() const noexcept { return numberOfValues() == 0; } + + ref findGroup(const ValueType &i) const { + return disjointSets.find(constFind(i))->second; + } + + ref findGroup(iterator it) const { + return disjointSets.find(constFind(*it))->second; + } + + void addValue(const ValueType value) { + if (internalStorage.find(value) != internalStorage.end()) { + return; + } + parent.insert({value, value}); + roots.insert(value); + rank.insert({value, 0}); + disjointSets.insert({value, new SetType(value)}); + + internalStorage.insert(value); + internalStorage_ty oldRoots = roots; + for (ValueType v : oldRoots) { + if (!areJoined(v, value) && + SetType::intersects(disjointSets.at(find(v)), + disjointSets.at(find(value)))) { + merge(v, value); + } + } + } + void getAllIndependentSets(std::vector> &result) const { + for (ValueType v : roots) + result.push_back(findGroup(v)); + } + + void add(const DisjointSetUnion &b) { + for (auto it : b.parent) { + parent.insert(it); + } + for (auto it : b.roots) { + roots.insert(it); + } + for (auto it : b.rank) { + rank.insert(it); + } + for (auto it : b.internalStorage) { + internalStorage.insert(it); + } + for (auto it : b.disjointSets) { + disjointSets.insert(it); + } + } + + DisjointSetUnion() {} + + DisjointSetUnion(const internalStorage_ty &is) { + for (ValueType v : is) { + addValue(v); + } + } + +public: + internalStorage_ty is() const { return internalStorage; } + + disjointSets_ty ds() const { return disjointSets; } +}; +} // namespace klee +#endif diff --git a/include/klee/Expr/IndependentConstraintSetUnion.h b/include/klee/Expr/IndependentConstraintSetUnion.h new file mode 100644 index 0000000000..3591cd5eff --- /dev/null +++ b/include/klee/Expr/IndependentConstraintSetUnion.h @@ -0,0 +1,46 @@ +#ifndef KLEE_INDEPENDENTCONSTRAINTSETUNION_H +#define KLEE_INDEPENDENTCONSTRAINTSETUNION_H + +#include "klee/Expr/Assignment.h" +#include "klee/Expr/IndependentSet.h" + +namespace klee { +class IndependentConstraintSetUnion + : public DisjointSetUnion, IndependentConstraintSet> { +public: + Assignment concretization; + +public: + ExprHashMap> concretizedExprs; + +public: + void updateConcretization(const Assignment &c); + void removeConcretization(const Assignment &remove); + void reEvaluateConcretization(const Assignment &newConcretization); + + IndependentConstraintSetUnion getConcretizedVersion() const; + IndependentConstraintSetUnion + getConcretizedVersion(const Assignment &c) const; + + IndependentConstraintSetUnion(); + IndependentConstraintSetUnion(const constraints_ty &is, + const SymcreteOrderedSet &os, + const Assignment &c); + IndependentConstraintSetUnion(ref ics); + + void + addIndependentConstraintSetUnion(const IndependentConstraintSetUnion &icsu); + + void getAllDependentConstraintSets( + ref e, + std::vector> &result) const; + void getAllIndependentConstraintSets( + ref e, + std::vector> &result) const; + + void addExpr(ref e); + void addSymcrete(ref s); +}; +} // namespace klee + +#endif diff --git a/lib/Expr/IndependentConstraintSetUnion.cpp b/lib/Expr/IndependentConstraintSetUnion.cpp new file mode 100644 index 0000000000..692e679234 --- /dev/null +++ b/lib/Expr/IndependentConstraintSetUnion.cpp @@ -0,0 +1,166 @@ +#include "klee/Expr/IndependentConstraintSetUnion.h" + +namespace klee { + +IndependentConstraintSetUnion::IndependentConstraintSetUnion() {} + +IndependentConstraintSetUnion::IndependentConstraintSetUnion( + const constraints_ty &is, const SymcreteOrderedSet &os, + const Assignment &c) { + for (ref e : is) { + addValue(e); + } + for (ref s : os) { + addSymcrete(s); + } + updateConcretization(c); +} + +IndependentConstraintSetUnion::IndependentConstraintSetUnion( + ref ics) { + for (ref e : ics->exprs) { + rank.replace({e, 0}); + internalStorage.insert(e); + disjointSets.replace({e, nullptr}); + } + + for (ref s : ics->symcretes) { + ref e = s->symcretized; + rank.replace({e, 0}); + internalStorage.insert(e); + disjointSets.replace({e, nullptr}); + } + + if (internalStorage.size() == 0) { + return; + } + + ref first = *(internalStorage.begin()); + for (ref e : internalStorage) { + parent.replace({e, first}); + } + rank.replace({first, 1}); + roots.insert(first); + disjointSets.replace({first, ics}); + concretization = ics->concretization; +} + +void IndependentConstraintSetUnion::addIndependentConstraintSetUnion( + const IndependentConstraintSetUnion &icsu) { + add(icsu); + concretization.addIndependentAssignment(icsu.concretization); +} + +void IndependentConstraintSetUnion::updateConcretization( + const Assignment &delta) { + for (ref e : roots) { + ref ics = disjointSets.at(e); + Assignment part = delta.part(ics->getSymcretes()); + ics = ics->updateConcretization(part, concretizedExprs); + disjointSets.replace({e, ics}); + } + for (auto it : delta.bindings) { + concretization.bindings.replace({it.first, it.second}); + } +} + +void IndependentConstraintSetUnion::removeConcretization( + const Assignment &remove) { + for (ref e : roots) { + ref ics = disjointSets.at(e); + Assignment part = remove.part(ics->getSymcretes()); + ics = ics->removeConcretization(part, concretizedExprs); + disjointSets.replace({e, ics}); + } + for (auto it : remove.bindings) { + concretization.bindings.remove(it.first); + } +} + +void IndependentConstraintSetUnion::reEvaluateConcretization( + const Assignment &newConcretization) { + Assignment delta; + Assignment removed; + for (const auto it : concretization) { + if (newConcretization.bindings.count(it.first) == 0) { + removed.bindings.insert(it); + } else if (newConcretization.bindings.at(it.first) != it.second) { + delta.bindings.insert(*(newConcretization.bindings.find(it.first))); + } + } + updateConcretization(delta); + removeConcretization(removed); +} + +void IndependentConstraintSetUnion::getAllIndependentConstraintSets( + ref e, + std::vector> &result) const { + ref compare = new IndependentConstraintSet(e); + for (ref r : roots) { + ref ics = disjointSets.at(r); + if (!IndependentConstraintSet::intersects(ics, compare)) { + result.push_back(ics); + } + } +} + +void IndependentConstraintSetUnion::getAllDependentConstraintSets( + ref e, + std::vector> &result) const { + ref compare = new IndependentConstraintSet(e); + for (ref r : roots) { + ref ics = disjointSets.at(r); + if (IndependentConstraintSet::intersects(ics, compare)) { + result.push_back(ics); + } + } +} + +void IndependentConstraintSetUnion::addExpr(ref e) { + addValue(e); + disjointSets.replace({find(e), disjointSets.at(find(e))->addExpr(e)}); +} + +void IndependentConstraintSetUnion::addSymcrete(ref s) { + ref value = s->symcretized; + if (internalStorage.find(value) != internalStorage.end()) { + return; + } + parent.insert({value, value}); + roots.insert(value); + rank.insert({value, 0}); + disjointSets.insert({value, new IndependentConstraintSet(s)}); + + internalStorage.insert(value); + internalStorage_ty oldRoots = roots; + for (ref v : oldRoots) { + if (!areJoined(v, value) && + IndependentConstraintSet::intersects(disjointSets.at(find(v)), + disjointSets.at(find(value)))) { + merge(v, value); + } + } + disjointSets.replace( + {find(value), disjointSets.at(find(value))->addExpr(value)}); +} + +IndependentConstraintSetUnion +IndependentConstraintSetUnion::getConcretizedVersion() const { + IndependentConstraintSetUnion icsu; + for (ref i : roots) { + ref root = disjointSets.at(i); + icsu.add(root->concretizedSets); + icsu.concretization.addIndependentAssignment(root->concretization); + } + icsu.concretizedExprs = concretizedExprs; + return icsu; +} + +IndependentConstraintSetUnion +IndependentConstraintSetUnion::getConcretizedVersion( + const Assignment &newConcretization) const { + IndependentConstraintSetUnion icsu = *this; + icsu.reEvaluateConcretization(newConcretization); + return icsu.getConcretizedVersion(); +} +} // namespace klee From 850ae7ff284c05d374d4fdb432bf07b8372966d3 Mon Sep 17 00:00:00 2001 From: dim8art Date: Sun, 20 Aug 2023 16:17:13 +0300 Subject: [PATCH 002/103] Rework IndependentSolver using persistent DSU --- include/klee/Expr/Constraints.h | 17 +- include/klee/Expr/IndependentSet.h | 111 ++++++--- lib/Expr/CMakeLists.txt | 1 + lib/Expr/Constraints.cpp | 74 +++++- lib/Expr/IndependentSet.cpp | 378 ++++++++++++++--------------- lib/Solver/IndependentSolver.cpp | 231 +++++++++--------- 6 files changed, 461 insertions(+), 351 deletions(-) diff --git a/include/klee/Expr/Constraints.h b/include/klee/Expr/Constraints.h index a14b9e191e..c65cee483f 100644 --- a/include/klee/Expr/Constraints.h +++ b/include/klee/Expr/Constraints.h @@ -16,6 +16,8 @@ #include "klee/Expr/Expr.h" #include "klee/Expr/ExprHashMap.h" #include "klee/Expr/ExprUtil.h" +#include "klee/Expr/IndependentConstraintSetUnion.h" +#include "klee/Expr/IndependentSet.h" #include "klee/Expr/Path.h" #include "klee/Expr/Symcrete.h" @@ -35,6 +37,8 @@ class ConstraintSet { public: ConstraintSet(constraints_ty cs, symcretes_ty symcretes, Assignment concretization); + ConstraintSet(ref ics); + ConstraintSet(const std::vector> &ics); ConstraintSet(); void addConstraint(ref e, const Assignment &delta); @@ -55,7 +59,8 @@ class ConstraintSet { return _constraints < b._constraints || (_constraints == b._constraints && _symcretes < b._symcretes); } - + ConstraintSet getConcretizedVersion() const; + ConstraintSet getConcretizedVersion(const Assignment &c) const; void dump() const; void print(llvm::raw_ostream &os) const; @@ -64,11 +69,21 @@ class ConstraintSet { const constraints_ty &cs() const; const symcretes_ty &symcretes() const; const Assignment &concretization() const; + const IndependentConstraintSetUnion &independentElements() const; + + void getAllIndependentConstraintsSets( + ref queryExpr, + std::vector> &result) const; + + void getAllDependentConstraintsSets( + ref queryExpr, + std::vector> &result) const; private: constraints_ty _constraints; symcretes_ty _symcretes; Assignment _concretization; + IndependentConstraintSetUnion _independentElements; }; class PathConstraints { diff --git a/include/klee/Expr/IndependentSet.h b/include/klee/Expr/IndependentSet.h index 9173d90678..ef29498f5a 100644 --- a/include/klee/Expr/IndependentSet.h +++ b/include/klee/Expr/IndependentSet.h @@ -1,9 +1,13 @@ #ifndef KLEE_INDEPENDENTSET_H #define KLEE_INDEPENDENTSET_H +#include "klee/ADT/DisjointSetUnion.h" +#include "klee/ADT/PersistentMap.h" +#include "klee/ADT/PersistentSet.h" +#include "klee/Expr/Assignment.h" #include "klee/Expr/Expr.h" #include "klee/Expr/ExprHashMap.h" -#include "klee/Solver/Solver.h" +#include "klee/Expr/Symcrete.h" #include "klee/Support/CompilerWarning.h" DISABLE_WARNING_PUSH @@ -11,8 +15,10 @@ DISABLE_WARNING_DEPRECATED_DECLARATIONS #include "llvm/Support/raw_ostream.h" DISABLE_WARNING_POP -#include +#include #include +#include +#include namespace klee { @@ -42,7 +48,7 @@ template class DenseSet { return modified; } - bool intersects(const DenseSet &b) { + bool intersects(const DenseSet &b) const { for (typename set_ty::iterator it = s.begin(), ie = s.end(); it != ie; ++it) if (b.s.count(*it)) return true; @@ -76,54 +82,89 @@ inline llvm::raw_ostream &operator<<(llvm::raw_ostream &os, return os; } -class IndependentElementSet { +class IndependentConstraintSet { +private: + using InnerSetUnion = DisjointSetUnion, IndependentConstraintSet>; + public: - typedef std::map> elements_ty; + // All containers need to become persistent to make fast copy and faster + // merge possible map from concretized to normal + typedef PersistentMap> elements_ty; elements_ty elements; // Represents individual elements of array accesses (arr[1]) - std::set - wholeObjects; // Represents symbolically accessed arrays (arr[x]) - constraints_ty exprs; // All expressions (constraints) that are associated - // with this factor - SymcreteOrderedSet symcretes; // All symcretes associated with this factor + PersistentSet + wholeObjects; // Represents symbolically accessed arrays (arr[x]) + PersistentSet> exprs; // All expressions (constraints) that are + // associated with this factor + PersistentSet> + symcretes; // All symcretes associated with this factor + + Assignment concretization; + + InnerSetUnion concretizedSets; + + ref addExpr(ref e) const; + ref + updateConcretization(const Assignment &delta, + ExprHashMap> &changedExprs) const; + ref + removeConcretization(const Assignment &delta, + ExprHashMap> &changedExprs) const; - IndependentElementSet(); - IndependentElementSet(ref e); - IndependentElementSet(ref s); - IndependentElementSet(const IndependentElementSet &ies); + void + addValuesToAssignment(const std::vector &objects, + const std::vector> &values, + Assignment &assign) const; - IndependentElementSet &operator=(const IndependentElementSet &ies); + IndependentConstraintSet(); + IndependentConstraintSet(ref e); + IndependentConstraintSet(ref s); + IndependentConstraintSet(const ref &ics); + + IndependentConstraintSet &operator=(const IndependentConstraintSet &ies); void print(llvm::raw_ostream &os) const; - // more efficient when this is the smaller set - bool intersects(const IndependentElementSet &b); + static bool intersects(ref a, + ref b); - // returns true iff set is changed by addition - bool add(const IndependentElementSet &b); + static ref + merge(ref a, + ref b); + + // Extracts which arrays are referenced from a particular independent set. + // Examines both the actual known array accesses arr[1] plus the undetermined + // accesses arr[x].Z + void calculateArrayReferences(std::vector &returnVector) const; + + SymcreteOrderedSet getSymcretes() const { + SymcreteOrderedSet a; + for (ref s : symcretes) { + a.insert(s); + } + return a; + } + + constraints_ty getConstraints() const { + constraints_ty a; + for (ref e : exprs) { + a.insert(e); + } + return a; + } + mutable class ReferenceCounter _refCount; }; +void calculateArraysInFactors( + const std::vector> &factors, + ref queryExpr, std::vector &returnVector); + inline llvm::raw_ostream &operator<<(llvm::raw_ostream &os, - const IndependentElementSet &ies) { + const IndependentConstraintSet &ies) { ies.print(os); return os; } -// Breaks down a constraint into all of it's individual pieces, returning a -// list of IndependentElementSets or the independent factors. -// -// Caller takes ownership of returned std::list. -std::list * -getAllIndependentConstraintsSets(const Query &query); - -IndependentElementSet getIndependentConstraints(const Query &query, - constraints_ty &result); - -// Extracts which arrays are referenced from a particular independent set. -// Examines both the actual known array accesses arr[1] plus the undetermined -// accesses arr[x]. -void calculateArrayReferences(const IndependentElementSet &ie, - std::vector &returnVector); } // namespace klee #endif /* KLEE_INDEPENDENTSET_H */ diff --git a/lib/Expr/CMakeLists.txt b/lib/Expr/CMakeLists.txt index b7ca4e0124..758a4ca743 100644 --- a/lib/Expr/CMakeLists.txt +++ b/lib/Expr/CMakeLists.txt @@ -22,6 +22,7 @@ add_library(kleaverExpr ExprSMTLIBPrinter.cpp ExprUtil.cpp ExprVisitor.cpp + IndependentConstraintSetUnion.cpp IndependentSet.cpp Path.cpp SourceBuilder.cpp diff --git a/lib/Expr/Constraints.cpp b/lib/Expr/Constraints.cpp index 802a75bea4..22d45d6d29 100644 --- a/lib/Expr/Constraints.cpp +++ b/lib/Expr/Constraints.cpp @@ -181,18 +181,36 @@ class ExprReplaceVisitor3 : public ExprVisitor { ConstraintSet::ConstraintSet(constraints_ty cs, symcretes_ty symcretes, Assignment concretization) - : _constraints(cs), _symcretes(symcretes), _concretization(concretization) { + : _constraints(cs), _symcretes(symcretes), _concretization(concretization), + _independentElements(_constraints, _symcretes, _concretization) {} + +ConstraintSet::ConstraintSet(ref ics) + : _constraints(ics->getConstraints()), _symcretes(ics->getSymcretes()), + _concretization(ics->concretization), _independentElements(ics) {} + +ConstraintSet::ConstraintSet( + const std::vector> &factors) { + for (auto ics : factors) { + constraints_ty constraints = ics->getConstraints(); + SymcreteOrderedSet symcretes = ics->getSymcretes(); + IndependentConstraintSetUnion icsu(ics); + _constraints.insert(constraints.begin(), constraints.end()); + _symcretes.insert(symcretes.begin(), symcretes.end()); + _concretization.addIndependentAssignment(ics->concretization); + _independentElements.addIndependentConstraintSetUnion(icsu); + } } -ConstraintSet::ConstraintSet() : _concretization(Assignment(true)) {} +ConstraintSet::ConstraintSet() {} void ConstraintSet::addConstraint(ref e, const Assignment &delta) { _constraints.insert(e); - + _independentElements.addExpr(e); // Update bindings for (auto i : delta.bindings) { - _concretization.bindings[i.first] = i.second; + _concretization.bindings.replace({i.first, i.second}); } + _independentElements.updateConcretization(delta); } IDType Symcrete::idCounter = 0; @@ -200,9 +218,14 @@ IDType Symcrete::idCounter = 0; void ConstraintSet::addSymcrete(ref s, const Assignment &concretization) { _symcretes.insert(s); + _independentElements.addSymcrete(s); + Assignment dependentConcretization; for (auto i : s->dependentArrays()) { - _concretization.bindings[i] = concretization.bindings.at(i); + _concretization.bindings.replace({i, concretization.bindings.at(i)}); + dependentConcretization.bindings.replace( + {i, concretization.bindings.at(i)}); } + _independentElements.updateConcretization(dependentConcretization); } bool ConstraintSet::isSymcretized(ref expr) const { @@ -217,9 +240,31 @@ bool ConstraintSet::isSymcretized(ref expr) const { void ConstraintSet::rewriteConcretization(const Assignment &a) { for (auto i : a.bindings) { if (concretization().bindings.count(i.first)) { - _concretization.bindings[i.first] = i.second; + _concretization.bindings.replace({i.first, i.second}); } } + _independentElements.updateConcretization(a); +} + +ConstraintSet ConstraintSet::getConcretizedVersion() const { + ConstraintSet cs; + cs._independentElements = _independentElements.getConcretizedVersion(); + + for (ref e : cs._independentElements.is()) { + cs._constraints.insert(e); + } + return cs; +} + +ConstraintSet ConstraintSet::getConcretizedVersion( + const Assignment &newConcretization) const { + ConstraintSet cs; + cs._independentElements = + _independentElements.getConcretizedVersion(newConcretization); + for (ref e : cs._independentElements.is()) { + cs._constraints.insert(e); + } + return cs; } void ConstraintSet::print(llvm::raw_ostream &os) const { @@ -246,6 +291,11 @@ const constraints_ty &ConstraintSet::cs() const { return _constraints; } const symcretes_ty &ConstraintSet::symcretes() const { return _symcretes; } +const IndependentConstraintSetUnion & +ConstraintSet::independentElements() const { + return _independentElements; +} + const Path &PathConstraints::path() const { return _path; } const ExprHashMap &PathConstraints::indexes() const { @@ -523,6 +573,18 @@ Simplificator::composeExprDependencies(const ExprHashMap &upper, return result; } +void ConstraintSet::getAllIndependentConstraintsSets( + ref queryExpr, + std::vector> &result) const { + _independentElements.getAllIndependentConstraintSets(queryExpr, result); +} + +void ConstraintSet::getAllDependentConstraintsSets( + ref queryExpr, + std::vector> &result) const { + _independentElements.getAllDependentConstraintSets(queryExpr, result); +} + std::vector ConstraintSet::gatherArrays() const { std::vector arrays; findObjects(_constraints.begin(), _constraints.end(), arrays); diff --git a/lib/Expr/IndependentSet.cpp b/lib/Expr/IndependentSet.cpp index d4fade9ef1..ed602599b2 100644 --- a/lib/Expr/IndependentSet.cpp +++ b/lib/Expr/IndependentSet.cpp @@ -1,6 +1,7 @@ #include "klee/Expr/IndependentSet.h" #include "klee/ADT/Ref.h" +#include "klee/Expr/Assignment.h" #include "klee/Expr/Constraints.h" #include "klee/Expr/ExprHashMap.h" #include "klee/Expr/ExprUtil.h" @@ -16,9 +17,87 @@ namespace klee { -IndependentElementSet::IndependentElementSet() {} +ref +IndependentConstraintSet::addExpr(ref e) const { + ref ics = new IndependentConstraintSet(this); + ics->concretizedSets.addValue(concretization.evaluate(e)); + return ics; +} + +ref +IndependentConstraintSet::updateConcretization( + const Assignment &delta, ExprHashMap> &concretizedExprs) const { + ref ics = new IndependentConstraintSet(this); + if (delta.bindings.size() == 0) { + return ics; + } + for (auto i : delta.bindings) { + ics->concretization.bindings.replace({i.first, i.second}); + } + InnerSetUnion DSU; + for (ref i : exprs) { + ref e = ics->concretization.evaluate(i); + concretizedExprs[i] = e; + DSU.addValue(e); + } + for (ref s : symcretes) { + DSU.addValue(EqExpr::create(ics->concretization.evaluate(s->symcretized), + s->symcretized)); + } + ics->concretizedSets = DSU; + return ics; +} -IndependentElementSet::IndependentElementSet(ref e) { +ref +IndependentConstraintSet::removeConcretization( + const Assignment &delta, ExprHashMap> &concretizedExprs) const { + ref ics = new IndependentConstraintSet(this); + if (delta.bindings.size() == 0) { + return ics; + } + for (auto i : delta.bindings) { + ics->concretization.bindings.remove(i.first); + } + InnerSetUnion DSU; + for (ref i : exprs) { + ref e = ics->concretization.evaluate(i); + concretizedExprs[i] = e; + DSU.addValue(e); + } + for (ref s : symcretes) { + DSU.addValue(EqExpr::create(ics->concretization.evaluate(s->symcretized), + s->symcretized)); + } + + ics->concretizedSets = DSU; + return ics; +} + +void IndependentConstraintSet::addValuesToAssignment( + const std::vector &objects, + const std::vector> &values, + Assignment &assign) const { + for (unsigned i = 0; i < objects.size(); i++) { + if (assign.bindings.count(objects[i])) { + SparseStorage value = assign.bindings.at(objects[i]); + assert(value.size() == values[i].size() && + "we're talking about the same array here"); + DenseSet ds = (elements.find(objects[i]))->second; + for (std::set::iterator it2 = ds.begin(); it2 != ds.end(); + it2++) { + unsigned index = *it2; + value.store(index, values[i].load(index)); + } + assign.bindings.replace({objects[i], value}); + } else { + assign.bindings.replace({objects[i], values[i]}); + } + } +} + +IndependentConstraintSet::IndependentConstraintSet() {} + +IndependentConstraintSet::IndependentConstraintSet(ref e) { exprs.insert(e); // Track all reads in the program. Determines whether reads are // concrete or symbolic. If they are symbolic, "collapses" array @@ -39,19 +118,23 @@ IndependentElementSet::IndependentElementSet(ref e) { if (ConstantExpr *CE = dyn_cast(re->index)) { // if index constant, then add to set of constraints operating // on that array (actually, don't add constraint, just set index) - DenseSet &dis = elements[array]; + DenseSet dis; + if (elements.find(array) != elements.end()) { + dis = (elements.find(array))->second; + } dis.add((unsigned)CE->getZExtValue(32)); + elements.replace({array, dis}); } else { elements_ty::iterator it2 = elements.find(array); if (it2 != elements.end()) - elements.erase(it2); + elements.remove(it2->first); wholeObjects.insert(array); } } } } -IndependentElementSet::IndependentElementSet(ref s) { +IndependentConstraintSet::IndependentConstraintSet(ref s) { symcretes.insert(s); for (Symcrete &dependentSymcrete : s->dependentSymcretes()) { @@ -93,35 +176,45 @@ IndependentElementSet::IndependentElementSet(ref s) { if (ConstantExpr *CE = dyn_cast(re->index)) { // if index constant, then add to set of constraints operating // on that array (actually, don't add constraint, just set index) - DenseSet &dis = elements[array]; + DenseSet dis; + if (elements.find(array) != elements.end()) { + dis = (elements.find(array))->second; + } dis.add((unsigned)CE->getZExtValue(32)); + elements.replace({array, dis}); } else { elements_ty::iterator it2 = elements.find(array); if (it2 != elements.end()) - elements.erase(it2); + elements.remove(it2->first); wholeObjects.insert(array); } } } } -IndependentElementSet::IndependentElementSet(const IndependentElementSet &ies) - : elements(ies.elements), wholeObjects(ies.wholeObjects), exprs(ies.exprs) { -} - -IndependentElementSet & -IndependentElementSet::operator=(const IndependentElementSet &ies) { - elements = ies.elements; - wholeObjects = ies.wholeObjects; - exprs = ies.exprs; +IndependentConstraintSet::IndependentConstraintSet( + const ref &ics) + : elements(ics->elements), wholeObjects(ics->wholeObjects), + exprs(ics->exprs), symcretes(ics->symcretes), + concretization(ics->concretization), + concretizedSets(ics->concretizedSets) {} + +IndependentConstraintSet & +IndependentConstraintSet::operator=(const IndependentConstraintSet &ics) { + elements = ics.elements; + wholeObjects = ics.wholeObjects; + exprs = ics.exprs; + symcretes = ics.symcretes; + concretization = ics.concretization; + concretizedSets = ics.concretizedSets; return *this; } -void IndependentElementSet::print(llvm::raw_ostream &os) const { +void IndependentConstraintSet::print(llvm::raw_ostream &os) const { os << "{"; bool first = true; - for (std::set::iterator it = wholeObjects.begin(), - ie = wholeObjects.end(); + for (PersistentSet::iterator it = wholeObjects.begin(), + ie = wholeObjects.end(); it != ie; ++it) { const Array *array = *it; @@ -133,7 +226,7 @@ void IndependentElementSet::print(llvm::raw_ostream &os) const { os << "MO" << array->getIdentifier(); } - for (elements_ty::const_iterator it = elements.begin(), ie = elements.end(); + for (elements_ty::iterator it = elements.begin(), ie = elements.end(); it != ie; ++it) { const Array *array = it->first; const DenseSet &dis = it->second; @@ -149,218 +242,123 @@ void IndependentElementSet::print(llvm::raw_ostream &os) const { os << "}"; } -// more efficient when this is the smaller set -bool IndependentElementSet::intersects(const IndependentElementSet &b) { +bool IndependentConstraintSet::intersects( + ref a, + ref b) { + if (a->wholeObjects.size() + a->elements.size() > + b->wholeObjects.size() + b->elements.size()) { + std::swap(a, b); + } // If there are any symbolic arrays in our query that b accesses - for (std::set::iterator it = wholeObjects.begin(), - ie = wholeObjects.end(); + for (PersistentSet::iterator it = a->wholeObjects.begin(), + ie = a->wholeObjects.end(); it != ie; ++it) { const Array *array = *it; - if (b.wholeObjects.count(array) || - b.elements.find(array) != b.elements.end()) + if (b->wholeObjects.count(array) || + b->elements.find(array) != b->elements.end()) return true; } - for (elements_ty::iterator it = elements.begin(), ie = elements.end(); + for (elements_ty::iterator it = a->elements.begin(), ie = a->elements.end(); it != ie; ++it) { const Array *array = it->first; // if the array we access is symbolic in b - if (b.wholeObjects.count(array)) + if (b->wholeObjects.count(array)) return true; - elements_ty::const_iterator it2 = b.elements.find(array); + elements_ty::iterator it2 = b->elements.find(array); // if any of the elements we access are also accessed by b - if (it2 != b.elements.end()) { - if (it->second.intersects(it2->second)) + if (it2 != b->elements.end()) { + if (it->second.intersects(it2->second)) { return true; + } } } // No need to check symcretes here, arrays must be sufficient. return false; } -// returns true iff set is changed by addition -bool IndependentElementSet::add(const IndependentElementSet &b) { - for (auto expr : b.exprs) { - exprs.insert(expr); - } +ref +IndependentConstraintSet::merge(ref A, + ref B) { + ref a = new IndependentConstraintSet(A); + ref b = new IndependentConstraintSet(B); - for (const ref &symcrete : b.symcretes) { - symcretes.insert(symcrete); + if (a->wholeObjects.size() + a->elements.size() < + b->wholeObjects.size() + b->elements.size()) { + std::swap(a, b); + } + for (ref expr : b->exprs) { + a->exprs.insert(expr); + } + for (const ref &symcrete : b->symcretes) { + a->symcretes.insert(symcrete); } - bool modified = false; - for (std::set::const_iterator it = b.wholeObjects.begin(), - ie = b.wholeObjects.end(); + for (PersistentSet::iterator it = b->wholeObjects.begin(), + ie = b->wholeObjects.end(); it != ie; ++it) { const Array *array = *it; - elements_ty::iterator it2 = elements.find(array); - if (it2 != elements.end()) { - modified = true; - elements.erase(it2); - wholeObjects.insert(array); + elements_ty::iterator it2 = a->elements.find(array); + if (it2 != a->elements.end()) { + a->elements.remove(it2->first); + a->wholeObjects.insert(array); } else { - if (!wholeObjects.count(array)) { - modified = true; - wholeObjects.insert(array); + if (!a->wholeObjects.count(array)) { + a->wholeObjects.insert(array); } } } - for (elements_ty::const_iterator it = b.elements.begin(), - ie = b.elements.end(); + for (elements_ty::iterator it = b->elements.begin(), ie = b->elements.end(); it != ie; ++it) { const Array *array = it->first; - if (!wholeObjects.count(array)) { - elements_ty::iterator it2 = elements.find(array); - if (it2 == elements.end()) { - modified = true; - elements.insert(*it); + if (!a->wholeObjects.count(array)) { + elements_ty::iterator it2 = a->elements.find(array); + if (it2 == a->elements.end()) { + a->elements.insert(*it); } else { - // Now need to see if there are any (z=?)'s - if (it2->second.add(it->second)) - modified = true; + DenseSet dis = it2->second; + dis.add(it->second); + a->elements.replace({array, dis}); } } } - return modified; + b->addValuesToAssignment(b->concretization.keys(), b->concretization.values(), + a->concretization); + a->concretizedSets.add(b->concretizedSets); + return a; } -// Breaks down a constraint into all of it's individual pieces, returning a -// list of IndependentElementSets or the independent factors. -// -// Caller takes ownership of returned std::list. -std::list * -getAllIndependentConstraintsSets(const Query &query) { - std::list *factors = - new std::list(); - ConstantExpr *CE = dyn_cast(query.expr); - if (CE) { - assert(CE && CE->isFalse() && - "the expr should always be false and " - "therefore not included in factors"); - } else { - ref neg = Expr::createIsZero(query.expr); - factors->push_back(IndependentElementSet(neg)); - } - - for (const auto &constraint : query.constraints.cs()) { - // iterate through all the previously separated constraints. Until we - // actually return, factors is treated as a queue of expressions to be - // evaluated. If the queue property isn't maintained, then the exprs - // could be returned in an order different from how they came it, negatively - // affecting later stages. - factors->push_back(IndependentElementSet(constraint)); - } - - for (const auto &symcrete : query.constraints.symcretes()) { - factors->push_back(IndependentElementSet(symcrete)); - } - - bool doneLoop = false; - do { - doneLoop = true; - std::list *done = - new std::list; - while (factors->size() > 0) { - IndependentElementSet current = factors->front(); - factors->pop_front(); - // This list represents the set of factors that are separate from current. - // Those that are not inserted into this list (queue) intersect with - // current. - std::list *keep = - new std::list; - while (factors->size() > 0) { - IndependentElementSet compare = factors->front(); - factors->pop_front(); - if (current.intersects(compare)) { - if (current.add(compare)) { - // Means that we have added (z=y)added to (x=y) - // Now need to see if there are any (z=?)'s - doneLoop = false; - } - } else { - keep->push_back(compare); - } - } - done->push_back(current); - delete factors; - factors = keep; - } - delete factors; - factors = done; - } while (!doneLoop); - - return factors; -} - -IndependentElementSet getIndependentConstraints(const Query &query, - constraints_ty &result) { - IndependentElementSet eltsClosure(query.expr); - std::vector, IndependentElementSet>> worklist; - - for (const auto &constraint : query.constraints.cs()) - worklist.push_back( - std::make_pair(constraint, IndependentElementSet(constraint))); - - for (const ref &symcrete : query.constraints.symcretes()) { - worklist.push_back( - std::make_pair(symcrete->symcretized, IndependentElementSet(symcrete))); - } - - // XXX This should be more efficient (in terms of low level copy stuff). - bool done = false; - do { - done = true; - std::vector, IndependentElementSet>> newWorklist; - for (std::vector, IndependentElementSet>>::iterator - it = worklist.begin(), - ie = worklist.end(); - it != ie; ++it) { - if (it->second.intersects(eltsClosure)) { - if (eltsClosure.add(it->second)) - done = false; - result.insert(it->first); - // Means that we have added (z=y)added to (x=y) - // Now need to see if there are any (z=?)'s - } else { - newWorklist.push_back(*it); - } - } - worklist.swap(newWorklist); - } while (!done); - - // KLEE_DEBUG( - // std::set> reqset(result.begin(), result.end()); - // errs() << "--\n"; errs() << "Q: " << query.expr << "\n"; - // errs() << "\telts: " << IndependentElementSet(query.expr) << "\n"; - // int i = 0; for (const auto &constraint - // : query.constraints) { - // errs() << "C" << i++ << ": " << constraint; - // errs() << " " - // << (reqset.count(constraint) ? "(required)" : "(independent)") - // << "\n"; - // errs() << "\telts: " << IndependentElementSet(constraint) << "\n"; - // } errs() << "elts closure: " - // << eltsClosure << "\n";); - - return eltsClosure; -} - -void calculateArrayReferences(const IndependentElementSet &ie, - std::vector &returnVector) { +void IndependentConstraintSet::calculateArrayReferences( + std::vector &returnVector) const { std::set thisSeen; - for (std::map>::const_iterator it = - ie.elements.begin(); - it != ie.elements.end(); it++) { + for (IndependentConstraintSet::elements_ty::iterator it = elements.begin(); + it != elements.end(); ++it) { thisSeen.insert(it->first); } - for (std::set::iterator it = ie.wholeObjects.begin(); - it != ie.wholeObjects.end(); it++) { - assert(*it); + for (PersistentSet::iterator it = wholeObjects.begin(); + it != wholeObjects.end(); ++it) { thisSeen.insert(*it); } for (std::set::iterator it = thisSeen.begin(); - it != thisSeen.end(); it++) { + it != thisSeen.end(); ++it) { returnVector.push_back(*it); } } +void calculateArraysInFactors( + const std::vector> &factors, + ref queryExpr, std::vector &returnVector) { + std::set returnSet; + for (ref ics : factors) { + std::vector result; + ics->calculateArrayReferences(result); + returnSet.insert(result.begin(), result.end()); + } + std::vector result; + ref queryExprSet = + new IndependentConstraintSet(queryExpr); + queryExprSet->calculateArrayReferences(result); + returnSet.insert(result.begin(), result.end()); + returnVector.insert(returnVector.begin(), returnSet.begin(), returnSet.end()); +} + } // namespace klee diff --git a/lib/Solver/IndependentSolver.cpp b/lib/Solver/IndependentSolver.cpp index 9e0139200a..a8c7fb8ede 100644 --- a/lib/Solver/IndependentSolver.cpp +++ b/lib/Solver/IndependentSolver.cpp @@ -64,32 +64,23 @@ class IndependentSolver : public SolverImpl { bool IndependentSolver::computeValidity(const Query &query, PartialValidity &result) { - constraints_ty required; - IndependentElementSet eltsClosure = - getIndependentConstraints(query, required); - ConstraintSet tmp( - required, eltsClosure.symcretes, - query.constraints.concretization().part(eltsClosure.symcretes)); + std::vector> factors; + query.getAllDependentConstraintsSets(factors); + ConstraintSet tmp(factors); return solver->impl->computeValidity(query.withConstraints(tmp), result); } bool IndependentSolver::computeTruth(const Query &query, bool &isValid) { - constraints_ty required; - IndependentElementSet eltsClosure = - getIndependentConstraints(query, required); - ConstraintSet tmp( - required, eltsClosure.symcretes, - query.constraints.concretization().part(eltsClosure.symcretes)); + std::vector> factors; + query.getAllDependentConstraintsSets(factors); + ConstraintSet tmp(factors); return solver->impl->computeTruth(query.withConstraints(tmp), isValid); } bool IndependentSolver::computeValue(const Query &query, ref &result) { - constraints_ty required; - IndependentElementSet eltsClosure = - getIndependentConstraints(query, required); - ConstraintSet tmp( - required, eltsClosure.symcretes, - query.constraints.concretization().part(eltsClosure.symcretes)); + std::vector> factors; + query.getAllDependentConstraintsSets(factors); + ConstraintSet tmp(factors); return solver->impl->computeValue(query.withConstraints(tmp), result); } @@ -99,22 +90,26 @@ bool IndependentSolver::computeValue(const Query &query, ref &result) { bool assertCreatedPointEvaluatesToTrue( const Query &query, const std::vector &objects, std::vector> &values, - std::map> &retMap) { + Assignment::bindings_ty &retMap) { // _allowFreeValues is set to true so that if there are missing bytes in the // assignment we will end up with a non ConstantExpr after evaluating the // assignment and fail - Assignment assign = Assignment(objects, values, /*_allowFreeValues=*/true); + Assignment assign = Assignment(objects, values); // Add any additional bindings. // The semantics of std::map should be to not insert a (key, value) // pair if it already exists so we should continue to use the assignment // from ``objects`` and ``values``. - if (retMap.size() > 0) - assign.bindings.insert(retMap.begin(), retMap.end()); - + if (retMap.size() > 0) { + for (auto it : retMap) { + assign.bindings.insert(it); + } + } for (auto const &constraint : query.constraints.cs()) { ref ret = assign.evaluate(constraint); - + if (!isa(ret)) { + ret = ret->rebuild(); + } assert(isa(ret) && "assignment evaluation did not result in constant"); ref evaluatedConstraint = dyn_cast(ret); @@ -124,15 +119,17 @@ bool assertCreatedPointEvaluatesToTrue( } ref neg = Expr::createIsZero(query.expr); ref q = assign.evaluate(neg); + if (!isa(q)) { + q = q->rebuild(); + } assert(isa(q) && "assignment evaluation did not result in constant"); return cast(q)->isTrue(); } -bool assertCreatedPointEvaluatesToTrue( - const Query &query, - std::map> &bindings, - std::map> &retMap) { +bool assertCreatedPointEvaluatesToTrue(const Query &query, + Assignment::bindings_ty &bindings, + Assignment::bindings_ty &retMap) { std::vector objects; std::vector> values; objects.reserve(bindings.size()); @@ -151,82 +148,89 @@ bool IndependentSolver::computeInitialValues( // This is important in case we don't have any constraints but // we need initial values for requested array objects. hasSolution = true; - // FIXME: When we switch to C++11 this should be a std::unique_ptr so we don't - // need to remember to manually call delete - std::list *factors = - getAllIndependentConstraintsSets(query); + Assignment retMap; + std::vector> dependentFactors; + query.getAllDependentConstraintsSets(dependentFactors); + ConstraintSet dependentConstriants(dependentFactors); + + std::vector dependentFactorsObjects; + calculateArraysInFactors(dependentFactors, query.expr, + dependentFactorsObjects); + + if (dependentFactorsObjects.size() != 0) { + std::vector> dependentFactorsValues; + + if (!solver->impl->computeInitialValues( + query.withConstraints(dependentConstriants), + dependentFactorsObjects, dependentFactorsValues, hasSolution)) { + values.clear(); + return false; + } else if (!hasSolution) { + values.clear(); + return true; + } else { + retMap = Assignment(dependentFactorsObjects, dependentFactorsValues); + } + } + + std::vector> independentFactors; + query.getAllIndependentConstraintsSets(independentFactors); // Used to rearrange all of the answers into the correct order - std::map> retMap; - for (std::list::iterator it = factors->begin(); - it != factors->end(); ++it) { + for (ref it : independentFactors) { std::vector arraysInFactor; - calculateArrayReferences(*it, arraysInFactor); + it->calculateArrayReferences(arraysInFactor); // Going to use this as the "fresh" expression for the Query() invocation // below assert(it->exprs.size() >= 1 && "No null/empty factors"); if (arraysInFactor.size() == 0) { continue; } - ConstraintSet tmp(it->exprs, it->symcretes, - query.constraints.concretization().part(it->symcretes)); + ConstraintSet tmp(it); std::vector> tempValues; if (!solver->impl->computeInitialValues( Query(tmp, ConstantExpr::alloc(0, Expr::Bool)), arraysInFactor, tempValues, hasSolution)) { values.clear(); - delete factors; + return false; } else if (!hasSolution) { values.clear(); - delete factors; + return true; } else { assert(tempValues.size() == arraysInFactor.size() && "Should be equal number arrays and answers"); - for (unsigned i = 0; i < tempValues.size(); i++) { - if (retMap.count(arraysInFactor[i])) { - // We already have an array with some partially correct answers, - // so we need to place the answers to the new query into the right - // spot while avoiding the undetermined values also in the array - SparseStorage *tempPtr = &retMap[arraysInFactor[i]]; - assert(tempPtr->size() == tempValues[i].size() && - "we're talking about the same array here"); - klee::DenseSet *ds = &(it->elements[arraysInFactor[i]]); - for (std::set::iterator it2 = ds->begin(); it2 != ds->end(); - it2++) { - unsigned index = *it2; - tempPtr->store(index, tempValues[i].load(index)); - } - } else { - // Dump all the new values into the array - retMap[arraysInFactor[i]] = tempValues[i]; - } - } + // We already have an array with some partially correct answers, + // so we need to place the answers to the new query into the right + // spot while avoiding the undetermined values also in the array + it->addValuesToAssignment(arraysInFactor, tempValues, retMap); } } - Assignment solutionAssignment(retMap, true); for (std::vector::const_iterator it = objects.begin(); it != objects.end(); it++) { const Array *arr = *it; - if (!retMap.count(arr)) { + if (!retMap.bindings.count(arr)) { // this means we have an array that is somehow related to the // constraint, but whose values aren't actually required to // satisfy the query. ref arrayConstantSize = - dyn_cast(solutionAssignment.evaluate(arr->size)); + dyn_cast(retMap.evaluate(arr->size)); + arrayConstantSize->dump(); assert(arrayConstantSize && "Array of symbolic size had not receive value for size!"); SparseStorage ret(arrayConstantSize->getZExtValue()); values.push_back(ret); } else { - values.push_back(retMap[arr]); + values.push_back(retMap.bindings.at(arr)); } } - assert(assertCreatedPointEvaluatesToTrue(query, objects, values, retMap) && + + assert(assertCreatedPointEvaluatesToTrue(query, objects, values, + retMap.bindings) && "should satisfy the equation"); - delete factors; + return true; } @@ -234,47 +238,54 @@ bool IndependentSolver::check(const Query &query, ref &result) { // We assume the query has a solution except proven differently // This is important in case we don't have any constraints but // we need initial values for requested array objects. + // result = new ValidResponse(ValidityCore()); + Assignment retMap; + std::vector> dependentFactors; + query.getAllDependentConstraintsSets(dependentFactors); + ConstraintSet dependentConstriants(dependentFactors); + + std::vector dependentFactorsObjects; + std::vector> dependentFactorsValues; + ref dependentFactorsResult; + + calculateArraysInFactors(dependentFactors, query.expr, + dependentFactorsObjects); + + if (dependentFactorsObjects.size() != 0) { + if (!solver->impl->check(query.withConstraints(dependentConstriants), + dependentFactorsResult)) { + return false; + } else if (isa(dependentFactorsResult)) { + result = dependentFactorsResult; + return true; + } else { + bool success = dependentFactorsResult->tryGetInitialValuesFor( + dependentFactorsObjects, dependentFactorsValues); + assert(success && "Can not get initial values (Independent solver)!"); + retMap = Assignment(dependentFactorsObjects, dependentFactorsValues); + } + } - // FIXME: When we switch to C++11 this should be a std::unique_ptr so we don't - // need to remember to manually call delete - std::list *factors = - getAllIndependentConstraintsSets(query); + std::vector> independentFactors; + query.getAllIndependentConstraintsSets(independentFactors); // Used to rearrange all of the answers into the correct order - std::map> retMap; - for (std::list::iterator it = factors->begin(); - it != factors->end(); ++it) { + for (ref it : independentFactors) { std::vector arraysInFactor; - calculateArrayReferences(*it, arraysInFactor); + it->calculateArrayReferences(arraysInFactor); // Going to use this as the "fresh" expression for the Query() invocation // below assert(it->exprs.size() >= 1 && "No null/empty factors"); if (arraysInFactor.size() == 0) { continue; } - - constraints_ty factorConstraints = it->exprs; - ref factorExpr = ConstantExpr::alloc(0, Expr::Bool); - auto factorConstraintsExprIterator = - std::find(factorConstraints.begin(), factorConstraints.end(), - query.negateExpr().expr); - if (factorConstraintsExprIterator != factorConstraints.end()) { - factorConstraints.erase(factorConstraintsExprIterator); - factorExpr = query.expr; - } - ref tempResult; std::vector> tempValues; if (!solver->impl->check( - Query(ConstraintSet( - factorConstraints, it->symcretes, - query.constraints.concretization().part(it->symcretes)), - factorExpr), + Query(ConstraintSet(it), ConstantExpr::alloc(0, Expr::Bool)), tempResult)) { - delete factors; return false; } else if (isa(tempResult)) { - delete factors; result = tempResult; return true; } else { @@ -283,46 +294,28 @@ bool IndependentSolver::check(const Query &query, ref &result) { assert(success && "Can not get initial values (Independent solver)!"); assert(tempValues.size() == arraysInFactor.size() && "Should be equal number arrays and answers"); - for (unsigned i = 0; i < tempValues.size(); i++) { - if (retMap.count(arraysInFactor[i])) { - // We already have an array with some partially correct answers, - // so we need to place the answers to the new query into the right - // spot while avoiding the undetermined values also in the array - SparseStorage *tempPtr = &retMap[arraysInFactor[i]]; - assert(tempPtr->size() == tempValues[i].size() && - "we're talking about the same array here"); - klee::DenseSet *ds = &(it->elements[arraysInFactor[i]]); - for (std::set::iterator it2 = ds->begin(); it2 != ds->end(); - it2++) { - unsigned index = *it2; - tempPtr->store(index, tempValues[i].load(index)); - } - } else { - // Dump all the new values into the array - retMap[arraysInFactor[i]] = tempValues[i]; - } - } + // We already have an array with some partially correct answers, + // so we need to place the answers to the new query into the right + // spot while avoiding the undetermined values also in the array + it->addValuesToAssignment(arraysInFactor, tempValues, retMap); } } - result = new InvalidResponse(retMap); - std::map> bindings; + result = new InvalidResponse(retMap.bindings); + Assignment::bindings_ty bindings; bool success = result->tryGetInitialValues(bindings); assert(success); - assert(assertCreatedPointEvaluatesToTrue(query, bindings, retMap) && + assert(assertCreatedPointEvaluatesToTrue(query, bindings, retMap.bindings) && "should satisfy the equation"); - delete factors; + return true; } bool IndependentSolver::computeValidityCore(const Query &query, ValidityCore &validityCore, bool &isValid) { - constraints_ty required; - IndependentElementSet eltsClosure = - getIndependentConstraints(query, required); - ConstraintSet tmp( - required, eltsClosure.symcretes, - query.constraints.concretization().part(eltsClosure.symcretes)); + std::vector> factors; + query.getAllDependentConstraintsSets(factors); + ConstraintSet tmp(factors); return solver->impl->computeValidityCore(query.withConstraints(tmp), validityCore, isValid); } From 15bd87d67853b27c561f5590945793ea1f51eaff Mon Sep 17 00:00:00 2001 From: dim8art Date: Sun, 20 Aug 2023 16:17:40 +0300 Subject: [PATCH 003/103] Reworking ConcretizingSolver --- lib/Solver/ConcretizingSolver.cpp | 190 ++++++++++++++++++------------ 1 file changed, 113 insertions(+), 77 deletions(-) diff --git a/lib/Solver/ConcretizingSolver.cpp b/lib/Solver/ConcretizingSolver.cpp index 36f5a81191..52ed3dbd11 100644 --- a/lib/Solver/ConcretizingSolver.cpp +++ b/lib/Solver/ConcretizingSolver.cpp @@ -55,18 +55,59 @@ class ConcretizingSolver : public SolverImpl { private: bool assertConcretization(const Query &query, const Assignment &assign) const; + bool getBrokenArrays(const Query &query, const Assignment &diff, + ref &result, + std::vector &brokenArrays); bool relaxSymcreteConstraints(const Query &query, ref &result); Query constructConcretizedQuery(const Query &, const Assignment &); + Query getConcretizedVersion(const Query &); + +private: + void reverseConcretization(ValidityCore &validityCore, + const ExprHashMap> &reverse, + ref reverseExpr); + void reverseConcretization(ref &res, + const ExprHashMap> &reverse, + ref reverseExpr); }; Query ConcretizingSolver::constructConcretizedQuery(const Query &query, const Assignment &assign) { - ConstraintSet constraints = assign.createConstraintsFromAssignment(); - for (auto e : query.constraints.cs()) { - constraints.addConstraint(e, {}); + ConstraintSet cs = query.constraints; + ref concretizedExpr = assign.evaluate(query.expr); + return Query(cs.getConcretizedVersion(assign), concretizedExpr); +} + +Query ConcretizingSolver::getConcretizedVersion(const Query &query) { + ConstraintSet cs = query.constraints; + ref concretizedExpr = cs.concretization().evaluate(query.expr); + return Query(cs.getConcretizedVersion(), concretizedExpr); +} + +void ConcretizingSolver::reverseConcretization( + ValidityCore &validityCore, const ExprHashMap> &reverse, + ref reverseExpr) { + validityCore.expr = reverseExpr; + for (auto e : reverse) { + if (validityCore.constraints.find(e.second) != + validityCore.constraints.end()) { + validityCore.constraints.erase(e.second); + validityCore.constraints.insert(e.first); + } + } +} + +void ConcretizingSolver::reverseConcretization( + ref &res, const ExprHashMap> &reverse, + ref reverseExpr) { + if (!isa(res)) { + return; } - return Query(constraints, query.expr); + ValidityCore validityCore; + res->tryGetValidityCore(validityCore); + reverseConcretization(validityCore, reverse, reverseExpr); + res = new ValidResponse(validityCore); } bool ConcretizingSolver::assertConcretization(const Query &query, @@ -80,6 +121,41 @@ bool ConcretizingSolver::assertConcretization(const Query &query, return true; } +bool ConcretizingSolver::getBrokenArrays( + const Query &query, const Assignment &assign, ref &result, + std::vector &brokenArrays) { + Query concretizedQuery = constructConcretizedQuery(query, assign); + ref CE = dyn_cast(concretizedQuery.expr); + if (CE && CE->isTrue()) { + findObjects(query.expr, brokenArrays); + result = new UnknownResponse(); + return true; + } + const ExprHashMap> &reverse = + concretizedQuery.constraints.independentElements().concretizedExprs; + ref reverseExpr = query.expr; + if (!solver->impl->check(concretizedQuery, result)) { + return false; + } + reverseConcretization(result, reverse, reverseExpr); + + /* No unsat cores were found for the query, so we can try to find new + * solution. */ + if (isa(result)) { + return true; + } + + ValidityCore validityCore; + bool success = result->tryGetValidityCore(validityCore); + assert(success); + + constraints_ty allValidityCoreConstraints = validityCore.constraints; + allValidityCoreConstraints.insert(validityCore.expr); + findObjects(allValidityCoreConstraints.begin(), + allValidityCoreConstraints.end(), brokenArrays); + return true; +} + bool ConcretizingSolver::relaxSymcreteConstraints(const Query &query, ref &result) { if (!query.containsSizeSymcretes()) { @@ -111,28 +187,17 @@ bool ConcretizingSolver::relaxSymcreteConstraints(const Query &query, bool wereConcretizationsRemoved = true; while (wereConcretizationsRemoved) { wereConcretizationsRemoved = false; - if (!solver->impl->check(constructConcretizedQuery(query, assignment), - result)) { + + std::vector currentlyBrokenSymcretizedArrays; + if (!getBrokenArrays(query, assignment, result, + currentlyBrokenSymcretizedArrays)) { return false; } - /* No unsat cores were found for the query, so we can try to find new - * solution. */ if (isa(result)) { break; } - ValidityCore validityCore; - bool success = result->tryGetValidityCore(validityCore); - assert(success); - - constraints_ty allValidityCoreConstraints = validityCore.constraints; - allValidityCoreConstraints.insert(validityCore.expr); - std::vector currentlyBrokenSymcretizedArrays; - findObjects(allValidityCoreConstraints.begin(), - allValidityCoreConstraints.end(), - currentlyBrokenSymcretizedArrays); - std::queue arrayQueue; std::queue addressQueue; @@ -159,9 +224,10 @@ bool ConcretizingSolver::relaxSymcreteConstraints(const Query &query, if (arrayQueue.empty() && addressArrayPresent) { while (!addressQueue.empty()) { - assignment.bindings.erase(addressQueue.front()); + assignment.bindings.remove(addressQueue.front()); addressQueue.pop(); } + if (!solver->impl->check(constructConcretizedQuery(query, assignment), result)) { return false; @@ -175,7 +241,7 @@ bool ConcretizingSolver::relaxSymcreteConstraints(const Query &query, while (!arrayQueue.empty()) { const Array *brokenArray = arrayQueue.front(); - assignment.bindings.erase(brokenArray); + assignment.bindings.remove(brokenArray); wereConcretizationsRemoved = true; arrayQueue.pop(); @@ -198,14 +264,15 @@ bool ConcretizingSolver::relaxSymcreteConstraints(const Query &query, } for (const ref &symcrete : currentlyBrokenSymcretes) { - constraints_ty required; - IndependentElementSet eltsClosure = getIndependentConstraints( - Query(query.constraints, - AndExpr::create(query.expr, - Expr::createIsZero(symcrete->symcretized))), - required); - for (ref symcrete : eltsClosure.symcretes) { - currentlyBrokenSymcretes.insert(symcrete); + std::vector> factors; + Query(query.constraints, + AndExpr::create(query.expr, + Expr::createIsZero(symcrete->symcretized))) + .getAllDependentConstraintsSets(factors); + for (ref ics : factors) { + for (ref symcrete : ics->symcretes) { + currentlyBrokenSymcretes.insert(symcrete); + } } } @@ -281,7 +348,7 @@ bool ConcretizingSolver::relaxSymcreteConstraints(const Query &query, } for (unsigned idx = 0; idx < objects.size(); ++idx) { - assignment.bindings[objects[idx]] = brokenSymcretizedValues[idx]; + assignment.bindings.replace({objects[idx], brokenSymcretizedValues[idx]}); } ExprHashMap> concretizations; @@ -378,37 +445,10 @@ bool ConcretizingSolver::computeValidity( assert(assertConcretization(query, assign) && "Assignment does not contain concretization for all symcrete arrays!"); - auto concretizedQuery = constructConcretizedQuery(query, assign); - if (!solver->impl->computeValidity(concretizedQuery, queryResult, - negatedQueryResult)) { + if (!check(query, queryResult) || + !check(query.negateExpr(), negatedQueryResult)) { return false; } - - std::vector> queryResultValues, - negatedQueryResultValues; - - std::vector objects = assign.keys(); - - assert(isa(queryResult) || - isa(negatedQueryResult)); - - // *No more than one* of queryResult and negatedQueryResult is possible, - // i.e. `mustBeTrue` with values from `assign`. - // Take one which is `mustBeTrue` with symcretes from `assign` - // and try to relax them to `mayBeFalse`. This solution should be - // appropriate for the remain branch. - - if (isa(queryResult)) { - if (!relaxSymcreteConstraints(query, queryResult)) { - return false; - } - } else if (isa(negatedQueryResult)) { - if (!relaxSymcreteConstraints(query.negateExpr(), negatedQueryResult)) { - return false; - } - } else { - } - return true; } @@ -421,12 +461,15 @@ bool ConcretizingSolver::check(const Query &query, assert(assertConcretization(query, assign) && "Assignment does not contain concretization for all symcrete arrays!"); - auto concretizedQuery = constructConcretizedQuery(query, assign); - if (!solver->impl->check(concretizedQuery, result)) { - return false; - } + auto concretizedQuery = getConcretizedVersion(query); - if (isa(result)) { + ref CE = dyn_cast(concretizedQuery.expr); + if (!CE || !CE->isTrue()) { + if (!solver->impl->check(concretizedQuery, result)) { + return false; + } + } + if ((CE && CE->isTrue()) || isa(result)) { if (!relaxSymcreteConstraints(query, result)) { return false; } @@ -455,8 +498,7 @@ bool ConcretizingSolver::computeTruth(const Query &query, bool &isValid) { query.constraints.concretization().evaluate(query.expr))) { isValid = CE->isTrue(); } else { - auto concretizedQuery = constructConcretizedQuery(query, assign); - + auto concretizedQuery = getConcretizedVersion(query); if (!solver->impl->computeTruth(concretizedQuery, isValid)) { return false; } @@ -471,9 +513,7 @@ bool ConcretizingSolver::computeTruth(const Query &query, bool &isValid) { if (!relaxSymcreteConstraints(query, result)) { return false; } - if (ref resultInvalidResponse = - dyn_cast(result)) { - assign = resultInvalidResponse->initialValuesFor(assign.keys()); + if (isa(result)) { isValid = false; } } @@ -491,7 +531,7 @@ bool ConcretizingSolver::computeValidityCore(const Query &query, assert(assertConcretization(query, assign) && "Assignment does not contain concretization for all symcrete arrays!"); - Query concretizedQuery = constructConcretizedQuery(query, assign); + Query concretizedQuery = getConcretizedVersion(query); if (ref CE = dyn_cast( query.constraints.concretization().evaluate(query.expr))) { @@ -544,7 +584,7 @@ bool ConcretizingSolver::computeValue(const Query &query, ref &result) { result = expr; return true; } - auto concretizedQuery = constructConcretizedQuery(query, assign); + auto concretizedQuery = getConcretizedVersion(query); return solver->impl->computeValue(concretizedQuery, result); } @@ -560,7 +600,7 @@ bool ConcretizingSolver::computeInitialValues( assert(assertConcretization(query, assign) && "Assignment does not contain concretization for all symcrete arrays!"); - auto concretizedQuery = constructConcretizedQuery(query, assign); + auto concretizedQuery = getConcretizedVersion(query); if (!solver->impl->computeInitialValues(concretizedQuery, objects, values, hasSolution)) { return false; @@ -576,11 +616,7 @@ bool ConcretizingSolver::computeInitialValues( if (ref resultInvalidResponse = dyn_cast(result)) { hasSolution = true; - assign = resultInvalidResponse->initialValuesFor(assign.keys()); - values = std::vector>(); - return solver->impl->computeInitialValues( - constructConcretizedQuery(query, assign), objects, values, - hasSolution); + result->tryGetInitialValuesFor(objects, values); } } From 3316cb08b44e72f10e0ed7d0eb832fb4898a922b Mon Sep 17 00:00:00 2001 From: dim8art Date: Sun, 20 Aug 2023 16:18:06 +0300 Subject: [PATCH 004/103] Add persistency to Assignment --- include/klee/Expr/Assignment.h | 71 ++++++++++++++++++++++------------ lib/Expr/Assignment.cpp | 36 ++++++++++------- 2 files changed, 67 insertions(+), 40 deletions(-) diff --git a/include/klee/Expr/Assignment.h b/include/klee/Expr/Assignment.h index ad48af0baa..61376ff940 100644 --- a/include/klee/Expr/Assignment.h +++ b/include/klee/Expr/Assignment.h @@ -10,6 +10,7 @@ #ifndef KLEE_ASSIGNMENT_H #define KLEE_ASSIGNMENT_H +#include "klee/ADT/PersistentMap.h" #include "klee/ADT/SparseStorage.h" #include "klee/Expr/ExprEvaluator.h" @@ -27,9 +28,9 @@ using symcretes_ty = SymcreteOrderedSet; class Assignment { public: - typedef std::map> bindings_ty; + using bindings_ty = + PersistentMap>; - bool allowFreeValues; bindings_ty bindings; friend bool operator==(const Assignment &lhs, const Assignment &rhs) { @@ -37,14 +38,10 @@ class Assignment { } public: - Assignment(bool _allowFreeValues = false) - : allowFreeValues(_allowFreeValues) {} - Assignment(const bindings_ty &_bindings, bool _allowFreeValues = false) - : allowFreeValues(_allowFreeValues), bindings(_bindings) {} + Assignment() {} + Assignment(const bindings_ty &_bindings) : bindings(_bindings) {} Assignment(const std::vector &objects, - const std::vector> &values, - bool _allowFreeValues = false) - : allowFreeValues(_allowFreeValues) { + const std::vector> &values) { assert(objects.size() == values.size()); for (unsigned i = 0; i < values.size(); ++i) { const Array *os = objects.at(i); @@ -53,19 +50,26 @@ class Assignment { } } - ref evaluate(const Array *mo, unsigned index) const; - ref evaluate(ref e) const; - ConstraintSet createConstraintsFromAssignment() const; + void addIndependentAssignment(const Assignment &b); + + ref evaluate(const Array *mo, unsigned index, + bool allowFreeValues = true) const; + ref evaluate(ref e, bool allowFreeValues = true) const; + constraints_ty createConstraintsFromAssignment() const; template - bool satisfies(InputIterator begin, InputIterator end); + bool satisfies(InputIterator begin, InputIterator end, + bool allowFreeValues = true); + template + bool satisfiesNonBoolean(InputIterator begin, InputIterator end, + bool allowFreeValues = true); void dump() const; Assignment diffWith(const Assignment &other) const; Assignment part(const SymcreteOrderedSet &symcretes) const; - bindings_ty::const_iterator begin() const { return bindings.begin(); } - bindings_ty::const_iterator end() const { return bindings.end(); } + bindings_ty::iterator begin() const { return bindings.begin(); } + bindings_ty::iterator end() const { return bindings.end(); } bool isEmpty() { return begin() == end(); } std::vector keys() const; @@ -74,22 +78,24 @@ class Assignment { class AssignmentEvaluator : public ExprEvaluator { const Assignment &a; + bool allowFreeValues; protected: ref getInitialValue(const Array &mo, unsigned index) { - return a.evaluate(&mo, index); + return a.evaluate(&mo, index, allowFreeValues); } public: - AssignmentEvaluator(const Assignment &_a) : a(_a) {} + AssignmentEvaluator(const Assignment &_a, bool _allowFreeValues) + : a(_a), allowFreeValues(_allowFreeValues) {} }; /***/ -inline ref Assignment::evaluate(const Array *array, - unsigned index) const { +inline ref Assignment::evaluate(const Array *array, unsigned index, + bool allowFreeValues) const { assert(array); - bindings_ty::const_iterator it = bindings.find(array); + bindings_ty::iterator it = bindings.find(array); if (it != bindings.end() && index < it->second.size()) { return ConstantExpr::alloc(it->second.load(index), array->getRange()); } else { @@ -102,17 +108,32 @@ inline ref Assignment::evaluate(const Array *array, } } -inline ref Assignment::evaluate(ref e) const { - AssignmentEvaluator v(*this); +inline ref Assignment::evaluate(ref e, bool allowFreeValues) const { + AssignmentEvaluator v(*this, allowFreeValues); return v.visit(e); } template -inline bool Assignment::satisfies(InputIterator begin, InputIterator end) { - AssignmentEvaluator v(*this); - for (; begin != end; ++begin) +inline bool Assignment::satisfies(InputIterator begin, InputIterator end, + bool allowFreeValues) { + AssignmentEvaluator v(*this, allowFreeValues); + for (; begin != end; ++begin) { + assert((*begin)->getWidth() == Expr::Bool && "constraints must be boolean"); if (!v.visit(*begin)->isTrue()) return false; + } + return true; +} + +template +inline bool Assignment::satisfiesNonBoolean(InputIterator begin, + InputIterator end, + bool allowFreeValues) { + AssignmentEvaluator v(*this, allowFreeValues); + for (; begin != end; ++begin) { + if (!isa(v.visit(*begin))) + return false; + } return true; } } // namespace klee diff --git a/lib/Expr/Assignment.cpp b/lib/Expr/Assignment.cpp index d43db33870..1cc7a76e1c 100644 --- a/lib/Expr/Assignment.cpp +++ b/lib/Expr/Assignment.cpp @@ -20,8 +20,8 @@ void Assignment::dump() const { llvm::errs() << "No bindings\n"; return; } - for (bindings_ty::const_iterator i = bindings.begin(), e = bindings.end(); - i != e; ++i) { + for (bindings_ty::iterator i = bindings.begin(), e = bindings.end(); i != e; + ++i) { llvm::errs() << (*i).first->getName() << "\n["; for (int j = 0, k = (*i).second.size(); j < k; ++j) llvm::errs() << (int)(*i).second.load(j) << ","; @@ -29,8 +29,14 @@ void Assignment::dump() const { } } -ConstraintSet Assignment::createConstraintsFromAssignment() const { - ConstraintSet result; +void Assignment::addIndependentAssignment(const Assignment &b) { + for (auto it : b) { + bindings.insert(it); + } +} + +constraints_ty Assignment::createConstraintsFromAssignment() const { + constraints_ty result; for (const auto &binding : bindings) { const auto &array = binding.first; const auto &values = binding.second; @@ -41,17 +47,15 @@ ConstraintSet Assignment::createConstraintsFromAssignment() const { uint64_t arraySize = arrayConstantSize->getZExtValue(); if (arraySize <= 8 && array->getRange() == Expr::Int8) { ref e = Expr::createTempRead(array, arraySize * array->getRange()); - result.addConstraint(EqExpr::create(e, evaluate(e)), {}); + result.insert(EqExpr::create(e, evaluate(e))); } else { for (unsigned arrayIndex = 0; arrayIndex < arraySize; ++arrayIndex) { unsigned char value = values.load(arrayIndex); - result.addConstraint( - EqExpr::create( - ReadExpr::create( - UpdateList(array, 0), - ConstantExpr::alloc(arrayIndex, array->getDomain())), - ConstantExpr::alloc(value, array->getRange())), - {}); + result.insert(EqExpr::create( + ReadExpr::create( + UpdateList(array, 0), + ConstantExpr::alloc(arrayIndex, array->getDomain())), + ConstantExpr::alloc(value, array->getRange()))); } } } @@ -59,7 +63,7 @@ ConstraintSet Assignment::createConstraintsFromAssignment() const { } Assignment Assignment::diffWith(const Assignment &other) const { - Assignment diffAssignment(allowFreeValues); + Assignment diffAssignment; for (const auto &it : other) { if (bindings.count(it.first) == 0 || bindings.at(it.first) != it.second) { diffAssignment.bindings.insert(it); @@ -87,10 +91,12 @@ std::vector> Assignment::values() const { } Assignment Assignment::part(const SymcreteOrderedSet &symcretes) const { - Assignment ret(allowFreeValues); + Assignment ret; for (auto symcrete : symcretes) { for (auto array : symcrete->dependentArrays()) { - ret.bindings.insert({array, bindings.at(array)}); + if (bindings.find(array) != bindings.end()) { + ret.bindings.insert({array, bindings.at(array)}); + } } } return ret; From f72486f8778dbec55e0e381aca636385128ee3ff Mon Sep 17 00:00:00 2001 From: dim8art Date: Sun, 20 Aug 2023 17:24:21 +0300 Subject: [PATCH 005/103] Rework solver chain + small refactoring changes --- include/klee/ADT/ImmutableMap.h | 27 +++++++++++ include/klee/ADT/PersistentMap.h | 4 ++ include/klee/Expr/Expr.h | 7 +++ include/klee/Solver/SolverUtil.h | 30 +++++++++--- lib/Core/Executor.cpp | 42 +++++++++------- lib/Core/SeedInfo.cpp | 8 ++- lib/Core/SeedInfo.h | 3 +- lib/Solver/AssignmentValidatingSolver.cpp | 8 ++- lib/Solver/CachingSolver.cpp | 1 - lib/Solver/CexCachingSolver.cpp | 59 ++++++++++++++++------- lib/Solver/ConstructSolverChain.cpp | 9 ++++ lib/Solver/FastCexSolver.cpp | 1 - lib/Solver/QueryLoggingSolver.cpp | 17 +++---- lib/Solver/Solver.cpp | 2 +- lib/Solver/ValidatingSolver.cpp | 5 +- lib/Solver/Z3Solver.cpp | 4 -- test/Expr/Evaluate.kquery | 2 +- test/Feature/DanglingConcreteReadExpr.c | 2 +- test/Solver/CexCacheValidityCoresCheck.c | 4 +- tools/kleaver/main.cpp | 11 ++--- unittests/Assignment/AssignmentTest.cpp | 2 +- unittests/Expr/ArrayExprTest.cpp | 3 +- 22 files changed, 168 insertions(+), 83 deletions(-) diff --git a/include/klee/ADT/ImmutableMap.h b/include/klee/ADT/ImmutableMap.h index d79a4d5790..44cacedc33 100644 --- a/include/klee/ADT/ImmutableMap.h +++ b/include/klee/ADT/ImmutableMap.h @@ -44,6 +44,32 @@ template > class ImmutableMap { return *this; } + bool operator==(const ImmutableMap &b) const { + if (size() != b.size()) { + return false; + } + for (iterator it1 = begin(), it2 = b.begin(); + it1 != end() && it2 != b.end(); ++it1, ++it2) { + if (*it1 != *it2) + return false; + } + return true; + } + + bool operator<(const ImmutableMap &b) const { + if (size() != b.size()) { + return size() < b.size(); + } + for (iterator it1 = begin(), it2 = b.begin(); + it1 != end() && it2 != b.end(); ++it1, ++it2) { + if (*it1 < *it2) + return true; + if (*it1 > *it2) + return false; + } + return false; + } + bool empty() const { return elts.empty(); } size_t count(const key_type &key) const { return elts.count(key); } const value_type *lookup(const key_type &key) const { @@ -80,6 +106,7 @@ template > class ImmutableMap { return elts.upper_bound(key); } + const D &at(const key_type &key) const { return find(key)->second; } static size_t getAllocated() { return Tree::allocated; } }; diff --git a/include/klee/ADT/PersistentMap.h b/include/klee/ADT/PersistentMap.h index bfec1824a0..dabc5495db 100644 --- a/include/klee/ADT/PersistentMap.h +++ b/include/klee/ADT/PersistentMap.h @@ -37,6 +37,8 @@ template > class PersistentMap { elts = b.elts; return *this; } + bool operator==(const PersistentMap &b) const { return elts == b.elts; } + bool operator<(const PersistentMap &b) const { return elts < b.elts; } bool empty() const { return elts.empty(); } size_t count(const key_type &key) const { return elts.count(key); } @@ -77,6 +79,8 @@ template > class PersistentMap { return *lookup(key); } } + + const D &at(const key_type &key) const { return elts.at(key); } }; } // namespace klee diff --git a/include/klee/Expr/Expr.h b/include/klee/Expr/Expr.h index 8e258b8f56..ab6826e25d 100644 --- a/include/klee/Expr/Expr.h +++ b/include/klee/Expr/Expr.h @@ -328,6 +328,13 @@ class Expr { // Given an array of new kids return a copy of the expression // but using those children. virtual ref rebuild(ref kids[/* getNumKids() */]) const = 0; + virtual ref rebuild() const { + ref kids[getNumKids()]; + for (unsigned i = 0; i < getNumKids(); ++i) { + kids[i] = getKid(i); + } + return rebuild(kids); + } /// isZero - Is this a constant zero. bool isZero() const; diff --git a/include/klee/Solver/SolverUtil.h b/include/klee/Solver/SolverUtil.h index d61c188cc0..d55f372de1 100644 --- a/include/klee/Solver/SolverUtil.h +++ b/include/klee/Solver/SolverUtil.h @@ -5,6 +5,7 @@ #include "klee/Expr/Constraints.h" #include "klee/Expr/Expr.h" #include "klee/Expr/ExprHashMap.h" +#include "klee/Expr/IndependentSet.h" #include "klee/System/Time.h" namespace klee { @@ -80,6 +81,16 @@ struct Query { (lhs.constraints == rhs.constraints && lhs.expr < rhs.expr); } + void getAllIndependentConstraintsSets( + std::vector> &result) const { + constraints.getAllIndependentConstraintsSets(expr, result); + } + + void getAllDependentConstraintsSets( + std::vector> &result) const { + constraints.getAllDependentConstraintsSets(expr, result); + } + /// Dump query void dump() const; }; @@ -239,20 +250,20 @@ class InvalidResponse : public SolverResponse { } bool tryGetInitialValues(Assignment::bindings_ty &values) const { - values.insert(result.bindings.begin(), result.bindings.end()); + values = result.bindings; return true; } Assignment initialValuesFor(const std::vector objects) const { std::vector> values; tryGetInitialValuesFor(objects, values); - return Assignment(objects, values, true); + return Assignment(objects, values); } Assignment initialValues() const { Assignment::bindings_ty values; tryGetInitialValues(values); - return Assignment(values, true); + return Assignment(values); } ResponseKind getResponseKind() const { return Invalid; }; @@ -276,15 +287,20 @@ class InvalidResponse : public SolverResponse { return result.bindings < ib.result.bindings; } - bool satisfies(std::set> &key) { - return result.satisfies(key.begin(), key.end()); + bool satisfies(const std::set> &key, bool allowFreeValues = true) { + return result.satisfies(key.begin(), key.end(), allowFreeValues); } - ref evaluate(ref &e) { return result.evaluate(e); } + bool satisfiesNonBoolean(const std::set> &key, + bool allowFreeValues = true) { + return result.satisfiesNonBoolean(key.begin(), key.end(), allowFreeValues); + } void dump() { result.dump(); } - ref evaluate(ref e) { return (result.evaluate(e)); } + ref evaluate(ref e, bool allowFreeValues = true) { + return (result.evaluate(e, allowFreeValues)); + } }; class UnknownResponse : public SolverResponse { diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index 064935305d..8bc362391d 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -1145,7 +1145,7 @@ Executor::StatePair Executor::fork(ExecutionState ¤t, ref condition, success = solver->mayBeFalse(current.constraints.cs(), condition, mayBeFalse, current.queryMetaData); } - if (success && !mayBeFalse) + if (!success || !mayBeFalse) terminateEverything = true; else res = PartialValidity::MayBeFalse; @@ -1154,7 +1154,7 @@ Executor::StatePair Executor::fork(ExecutionState ¤t, ref condition, bool mayBeTrue; success = solver->mayBeTrue(current.constraints.cs(), condition, mayBeTrue, current.queryMetaData); - if (success && !mayBeTrue) + if (!success || !mayBeTrue) terminateEverything = true; else res = PartialValidity::MayBeTrue; @@ -5419,18 +5419,19 @@ MemoryObject *Executor::allocate(ExecutionState &state, ref size, std::vector> symbolicSizesTerms = { ZExtExpr::create(size, pointerWidthInBits)}; - constraints_ty required; - IndependentElementSet eltsClosure = getIndependentConstraints( - Query(state.constraints.cs(), ZExtExpr::create(size, pointerWidthInBits)), - required); + std::vector> factors; + Query(state.constraints.cs(), ZExtExpr::create(size, pointerWidthInBits)) + .getAllDependentConstraintsSets(factors); + /* Collect dependent size symcretes. */ - for (ref symcrete : eltsClosure.symcretes) { - if (isa(symcrete)) { - symbolicSizesTerms.push_back( - ZExtExpr::create(symcrete->symcretized, pointerWidthInBits)); + for (ref ics : factors) { + for (ref symcrete : ics->symcretes) { + if (isa(symcrete)) { + symbolicSizesTerms.push_back( + ZExtExpr::create(symcrete->symcretized, pointerWidthInBits)); + } } } - ref symbolicSizesSum = createNonOverflowingSumExpr(symbolicSizesTerms); std::vector objects; @@ -5441,7 +5442,7 @@ MemoryObject *Executor::allocate(ExecutionState &state, ref size, return nullptr; } - Assignment assignment(objects, values, true); + Assignment assignment(objects, values); uint64_t sizeMemoryObject = cast(assignment.evaluate(size))->getZExtValue(); @@ -5471,7 +5472,8 @@ MemoryObject *Executor::allocate(ExecutionState &state, ref size, state.addPointerResolution(addressExpr, mo); } - assignment.bindings[addressArray] = sparseBytesFromValue(mo->address); + assignment.bindings.replace( + {addressArray, sparseBytesFromValue(mo->address)}); state.constraints.addSymcrete(sizeSymcrete, assignment); state.constraints.addSymcrete(addressSymcrete, assignment); @@ -6428,8 +6430,8 @@ void Executor::executeMakeSymbolic(ExecutionState &state, if (!obj) { if (ZeroSeedExtension) { - si.assignment.bindings[array] = - SparseStorage(mo->size, 0); + si.assignment.bindings.replace( + {array, SparseStorage(mo->size, 0)}); } else if (!AllowSeedExtension) { terminateStateOnUserError(state, "ran out of inputs during seeding"); @@ -6449,14 +6451,18 @@ void Executor::executeMakeSymbolic(ExecutionState &state, terminateStateOnUserError(state, msg.str()); break; } else { - SparseStorage &values = - si.assignment.bindings[array]; + SparseStorage values; + if (si.assignment.bindings.find(array) != + si.assignment.bindings.end()) { + values = si.assignment.bindings.at(array); + } values.resize(std::min(mo->size, obj->numBytes)); values.store(0, obj->bytes, obj->bytes + std::min(obj->numBytes, mo->size)); if (ZeroSeedExtension) { values.resize(mo->size); } + si.assignment.bindings.replace({array, values}); } } } @@ -7077,7 +7083,7 @@ bool Executor::getSymbolicSolution(const ExecutionState &state, KTest &res) { o->pointers = nullptr; } - Assignment model = Assignment(objects, values, true); + Assignment model = Assignment(objects, values); for (auto binding : state.constraints.cs().concretization().bindings) { model.bindings.insert(binding); } diff --git a/lib/Core/SeedInfo.cpp b/lib/Core/SeedInfo.cpp index 143baae61e..bea2a646a8 100644 --- a/lib/Core/SeedInfo.cpp +++ b/lib/Core/SeedInfo.cpp @@ -107,7 +107,9 @@ void SeedInfo::patchSeed(const ExecutionState &state, ref condition, solver->getValue(required, read, value, state.queryMetaData); assert(success && "FIXME: Unhandled solver failure"); (void)success; - it2->second.store(i, value->getZExtValue(8)); + auto s = it2->second; + s.store(i, value->getZExtValue(8)); + assignment.bindings.replace({it2->first, s}); required.addConstraint( EqExpr::create( read, ConstantExpr::alloc(it2->second.load(i), Expr::Int8)), @@ -151,7 +153,9 @@ void SeedInfo::patchSeed(const ExecutionState &state, ref condition, solver->getValue(required, read, value, state.queryMetaData); assert(success && "FIXME: Unhandled solver failure"); (void)success; - it->second.store(i, value->getZExtValue(8)); + auto s = it->second; + s.store(i, value->getZExtValue(8)); + assignment.bindings.replace({it->first, s}); required.addConstraint( EqExpr::create(read, ConstantExpr::alloc(it->second.load(i), Expr::Int8)), diff --git a/lib/Core/SeedInfo.h b/lib/Core/SeedInfo.h index a513665fdb..ee84133bc3 100644 --- a/lib/Core/SeedInfo.h +++ b/lib/Core/SeedInfo.h @@ -32,8 +32,7 @@ class SeedInfo { std::set used; public: - explicit SeedInfo(KTest *_input) - : assignment(true), input(_input), inputPosition(0) {} + explicit SeedInfo(KTest *_input) : input(_input), inputPosition(0) {} KTestObject *getNextInput(const MemoryObject *mo, bool byName); diff --git a/lib/Solver/AssignmentValidatingSolver.cpp b/lib/Solver/AssignmentValidatingSolver.cpp index dde0f1a23d..4df43ae869 100644 --- a/lib/Solver/AssignmentValidatingSolver.cpp +++ b/lib/Solver/AssignmentValidatingSolver.cpp @@ -65,9 +65,8 @@ void AssignmentValidatingSolver::validateAssigment( std::vector> &values) { // Use `_allowFreeValues` so that if we are missing an assignment // we can't compute a constant and flag this as a problem. - Assignment assignment(objects, values, /*_allowFreeValues=*/true); + Assignment assignment(objects, values); // Check computed assignment satisfies query - assert(!query.containsSymcretes()); for (const auto &constraint : query.constraints.cs()) { ref constraintEvaluated = assignment.evaluate(constraint); ConstantExpr *CE = dyn_cast(constraintEvaluated); @@ -143,7 +142,6 @@ bool AssignmentValidatingSolver::check(const Query &query, } ExprHashSet expressions; - assert(!query.containsSymcretes()); expressions.insert(query.constraints.cs().begin(), query.constraints.cs().end()); expressions.insert(query.expr); @@ -170,10 +168,10 @@ void AssignmentValidatingSolver::dumpAssignmentQuery( const Query &query, const Assignment &assignment) { // Create a Query that is augmented with constraints that // enforce the given assignment. - auto constraints = assignment.createConstraintsFromAssignment(); + auto constraints = + ConstraintSet(assignment.createConstraintsFromAssignment(), {}, {}); // Add Constraints from `query` - assert(!query.containsSymcretes()); for (const auto &constraint : query.constraints.cs()) constraints.addConstraint(constraint, {}); diff --git a/lib/Solver/CachingSolver.cpp b/lib/Solver/CachingSolver.cpp index de43695d5e..dbd9dbf39a 100644 --- a/lib/Solver/CachingSolver.cpp +++ b/lib/Solver/CachingSolver.cpp @@ -53,7 +53,6 @@ class CachingSolver : public SolverImpl { unsigned operator()(const CacheEntry &ce) const { unsigned result = ce.query->hash(); - assert(ce.constraints.symcretes().empty()); for (auto const &constraint : ce.constraints.cs()) { result ^= constraint->hash(); } diff --git a/lib/Solver/CexCachingSolver.cpp b/lib/Solver/CexCachingSolver.cpp index da3303359d..2e26971040 100644 --- a/lib/Solver/CexCachingSolver.cpp +++ b/lib/Solver/CexCachingSolver.cpp @@ -127,12 +127,23 @@ struct isInvalidResponse { }; struct isValidOrSatisfyingResponse { - KeyType &key; - - isValidOrSatisfyingResponse(KeyType &_key) : key(_key) {} + KeyType booleanKey; + KeyType nonBooleanKey; + isValidOrSatisfyingResponse(KeyType &_key) { + for (auto i : _key) { + if (i->getWidth() == Expr::Bool) { + booleanKey.insert(i); + } else { + nonBooleanKey.insert(i); + } + } + } bool operator()(ref a) const { - return isa(a) || cast(a)->satisfies(key); + return isa(a) || + (isa(a) && + cast(a)->satisfies(booleanKey) && + cast(a)->satisfiesNonBoolean(nonBooleanKey)); } }; @@ -215,8 +226,10 @@ bool CexCachingSolver::searchForResponse(KeyType &key, /// an unsatisfiable query). \return True if a cached result was found. bool CexCachingSolver::lookupResponse(const Query &query, KeyType &key, ref &result) { - assert(!query.containsSymcretes()); key = KeyType(query.constraints.cs().begin(), query.constraints.cs().end()); + for (ref s : query.constraints.symcretes()) { + key.insert(s->symcretized); + } ref neg = Expr::createIsZero(query.expr); if (ConstantExpr *CE = dyn_cast(neg)) { if (CE->isFalse()) { @@ -240,8 +253,9 @@ bool CexCachingSolver::lookupResponse(const Query &query, KeyType &key, bool CexCachingSolver::getResponse(const Query &query, ref &result) { KeyType key; - if (lookupResponse(query, key, result)) + if (lookupResponse(query, key, result)) { return true; + } if (!solver->impl->check(query, result)) { return false; @@ -264,14 +278,15 @@ bool CexCachingSolver::getResponse(const Query &query, } ValidityCore resultCore; - if (CexCacheValidityCores && result->tryGetValidityCore(resultCore)) { + if (CexCacheValidityCores && isa(result)) { + result->tryGetValidityCore(resultCore); KeyType resultCoreConstarints(resultCore.constraints.begin(), resultCore.constraints.end()); ref neg = Expr::createIsZero(query.expr); resultCoreConstarints.insert(neg); cache.insert(resultCoreConstarints, result); - cache.insert(key, result); - } else { + } + if (isa(result) || isa(result)) { cache.insert(key, result); } @@ -290,7 +305,7 @@ bool CexCachingSolver::computeValidity(const Query &query, return false; assert(isa(a) && "computeValidity() must have assignment"); - ref q = cast(a)->evaluate(query.expr); + ref q = cast(a)->evaluate(query.expr, false); if (!isa(q) && solver->impl->computeValue(query, q)) return false; @@ -301,13 +316,23 @@ bool CexCachingSolver::computeValidity(const Query &query, if (cast(q)->isTrue()) { if (!getResponse(query, a)) return false; - result = - isa(a) ? PValidity::MustBeTrue : PValidity::TrueOrFalse; + if (isa(a)) { + result = PValidity::MustBeTrue; + } else if (isa(a)) { + result = PValidity::TrueOrFalse; + } else { + result = PValidity::MayBeTrue; + } } else { if (!getResponse(query.negateExpr(), a)) return false; - result = - isa(a) ? PValidity::MustBeFalse : PValidity::TrueOrFalse; + if (isa(a)) { + result = PValidity::MustBeFalse; + } else if (isa(a)) { + result = PValidity::TrueOrFalse; + } else { + result = PValidity::MayBeFalse; + } } return true; @@ -334,7 +359,7 @@ bool CexCachingSolver::computeTruth(const Query &query, bool &isValid) { if (!getResponse(query, a)) return false; - isValid = isa(a); + isValid = !isa(a); return true; } @@ -346,7 +371,7 @@ bool CexCachingSolver::computeValue(const Query &query, ref &result) { if (!getResponse(query.withFalse(), a)) return false; assert(isa(a) && "computeValue() must have assignment"); - result = cast(a)->evaluate(query.expr); + result = cast(a)->evaluate(query.expr, false); if (!isa(result) && solver->impl->computeValue(query, result)) return false; @@ -365,7 +390,7 @@ bool CexCachingSolver::computeInitialValues( return false; hasSolution = isa(a); - if (isa(a)) + if (!hasSolution) return true; // FIXME: We should use smarter assignment for result so we don't diff --git a/lib/Solver/ConstructSolverChain.cpp b/lib/Solver/ConstructSolverChain.cpp index a8eb1e2fe7..f8c9c8d522 100644 --- a/lib/Solver/ConstructSolverChain.cpp +++ b/lib/Solver/ConstructSolverChain.cpp @@ -73,6 +73,15 @@ std::unique_ptr constructSolverChain( if (UseConcretizingSolver) solver = createConcretizingSolver(std::move(solver), addressGenerator); + if (UseCexCache && UseConcretizingSolver) + solver = createCexCachingSolver(std::move(solver)); + + if (UseBranchCache && UseConcretizingSolver) + solver = createCachingSolver(std::move(solver)); + + if (UseIndependentSolver && UseConcretizingSolver) + solver = createIndependentSolver(std::move(solver)); + if (DebugValidateSolver) solver = createValidatingSolver(std::move(solver), rawCoreSolver, false); diff --git a/lib/Solver/FastCexSolver.cpp b/lib/Solver/FastCexSolver.cpp index 3ba7904ac4..3276b3d1be 100644 --- a/lib/Solver/FastCexSolver.cpp +++ b/lib/Solver/FastCexSolver.cpp @@ -1088,7 +1088,6 @@ FastCexSolver::~FastCexSolver() {} /// \return - True if the propogation was able to prove validity or invalidity. static bool propagateValues(const Query &query, CexData &cd, bool checkExpr, bool &isValid) { - assert(!query.containsSymcretes()); for (const auto &constraint : query.constraints.cs()) { cd.propagatePossibleValue(constraint, 1); cd.propagateExactValue(constraint, 1); diff --git a/lib/Solver/QueryLoggingSolver.cpp b/lib/Solver/QueryLoggingSolver.cpp index e35ca0daaa..0bbd631805 100644 --- a/lib/Solver/QueryLoggingSolver.cpp +++ b/lib/Solver/QueryLoggingSolver.cpp @@ -193,11 +193,11 @@ bool QueryLoggingSolver::computeInitialValues( new InvalidResponse(allObjects, allValues); success = invalidResponse->tryGetInitialValuesFor(objects, values); assert(success); - Assignment allSolutionAssignment(allObjects, allValues, true); + Assignment allSolutionAssignment(allObjects, allValues); std::vector>::iterator values_it = values.begin(); - Assignment solutionAssignment(objects, values, true); + Assignment solutionAssignment(objects, values); for (std::vector::const_iterator i = objects.begin(), e = objects.end(); i != e; ++i, ++values_it) { @@ -241,13 +241,12 @@ bool QueryLoggingSolver::check(const Query &query, logBuffer << queryCommentSign << " Solvable: " << (hasSolution ? "true" : "false") << "\n"; if (hasSolution) { - std::map> initialValues; + Assignment::bindings_ty initialValues; result->tryGetInitialValues(initialValues); - Assignment solutionAssignment(initialValues, true); + Assignment solutionAssignment(initialValues); - for (std::map>::const_iterator - i = initialValues.begin(), - e = initialValues.end(); + for (Assignment::bindings_ty::iterator i = initialValues.begin(), + e = initialValues.end(); i != e; ++i) { const Array *array = i->first; const SparseStorage &data = i->second; @@ -271,7 +270,7 @@ bool QueryLoggingSolver::check(const Query &query, result->tryGetValidityCore(validityCore); logBuffer << queryCommentSign << " ValidityCore:\n"; - printQuery(Query(ConstraintSet(validityCore.constraints, {}, {true}), + printQuery(Query(ConstraintSet(validityCore.constraints, {}, {}), validityCore.expr)); } } @@ -300,7 +299,7 @@ bool QueryLoggingSolver::computeValidityCore(const Query &query, if (isValid) { logBuffer << queryCommentSign << " ValidityCore:\n"; - printQuery(Query(ConstraintSet(validityCore.constraints, {}, {true}), + printQuery(Query(ConstraintSet(validityCore.constraints, {}, {}), validityCore.expr)); } diff --git a/lib/Solver/Solver.cpp b/lib/Solver/Solver.cpp index ec30aa9b19..d45e071d61 100644 --- a/lib/Solver/Solver.cpp +++ b/lib/Solver/Solver.cpp @@ -335,5 +335,5 @@ void Query::dump() const { } void ValidityCore::dump() const { - Query(ConstraintSet(constraints, {}, {true}), expr).dump(); + Query(ConstraintSet(constraints, {}, {}), expr).dump(); } diff --git a/lib/Solver/ValidatingSolver.cpp b/lib/Solver/ValidatingSolver.cpp index ddae26f2e3..65069e32bb 100644 --- a/lib/Solver/ValidatingSolver.cpp +++ b/lib/Solver/ValidatingSolver.cpp @@ -95,7 +95,6 @@ bool ValidatingSolver::computeInitialValues( const Query &query, const std::vector &objects, std::vector> &values, bool &hasSolution) { bool answer; - assert(!query.containsSymcretes()); if (!solver->impl->computeInitialValues(query, objects, values, hasSolution)) return false; @@ -104,7 +103,7 @@ bool ValidatingSolver::computeInitialValues( // Assert the bindings as constraints, and verify that the // conjunction of the actual constraints is satisfiable. ConstraintSet bindings; - Assignment solutionAssignment(objects, values, true); + Assignment solutionAssignment(objects, values); for (unsigned i = 0; i != values.size(); ++i) { const Array *array = objects[i]; @@ -159,7 +158,7 @@ bool ValidatingSolver::check(const Query &query, ref &result) { // conjunction of the actual constraints is satisfiable. ConstraintSet bindings; - std::map> initialValues; + Assignment::bindings_ty initialValues; cast(result)->tryGetInitialValues(initialValues); Assignment solutionAssignment(initialValues); for (auto &arrayValues : initialValues) { diff --git a/lib/Solver/Z3Solver.cpp b/lib/Solver/Z3Solver.cpp index 3a92ae7fe1..755f47ee92 100644 --- a/lib/Solver/Z3Solver.cpp +++ b/lib/Solver/Z3Solver.cpp @@ -217,7 +217,6 @@ char *Z3SolverImpl::getConstraintLog(const Query &query) { break; } ConstantArrayFinder constant_arrays_in_query; - assert(!query.containsSymcretes()); for (auto const &constraint : query.constraints.cs()) { assumptions.push_back(temp_builder->construct(constraint)); constant_arrays_in_query.visit(constraint); @@ -309,7 +308,6 @@ bool Z3SolverImpl::computeInitialValues( bool Z3SolverImpl::check(const Query &query, ref &result) { ExprHashSet expressions; - assert(!query.containsSymcretes()); expressions.insert(query.constraints.cs().begin(), query.constraints.cs().end()); expressions.insert(query.expr); @@ -347,8 +345,6 @@ bool Z3SolverImpl::internalRunSolver( std::vector> *values, ValidityCore *validityCore, bool &hasSolution) { - assert(!query.containsSymcretes()); - if (ProduceUnsatCore && validityCore) { enableUnsatCore(); } else { diff --git a/test/Expr/Evaluate.kquery b/test/Expr/Evaluate.kquery index 6738c872eb..e6b0d1e1a4 100644 --- a/test/Expr/Evaluate.kquery +++ b/test/Expr/Evaluate.kquery @@ -1,4 +1,4 @@ -# RUN: %kleaver -evaluate %s > %t.log +# RUN: %kleaver -evaluate --use-concretizing-solver=false %s > %t.log arr01 : (array (w64 4) (makeSymbolic arr0 0)) arr12 : (array (w64 8) (makeSymbolic arr1 0)) diff --git a/test/Feature/DanglingConcreteReadExpr.c b/test/Feature/DanglingConcreteReadExpr.c index 4f4dd6cc23..d41d19e1c5 100644 --- a/test/Feature/DanglingConcreteReadExpr.c +++ b/test/Feature/DanglingConcreteReadExpr.c @@ -1,6 +1,6 @@ // RUN: %clang %s -emit-llvm %O0opt -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --optimize=false --output-dir=%t.klee-out %t1.bc +// RUN: %klee --optimize=false --use-cex-cache=false --output-dir=%t.klee-out %t1.bc // RUN: grep "total queries = 2" %t.klee-out/info #include diff --git a/test/Solver/CexCacheValidityCoresCheck.c b/test/Solver/CexCacheValidityCoresCheck.c index 26ba133d63..0e48f6f24f 100644 --- a/test/Solver/CexCacheValidityCoresCheck.c +++ b/test/Solver/CexCacheValidityCoresCheck.c @@ -30,6 +30,6 @@ int main(int argc, char **argv) { } } // CHECK-CACHE-ON: QCexCacheHits,SolverQueries -// CHECK-CACHE-ON: 1461,202 +// CHECK-CACHE-ON: 1460,202 // CHECK-CACHE-OFF: QCexCacheHits,SolverQueries -// CHECK-CACHE-OFF: 1011,652 +// CHECK-CACHE-OFF: 1010,652 diff --git a/tools/kleaver/main.cpp b/tools/kleaver/main.cpp index 441e7ffacf..a56ab4c7fb 100644 --- a/tools/kleaver/main.cpp +++ b/tools/kleaver/main.cpp @@ -228,9 +228,8 @@ static bool EvaluateInputAST(const char *Filename, const llvm::MemoryBuffer *MB, for (auto i : QC->Constraints) { constraints.insert(i); } - if (S->mustBeTrue( - Query(ConstraintSet(constraints, {}, {true}), QC->Query), - result)) { + if (S->mustBeTrue(Query(ConstraintSet(constraints, {}, {}), QC->Query), + result)) { llvm::outs() << (result ? "VALID" : "INVALID"); } else { llvm::outs() << "FAIL (reason: " @@ -251,7 +250,7 @@ static bool EvaluateInputAST(const char *Filename, const llvm::MemoryBuffer *MB, constraints.insert(i); } if (S->getValue( - Query(ConstraintSet(constraints, {}, {true}), QC->Values[0]), + Query(ConstraintSet(constraints, {}, {}), QC->Values[0]), result)) { llvm::outs() << "INVALID\n"; llvm::outs() << "\tExpr 0:\t" << result; @@ -270,7 +269,7 @@ static bool EvaluateInputAST(const char *Filename, const llvm::MemoryBuffer *MB, } if (S->getInitialValues( - Query(ConstraintSet(constraints, {}, {true}), QC->Query), + Query(ConstraintSet(constraints, {}, {}), QC->Query), QC->Objects, result)) { llvm::outs() << "INVALID\n"; Assignment solutionAssugnment(QC->Objects, result); @@ -383,7 +382,7 @@ static bool printInputAsSMTLIBv2(const char *Filename, constraints.insert(i); } - ConstraintSet constraintM(constraints, {}, {true}); + ConstraintSet constraintM(constraints, {}, {}); Query query(constraintM, QC->Query); printer.setQuery(query); diff --git a/unittests/Assignment/AssignmentTest.cpp b/unittests/Assignment/AssignmentTest.cpp index f7906ef73b..410a4ce357 100644 --- a/unittests/Assignment/AssignmentTest.cpp +++ b/unittests/Assignment/AssignmentTest.cpp @@ -27,7 +27,7 @@ TEST(AssignmentTest, FoldNotOptimized) { values.push_back(value); // We want to simplify to a constant so allow free values so // if the assignment is incomplete we don't get back a constant. - Assignment assignment(objects, values, /*_allowFreeValues=*/true); + Assignment assignment(objects, values); // Now make an expression that reads from the array at position // zero. diff --git a/unittests/Expr/ArrayExprTest.cpp b/unittests/Expr/ArrayExprTest.cpp index 866e6d3fd7..68b6948612 100644 --- a/unittests/Expr/ArrayExprTest.cpp +++ b/unittests/Expr/ArrayExprTest.cpp @@ -65,8 +65,7 @@ TEST(ArrayExprTest, HashCollisions) { SparseStorage value({6, 0, 0, 0}); std::vector> values = {value}; std::vector assigmentArrays = {symArray}; - auto a = std::make_unique(assigmentArrays, values, - /*_allowFreeValues=*/true); + auto a = std::make_unique(assigmentArrays, values); EXPECT_NE(a->evaluate(updatedRead), a->evaluate(firstRead)); EXPECT_EQ(a->evaluate(updatedRead), getConstant(42, Expr::Int8)); From 9a96f85ea9583f5bc82d904eb7fbb3e6f5126837 Mon Sep 17 00:00:00 2001 From: Yurii Kostyukov Date: Tue, 15 Aug 2023 12:38:12 +0300 Subject: [PATCH 006/103] [fix] Solvers performance fixes Solvers: - Fixed CexCachingSolver so that the core solver (Z3/STP) does not get stupid queries, like `false` or `not false` Tests: - Changed total queries in `Feature/DanglingConcreteReadExpr.c` test from 2 to 1 as its first query to Z3 was `not false` - Decreased QCexCacheHits in `Solver/CexCacheValidityCoresCheck.c` test by one for the same reason - Activated tests in `test/Solver` --- include/klee/Solver/SolverImpl.h | 2 +- include/klee/Solver/SolverUtil.h | 2 ++ lib/Expr/IndependentConstraintSetUnion.cpp | 2 +- lib/Solver/CexCachingSolver.cpp | 20 ++++++++------------ test/Feature/DanglingConcreteReadExpr.c | 6 +++--- test/Solver/CrosscheckCoreStpZ3.c | 6 +++--- test/Solver/DummySolver.c | 2 +- test/Solver/ValidatingSolver.c | 6 +++--- 8 files changed, 22 insertions(+), 24 deletions(-) diff --git a/include/klee/Solver/SolverImpl.h b/include/klee/Solver/SolverImpl.h index bd5937ed11..3e24a16ed7 100644 --- a/include/klee/Solver/SolverImpl.h +++ b/include/klee/Solver/SolverImpl.h @@ -22,7 +22,7 @@ class ExecutionState; class Expr; struct Query; -/// SolverImpl - Abstract base clase for solver implementations. +/// SolverImpl - Abstract base class for solver implementations. class SolverImpl { public: SolverImpl() = default; diff --git a/include/klee/Solver/SolverUtil.h b/include/klee/Solver/SolverUtil.h index d55f372de1..6b453947b4 100644 --- a/include/klee/Solver/SolverUtil.h +++ b/include/klee/Solver/SolverUtil.h @@ -231,6 +231,8 @@ class InvalidResponse : public SolverResponse { InvalidResponse(Assignment::bindings_ty &initialValues) : result(initialValues) {} + explicit InvalidResponse() : result() {} + bool tryGetInitialValuesFor( const std::vector &objects, std::vector> &values) const { diff --git a/lib/Expr/IndependentConstraintSetUnion.cpp b/lib/Expr/IndependentConstraintSetUnion.cpp index 692e679234..3ec73081cb 100644 --- a/lib/Expr/IndependentConstraintSetUnion.cpp +++ b/lib/Expr/IndependentConstraintSetUnion.cpp @@ -81,7 +81,7 @@ void IndependentConstraintSetUnion::reEvaluateConcretization( const Assignment &newConcretization) { Assignment delta; Assignment removed; - for (const auto it : concretization) { + for (const auto &it : concretization) { if (newConcretization.bindings.count(it.first) == 0) { removed.bindings.insert(it); } else if (newConcretization.bindings.at(it.first) != it.second) { diff --git a/lib/Solver/CexCachingSolver.cpp b/lib/Solver/CexCachingSolver.cpp index 2e26971040..4a9e3a06bf 100644 --- a/lib/Solver/CexCachingSolver.cpp +++ b/lib/Solver/CexCachingSolver.cpp @@ -301,17 +301,9 @@ bool CexCachingSolver::computeValidity(const Query &query, PartialValidity &result) { TimerStatIncrementer t(stats::cexCacheTime); ref a; - if (!getResponse(query.withFalse(), a)) + ref q; + if (!computeValue(query, q)) return false; - assert(isa(a) && "computeValidity() must have assignment"); - - ref q = cast(a)->evaluate(query.expr, false); - - if (!isa(q) && solver->impl->computeValue(query, q)) - return false; - - assert(isa(q) && - "assignment evaluation did not result in constant"); if (cast(q)->isTrue()) { if (!getResponse(query, a)) @@ -368,8 +360,12 @@ bool CexCachingSolver::computeValue(const Query &query, ref &result) { TimerStatIncrementer t(stats::cexCacheTime); ref a; - if (!getResponse(query.withFalse(), a)) - return false; + if (!query.constraints.cs().empty()) { + if (!getResponse(query.withFalse(), a)) + return false; + } else { + a = new InvalidResponse(); + } assert(isa(a) && "computeValue() must have assignment"); result = cast(a)->evaluate(query.expr, false); diff --git a/test/Feature/DanglingConcreteReadExpr.c b/test/Feature/DanglingConcreteReadExpr.c index d41d19e1c5..1f8a5a347a 100644 --- a/test/Feature/DanglingConcreteReadExpr.c +++ b/test/Feature/DanglingConcreteReadExpr.c @@ -1,7 +1,7 @@ // RUN: %clang %s -emit-llvm %O0opt -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --optimize=false --use-cex-cache=false --output-dir=%t.klee-out %t1.bc -// RUN: grep "total queries = 2" %t.klee-out/info +// RUN: %klee --optimize=false --output-dir=%t.klee-out %t1.bc +// RUN: grep "total queries = 1" %t.klee-out/info #include @@ -12,7 +12,7 @@ int main() { y = x; - // should be exactly two queries (prove x is/is not 10) + // should be exactly one query (prove x is 10) // eventually should be 0 when we have fast solver if (x == 10) { assert(y == 10); diff --git a/test/Solver/CrosscheckCoreStpZ3.c b/test/Solver/CrosscheckCoreStpZ3.c index 9847d8a69b..471f7d40e3 100644 --- a/test/Solver/CrosscheckCoreStpZ3.c +++ b/test/Solver/CrosscheckCoreStpZ3.c @@ -2,9 +2,9 @@ // REQUIRES: z3 // RUN: %clang %s -emit-llvm %O0opt -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --solver-backend=stp --use-forked-solver=false --debug-crosscheck-core-solver=z3 %t1.bc +// RUN: %klee --output-dir=%t.klee-out --solver-backend=stp --use-forked-solver=false --debug-crosscheck-core-solver=z3 %t1.bc 2>&1 | FileCheck %s #include "ExerciseSolver.c.inc" -// CHECK: KLEE: done: completed paths = 15 -// CHECK: KLEE: done: partially completed paths = 0 +// CHECK: KLEE: done: completed paths = 9 +// CHECK: KLEE: done: partially completed paths = 5 diff --git a/test/Solver/DummySolver.c b/test/Solver/DummySolver.c index f6fe3671be..51c35e936f 100644 --- a/test/Solver/DummySolver.c +++ b/test/Solver/DummySolver.c @@ -1,6 +1,6 @@ // RUN: %clang %s -emit-llvm %O0opt -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --solver-backend=dummy %t1.bc +// RUN: %klee --output-dir=%t.klee-out --solver-backend=dummy %t1.bc 2>&1 | FileCheck %s #include "ExerciseSolver.c.inc" diff --git a/test/Solver/ValidatingSolver.c b/test/Solver/ValidatingSolver.c index 86799a85f2..d492ff9264 100644 --- a/test/Solver/ValidatingSolver.c +++ b/test/Solver/ValidatingSolver.c @@ -1,8 +1,8 @@ // RUN: %clang %s -emit-llvm %O0opt -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --debug-validate-solver --debug-assignment-validating-solver %t1.bc +// RUN: %klee --output-dir=%t.klee-out --debug-validate-solver --debug-assignment-validating-solver %t1.bc 2>&1 | FileCheck %s #include "ExerciseSolver.c.inc" -// CHECK: KLEE: done: completed paths = 15 -// CHECK: KLEE: done: partially completed paths = 0 \ No newline at end of file +// CHECK: KLEE: done: completed paths = 9 +// CHECK: KLEE: done: partially completed paths = 5 \ No newline at end of file From 7f5db38fce6d918be2354064dbc1fcf6ce9106c7 Mon Sep 17 00:00:00 2001 From: Yurii Kostyukov Date: Tue, 12 Sep 2023 12:34:41 +0300 Subject: [PATCH 007/103] [feat] Z3 Tree incremental solver --- include/klee/ADT/Incremental.h | 358 +++++++++ include/klee/Expr/Constraints.h | 8 +- include/klee/Solver/IncompleteSolver.h | 1 + include/klee/Solver/Solver.h | 9 + include/klee/Solver/SolverCmdLine.h | 3 + include/klee/Solver/SolverImpl.h | 2 + include/klee/Solver/SolverUtil.h | 35 +- lib/Core/ExecutionState.cpp | 10 +- lib/Core/ExecutionState.h | 8 +- lib/Core/Executor.cpp | 9 +- lib/Core/ImpliedValue.cpp | 11 +- lib/Core/TimingSolver.cpp | 58 +- lib/Core/TimingSolver.h | 4 + lib/Expr/Constraints.cpp | 2 + lib/Solver/AssignmentValidatingSolver.cpp | 17 +- lib/Solver/CachingSolver.cpp | 5 + lib/Solver/CexCachingSolver.cpp | 5 + lib/Solver/ConcretizingSolver.cpp | 23 +- lib/Solver/CoreSolver.cpp | 11 +- lib/Solver/DummySolver.cpp | 3 + lib/Solver/IncompleteSolver.cpp | 11 +- lib/Solver/IndependentSolver.cpp | 9 +- lib/Solver/MetaSMTSolver.cpp | 1 + lib/Solver/QueryLoggingSolver.cpp | 10 +- lib/Solver/QueryLoggingSolver.h | 1 + lib/Solver/STPSolver.cpp | 1 + lib/Solver/Solver.cpp | 19 +- lib/Solver/SolverCmdLine.cpp | 18 +- lib/Solver/SolverImpl.cpp | 7 +- lib/Solver/ValidatingSolver.cpp | 12 +- lib/Solver/Z3Builder.cpp | 4 +- lib/Solver/Z3Builder.h | 14 +- lib/Solver/Z3Solver.cpp | 846 +++++++++++++++++----- lib/Solver/Z3Solver.h | 13 +- test/Solver/CallComputeValue.c | 21 + test/Solver/CrosscheckZ3AndZ3TreeInc.c | 11 + tools/kleaver/main.cpp | 40 +- unittests/Solver/SolverTest.cpp | 6 +- unittests/Solver/Z3SolverTest.cpp | 2 +- 39 files changed, 1286 insertions(+), 342 deletions(-) create mode 100644 include/klee/ADT/Incremental.h create mode 100644 test/Solver/CallComputeValue.c create mode 100644 test/Solver/CrosscheckZ3AndZ3TreeInc.c diff --git a/include/klee/ADT/Incremental.h b/include/klee/ADT/Incremental.h new file mode 100644 index 0000000000..b2e8417350 --- /dev/null +++ b/include/klee/ADT/Incremental.h @@ -0,0 +1,358 @@ +//===---- Incremental.h -----------------------------------------*- C++ -*-===// +// +// The KLEE Symbolic Virtual Machine +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef KLEE_INCREMENTAL_H +#define KLEE_INCREMENTAL_H + +#include +#include +#include +#include +#include +#include + +#include "klee/Expr/ExprUtil.h" + +namespace klee { + +template +void extend(std::vector<_Tp, _Alloc> &ths, + const std::vector<_Tp, _Alloc> &other) { + ths.reserve(ths.size() + other.size()); + ths.insert(ths.end(), other.begin(), other.end()); +} + +template > +class inc_vector { +public: + using vec = std::vector<_Tp, _Alloc>; + using frame_size_it = std::vector::const_iterator; + using frame_it = typename vec::const_iterator; + + /// It is public, so that all vector operations are supported + /// Everything pushed to v is pushed to the last frame + vec v; + + std::vector frame_sizes; + +private: + // v.size() == sum(frame_sizes) + size of the fresh frame + + size_t freshFrameSize() const { + return v.size() - + std::accumulate(frame_sizes.begin(), frame_sizes.end(), 0); + } + + void take(size_t n, size_t &frames_count, size_t &frame_index) const { + size_t i = 0; + size_t c = n; + for (; i < frame_sizes.size(); i++) { + if (frame_sizes[i] > c) + break; + c -= frame_sizes[i]; + } + frames_count = c; + frame_index = i; + } + +public: + inc_vector() {} + inc_vector(const std::vector<_Tp> &constraints) : v(constraints) {} + + void clear() { + v.clear(); + frame_sizes.clear(); + } + + frame_size_it begin() const { return frame_sizes.cbegin(); } + frame_size_it end() const { return frame_sizes.cend(); } + size_t framesSize() const { return frame_sizes.size() + 1; } + + frame_it begin(int frame_index) const { + assert(-(long long)framesSize() <= (long long)frame_index && + (long long)frame_index <= (long long)framesSize()); + if (frame_index < 0) + frame_index += framesSize(); + if ((long long)frame_index == (long long)framesSize()) + return v.end(); + auto fend = frame_sizes.begin() + frame_index; + auto shift = std::accumulate(frame_sizes.begin(), fend, 0); + return v.begin() + shift; + } + frame_it end(int frame_index) const { return begin(frame_index + 1); } + size_t size(size_t frame_index) const { + assert(frame_index < framesSize()); + if (frame_index == framesSize() - 1) // last frame + return freshFrameSize(); + return frame_sizes[frame_index]; + } + + void pop(size_t popFrames) { + assert(freshFrameSize() == 0); + if (popFrames == 0) + return; + size_t toPop = + std::accumulate(frame_sizes.end() - popFrames, frame_sizes.end(), 0); + v.resize(v.size() - toPop); + frame_sizes.resize(frame_sizes.size() - popFrames); + } + + void push() { + auto freshSize = freshFrameSize(); + frame_sizes.push_back(freshSize); + assert(freshFrameSize() == 0); + } + + /// ensures that last frame is empty + void extend(const std::vector<_Tp, _Alloc> &other) { + assert(freshFrameSize() == 0); + // push(); + klee::extend(v, other); + push(); + } + + /// ensures that last frame is empty + void extend(const inc_vector<_Tp, _Alloc> &other) { + assert(freshFrameSize() == 0); + for (size_t i = 0, e = other.framesSize(); i < e; i++) { + v.reserve(v.size() + other.size(i)); + v.insert(v.end(), other.begin(i), other.end(i)); + push(); + } + } + + void takeAfter(size_t n, inc_vector<_Tp, _Alloc> &result) const { + size_t frames_count, frame_index; + take(n, frames_count, frame_index); + result = *this; + std::vector<_Tp, _Alloc>(result.v.begin() + n, result.v.end()) + .swap(result.v); + std::vector(result.frame_sizes.begin() + frame_index, + result.frame_sizes.end()) + .swap(result.frame_sizes); + if (frames_count) + result.frame_sizes[0] -= frames_count; + } + + void butLast(inc_vector<_Tp, _Alloc> &result) const { + assert(!v.empty() && "butLast of empty vector"); + assert(freshFrameSize() && "butLast of empty fresh frame"); + result = *this; + result.v.pop_back(); + } + + void takeBefore(size_t n, size_t &toPop, size_t &takeFromOther) const { + take(n, takeFromOther, toPop); + toPop = frame_sizes.size() - toPop; + } +}; + +using FrameId = size_t; +using FrameIds = std::unordered_set; + +template , + typename _Pred = std::equal_to<_Value>, + typename _Alloc = std::allocator<_Value>> +class inc_uset { +private: + class MinFrameIds { + FrameIds ids; + FrameId min = std::numeric_limits::max(); + + public: + bool empty() const { return ids.empty(); } + + bool hasMin(FrameId other) const { return min == other && !ids.empty(); } + + void insert(FrameId i) { + ids.insert(i); + if (i < min) + min = i; + } + + MinFrameIds bound(FrameId upperBound) { + MinFrameIds result; + std::copy_if(ids.begin(), ids.end(), + std::inserter(result.ids, result.ids.begin()), + [upperBound](FrameId i) { return i <= upperBound; }); + auto min_it = std::min_element(result.ids.begin(), result.ids.end()); + if (min_it == result.ids.end()) + result.min = std::numeric_limits::max(); + else + result.min = *min_it; + return result; + } + }; + + using idMap = std::unordered_map<_Value, MinFrameIds, _Hash, _Pred, _Alloc>; + using citerator = typename idMap::const_iterator; + idMap ids; + FrameId current_frame = 0; + +public: + size_t framesSize() const { return current_frame + 1; } + + void clear() { + ids.clear(); + current_frame = 0; + } + + class frame_it + : public std::iterator, int> { + citerator set_it; + const citerator set_ite; + const FrameId frame_index = 0; + + void gotoNext() { + while (set_it != set_ite && !set_it->second.hasMin(frame_index)) + set_it++; + } + + public: + using value_type = _Value; + + explicit frame_it(const idMap &ids) + : set_it(ids.end()), set_ite(ids.end()) {} + explicit frame_it(const idMap &ids, FrameId frame_index) + : set_it(ids.begin()), set_ite(ids.end()), frame_index(frame_index) { + gotoNext(); + } + + bool operator!=(const frame_it &other) const { + return set_it != other.set_it; + } + + const _Value &operator*() const { return set_it->first; } + + frame_it &operator++() { + if (set_it != set_ite) { + set_it++; + gotoNext(); + } + return *this; + } + }; + + class all_it + : public std::iterator, int> { + citerator set_it; + + public: + using value_type = _Value; + + explicit all_it(citerator set_it) : set_it(set_it) {} + + bool operator!=(const all_it &other) const { + return set_it != other.set_it; + } + + const _Value &operator*() const { return set_it->first; } + + all_it &operator++() { + set_it++; + return *this; + } + }; + + all_it begin() const { return all_it(ids.begin()); } + all_it end() const { return all_it(ids.end()); } + + frame_it begin(int frame_index) const { + assert(-(long long)framesSize() <= (long long)frame_index && + (long long)frame_index <= (long long)framesSize()); + if (frame_index < 0) + frame_index += framesSize(); + return frame_it(ids, frame_index); + } + frame_it end(int frame_index) const { return frame_it(ids); } + + void insert(const _Value &v) { ids[v].insert(current_frame); } + + template + void insert(_InputIterator __first, _InputIterator __last) { + for (; __first != __last; __first++) + ids[*__first].insert(current_frame); + } + + void pop(size_t popFrames) { + current_frame -= popFrames; + idMap newIdMap; + for (auto &keyAndIds : ids) { + MinFrameIds newIds = keyAndIds.second.bound(current_frame); + if (!newIds.empty()) + newIdMap.insert(std::make_pair(keyAndIds.first, newIds)); + } + ids = newIdMap; + } + + void push() { current_frame++; } +}; + +template , + typename _Pred = std::equal_to<_Key>, + typename _Alloc = std::allocator>> +class inc_umap { +private: + std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc> map; + using idMap = std::unordered_map<_Key, FrameIds, _Hash, _Pred, _Alloc>; + idMap ids; + FrameId current_frame = 0; + +public: + void clear() { + map.clear(); + ids.clear(); + current_frame = 0; + } + + void insert(const std::pair<_Key, _Tp> &pair) { + map.insert(pair); + ids[pair.first].insert(current_frame); + } + + _Tp &operator[](const _Key &key) { + ids[key].insert(current_frame); + return map[key]; + } + + size_t count(const _Key &key) const { return map.count(key); } + + const _Tp &at(_Key &key) const { return map.at(key); } + + void pop(size_t popFrames) { + current_frame -= popFrames; + idMap newIdMap; + for (auto &keyAndIds : ids) { + FrameIds newIds; + for (auto id : keyAndIds.second) + if (id <= current_frame) + newIds.insert(id); + if (newIds.empty()) + map.erase(keyAndIds.first); + else + newIdMap.insert(std::make_pair(keyAndIds.first, newIds)); + } + ids = newIdMap; + } + + void push() { current_frame++; } + + void dump() const { + for (auto kv : map) { + kv.first.dump(); + llvm::errs() << "----->\n"; + kv.second.dump(); + llvm::errs() << "\n;;;;;;;;;\n"; + } + } +}; + +} // namespace klee + +#endif /* KLEE_INCREMENTAL_H */ diff --git a/include/klee/Expr/Constraints.h b/include/klee/Expr/Constraints.h index c65cee483f..a87cd0ce3c 100644 --- a/include/klee/Expr/Constraints.h +++ b/include/klee/Expr/Constraints.h @@ -37,9 +37,11 @@ class ConstraintSet { public: ConstraintSet(constraints_ty cs, symcretes_ty symcretes, Assignment concretization); - ConstraintSet(ref ics); - ConstraintSet(const std::vector> &ics); - ConstraintSet(); + explicit ConstraintSet(ref ics); + explicit ConstraintSet( + const std::vector> &ics); + explicit ConstraintSet(constraints_ty cs); + explicit ConstraintSet(); void addConstraint(ref e, const Assignment &delta); void addSymcrete(ref s, const Assignment &concretization); diff --git a/include/klee/Solver/IncompleteSolver.h b/include/klee/Solver/IncompleteSolver.h index 4f47c1cdd6..65dac30c4b 100644 --- a/include/klee/Solver/IncompleteSolver.h +++ b/include/klee/Solver/IncompleteSolver.h @@ -80,6 +80,7 @@ class StagedSolverImpl : public SolverImpl { SolverRunStatus getOperationStatusCode(); char *getConstraintLog(const Query &); void setCoreSolverTimeout(time::Span timeout); + void notifyStateTermination(std::uint32_t id); }; } // namespace klee diff --git a/include/klee/Solver/Solver.h b/include/klee/Solver/Solver.h index 30b344efec..c39d8a2ae3 100644 --- a/include/klee/Solver/Solver.h +++ b/include/klee/Solver/Solver.h @@ -191,6 +191,10 @@ class Solver { virtual char *getConstraintLog(const Query &query); virtual void setCoreSolverTimeout(time::Span timeout); + + /// @brief Notify the solver that the state with specified id has been + /// terminated + void notifyStateTermination(std::uint32_t id); }; /* *** */ @@ -264,6 +268,11 @@ std::unique_ptr createCoreSolver(CoreSolverType cst); std::unique_ptr createConcretizingSolver(std::unique_ptr s, AddressGenerator *addressGenerator); + +/// Return a list of all unique symbolic objects referenced by the +/// given Query. +void findSymbolicObjects(const Query &query, + std::vector &results); } // namespace klee #endif /* KLEE_SOLVER_H */ diff --git a/include/klee/Solver/SolverCmdLine.h b/include/klee/Solver/SolverCmdLine.h index 7fbfac0394..6bd0c285bb 100644 --- a/include/klee/Solver/SolverCmdLine.h +++ b/include/klee/Solver/SolverCmdLine.h @@ -50,6 +50,8 @@ extern llvm::cl::opt CoreSolverOptimizeDivides; extern llvm::cl::opt UseAssignmentValidatingSolver; +extern llvm::cl::opt MaxSolversApproxTreeInc; + /// The different query logging solvers that can be switched on/off enum QueryLoggingSolverType { ALL_KQUERY, ///< Log all queries in .kquery (KQuery) format @@ -65,6 +67,7 @@ enum CoreSolverType { METASMT_SOLVER, DUMMY_SOLVER, Z3_SOLVER, + Z3_TREE_SOLVER, NO_SOLVER }; diff --git a/include/klee/Solver/SolverImpl.h b/include/klee/Solver/SolverImpl.h index 3e24a16ed7..da8e510f22 100644 --- a/include/klee/Solver/SolverImpl.h +++ b/include/klee/Solver/SolverImpl.h @@ -119,6 +119,8 @@ class SolverImpl { } virtual void setCoreSolverTimeout(time::Span timeout){}; + + virtual void notifyStateTermination(std::uint32_t id) = 0; }; } // namespace klee diff --git a/include/klee/Solver/SolverUtil.h b/include/klee/Solver/SolverUtil.h index 6b453947b4..bb66e7a179 100644 --- a/include/klee/Solver/SolverUtil.h +++ b/include/klee/Solver/SolverUtil.h @@ -42,6 +42,9 @@ enum class Validity { True = 1, False = -1, Unknown = 0 }; struct SolverQueryMetaData { /// @brief Costs for all queries issued for this state time::Span queryCost; + + /// @brief Caller state id + std::uint32_t id = 0; }; struct Query { @@ -49,25 +52,36 @@ struct Query { const ConstraintSet constraints; ref expr; - Query(const ConstraintSet &_constraints, ref _expr) - : constraints(_constraints), expr(_expr) {} + /// @brief id of the state initiated this query + const std::uint32_t id; + + Query(const ConstraintSet &_constraints, ref _expr, std::uint32_t _id) + : constraints(_constraints), expr(_expr), id(_id) {} + + /// This constructor should be used *only* if + /// this query is created *not* from some known ExecutionState + /// Otherwise consider using the above constructor + Query(const constraints_ty &cs, ref e) + : Query(ConstraintSet(cs), e, 0) {} Query(const Query &query) - : constraints(query.constraints), expr(query.expr) {} + : constraints(query.constraints), expr(query.expr), id(query.id) {} /// withExpr - Return a copy of the query with the given expression. - Query withExpr(ref _expr) const { return Query(constraints, _expr); } + Query withExpr(ref _expr) const { + return Query(constraints, _expr, id); + } /// withFalse - Return a copy of the query with a false expression. Query withFalse() const { - return Query(constraints, ConstantExpr::alloc(0, Expr::Bool)); + return Query(constraints, Expr::createFalse(), id); } /// negateExpr - Return a copy of the query with the expression negated. Query negateExpr() const { return withExpr(Expr::createIsZero(expr)); } Query withConstraints(const ConstraintSet &_constraints) const { - return Query(_constraints, expr); + return Query(_constraints, expr, id); } /// Get all arrays that figure in the query std::vector gatherArrays() const; @@ -108,11 +122,8 @@ struct ValidityCore { ValidityCore(const constraints_typ &_constraints, ref _expr) : constraints(_constraints), expr(_expr) {} - ValidityCore(const ExprHashSet &_constraints, ref _expr) : expr(_expr) { - for (auto e : _constraints) { - constraints.insert(e); - } - } + ValidityCore(const ExprHashSet &_constraints, ref _expr) + : constraints(_constraints.begin(), _constraints.end()), expr(_expr) {} /// withExpr - Return a copy of the validity core with the given expression. ValidityCore withExpr(ref _expr) const { @@ -128,6 +139,8 @@ struct ValidityCore { /// negated. ValidityCore negateExpr() const { return withExpr(Expr::createIsZero(expr)); } + Query toQuery() const; + /// Dump validity core void dump() const; diff --git a/lib/Core/ExecutionState.cpp b/lib/Core/ExecutionState.cpp index ddec6ec63b..a623d7c289 100644 --- a/lib/Core/ExecutionState.cpp +++ b/lib/Core/ExecutionState.cpp @@ -182,7 +182,9 @@ ExecutionState::ExecutionState(const ExecutionState &state) returnValue(state.returnValue), gepExprBases(state.gepExprBases), prevTargets_(state.prevTargets_), targets_(state.targets_), prevHistory_(state.prevHistory_), history_(state.history_), - isTargeted_(state.isTargeted_) {} + isTargeted_(state.isTargeted_) { + queryMetaData.id = state.id; +} ExecutionState *ExecutionState::branch() { depth++; @@ -496,3 +498,9 @@ bool ExecutionState::reachedTarget(ref target) const { return pc == target->getBlock()->getFirstInstruction(); } } + +Query ExecutionState::toQuery(ref head) const { + return Query(constraints.cs(), head, id); +} + +Query ExecutionState::toQuery() const { return toQuery(Expr::createFalse()); } diff --git a/lib/Core/ExecutionState.h b/lib/Core/ExecutionState.h index c0bfeb7301..c071448c92 100644 --- a/lib/Core/ExecutionState.h +++ b/lib/Core/ExecutionState.h @@ -436,12 +436,18 @@ class ExecutionState { void addConstraint(ref e, const Assignment &c); void addCexPreference(const ref &cond); + Query toQuery(ref head) const; + Query toQuery() const; + void dumpStack(llvm::raw_ostream &out) const; bool visited(KBlock *block) const; std::uint32_t getID() const { return id; }; - void setID() { id = nextID++; }; + void setID() { + id = nextID++; + queryMetaData.id = id; + }; llvm::BasicBlock *getInitPCBlock() const; llvm::BasicBlock *getPrevPCBlock() const; llvm::BasicBlock *getPCBlock() const; diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index 8bc362391d..4f9aa76701 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -4507,6 +4507,7 @@ void Executor::terminateState(ExecutionState &state, interpreterHandler->incPathsExplored(); state.pc = state.prevPC; targetCalculator->update(state); + solver->notifyStateTermination(state.id); removedStates.push_back(&state); } @@ -5420,7 +5421,7 @@ MemoryObject *Executor::allocate(ExecutionState &state, ref size, ZExtExpr::create(size, pointerWidthInBits)}; std::vector> factors; - Query(state.constraints.cs(), ZExtExpr::create(size, pointerWidthInBits)) + state.toQuery(ZExtExpr::create(size, pointerWidthInBits)) .getAllDependentConstraintsSets(factors); /* Collect dependent size symcretes. */ @@ -6832,7 +6833,7 @@ void Executor::getConstraintLog(const ExecutionState &state, std::string &res, switch (logFormat) { case STP: { - Query query(state.constraints.cs(), ConstantExpr::alloc(0, Expr::Bool)); + auto query = state.toQuery(); char *log = solver->getConstraintLog(query); res = std::string(log); free(log); @@ -6850,7 +6851,7 @@ void Executor::getConstraintLog(const ExecutionState &state, std::string &res, llvm::raw_string_ostream info(Str); ExprSMTLIBPrinter printer; printer.setOutput(info); - Query query(state.constraints.cs(), ConstantExpr::alloc(0, Expr::Bool)); + auto query = state.toQuery(); printer.setQuery(query); printer.generateOutput(); res = info.str(); @@ -7004,7 +7005,7 @@ Assignment Executor::computeConcretization(const ConstraintSet &constraints, ref condition, SolverQueryMetaData &queryMetaData) { Assignment concretization; - if (Query(constraints, condition).containsSymcretes()) { + if (Query(constraints, condition, queryMetaData.id).containsSymcretes()) { ref response; solver->setTimeout(coreSolverTimeout); bool success = solver->getResponse( diff --git a/lib/Core/ImpliedValue.cpp b/lib/Core/ImpliedValue.cpp index 8841ffab3c..81d3e3faf8 100644 --- a/lib/Core/ImpliedValue.cpp +++ b/lib/Core/ImpliedValue.cpp @@ -203,8 +203,8 @@ void ImpliedValue::checkForImpliedValues(Solver *S, ref e, std::set> readsSet(reads.begin(), reads.end()); reads = std::vector>(readsSet.begin(), readsSet.end()); - ConstraintSet assumption; - assumption.addConstraint(EqExpr::create(e, value), {}); + constraints_ty assumption; + assumption.insert(EqExpr::create(e, value)); // obscure... we need to make sure that all the read indices are // bounds checked. if we don't do this we can end up constructing @@ -212,11 +212,8 @@ void ImpliedValue::checkForImpliedValues(Solver *S, ref e, // bounds indices which will not get picked up. this is of utmost // importance if we are being backed by the CexCachingSolver. - for (std::vector>::iterator i = reads.begin(), ie = reads.end(); - i != ie; ++i) { - ReadExpr *re = i->get(); - assumption.addConstraint(UltExpr::create(re->index, re->updates.root->size), - {}); + for (const auto &re : reads) { + assumption.insert(UltExpr::create(re->index, re->updates.root->size)); } for (const auto &var : reads) { diff --git a/lib/Core/TimingSolver.cpp b/lib/Core/TimingSolver.cpp index edae9a3a5b..91d1d57e9c 100644 --- a/lib/Core/TimingSolver.cpp +++ b/lib/Core/TimingSolver.cpp @@ -44,11 +44,11 @@ bool TimingSolver::evaluate(const ConstraintSet &constraints, ref expr, ref queryResult; ref negatedQueryResult; + Query query(constraints, expr, metaData.id); bool success = produceValidityCore - ? solver->evaluate(Query(constraints, expr), queryResult, - negatedQueryResult) - : solver->evaluate(Query(constraints, expr), result); + ? solver->evaluate(query, queryResult, negatedQueryResult) + : solver->evaluate(query, result); if (success && produceValidityCore) { if (isa(queryResult) && @@ -91,12 +91,12 @@ bool TimingSolver::tryGetUnique(const ConstraintSet &constraints, ref e, e = optimizer.optimizeExpr(e, true); TimerStatIncrementer timer(stats::solverTime); - if (!solver->getValue(Query(constraints, e), value)) { + if (!solver->getValue(Query(constraints, e, metaData.id), value)) { return false; } ref cond = EqExpr::create(e, value); cond = optimizer.optimizeExpr(cond, false); - if (!solver->mustBeTrue(Query(constraints, cond), isTrue)) { + if (!solver->mustBeTrue(Query(constraints, cond, metaData.id), isTrue)) { return false; } if (isTrue) { @@ -125,11 +125,11 @@ bool TimingSolver::mustBeTrue(const ConstraintSet &constraints, ref expr, expr = Simplificator::simplifyExpr(constraints, expr).simplified; ValidityCore validityCore; + Query query(constraints, expr, metaData.id); bool success = produceValidityCore - ? solver->getValidityCore(Query(constraints, expr), - validityCore, result) - : solver->mustBeTrue(Query(constraints, expr), result); + ? solver->getValidityCore(query, validityCore, result) + : solver->mustBeTrue(query, result); metaData.queryCost += timer.delta(); @@ -178,7 +178,8 @@ bool TimingSolver::getValue(const ConstraintSet &constraints, ref expr, if (simplifyExprs) expr = Simplificator::simplifyExpr(constraints, expr).simplified; - bool success = solver->getValue(Query(constraints, expr), result); + bool success = + solver->getValue(Query(constraints, expr, metaData.id), result); metaData.queryCost += timer.delta(); @@ -201,8 +202,8 @@ bool TimingSolver::getMinimalUnsignedValue(const ConstraintSet &constraints, if (simplifyExprs) expr = Simplificator::simplifyExpr(constraints, expr).simplified; - bool success = - solver->getMinimalUnsignedValue(Query(constraints, expr), result); + bool success = solver->getMinimalUnsignedValue( + Query(constraints, expr, metaData.id), result); metaData.queryCost += timer.delta(); @@ -220,15 +221,11 @@ bool TimingSolver::getInitialValues( TimerStatIncrementer timer(stats::solverTime); ref queryResult; + Query query(constraints, Expr::createFalse(), metaData.id); - bool success = - produceValidityCore - ? solver->check( - Query(constraints, ConstantExpr::alloc(0, Expr::Bool)), - queryResult) - : solver->getInitialValues( - Query(constraints, ConstantExpr::alloc(0, Expr::Bool)), objects, - result); + bool success = produceValidityCore + ? solver->check(query, queryResult) + : solver->getInitialValues(query, objects, result); if (success && produceValidityCore && isa(queryResult)) { success = queryResult->tryGetInitialValuesFor(objects, result); @@ -251,22 +248,22 @@ bool TimingSolver::evaluate(const ConstraintSet &constraints, ref expr, auto simplified = simplification.simplified; auto dependency = simplification.dependency; if (auto CE = dyn_cast(simplified)) { + Query query(constraints, simplified, metaData.id); if (CE->isTrue()) { queryResult = new ValidResponse(ValidityCore(dependency, expr)); - return solver->check(Query(constraints, simplified).negateExpr(), - negatedQueryResult); + return solver->check(query.negateExpr(), negatedQueryResult); } else { negatedQueryResult = new ValidResponse( ValidityCore(dependency, Expr::createIsZero(expr))); - return solver->check(Query(constraints, simplified), queryResult); + return solver->check(query, queryResult); } } else { expr = simplified; } } - bool success = solver->evaluate(Query(constraints, expr), queryResult, - negatedQueryResult); + bool success = solver->evaluate(Query(constraints, expr, metaData.id), + queryResult, negatedQueryResult); metaData.queryCost += timer.delta(); @@ -300,8 +297,8 @@ bool TimingSolver::getValidityCore(const ConstraintSet &constraints, } } - bool success = - solver->getValidityCore(Query(constraints, expr), validityCore, result); + bool success = solver->getValidityCore(Query(constraints, expr, metaData.id), + validityCore, result); metaData.queryCost += timer.delta(); @@ -334,7 +331,8 @@ bool TimingSolver::getResponse(const ConstraintSet &constraints, ref expr, } } - bool success = solver->check(Query(constraints, expr), queryResult); + bool success = + solver->check(Query(constraints, expr, metaData.id), queryResult); metaData.queryCost += timer.delta(); @@ -346,8 +344,12 @@ TimingSolver::getRange(const ConstraintSet &constraints, ref expr, SolverQueryMetaData &metaData, time::Span timeout) { ++stats::queries; TimerStatIncrementer timer(stats::solverTime); - auto query = Query(constraints, expr); + Query query(constraints, expr, metaData.id); auto result = solver->getRange(query, timeout); metaData.queryCost += timer.delta(); return result; } + +void TimingSolver::notifyStateTermination(std::uint32_t id) { + solver->notifyStateTermination(id); +} diff --git a/lib/Core/TimingSolver.h b/lib/Core/TimingSolver.h index fbf65c4a56..7692d50377 100644 --- a/lib/Core/TimingSolver.h +++ b/lib/Core/TimingSolver.h @@ -49,6 +49,10 @@ class TimingSolver { return solver->getConstraintLog(query); } + /// @brief Notify the solver that the state with specified id has been + /// terminated + void notifyStateTermination(std::uint32_t id); + bool evaluate(const ConstraintSet &, ref, PartialValidity &result, SolverQueryMetaData &metaData, bool produceValidityCore = false); diff --git a/lib/Expr/Constraints.cpp b/lib/Expr/Constraints.cpp index 22d45d6d29..a1612e9c74 100644 --- a/lib/Expr/Constraints.cpp +++ b/lib/Expr/Constraints.cpp @@ -201,6 +201,8 @@ ConstraintSet::ConstraintSet( } } +ConstraintSet::ConstraintSet(constraints_ty cs) : ConstraintSet(cs, {}, {}) {} + ConstraintSet::ConstraintSet() {} void ConstraintSet::addConstraint(ref e, const Assignment &delta) { diff --git a/lib/Solver/AssignmentValidatingSolver.cpp b/lib/Solver/AssignmentValidatingSolver.cpp index 4df43ae869..8284f0502e 100644 --- a/lib/Solver/AssignmentValidatingSolver.cpp +++ b/lib/Solver/AssignmentValidatingSolver.cpp @@ -44,6 +44,7 @@ class AssignmentValidatingSolver : public SolverImpl { SolverRunStatus getOperationStatusCode(); char *getConstraintLog(const Query &); void setCoreSolverTimeout(time::Span timeout); + void notifyStateTermination(std::uint32_t id); }; // TODO: use computeInitialValues for all queries for more stress testing @@ -141,13 +142,8 @@ bool AssignmentValidatingSolver::check(const Query &query, return true; } - ExprHashSet expressions; - expressions.insert(query.constraints.cs().begin(), - query.constraints.cs().end()); - expressions.insert(query.expr); - std::vector objects; - findSymbolicObjects(expressions.begin(), expressions.end(), objects); + findSymbolicObjects(query, objects); std::vector> values; assert(isa(result)); @@ -168,14 +164,13 @@ void AssignmentValidatingSolver::dumpAssignmentQuery( const Query &query, const Assignment &assignment) { // Create a Query that is augmented with constraints that // enforce the given assignment. - auto constraints = - ConstraintSet(assignment.createConstraintsFromAssignment(), {}, {}); + ConstraintSet constraints(assignment.createConstraintsFromAssignment()); // Add Constraints from `query` for (const auto &constraint : query.constraints.cs()) constraints.addConstraint(constraint, {}); - Query augmentedQuery(constraints, query.expr); + Query augmentedQuery = query.withConstraints(constraints); // Ask the solver for the log for this query. char *logText = solver->getConstraintLog(augmentedQuery); @@ -196,6 +191,10 @@ void AssignmentValidatingSolver::setCoreSolverTimeout(time::Span timeout) { return solver->impl->setCoreSolverTimeout(timeout); } +void AssignmentValidatingSolver::notifyStateTermination(std::uint32_t id) { + solver->impl->notifyStateTermination(id); +} + std::unique_ptr createAssignmentValidatingSolver(std::unique_ptr s) { return std::make_unique( diff --git a/lib/Solver/CachingSolver.cpp b/lib/Solver/CachingSolver.cpp index dbd9dbf39a..a84b686474 100644 --- a/lib/Solver/CachingSolver.cpp +++ b/lib/Solver/CachingSolver.cpp @@ -89,6 +89,7 @@ class CachingSolver : public SolverImpl { SolverRunStatus getOperationStatusCode(); char *getConstraintLog(const Query &); void setCoreSolverTimeout(time::Span timeout); + void notifyStateTermination(std::uint32_t id); }; /** @returns the canonical version of the given query. The reference @@ -387,6 +388,10 @@ void CachingSolver::setCoreSolverTimeout(time::Span timeout) { solver->impl->setCoreSolverTimeout(timeout); } +void CachingSolver::notifyStateTermination(std::uint32_t id) { + solver->impl->notifyStateTermination(id); +} + /// std::unique_ptr diff --git a/lib/Solver/CexCachingSolver.cpp b/lib/Solver/CexCachingSolver.cpp index 4a9e3a06bf..92a209e4f9 100644 --- a/lib/Solver/CexCachingSolver.cpp +++ b/lib/Solver/CexCachingSolver.cpp @@ -112,6 +112,7 @@ class CexCachingSolver : public SolverImpl { SolverRunStatus getOperationStatusCode(); char *getConstraintLog(const Query &query); void setCoreSolverTimeout(time::Span timeout); + void notifyStateTermination(std::uint32_t id); }; /// @@ -445,6 +446,10 @@ void CexCachingSolver::setCoreSolverTimeout(time::Span timeout) { solver->impl->setCoreSolverTimeout(timeout); } +void CexCachingSolver::notifyStateTermination(std::uint32_t id) { + solver->impl->notifyStateTermination(id); +} + /// std::unique_ptr diff --git a/lib/Solver/ConcretizingSolver.cpp b/lib/Solver/ConcretizingSolver.cpp index 52ed3dbd11..c2d717ceed 100644 --- a/lib/Solver/ConcretizingSolver.cpp +++ b/lib/Solver/ConcretizingSolver.cpp @@ -52,6 +52,7 @@ class ConcretizingSolver : public SolverImpl { SolverRunStatus getOperationStatusCode(); char *getConstraintLog(const Query &); void setCoreSolverTimeout(time::Span timeout); + void notifyStateTermination(std::uint32_t id); private: bool assertConcretization(const Query &query, const Assignment &assign) const; @@ -76,13 +77,13 @@ Query ConcretizingSolver::constructConcretizedQuery(const Query &query, const Assignment &assign) { ConstraintSet cs = query.constraints; ref concretizedExpr = assign.evaluate(query.expr); - return Query(cs.getConcretizedVersion(assign), concretizedExpr); + return Query(cs.getConcretizedVersion(assign), concretizedExpr, query.id); } Query ConcretizingSolver::getConcretizedVersion(const Query &query) { ConstraintSet cs = query.constraints; ref concretizedExpr = cs.concretization().evaluate(query.expr); - return Query(cs.getConcretizedVersion(), concretizedExpr); + return Query(cs.getConcretizedVersion(), concretizedExpr, query.id); } void ConcretizingSolver::reverseConcretization( @@ -265,9 +266,9 @@ bool ConcretizingSolver::relaxSymcreteConstraints(const Query &query, for (const ref &symcrete : currentlyBrokenSymcretes) { std::vector> factors; - Query(query.constraints, - AndExpr::create(query.expr, - Expr::createIsZero(symcrete->symcretized))) + query + .withExpr(AndExpr::create( + query.expr, Expr::createIsZero(symcrete->symcretized))) .getAllDependentConstraintsSets(factors); for (ref ics : factors) { for (ref symcrete : ics->symcretes) { @@ -322,7 +323,8 @@ bool ConcretizingSolver::relaxSymcreteConstraints(const Query &query, UgtExpr::create( symbolicSizesSum, ConstantExpr::create(SymbolicAllocationThreshold, - symbolicSizesSum->getWidth()))), + symbolicSizesSum->getWidth())), + query.id), response)) { return false; } @@ -331,14 +333,15 @@ bool ConcretizingSolver::relaxSymcreteConstraints(const Query &query, ref minimalValueOfSum; /* Receive model with a smallest sum as possible. */ if (!solver->impl->computeMinimalUnsignedValue( - Query(queryConstraints, symbolicSizesSum), minimalValueOfSum)) { + Query(queryConstraints, symbolicSizesSum, query.id), + minimalValueOfSum)) { return false; } bool hasSolution = false; if (!solver->impl->computeInitialValues( Query(queryConstraints, - EqExpr::create(symbolicSizesSum, minimalValueOfSum)) + EqExpr::create(symbolicSizesSum, minimalValueOfSum), query.id) .negateExpr(), objects, brokenSymcretizedValues, hasSolution)) { return false; @@ -632,6 +635,10 @@ void ConcretizingSolver::setCoreSolverTimeout(time::Span timeout) { solver->setCoreSolverTimeout(timeout); } +void ConcretizingSolver::notifyStateTermination(std::uint32_t id) { + solver->impl->notifyStateTermination(id); +} + std::unique_ptr createConcretizingSolver(std::unique_ptr s, AddressGenerator *addressGenerator) { diff --git a/lib/Solver/CoreSolver.cpp b/lib/Solver/CoreSolver.cpp index b6de1024b8..e44e8c37a1 100644 --- a/lib/Solver/CoreSolver.cpp +++ b/lib/Solver/CoreSolver.cpp @@ -28,6 +28,7 @@ DISABLE_WARNING_POP namespace klee { std::unique_ptr createCoreSolver(CoreSolverType cst) { + bool isTreeSolver = false; switch (cst) { case STP_SOLVER: #ifdef ENABLE_STP @@ -54,16 +55,22 @@ std::unique_ptr createCoreSolver(CoreSolverType cst) { #endif case DUMMY_SOLVER: return createDummySolver(); + case Z3_TREE_SOLVER: + isTreeSolver = true; case Z3_SOLVER: #ifdef ENABLE_Z3 klee_message("Using Z3 solver backend"); + Z3BuilderType type; #ifdef ENABLE_FP klee_message("Using Z3 bitvector builder"); - return std::make_unique(KLEE_BITVECTOR); + type = KLEE_BITVECTOR; #else klee_message("Using Z3 core builder"); - return std::make_unique(KLEE_CORE); + type = KLEE_CORE; #endif + if (isTreeSolver) + return std::make_unique(type, MaxSolversApproxTreeInc); + return std::make_unique(type); #else klee_message("Not compiled with Z3 support"); return NULL; diff --git a/lib/Solver/DummySolver.cpp b/lib/Solver/DummySolver.cpp index b039581ab1..89f4429896 100644 --- a/lib/Solver/DummySolver.cpp +++ b/lib/Solver/DummySolver.cpp @@ -30,6 +30,7 @@ class DummySolverImpl : public SolverImpl { bool computeValidityCore(const Query &query, ValidityCore &validityCore, bool &isValid); SolverRunStatus getOperationStatusCode(); + void notifyStateTermination(std::uint32_t id); }; DummySolverImpl::DummySolverImpl() {} @@ -79,6 +80,8 @@ SolverImpl::SolverRunStatus DummySolverImpl::getOperationStatusCode() { return SOLVER_RUN_STATUS_FAILURE; } +void DummySolverImpl::notifyStateTermination(std::uint32_t id) {} + std::unique_ptr createDummySolver() { return std::make_unique(std::make_unique()); } diff --git a/lib/Solver/IncompleteSolver.cpp b/lib/Solver/IncompleteSolver.cpp index 5fd7c74b3b..85ad5a8d6d 100644 --- a/lib/Solver/IncompleteSolver.cpp +++ b/lib/Solver/IncompleteSolver.cpp @@ -119,13 +119,8 @@ bool StagedSolverImpl::computeInitialValues( } bool StagedSolverImpl::check(const Query &query, ref &result) { - ExprHashSet expressions; - expressions.insert(query.constraints.cs().begin(), - query.constraints.cs().end()); - expressions.insert(query.expr); - std::vector objects; - findSymbolicObjects(expressions.begin(), expressions.end(), objects); + findSymbolicObjects(query, objects); std::vector> values; bool hasSolution; @@ -157,3 +152,7 @@ char *StagedSolverImpl::getConstraintLog(const Query &query) { void StagedSolverImpl::setCoreSolverTimeout(time::Span timeout) { secondary->impl->setCoreSolverTimeout(timeout); } + +void StagedSolverImpl::notifyStateTermination(std::uint32_t id) { + secondary->impl->notifyStateTermination(id); +} diff --git a/lib/Solver/IndependentSolver.cpp b/lib/Solver/IndependentSolver.cpp index a8c7fb8ede..5d16a15a09 100644 --- a/lib/Solver/IndependentSolver.cpp +++ b/lib/Solver/IndependentSolver.cpp @@ -60,6 +60,7 @@ class IndependentSolver : public SolverImpl { SolverRunStatus getOperationStatusCode(); char *getConstraintLog(const Query &); void setCoreSolverTimeout(time::Span timeout); + void notifyStateTermination(std::uint32_t id); }; bool IndependentSolver::computeValidity(const Query &query, @@ -189,7 +190,7 @@ bool IndependentSolver::computeInitialValues( ConstraintSet tmp(it); std::vector> tempValues; if (!solver->impl->computeInitialValues( - Query(tmp, ConstantExpr::alloc(0, Expr::Bool)), arraysInFactor, + Query(tmp, Expr::createFalse(), query.id), arraysInFactor, tempValues, hasSolution)) { values.clear(); @@ -282,7 +283,7 @@ bool IndependentSolver::check(const Query &query, ref &result) { ref tempResult; std::vector> tempValues; if (!solver->impl->check( - Query(ConstraintSet(it), ConstantExpr::alloc(0, Expr::Bool)), + Query(ConstraintSet(it), Expr::createFalse(), query.id), tempResult)) { return false; } else if (isa(tempResult)) { @@ -332,6 +333,10 @@ void IndependentSolver::setCoreSolverTimeout(time::Span timeout) { solver->impl->setCoreSolverTimeout(timeout); } +void IndependentSolver::notifyStateTermination(std::uint32_t id) { + solver->impl->notifyStateTermination(id); +} + std::unique_ptr klee::createIndependentSolver(std::unique_ptr s) { return std::make_unique( diff --git a/lib/Solver/MetaSMTSolver.cpp b/lib/Solver/MetaSMTSolver.cpp index 17e0972904..f162013864 100644 --- a/lib/Solver/MetaSMTSolver.cpp +++ b/lib/Solver/MetaSMTSolver.cpp @@ -95,6 +95,7 @@ template class MetaSMTSolverImpl : public SolverImpl { char *getConstraintLog(const Query &); void setCoreSolverTimeout(time::Span timeout) { _timeout = timeout; } + void notifyStateTermination(std::uint32_t id) {} bool computeTruth(const Query &, bool &isValid); bool computeValue(const Query &, ref &result); diff --git a/lib/Solver/QueryLoggingSolver.cpp b/lib/Solver/QueryLoggingSolver.cpp index 0bbd631805..45b6af359d 100644 --- a/lib/Solver/QueryLoggingSolver.cpp +++ b/lib/Solver/QueryLoggingSolver.cpp @@ -270,8 +270,7 @@ bool QueryLoggingSolver::check(const Query &query, result->tryGetValidityCore(validityCore); logBuffer << queryCommentSign << " ValidityCore:\n"; - printQuery(Query(ConstraintSet(validityCore.constraints, {}, {}), - validityCore.expr)); + printQuery(validityCore.toQuery()); } } logBuffer << "\n"; @@ -299,8 +298,7 @@ bool QueryLoggingSolver::computeValidityCore(const Query &query, if (isValid) { logBuffer << queryCommentSign << " ValidityCore:\n"; - printQuery(Query(ConstraintSet(validityCore.constraints, {}, {}), - validityCore.expr)); + printQuery(validityCore.toQuery()); } logBuffer << "\n"; @@ -321,3 +319,7 @@ char *QueryLoggingSolver::getConstraintLog(const Query &query) { void QueryLoggingSolver::setCoreSolverTimeout(time::Span timeout) { solver->impl->setCoreSolverTimeout(timeout); } + +void QueryLoggingSolver::notifyStateTermination(std::uint32_t id) { + solver->impl->notifyStateTermination(id); +} diff --git a/lib/Solver/QueryLoggingSolver.h b/lib/Solver/QueryLoggingSolver.h index 16e50f5546..3dd2f1a357 100644 --- a/lib/Solver/QueryLoggingSolver.h +++ b/lib/Solver/QueryLoggingSolver.h @@ -81,6 +81,7 @@ class QueryLoggingSolver : public SolverImpl { SolverRunStatus getOperationStatusCode(); char *getConstraintLog(const Query &); void setCoreSolverTimeout(time::Span timeout); + void notifyStateTermination(std::uint32_t id); }; #endif /* KLEE_QUERYLOGGINGSOLVER_H */ diff --git a/lib/Solver/STPSolver.cpp b/lib/Solver/STPSolver.cpp index 4893115926..5927a90038 100644 --- a/lib/Solver/STPSolver.cpp +++ b/lib/Solver/STPSolver.cpp @@ -104,6 +104,7 @@ class STPSolverImpl : public SolverImpl { void setCoreSolverTimeout(time::Span timeout) override { this->timeout = timeout; } + void notifyStateTermination(std::uint32_t id) override {} bool computeTruth(const Query &, bool &isValid) override; bool computeValue(const Query &, ref &result) override; diff --git a/lib/Solver/Solver.cpp b/lib/Solver/Solver.cpp index d45e071d61..f6b0652235 100644 --- a/lib/Solver/Solver.cpp +++ b/lib/Solver/Solver.cpp @@ -162,6 +162,10 @@ bool Solver::check(const Query &query, ref &queryResult) { return impl->check(query, queryResult); } +void Solver::notifyStateTermination(std::uint32_t id) { + impl->notifyStateTermination(id); +} + static std::pair, ref> getDefaultRange() { return std::make_pair(ConstantExpr::create(0, 64), ConstantExpr::create(0, 64)); @@ -327,6 +331,15 @@ bool Query::containsSizeSymcretes() const { return false; } +void klee::findSymbolicObjects(const Query &query, + std::vector &results) { + ExprHashSet expressions; + expressions.insert(query.constraints.cs().begin(), + query.constraints.cs().end()); + expressions.insert(query.expr); + findSymbolicObjects(expressions.begin(), expressions.end(), results); +} + void Query::dump() const { constraints.dump(); llvm::errs() << "Query [\n"; @@ -334,6 +347,6 @@ void Query::dump() const { llvm::errs() << "]\n"; } -void ValidityCore::dump() const { - Query(ConstraintSet(constraints, {}, {}), expr).dump(); -} +Query ValidityCore::toQuery() const { return Query(constraints, expr); } + +void ValidityCore::dump() const { toQuery().dump(); } diff --git a/lib/Solver/SolverCmdLine.cpp b/lib/Solver/SolverCmdLine.cpp index 0c96fb1263..0f51525d53 100644 --- a/lib/Solver/SolverCmdLine.cpp +++ b/lib/Solver/SolverCmdLine.cpp @@ -123,6 +123,13 @@ cl::opt UseAssignmentValidatingSolver( cl::desc("Debug the correctness of generated assignments (default=false)"), cl::cat(SolvingCat)); +cl::opt + MaxSolversApproxTreeInc("max-solvers-approx-tree-inc", + cl::desc("Maximum size of the Z3 solver pool for " + "approximating tree incrementality." + " Set to 0 to disable (default=0)"), + cl::init(0), cl::cat(SolvingCat)); + void KCommandLine::HideOptions(llvm::cl::OptionCategory &Category) { StringMap &map = cl::getRegisteredOptions(); @@ -196,11 +203,12 @@ cl::opt MetaSMTBackend( cl::opt CoreSolverToUse( "solver-backend", cl::desc("Specifiy the core solver backend to use"), - cl::values(clEnumValN(STP_SOLVER, "stp", "STP" STP_IS_DEFAULT_STR), - clEnumValN(METASMT_SOLVER, "metasmt", - "metaSMT" METASMT_IS_DEFAULT_STR), - clEnumValN(DUMMY_SOLVER, "dummy", "Dummy solver"), - clEnumValN(Z3_SOLVER, "z3", "Z3" Z3_IS_DEFAULT_STR)), + cl::values( + clEnumValN(STP_SOLVER, "stp", "STP" STP_IS_DEFAULT_STR), + clEnumValN(METASMT_SOLVER, "metasmt", "metaSMT" METASMT_IS_DEFAULT_STR), + clEnumValN(DUMMY_SOLVER, "dummy", "Dummy solver"), + clEnumValN(Z3_SOLVER, "z3", "Z3" Z3_IS_DEFAULT_STR), + clEnumValN(Z3_TREE_SOLVER, "z3-tree", "Z3 tree-incremental solver")), cl::init(DEFAULT_CORE_SOLVER), cl::cat(SolvingCat)); cl::opt DebugCrossCheckCoreSolverWith( diff --git a/lib/Solver/SolverImpl.cpp b/lib/Solver/SolverImpl.cpp index 033f1d6d19..2768ce3ce9 100644 --- a/lib/Solver/SolverImpl.cpp +++ b/lib/Solver/SolverImpl.cpp @@ -42,13 +42,8 @@ bool SolverImpl::computeValidity(const Query &query, } bool SolverImpl::check(const Query &query, ref &result) { - ExprHashSet expressions; - expressions.insert(query.constraints.cs().begin(), - query.constraints.cs().end()); - expressions.insert(query.expr); - std::vector objects; - findSymbolicObjects(expressions.begin(), expressions.end(), objects); + findSymbolicObjects(query, objects); std::vector> values; bool hasSolution; diff --git a/lib/Solver/ValidatingSolver.cpp b/lib/Solver/ValidatingSolver.cpp index 65069e32bb..7e065f77bb 100644 --- a/lib/Solver/ValidatingSolver.cpp +++ b/lib/Solver/ValidatingSolver.cpp @@ -43,6 +43,7 @@ class ValidatingSolver : public SolverImpl { SolverRunStatus getOperationStatusCode(); char *getConstraintLog(const Query &); void setCoreSolverTimeout(time::Span timeout); + void notifyStateTermination(std::uint32_t id); }; bool ValidatingSolver::computeTruth(const Query &query, bool &isValid) { @@ -127,7 +128,8 @@ bool ValidatingSolver::computeInitialValues( for (auto const &constraint : query.constraints.cs()) constraints = AndExpr::create(constraints, constraint); - if (!oracle->impl->computeTruth(Query(bindings, constraints), answer)) + if (!oracle->impl->computeTruth(Query(bindings, constraints, query.id), + answer)) return false; if (!answer) assert(0 && "invalid solver result (computeInitialValues)"); @@ -183,7 +185,8 @@ bool ValidatingSolver::check(const Query &query, ref &result) { for (auto const &constraint : query.constraints.cs()) constraints = AndExpr::create(constraints, constraint); - if (!oracle->impl->computeTruth(Query(bindings, constraints), banswer)) + if (!oracle->impl->computeTruth(Query(bindings, constraints, query.id), + banswer)) return false; if (!banswer) assert(0 && "invalid solver result (computeInitialValues)"); @@ -228,6 +231,11 @@ void ValidatingSolver::setCoreSolverTimeout(time::Span timeout) { solver->impl->setCoreSolverTimeout(timeout); } +void ValidatingSolver::notifyStateTermination(std::uint32_t id) { + solver->impl->notifyStateTermination(id); + oracle->impl->notifyStateTermination(id); +} + std::unique_ptr createValidatingSolver(std::unique_ptr s, Solver *oracle, bool ownsOracle) { diff --git a/lib/Solver/Z3Builder.cpp b/lib/Solver/Z3Builder.cpp index f74bf27a54..e80feae88c 100644 --- a/lib/Solver/Z3Builder.cpp +++ b/lib/Solver/Z3Builder.cpp @@ -30,14 +30,14 @@ using namespace klee; namespace klee { // Declared here rather than `Z3Builder.h` so they can be called in gdb. -template <> void Z3NodeHandle::dump() { +template <> void Z3NodeHandle::dump() const { llvm::errs() << "Z3SortHandle:\n" << ::Z3_sort_to_string(context, node) << "\n"; } template <> unsigned Z3NodeHandle::hash() { return Z3_get_ast_hash(context, as_ast()); } -template <> void Z3NodeHandle::dump() { +template <> void Z3NodeHandle::dump() const { llvm::errs() << "Z3ASTHandle:\n" << ::Z3_ast_to_string(context, as_ast()) << "\n"; } diff --git a/lib/Solver/Z3Builder.h b/lib/Solver/Z3Builder.h index 0ad50c151c..7b407c6e3d 100644 --- a/lib/Solver/Z3Builder.h +++ b/lib/Solver/Z3Builder.h @@ -31,7 +31,7 @@ template class Z3NodeHandle { private: // To be specialised - inline ::Z3_ast as_ast(); + inline ::Z3_ast as_ast() const; public: Z3NodeHandle() : node(NULL), context(NULL) {} @@ -73,7 +73,7 @@ template class Z3NodeHandle { return *this; } // To be specialised - void dump(); + void dump() const; operator T() const { return node; } @@ -82,19 +82,21 @@ template class Z3NodeHandle { }; // Specialise for Z3_sort -template <> inline ::Z3_ast Z3NodeHandle::as_ast() { +template <> inline ::Z3_ast Z3NodeHandle::as_ast() const { // In Z3 internally this call is just a cast. We could just do that // instead to simplify our implementation but this seems cleaner. return ::Z3_sort_to_ast(context, node); } typedef Z3NodeHandle Z3SortHandle; -template <> void Z3NodeHandle::dump() __attribute__((used)); +template <> void Z3NodeHandle::dump() const __attribute__((used)); template <> unsigned Z3NodeHandle::hash() __attribute__((used)); // Specialise for Z3_ast -template <> inline ::Z3_ast Z3NodeHandle::as_ast() { return node; } +template <> inline ::Z3_ast Z3NodeHandle::as_ast() const { + return node; +} typedef Z3NodeHandle Z3ASTHandle; -template <> void Z3NodeHandle::dump() __attribute__((used)); +template <> void Z3NodeHandle::dump() const __attribute__((used)); template <> unsigned Z3NodeHandle::hash() __attribute__((used)); struct Z3ASTHandleHash { diff --git a/lib/Solver/Z3Solver.cpp b/lib/Solver/Z3Solver.cpp index 755f47ee92..d5f2232a6e 100644 --- a/lib/Solver/Z3Solver.cpp +++ b/lib/Solver/Z3Solver.cpp @@ -8,11 +8,6 @@ //===----------------------------------------------------------------------===// #include "klee/Config/config.h" -#include "klee/Support/ErrorHandling.h" -#include "klee/Support/FileHandling.h" -#include "klee/Support/OptionCategories.h" - -#include #ifdef ENABLE_Z3 @@ -21,17 +16,20 @@ #include "Z3CoreBuilder.h" #include "Z3Solver.h" +#include "klee/ADT/Incremental.h" #include "klee/ADT/SparseStorage.h" #include "klee/Expr/Assignment.h" #include "klee/Expr/Constraints.h" #include "klee/Expr/ExprUtil.h" #include "klee/Solver/Solver.h" #include "klee/Solver/SolverImpl.h" +#include "klee/Support/ErrorHandling.h" +#include "klee/Support/FileHandling.h" +#include "klee/Support/OptionCategories.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/raw_ostream.h" -#include -#include +#include namespace { // NOTE: Very useful for debugging Z3 behaviour. These files can be given to @@ -67,30 +65,201 @@ DISABLE_WARNING_POP namespace klee { -class Z3SolverImpl : public SolverImpl { +using ConstraintFrames = inc_vector>; +using ExprIncMap = + inc_umap, Z3ASTHandleHash, Z3ASTHandleCmp>; +using Z3ASTIncMap = + inc_umap; +using ExprIncSet = + inc_uset, klee::util::ExprHash, klee::util::ExprCmp>; +using Z3ASTIncSet = inc_uset; + +void dump(const ConstraintFrames &frames) { + llvm::errs() << "frame sizes:"; + for (auto size : frames.frame_sizes) { + llvm::errs() << " " << size; + } + llvm::errs() << "\n"; + llvm::errs() << "frames:\n"; + for (auto &x : frames.v) { + llvm::errs() << x->toString() << "\n"; + } +} + +class ConstraintQuery { private: + // this should be used when only query is needed, se comment below + ref expr; + +public: + // KLEE Queries are validity queries i.e. + // ∀ X Constraints(X) → query(X) + // but Z3 works in terms of satisfiability so instead we ask the + // negation of the equivalent i.e. + // ∃ X Constraints(X) ∧ ¬ query(X) + // so this `constraints` field contains: Constraints(X) ∧ ¬ query(X) + ConstraintFrames constraints; + + explicit ConstraintQuery() {} + + explicit ConstraintQuery(const ConstraintFrames &frames, const ref &e) + : expr(e), constraints(frames) {} + explicit ConstraintQuery(ConstraintFrames &&frames, ref &&e) + : expr(std::move(e)), constraints(std::move(frames)) {} + + explicit ConstraintQuery(const Query &q, bool incremental) : expr(q.expr) { + if (incremental) { + for (auto &constraint : q.constraints.cs()) { + constraints.v.push_back(constraint); + constraints.push(); + } + } else { + const auto &other = q.constraints.cs(); + constraints.v.reserve(other.size()); + constraints.v.insert(constraints.v.end(), other.begin(), other.end()); + } + if (q.expr->getWidth() == Expr::Bool && !q.expr->isFalse()) + constraints.v.push_back(NotExpr::create(q.expr)); + } + + size_t size() const { return constraints.v.size(); } + + ref getOriginalQueryExpr() const { return expr; } + + ConstraintQuery withFalse() const { + return ConstraintQuery(ConstraintFrames(constraints), Expr::createFalse()); + } + + std::vector gatherArrays() const { + std::vector arrays; + findObjects(constraints.v.begin(), constraints.v.end(), arrays); + return arrays; + } +}; + +enum class ObjectAssignment { + NotNeeded, + NeededForObjectsFromEnv, + NeededForObjectsFromQuery +}; + +struct Z3SolverEnv { + using arr_vec = std::vector; + inc_vector objects; + arr_vec objectsForGetModel; + inc_vector z3_ast_expr_constraints; + ExprIncMap z3_ast_expr_to_klee_expr; + Z3ASTIncMap expr_to_track; + inc_umap usedArrayBytes; + ExprIncSet symbolicObjects; + + explicit Z3SolverEnv(){}; + explicit Z3SolverEnv(const arr_vec &objects); + + void pop(size_t popSize); + void push(); + void clear(); + + const arr_vec *getObjectsForGetModel(ObjectAssignment oa) const; +}; + +Z3SolverEnv::Z3SolverEnv(const std::vector &objects) + : objectsForGetModel(objects) {} + +void Z3SolverEnv::pop(size_t popSize) { + if (popSize == 0) + return; + objects.pop(popSize); + objectsForGetModel.clear(); + z3_ast_expr_constraints.pop(popSize); + z3_ast_expr_to_klee_expr.pop(popSize); + expr_to_track.pop(popSize); + usedArrayBytes.pop(popSize); + symbolicObjects.pop(popSize); +} + +void Z3SolverEnv::push() { + objects.push(); + z3_ast_expr_constraints.push(); + z3_ast_expr_to_klee_expr.push(); + expr_to_track.push(); + usedArrayBytes.push(); + symbolicObjects.push(); +} + +void Z3SolverEnv::clear() { + objects.clear(); + objectsForGetModel.clear(); + z3_ast_expr_constraints.clear(); + z3_ast_expr_to_klee_expr.clear(); + expr_to_track.clear(); + usedArrayBytes.clear(); + symbolicObjects.clear(); +} + +const Z3SolverEnv::arr_vec * +Z3SolverEnv::getObjectsForGetModel(ObjectAssignment oa) const { + switch (oa) { + case ObjectAssignment::NotNeeded: + return nullptr; + case ObjectAssignment::NeededForObjectsFromEnv: + return &objectsForGetModel; + case ObjectAssignment::NeededForObjectsFromQuery: + return &objects.v; + } +} + +class Z3SolverImpl : public SolverImpl { +protected: std::unique_ptr builder; + ::Z3_params solverParameters; + +private: Z3BuilderType builderType; time::Span timeout; - SolverRunStatus runStatusCode; + SolverImpl::SolverRunStatus runStatusCode; std::unique_ptr dumpedQueriesFile; - ::Z3_params solverParameters; // Parameter symbols ::Z3_symbol timeoutParamStrSymbol; ::Z3_symbol unsatCoreParamStrSymbol; - bool internalRunSolver(const Query &, - const std::vector *objects, + bool internalRunSolver(const ConstraintQuery &query, Z3SolverEnv &env, + ObjectAssignment needObjects, std::vector> *values, ValidityCore *validityCore, bool &hasSolution); + bool validateZ3Model(::Z3_solver &theSolver, ::Z3_model &theModel); -public: + SolverImpl::SolverRunStatus + handleSolverResponse(::Z3_solver theSolver, ::Z3_lbool satisfiable, + const Z3SolverEnv &env, ObjectAssignment needObjects, + std::vector> *values, + bool &hasSolution); + +protected: Z3SolverImpl(Z3BuilderType type); ~Z3SolverImpl(); - char *getConstraintLog(const Query &); - void setCoreSolverTimeout(time::Span _timeout) { + virtual Z3_solver initNativeZ3(const ConstraintQuery &query, + Z3ASTIncSet &assertions) = 0; + virtual void deinitNativeZ3(Z3_solver theSolver) = 0; + virtual void push(Z3_context c, Z3_solver s) = 0; + + bool computeTruth(const ConstraintQuery &, Z3SolverEnv &env, bool &isValid); + bool computeValue(const ConstraintQuery &, Z3SolverEnv &env, + ref &result); + bool computeInitialValues(const ConstraintQuery &, Z3SolverEnv &env, + std::vector> &values, + bool &hasSolution); + bool check(const ConstraintQuery &query, Z3SolverEnv &env, + ref &result); + bool computeValidityCore(const ConstraintQuery &query, Z3SolverEnv &env, + ValidityCore &validityCore, bool &isValid); + +public: + char *getConstraintLog(const Query &) final; + SolverImpl::SolverRunStatus getOperationStatusCode() final; + void setCoreSolverTimeout(time::Span _timeout) final { timeout = _timeout; auto timeoutInMilliSeconds = @@ -109,26 +278,20 @@ class Z3SolverImpl : public SolverImpl { Z3_FALSE); } - bool computeTruth(const Query &, bool &isValid); - bool computeValue(const Query &, ref &result); - bool computeInitialValues(const Query &, - const std::vector &objects, - std::vector> &values, - bool &hasSolution); - bool check(const Query &query, ref &result); - bool computeValidityCore(const Query &query, ValidityCore &validityCore, - bool &isValid); - SolverRunStatus handleSolverResponse( - ::Z3_solver theSolver, ::Z3_lbool satisfiable, - const std::vector *objects, - std::vector> *values, - const std::unordered_map &usedArrayBytes, - bool &hasSolution); - SolverRunStatus getOperationStatusCode(); + // pass virtual functions to children + using SolverImpl::check; + using SolverImpl::computeInitialValues; + using SolverImpl::computeTruth; + using SolverImpl::computeValidityCore; + using SolverImpl::computeValue; }; +void deleteNativeZ3(Z3_context ctx, Z3_solver theSolver) { + Z3_solver_dec_ref(ctx, theSolver); +} + Z3SolverImpl::Z3SolverImpl(Z3BuilderType type) - : builderType(type), runStatusCode(SOLVER_RUN_STATUS_FAILURE) { + : builderType(type), runStatusCode(SolverImpl::SOLVER_RUN_STATUS_FAILURE) { switch (type) { case KLEE_CORE: builder = std::unique_ptr(new Z3CoreBuilder( @@ -185,17 +348,6 @@ Z3SolverImpl::~Z3SolverImpl() { Z3_params_dec_ref(builder->ctx, solverParameters); } -Z3Solver::Z3Solver(Z3BuilderType type) - : Solver(std::make_unique(type)) {} - -char *Z3Solver::getConstraintLog(const Query &query) { - return impl->getConstraintLog(query); -} - -void Z3Solver::setCoreSolverTimeout(time::Span timeout) { - impl->setCoreSolverTimeout(timeout); -} - char *Z3SolverImpl::getConstraintLog(const Query &query) { std::vector assumptions; // We use a different builder here because we don't want to interfere @@ -272,76 +424,74 @@ char *Z3SolverImpl::getConstraintLog(const Query &query) { return strdup(result); } -bool Z3SolverImpl::computeTruth(const Query &query, bool &isValid) { +bool Z3SolverImpl::computeTruth(const ConstraintQuery &query, Z3SolverEnv &env, + bool &isValid) { bool hasSolution = false; // to remove compiler warning - bool status = internalRunSolver(query, /*objects=*/NULL, /*values=*/NULL, + bool status = internalRunSolver(query, /*env=*/env, + ObjectAssignment::NotNeeded, /*values=*/NULL, /*validityCore=*/NULL, hasSolution); isValid = !hasSolution; return status; } -bool Z3SolverImpl::computeValue(const Query &query, ref &result) { - std::vector objects; +bool Z3SolverImpl::computeValue(const ConstraintQuery &query, Z3SolverEnv &env, + ref &result) { std::vector> values; bool hasSolution; // Find the object used in the expression, and compute an assignment // for them. - findSymbolicObjects(query.expr, objects); - if (!computeInitialValues(query.withFalse(), objects, values, hasSolution)) + findSymbolicObjects(query.getOriginalQueryExpr(), env.objectsForGetModel); + if (!computeInitialValues(query.withFalse(), env, values, hasSolution)) return false; assert(hasSolution && "state has invalid constraint set"); // Evaluate the expression with the computed assignment. - Assignment a(objects, values); - result = a.evaluate(query.expr); + Assignment a(env.objectsForGetModel, values); + result = a.evaluate(query.getOriginalQueryExpr()); return true; } bool Z3SolverImpl::computeInitialValues( - const Query &query, const std::vector &objects, + const ConstraintQuery &query, Z3SolverEnv &env, std::vector> &values, bool &hasSolution) { - return internalRunSolver(query, &objects, &values, /*validityCore=*/NULL, - hasSolution); + return internalRunSolver(query, env, + ObjectAssignment::NeededForObjectsFromEnv, &values, + /*validityCore=*/NULL, hasSolution); } -bool Z3SolverImpl::check(const Query &query, ref &result) { - ExprHashSet expressions; - expressions.insert(query.constraints.cs().begin(), - query.constraints.cs().end()); - expressions.insert(query.expr); - - std::vector objects; - findSymbolicObjects(expressions.begin(), expressions.end(), objects); +bool Z3SolverImpl::check(const ConstraintQuery &query, Z3SolverEnv &env, + ref &result) { std::vector> values; - ValidityCore validityCore; - bool hasSolution = false; - bool status = - internalRunSolver(query, &objects, &values, &validityCore, hasSolution); + internalRunSolver(query, env, ObjectAssignment::NeededForObjectsFromQuery, + &values, &validityCore, hasSolution); if (status) { result = hasSolution - ? (SolverResponse *)new InvalidResponse(objects, values) + ? (SolverResponse *)new InvalidResponse(env.objects.v, values) : (SolverResponse *)new ValidResponse(validityCore); } return status; } -bool Z3SolverImpl::computeValidityCore(const Query &query, +bool Z3SolverImpl::computeValidityCore(const ConstraintQuery &query, + Z3SolverEnv &env, ValidityCore &validityCore, bool &isValid) { bool hasSolution = false; // to remove compiler warning - bool status = internalRunSolver(query, /*objects=*/NULL, /*values=*/NULL, - &validityCore, hasSolution); + bool status = + internalRunSolver(query, /*env=*/env, ObjectAssignment::NotNeeded, + /*values=*/NULL, &validityCore, hasSolution); isValid = !hasSolution; return status; } bool Z3SolverImpl::internalRunSolver( - const Query &query, const std::vector *objects, + const ConstraintQuery &query, Z3SolverEnv &env, + ObjectAssignment needObjects, std::vector> *values, ValidityCore *validityCore, bool &hasSolution) { @@ -359,107 +509,86 @@ bool Z3SolverImpl::internalRunSolver( // TODO: Investigate using a custom tactic as described in // https://github.com/klee/klee/issues/653 - Z3_goal goal = Z3_mk_goal(builder->ctx, false, false, false); - Z3_goal_inc_ref(builder->ctx, goal); - - // TODO: make a RAII - Z3_probe probe = Z3_mk_probe(builder->ctx, "is-qfaufbv"); - Z3_probe_inc_ref(builder->ctx, probe); + runStatusCode = SolverImpl::SOLVER_RUN_STATUS_FAILURE; + + std::unordered_set all_constant_arrays_in_query; + Z3ASTIncSet exprs; + + for (size_t i = 0; i < query.constraints.framesSize(); + i++, env.push(), exprs.push()) { + ConstantArrayFinder constant_arrays_in_query; + env.symbolicObjects.insert(query.constraints.begin(i), + query.constraints.end(i)); + // FIXME: findSymbolicObjects template does not support inc_uset::iterator + // findSymbolicObjects(env.symbolicObjects.begin(-1), + // env.symbolicObjects.end(-1), env.objects.v); + std::vector> tmp(env.symbolicObjects.begin(-1), + env.symbolicObjects.end(-1)); + findSymbolicObjects(tmp.begin(), tmp.end(), env.objects.v); + for (auto cs_it = query.constraints.begin(i), + cs_ite = query.constraints.end(i); + cs_it != cs_ite; cs_it++) { + const auto &constraint = *cs_it; + Z3ASTHandle z3Constraint = builder->construct(constraint); + if (ProduceUnsatCore && validityCore) { + Z3ASTHandle p = builder->buildFreshBoolConst(); + env.z3_ast_expr_to_klee_expr.insert({p, constraint}); + env.z3_ast_expr_constraints.v.push_back(p); + env.expr_to_track[z3Constraint] = p; + } - runStatusCode = SOLVER_RUN_STATUS_FAILURE; + exprs.insert(z3Constraint); - ConstantArrayFinder constant_arrays_in_query; - std::vector z3_ast_expr_constraints; - std::unordered_map, Z3ASTHandleHash, Z3ASTHandleCmp> - z3_ast_expr_to_klee_expr; + constant_arrays_in_query.visit(constraint); - std::unordered_map - expr_to_track; - std::unordered_set exprs; - - for (auto const &constraint : query.constraints.cs()) { - Z3ASTHandle z3Constraint = builder->construct(constraint); - if (ProduceUnsatCore && validityCore) { - Z3ASTHandle p = builder->buildFreshBoolConst(); - z3_ast_expr_to_klee_expr.insert({p, constraint}); - z3_ast_expr_constraints.push_back(p); - expr_to_track[z3Constraint] = p; + std::vector> reads; + findReads(constraint, true, reads); + for (const auto &readExpr : reads) { + auto readFromArray = readExpr->updates.root; + assert(readFromArray); + env.usedArrayBytes[readFromArray].insert(readExpr->index); + } } - Z3_goal_assert(builder->ctx, goal, z3Constraint); - exprs.insert(z3Constraint); + for (auto constant_array : constant_arrays_in_query.results) { + assert(builder->constant_array_assertions.count(constant_array) == 1 && + "Constant array found in query, but not handled by Z3Builder"); + if (all_constant_arrays_in_query.count(constant_array)) + continue; + all_constant_arrays_in_query.insert(constant_array); + const auto &cas = builder->constant_array_assertions[constant_array]; + exprs.insert(cas.begin(), cas.end()); + } - constant_arrays_in_query.visit(constraint); + // Assert an generated side constraints we have to this last so that all + // other constraints have been traversed so we have all the side constraints + // needed. + exprs.insert(builder->sideConstraints.begin(), + builder->sideConstraints.end()); } + exprs.pop(1); // drop last empty frame + ++stats::solverQueries; - if (objects) + if (!env.objects.v.empty()) ++stats::queryCounterexamples; - Z3ASTHandle z3QueryExpr = - Z3ASTHandle(builder->construct(query.expr), builder->ctx); - constant_arrays_in_query.visit(query.expr); - - for (auto const &constant_array : constant_arrays_in_query.results) { - assert(builder->constant_array_assertions.count(constant_array) == 1 && - "Constant array found in query, but not handled by Z3Builder"); - for (auto const &arrayIndexValueExpr : - builder->constant_array_assertions[constant_array]) { - Z3_goal_assert(builder->ctx, goal, arrayIndexValueExpr); - exprs.insert(arrayIndexValueExpr); - } - } - - // KLEE Queries are validity queries i.e. - // ∀ X Constraints(X) → query(X) - // but Z3 works in terms of satisfiability so instead we ask the - // negation of the equivalent i.e. - // ∃ X Constraints(X) ∧ ¬ query(X) - Z3ASTHandle z3NotQueryExpr = - Z3ASTHandle(Z3_mk_not(builder->ctx, z3QueryExpr), builder->ctx); - Z3_goal_assert(builder->ctx, goal, z3NotQueryExpr); - - // Assert an generated side constraints we have to this last so that all other - // constraints have been traversed so we have all the side constraints needed. - for (std::vector::iterator it = builder->sideConstraints.begin(), - ie = builder->sideConstraints.end(); - it != ie; ++it) { - Z3ASTHandle sideConstraint = *it; - Z3_goal_assert(builder->ctx, goal, sideConstraint); - exprs.insert(sideConstraint); - } - - std::vector arrays = query.gatherArrays(); - bool forceTactic = true; - for (const Array *array : arrays) { - if (isa(array->source)) { - forceTactic = false; - break; - } - } - - Z3_solver theSolver; - if (forceTactic && Z3_probe_apply(builder->ctx, probe, goal)) { - theSolver = Z3_mk_solver_for_logic( - builder->ctx, Z3_mk_string_symbol(builder->ctx, "QF_AUFBV")); - } else { - theSolver = Z3_mk_solver(builder->ctx); - } - Z3_solver_inc_ref(builder->ctx, theSolver); - Z3_solver_set_params(builder->ctx, theSolver, solverParameters); - - for (std::unordered_set::iterator it = exprs.begin(), - ie = exprs.end(); - it != ie; ++it) { - Z3ASTHandle expr = *it; - if (expr_to_track.count(expr)) { - Z3_solver_assert_and_track(builder->ctx, theSolver, expr, - expr_to_track[expr]); - } else { - Z3_solver_assert(builder->ctx, theSolver, expr); + Z3_solver theSolver = initNativeZ3(query, exprs); + + for (size_t i = 0; i < exprs.framesSize(); i++) { + push(builder->ctx, theSolver); + for (auto it = exprs.begin(i), ie = exprs.end(i); it != ie; ++it) { + Z3ASTHandle expr = *it; + if (env.expr_to_track.count(expr)) { + Z3_solver_assert_and_track(builder->ctx, theSolver, expr, + env.expr_to_track[expr]); + } else { + Z3_solver_assert(builder->ctx, theSolver, expr); + } } } - Z3_solver_assert(builder->ctx, theSolver, z3NotQueryExpr); + assert(!Z3_solver_get_num_scopes(builder->ctx, theSolver) || + Z3_solver_get_num_scopes(builder->ctx, theSolver) + 1 == + env.objects.framesSize()); if (dumpedQueriesFile) { *dumpedQueriesFile << "; start Z3 query\n"; @@ -472,22 +601,9 @@ bool Z3SolverImpl::internalRunSolver( dumpedQueriesFile->flush(); } - constraints_ty allConstraints = query.constraints.cs(); - allConstraints.insert(query.expr); - std::unordered_map usedArrayBytes; - for (auto constraint : allConstraints) { - std::vector> reads; - findReads(constraint, true, reads); - for (auto readExpr : reads) { - const Array *readFromArray = readExpr->updates.root; - assert(readFromArray); - usedArrayBytes[readFromArray].insert(readExpr->index); - } - } - ::Z3_lbool satisfiable = Z3_solver_check(builder->ctx, theSolver); - runStatusCode = handleSolverResponse(theSolver, satisfiable, objects, values, - usedArrayBytes, hasSolution); + runStatusCode = handleSolverResponse(theSolver, satisfiable, env, needObjects, + values, hasSolution); if (ProduceUnsatCore && validityCore && satisfiable == Z3_L_FALSE) { constraints_ty unsatCore; Z3_ast_vector z3_unsat_core = @@ -504,15 +620,15 @@ bool Z3SolverImpl::internalRunSolver( z3_ast_expr_unsat_core.insert(constraint); } - for (auto &z3_constraint : z3_ast_expr_constraints) { + for (const auto &z3_constraint : env.z3_ast_expr_constraints.v) { if (z3_ast_expr_unsat_core.find(z3_constraint) != z3_ast_expr_unsat_core.end()) { - ref constraint = z3_ast_expr_to_klee_expr[z3_constraint]; + ref constraint = env.z3_ast_expr_to_klee_expr[z3_constraint]; unsatCore.insert(constraint); } } assert(validityCore && "validityCore cannot be nullptr"); - *validityCore = ValidityCore(unsatCore, query.expr); + *validityCore = ValidityCore(unsatCore, query.getOriginalQueryExpr()); Z3_ast_vector assertions = Z3_solver_get_assertions(builder->ctx, theSolver); @@ -527,9 +643,7 @@ bool Z3SolverImpl::internalRunSolver( Z3_ast_vector_dec_ref(builder->ctx, assertions); } - Z3_goal_dec_ref(builder->ctx, goal); - Z3_probe_dec_ref(builder->ctx, probe); - Z3_solver_dec_ref(builder->ctx, theSolver); + deinitNativeZ3(theSolver); // Clear the builder's cache to prevent memory usage exploding. // By using ``autoClearConstructCache=false`` and clearning now @@ -554,17 +668,16 @@ bool Z3SolverImpl::internalRunSolver( } SolverImpl::SolverRunStatus Z3SolverImpl::handleSolverResponse( - ::Z3_solver theSolver, ::Z3_lbool satisfiable, - const std::vector *objects, - std::vector> *values, - const std::unordered_map &usedArrayBytes, - bool &hasSolution) { + ::Z3_solver theSolver, ::Z3_lbool satisfiable, const Z3SolverEnv &env, + ObjectAssignment needObjects, + std::vector> *values, bool &hasSolution) { switch (satisfiable) { case Z3_L_TRUE: { hasSolution = true; + auto objects = env.getObjectsForGetModel(needObjects); if (!objects) { // No assignment is needed - assert(values == NULL); + assert(!values); return SolverImpl::SOLVER_RUN_STATUS_SUCCESS_SOLVABLE; } assert(values && "values cannot be nullptr"); @@ -572,10 +685,7 @@ SolverImpl::SolverRunStatus Z3SolverImpl::handleSolverResponse( assert(theModel && "Failed to retrieve model"); Z3_model_inc_ref(builder->ctx, theModel); values->reserve(objects->size()); - for (std::vector::const_iterator it = objects->begin(), - ie = objects->end(); - it != ie; ++it) { - const Array *array = *it; + for (auto array : *objects) { SparseStorage data; ::Z3_ast arraySizeExpr; @@ -592,9 +702,9 @@ SolverImpl::SolverRunStatus Z3SolverImpl::handleSolverResponse( assert(success && "Failed to get size"); data.resize(arraySize); - if (usedArrayBytes.count(array)) { + if (env.usedArrayBytes.count(array)) { std::unordered_set offsetValues; - for (ref offsetExpr : usedArrayBytes.at(array)) { + for (const ref &offsetExpr : env.usedArrayBytes.at(array)) { ::Z3_ast arrayElementOffsetExpr; Z3_model_eval(builder->ctx, theModel, builder->construct(offsetExpr), Z3_TRUE, &arrayElementOffsetExpr); @@ -730,5 +840,355 @@ bool Z3SolverImpl::validateZ3Model(::Z3_solver &theSolver, SolverImpl::SolverRunStatus Z3SolverImpl::getOperationStatusCode() { return runStatusCode; } + +class Z3NonIncSolverImpl final : public Z3SolverImpl { +private: +public: + Z3NonIncSolverImpl(Z3BuilderType type) : Z3SolverImpl(type) {} + + /// implementation of Z3SolverImpl interface + Z3_solver initNativeZ3(const ConstraintQuery &query, + Z3ASTIncSet &assertions) override { + Z3_solver theSolver = nullptr; + auto arrays = query.gatherArrays(); + bool forceTactic = true; + for (auto array : arrays) { + if (isa(array->source)) { + forceTactic = false; + break; + } + } + + auto ctx = builder->ctx; + if (forceTactic) { + Z3_probe probe = Z3_mk_probe(ctx, "is-qfaufbv"); + Z3_probe_inc_ref(ctx, probe); + Z3_goal goal = Z3_mk_goal(ctx, false, false, false); + Z3_goal_inc_ref(ctx, goal); + + for (auto constraint : assertions) + Z3_goal_assert(ctx, goal, constraint); + if (Z3_probe_apply(ctx, probe, goal)) + theSolver = + Z3_mk_solver_for_logic(ctx, Z3_mk_string_symbol(ctx, "QF_AUFBV")); + Z3_goal_dec_ref(ctx, goal); + Z3_probe_dec_ref(ctx, probe); + } + if (!theSolver) + theSolver = Z3_mk_solver(ctx); + Z3_solver_inc_ref(ctx, theSolver); + Z3_solver_set_params(ctx, theSolver, solverParameters); + return theSolver; + } + void deinitNativeZ3(Z3_solver theSolver) override { + deleteNativeZ3(builder->ctx, theSolver); + } + void push(Z3_context c, Z3_solver s) override {} + + /// implementation of the SolverImpl interface + bool computeTruth(const Query &query, bool &isValid) override { + Z3SolverEnv env; + return Z3SolverImpl::computeTruth(ConstraintQuery(query, false), env, + isValid); + } + bool computeValue(const Query &query, ref &result) override { + Z3SolverEnv env; + return Z3SolverImpl::computeValue(ConstraintQuery(query, false), env, + result); + } + bool computeInitialValues(const Query &query, + const std::vector &objects, + std::vector> &values, + bool &hasSolution) override { + Z3SolverEnv env(objects); + return Z3SolverImpl::computeInitialValues(ConstraintQuery(query, false), + env, values, hasSolution); + } + bool check(const Query &query, ref &result) override { + Z3SolverEnv env; + return Z3SolverImpl::check(ConstraintQuery(query, false), env, result); + } + bool computeValidityCore(const Query &query, ValidityCore &validityCore, + bool &isValid) override { + Z3SolverEnv env; + return Z3SolverImpl::computeValidityCore(ConstraintQuery(query, false), env, + validityCore, isValid); + } + void notifyStateTermination(std::uint32_t id) override {} +}; + +Z3Solver::Z3Solver(Z3BuilderType type) + : Solver(std::make_unique(type)) {} + +struct ConstraintDistance { + size_t toPopSize = 0; + ConstraintQuery toPush; + + explicit ConstraintDistance() {} + ConstraintDistance(const ConstraintQuery &q) : toPush(q) {} + explicit ConstraintDistance(size_t toPopSize, const ConstraintQuery &q) + : toPopSize(toPopSize), toPush(q) {} + + size_t getDistance() const { return toPopSize + toPush.size(); } + + bool isOnlyPush() const { return toPopSize == 0; } + + void dump() const { + llvm::errs() << "ConstraintDistance: pop: " << toPopSize << "; push:\n"; + klee::dump(toPush.constraints); + } +}; + +class Z3IncNativeSolver { +private: + Z3_solver nativeSolver = nullptr; + Z3_context ctx; + Z3_params solverParameters; + /// underlying solver frames + /// saved only for calculating distances from next queries + ConstraintFrames frames; + + void pop(size_t popSize); + void push(); + +public: + Z3SolverEnv env; + std::uint32_t stateID = 0; + bool isRecycled = false; + + Z3IncNativeSolver(Z3_context ctx, Z3_params solverParameters) + : ctx(ctx), solverParameters(solverParameters) {} + ~Z3IncNativeSolver(); + + void clear(); + + void distance(const ConstraintQuery &query, ConstraintDistance &delta) const; + + void popPush(ConstraintDistance &delta); + + Z3_solver getOrInit(); + + bool isConsistent() const { + auto num_scopes = + nativeSolver ? Z3_solver_get_num_scopes(ctx, nativeSolver) : 0; + bool consistentWithZ3 = num_scopes + 1 == frames.framesSize(); + assert(consistentWithZ3); + bool constistentItself = frames.framesSize() == env.objects.framesSize(); + assert(constistentItself); + return consistentWithZ3 && constistentItself; + } + + void dump() const { ::klee::dump(frames); } +}; + +void Z3IncNativeSolver::pop(size_t popSize) { + if (!nativeSolver || !popSize) + return; + Z3_solver_pop(ctx, nativeSolver, popSize); +} + +void Z3IncNativeSolver::popPush(ConstraintDistance &delta) { + env.pop(delta.toPopSize); + pop(delta.toPopSize); + frames.pop(delta.toPopSize); + frames.extend(delta.toPush.constraints); +} + +Z3_solver Z3IncNativeSolver::getOrInit() { + if (nativeSolver == nullptr) { + nativeSolver = Z3_mk_solver(ctx); + Z3_solver_inc_ref(ctx, nativeSolver); + Z3_solver_set_params(ctx, nativeSolver, solverParameters); + } + return nativeSolver; +} + +Z3IncNativeSolver::~Z3IncNativeSolver() { + if (nativeSolver != nullptr) + deleteNativeZ3(ctx, nativeSolver); +} + +void Z3IncNativeSolver::clear() { + if (!nativeSolver) + return; + env.clear(); + frames.clear(); + Z3_solver_reset(ctx, nativeSolver); + isRecycled = false; +} + +void Z3IncNativeSolver::distance(const ConstraintQuery &query, + ConstraintDistance &delta) const { + auto sit = frames.v.begin(); + auto site = frames.v.end(); + auto qit = query.constraints.v.begin(); + auto qite = query.constraints.v.end(); + auto it = frames.begin(); + auto ite = frames.end(); + size_t intersect = 0; + for (; it != ite && sit != site && qit != qite && *sit == *qit; it++) { + size_t frame_size = *it; + for (size_t i = 0; + i < frame_size && sit != site && qit != qite && *sit == *qit; + i++, sit++, qit++, intersect++) { + } + } + for (; sit != site && qit != qite && *sit == *qit; + sit++, qit++, intersect++) { + } + size_t toPop, extraTakeFromOther; + ConstraintFrames d; + if (sit == site) { // solver frames ended + toPop = 0; + extraTakeFromOther = 0; + } else { + frames.takeBefore(intersect, toPop, extraTakeFromOther); + } + query.constraints.takeAfter(intersect - extraTakeFromOther, d); + ConstraintQuery q(std::move(d), query.getOriginalQueryExpr()); + delta = ConstraintDistance(toPop, std::move(q)); +} + +class Z3TreeSolverImpl final : public Z3SolverImpl { +private: + using solvers_ty = std::vector>; + using solvers_it = solvers_ty::iterator; + + const size_t maxSolvers; + std::unique_ptr currentSolver = nullptr; + solvers_ty solvers; + + void findSuitableSolver(const ConstraintQuery &query, + ConstraintDistance &delta); + void setSolver(solvers_it &it, bool recycle = false); + ConstraintQuery prepare(const Query &q); + +public: + Z3TreeSolverImpl(Z3BuilderType type, size_t maxSolvers) + : Z3SolverImpl(type), maxSolvers(maxSolvers){}; + + /// implementation of Z3SolverImpl interface + Z3_solver initNativeZ3(const ConstraintQuery &query, + Z3ASTIncSet &assertions) override { + return currentSolver->getOrInit(); + } + void deinitNativeZ3(Z3_solver theSolver) override { + assert(currentSolver->isConsistent()); + solvers.push_back(std::move(currentSolver)); + } + void push(Z3_context c, Z3_solver s) override { Z3_solver_push(c, s); } + + /// implementation of the SolverImpl interface + bool computeTruth(const Query &query, bool &isValid) override; + bool computeValue(const Query &query, ref &result) override; + bool computeInitialValues(const Query &query, + const std::vector &objects, + std::vector> &values, + bool &hasSolution) override; + bool check(const Query &query, ref &result) override; + bool computeValidityCore(const Query &query, ValidityCore &validityCore, + bool &isValid) override; + + void notifyStateTermination(std::uint32_t id) override; +}; + +void Z3TreeSolverImpl::setSolver(solvers_it &it, bool recycle) { + assert(it != solvers.end()); + currentSolver = std::move(*it); + solvers.erase(it); + currentSolver->isRecycled = false; + if (recycle) + currentSolver->clear(); +} + +void Z3TreeSolverImpl::findSuitableSolver(const ConstraintQuery &query, + ConstraintDistance &delta) { + ConstraintDistance min_delta; + auto min_distance = std::numeric_limits::max(); + auto min_it = solvers.end(); + auto free_it = solvers.end(); + for (auto it = solvers.begin(), ite = min_it; it != ite; it++) { + if ((*it)->isRecycled) + free_it = it; + (*it)->distance(query, delta); + if (delta.isOnlyPush()) { + setSolver(it); + return; + } + auto distance = delta.getDistance(); + if (distance < min_distance) { + min_delta = delta; + min_distance = distance; + min_it = it; + } + } + if (solvers.size() < maxSolvers) { + delta = ConstraintDistance(query); + if (delta.getDistance() < min_distance) { + // it is cheaper to create new solver + if (free_it == solvers.end()) + currentSolver = + std::make_unique(builder->ctx, solverParameters); + else + setSolver(free_it, /*recycle=*/true); + return; + } + } + assert(min_it != solvers.end()); + delta = min_delta; + setSolver(min_it); +} + +ConstraintQuery Z3TreeSolverImpl::prepare(const Query &q) { + ConstraintDistance delta; + ConstraintQuery query(q, true); + findSuitableSolver(query, delta); + assert(currentSolver->isConsistent()); + currentSolver->stateID = q.id; + currentSolver->popPush(delta); + return delta.toPush; +} + +bool Z3TreeSolverImpl::computeTruth(const Query &query, bool &isValid) { + auto q = prepare(query); + return Z3SolverImpl::computeTruth(q, currentSolver->env, isValid); +} + +bool Z3TreeSolverImpl::computeValue(const Query &query, ref &result) { + auto q = prepare(query); + return Z3SolverImpl::computeValue(q, currentSolver->env, result); +} + +bool Z3TreeSolverImpl::computeInitialValues( + const Query &query, const std::vector &objects, + std::vector> &values, bool &hasSolution) { + auto q = prepare(query); + currentSolver->env.objectsForGetModel = objects; + return Z3SolverImpl::computeInitialValues(q, currentSolver->env, values, + hasSolution); +} + +bool Z3TreeSolverImpl::check(const Query &query, ref &result) { + auto q = prepare(query); + return Z3SolverImpl::check(q, currentSolver->env, result); +} + +bool Z3TreeSolverImpl::computeValidityCore(const Query &query, + ValidityCore &validityCore, + bool &isValid) { + auto q = prepare(query); + return Z3SolverImpl::computeValidityCore(q, currentSolver->env, validityCore, + isValid); +} + +void Z3TreeSolverImpl::notifyStateTermination(std::uint32_t id) { + for (auto &s : solvers) + if (s->stateID == id) + s->isRecycled = true; +} + +Z3TreeSolver::Z3TreeSolver(Z3BuilderType type, unsigned maxSolvers) + : Solver(std::make_unique(type, maxSolvers)) {} + } // namespace klee #endif // ENABLE_Z3 diff --git a/lib/Solver/Z3Solver.h b/lib/Solver/Z3Solver.h index 0189dec08f..6b4aca126b 100644 --- a/lib/Solver/Z3Solver.h +++ b/lib/Solver/Z3Solver.h @@ -23,16 +23,13 @@ class Z3Solver : public Solver { public: /// Z3Solver - Construct a new Z3Solver. Z3Solver(Z3BuilderType type); +}; - /// Get the query in SMT-LIBv2 format. - /// \return A C-style string. The caller is responsible for freeing this. - virtual char *getConstraintLog(const Query &); - - /// setCoreSolverTimeout - Set constraint solver timeout delay to the given - /// value; 0 - /// is off. - virtual void setCoreSolverTimeout(time::Span timeout); +class Z3TreeSolver : public Solver { +public: + Z3TreeSolver(Z3BuilderType type, unsigned maxSolvers); }; + } // namespace klee #endif /* KLEE_Z3SOLVER_H */ diff --git a/test/Solver/CallComputeValue.c b/test/Solver/CallComputeValue.c new file mode 100644 index 0000000000..3e0dbe408f --- /dev/null +++ b/test/Solver/CallComputeValue.c @@ -0,0 +1,21 @@ +// REQUIRES: z3 +// RUN: %clang %s -emit-llvm %O0opt -c -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --search=bfs --solver-backend=z3-tree --max-solvers-approx-tree-inc=4 --debug-crosscheck-core-solver=z3 --debug-z3-validate-models --debug-assignment-validating-solver --use-cex-cache=false %t1.bc 2>&1 | FileCheck %s + +#include "klee/klee.h" + +int main() { + int y; + klee_make_symbolic(&y, sizeof(y), "y"); + int *x; + klee_make_symbolic(&x, sizeof(x), "x"); + if (!x) + return 0; + if (*x == y) + return 1; + return 2; +} + +// CHECK: KLEE: done: completed paths = 17 +// CHECK: KLEE: done: partially completed paths = 0 diff --git a/test/Solver/CrosscheckZ3AndZ3TreeInc.c b/test/Solver/CrosscheckZ3AndZ3TreeInc.c new file mode 100644 index 0000000000..9c4c499a26 --- /dev/null +++ b/test/Solver/CrosscheckZ3AndZ3TreeInc.c @@ -0,0 +1,11 @@ +// REQUIRES: z3 +// RUN: %clang %s -emit-llvm %O0opt -c -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --search=bfs --solver-backend=z3-tree --max-solvers-approx-tree-inc=4 --debug-crosscheck-core-solver=z3 --debug-z3-validate-models --debug-assignment-validating-solver --use-cex-cache=false %t1.bc 2>&1 | FileCheck %s +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --search=dfs --solver-backend=z3-tree --max-solvers-approx-tree-inc=64 --debug-crosscheck-core-solver=z3 --debug-z3-validate-models --debug-assignment-validating-solver --use-cex-cache=false %t1.bc 2>&1 | FileCheck %s + +#include "ExerciseSolver.c.inc" + +// CHECK: KLEE: done: completed paths = 10 +// CHECK: KLEE: done: partially completed paths = 4 diff --git a/tools/kleaver/main.cpp b/tools/kleaver/main.cpp index a56ab4c7fb..5488055bd2 100644 --- a/tools/kleaver/main.cpp +++ b/tools/kleaver/main.cpp @@ -224,12 +224,9 @@ static bool EvaluateInputAST(const char *Filename, const llvm::MemoryBuffer *MB, assert("FIXME: Support counterexample query commands!"); if (QC->Values.empty() && QC->Objects.empty()) { bool result; - constraints_ty constraints; - for (auto i : QC->Constraints) { - constraints.insert(i); - } - if (S->mustBeTrue(Query(ConstraintSet(constraints, {}, {}), QC->Query), - result)) { + constraints_ty constraints(QC->Constraints.begin(), + QC->Constraints.end()); + if (S->mustBeTrue(Query(constraints, QC->Query), result)) { llvm::outs() << (result ? "VALID" : "INVALID"); } else { llvm::outs() << "FAIL (reason: " @@ -245,13 +242,9 @@ static bool EvaluateInputAST(const char *Filename, const llvm::MemoryBuffer *MB, assert(QC->Query->isFalse() && "FIXME: Support counterexamples with non-trivial query!"); ref result; - constraints_ty constraints; - for (auto i : QC->Constraints) { - constraints.insert(i); - } - if (S->getValue( - Query(ConstraintSet(constraints, {}, {}), QC->Values[0]), - result)) { + constraints_ty constraints(QC->Constraints.begin(), + QC->Constraints.end()); + if (S->getValue(Query(constraints, QC->Values[0]), result)) { llvm::outs() << "INVALID\n"; llvm::outs() << "\tExpr 0:\t" << result; } else { @@ -263,14 +256,11 @@ static bool EvaluateInputAST(const char *Filename, const llvm::MemoryBuffer *MB, } else { std::vector> result; - constraints_ty constraints; - for (auto i : QC->Constraints) { - constraints.insert(i); - } + constraints_ty constraints(QC->Constraints.begin(), + QC->Constraints.end()); - if (S->getInitialValues( - Query(ConstraintSet(constraints, {}, {}), QC->Query), - QC->Objects, result)) { + if (S->getInitialValues(Query(constraints, QC->Query), QC->Objects, + result)) { llvm::outs() << "INVALID\n"; Assignment solutionAssugnment(QC->Objects, result); for (unsigned i = 0, e = result.size(); i != e; ++i) { @@ -377,13 +367,9 @@ static bool printInputAsSMTLIBv2(const char *Filename, * constraint in the constraint set is set to NULL and * will later cause a NULL pointer dereference. */ - constraints_ty constraints; - for (auto i : QC->Constraints) { - constraints.insert(i); - } - - ConstraintSet constraintM(constraints, {}, {}); - Query query(constraintM, QC->Query); + constraints_ty constraints(QC->Constraints.begin(), + QC->Constraints.end()); + Query query(constraints, QC->Query); printer.setQuery(query); if (!QC->Objects.empty()) diff --git a/unittests/Solver/SolverTest.cpp b/unittests/Solver/SolverTest.cpp index 3206bd1a18..a208376c7d 100644 --- a/unittests/Solver/SolverTest.cpp +++ b/unittests/Solver/SolverTest.cpp @@ -82,9 +82,9 @@ void testOperation(Solver &solver, int value, Expr::Width operandWidth, ref queryExpr = EqExpr::create(fullySymbolicExpr, partiallyConstantExpr); - ConstraintSet constraints; - constraints.addConstraint( - Simplificator::simplifyExpr(ConstraintSet(), expr).simplified, {}); + constraints_ty constraints; + constraints.insert( + Simplificator::simplifyExpr(ConstraintSet(), expr).simplified); bool res; bool success = solver.mustBeTrue(Query(constraints, queryExpr), res); EXPECT_EQ(true, success) << "Constraint solving failed"; diff --git a/unittests/Solver/Z3SolverTest.cpp b/unittests/Solver/Z3SolverTest.cpp index 8c8d84e9be..d10a7b853c 100644 --- a/unittests/Solver/Z3SolverTest.cpp +++ b/unittests/Solver/Z3SolverTest.cpp @@ -37,7 +37,7 @@ class Z3SolverTest : public ::testing::Test { }; TEST_F(Z3SolverTest, GetConstraintLog) { - ConstraintSet Constraints; + constraints_ty Constraints; const std::vector ConstantValues{1, 2, 3, 4}; std::vector> ConstantExpressions; From 2428e2b40a865b6a72e96e6fb53a32a6d92ce17d Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Wed, 13 Sep 2023 01:11:21 +0400 Subject: [PATCH 008/103] [feat] Improve `TargetCalculator` --- include/klee/Module/CodeGraphDistance.h | 9 ++ include/klee/Module/KModule.h | 7 ++ lib/Core/ExecutionState.cpp | 4 +- lib/Core/ExecutionState.h | 2 +- lib/Core/TargetCalculator.cpp | 152 +++++++++++++++++------- lib/Core/TargetCalculator.h | 11 +- lib/Core/TargetManager.cpp | 8 +- lib/Module/CodeGraphDistance.cpp | 19 +++ 8 files changed, 161 insertions(+), 51 deletions(-) diff --git a/include/klee/Module/CodeGraphDistance.h b/include/klee/Module/CodeGraphDistance.h index 3192344ec4..3d8175a1e7 100644 --- a/include/klee/Module/CodeGraphDistance.h +++ b/include/klee/Module/CodeGraphDistance.h @@ -30,6 +30,9 @@ class CodeGraphDistance { std::unordered_map>>; + using functionBranchesSet = + std::unordered_map>>; + private: blockDistanceMap blockDistance; blockDistanceMap blockBackwardDistance; @@ -41,6 +44,8 @@ class CodeGraphDistance { functionDistanceList functionSortedDistance; functionDistanceList functionSortedBackwardDistance; + functionBranchesSet functionBranches; + private: void calculateDistance(KBlock *bb); void calculateBackwardDistance(KBlock *bb); @@ -48,6 +53,8 @@ class CodeGraphDistance { void calculateDistance(KFunction *kf); void calculateBackwardDistance(KFunction *kf); + void calculateFunctionBranches(KFunction *kf); + public: const std::unordered_map &getDistance(KBlock *kb); const std::unordered_map & @@ -68,6 +75,8 @@ class CodeGraphDistance { void getNearestPredicateSatisfying(KBlock *from, KBlockPredicate predicate, std::set &result); + + const std::map> &getFunctionBranches(KFunction *kf); }; } // namespace klee diff --git a/include/klee/Module/KModule.h b/include/klee/Module/KModule.h index bfd30c019b..e601d91e43 100644 --- a/include/klee/Module/KModule.h +++ b/include/klee/Module/KModule.h @@ -189,6 +189,13 @@ struct KFunction : public KCallable { } }; +struct KBlockCompare { + bool operator()(const KBlock *a, const KBlock *b) const { + return a->parent->id < b->parent->id || + (a->parent->id == b->parent->id && a->id < b->id); + } +}; + class KConstant { public: /// Actual LLVM constant this represents. diff --git a/lib/Core/ExecutionState.cpp b/lib/Core/ExecutionState.cpp index a623d7c289..5ce9492467 100644 --- a/lib/Core/ExecutionState.cpp +++ b/lib/Core/ExecutionState.cpp @@ -473,7 +473,7 @@ void ExecutionState::increaseLevel() { if (prevPC->inst->isTerminator() && kmodule->inMainModule(*kf->function)) { auto srcLevel = stack.infoStack().back().multilevel[srcbb].second; stack.infoStack().back().multilevel.replace({srcbb, srcLevel + 1}); - level.insert(srcbb); + level.insert(prevPC->parent); } if (srcbb != dstbb) { transitionLevel.insert(std::make_pair(srcbb, dstbb)); @@ -485,7 +485,7 @@ bool ExecutionState::isGEPExpr(ref expr) const { } bool ExecutionState::visited(KBlock *block) const { - return level.count(block->basicBlock) != 0; + return level.count(block) != 0; } bool ExecutionState::reachedTarget(ref target) const { diff --git a/lib/Core/ExecutionState.h b/lib/Core/ExecutionState.h index c071448c92..575d81f1e8 100644 --- a/lib/Core/ExecutionState.h +++ b/lib/Core/ExecutionState.h @@ -290,7 +290,7 @@ class ExecutionState { std::uint32_t depth = 0; /// @brief Exploration level, i.e., number of times KLEE cycled for this state - std::unordered_set level; + std::set level; std::unordered_set transitionLevel; /// @brief Address space used by this state (e.g. Global and Heap) diff --git a/lib/Core/TargetCalculator.cpp b/lib/Core/TargetCalculator.cpp index c2340e4af2..7116117077 100644 --- a/lib/Core/TargetCalculator.cpp +++ b/lib/Core/TargetCalculator.cpp @@ -39,28 +39,66 @@ llvm::cl::opt TargetCalculatorMode( void TargetCalculator::update(const ExecutionState &state) { Function *initialFunction = state.getInitPCBlock()->getParent(); - switch (TargetCalculatorMode) { - case TargetCalculateBy::Default: - blocksHistory[initialFunction][state.getPrevPCBlock()].insert( - state.getInitPCBlock()); - if (state.prevPC == state.prevPC->parent->getLastInstruction()) { - coveredBlocks[state.getPrevPCBlock()->getParent()].insert( - state.getPrevPCBlock()); + + if (state.prevPC == state.prevPC->parent->getLastInstruction()) { + coveredBlocks[state.getPrevPCBlock()->getParent()].insert( + state.prevPC->parent); + } + if (state.prevPC == state.prevPC->parent->getLastInstruction()) { + unsigned index = 0; + coveredBranches[state.prevPC->parent->parent][state.prevPC->parent]; + for (auto succ : successors(state.getPrevPCBlock())) { + if (succ == state.getPCBlock()) { + coveredBranches[state.prevPC->parent->parent][state.prevPC->parent] + .insert(index); + break; + } + ++index; } - if (state.prevPC == state.prevPC->parent->getLastInstruction()) { - unsigned index = 0; - coveredBranches[state.getPrevPCBlock()->getParent()] - [state.getPrevPCBlock()]; - for (auto succ : successors(state.getPrevPCBlock())) { - if (succ == state.getPCBlock()) { - coveredBranches[state.getPrevPCBlock()->getParent()] - [state.getPrevPCBlock()] - .insert(index); - break; + if (!coveredFunctionsInBranches.count(state.prevPC->parent->parent) && + codeGraphDistance.getFunctionBranches(state.prevPC->parent->parent) == + coveredBranches[state.prevPC->parent->parent]) { + coveredFunctionsInBranches.insert(state.prevPC->parent->parent); + } + if (!fullyCoveredFunctions.count(state.prevPC->parent->parent) && + coveredFunctionsInBranches.count(state.prevPC->parent->parent)) { + bool covered = true; + std::set fnsTaken; + std::deque fns; + fns.push_back(state.prevPC->parent->parent); + + while (!fns.empty() && covered) { + KFunction *currKF = fns.front(); + fnsTaken.insert(currKF); + for (auto &kcallBlock : currKF->kCallBlocks) { + if (kcallBlock->calledFunctions.size() == 1) { + auto calledFunction = *kcallBlock->calledFunctions.begin(); + KFunction *calledKFunction = state.prevPC->parent->parent->parent + ->functionMap[calledFunction]; + if (calledKFunction->numInstructions != 0 && + coveredFunctionsInBranches.count(calledKFunction) == 0) { + covered = false; + break; + } + if (!fnsTaken.count(calledKFunction) && + fullyCoveredFunctions.count(calledKFunction) == 0) { + fns.push_back(calledKFunction); + } + } } - ++index; + fns.pop_front(); + } + + if (covered) { + fullyCoveredFunctions.insert(state.prevPC->parent->parent); } } + } + + switch (TargetCalculatorMode) { + case TargetCalculateBy::Default: + blocksHistory[initialFunction][state.getPrevPCBlock()].insert( + state.initPC->parent); break; case TargetCalculateBy::Blocks: @@ -81,10 +119,10 @@ bool TargetCalculator::differenceIsEmpty( const ExecutionState &state, const std::unordered_map &history, KBlock *target) { - std::vector diff; - std::set left(state.level.begin(), state.level.end()); - std::set right(history.at(target->basicBlock).begin(), - history.at(target->basicBlock).end()); + std::vector diff; + std::set left(state.level.begin(), state.level.end()); + std::set right(history.at(target->basicBlock).begin(), + history.at(target->basicBlock).end()); std::set_difference(left.begin(), left.end(), right.begin(), right.end(), std::inserter(diff, diff.begin())); return diff.empty(); @@ -112,27 +150,35 @@ bool TargetCalculator::uncoveredBlockPredicate(ExecutionState *state, std::unordered_map &transitionHistory = transitionsHistory[initialFunction]; bool result = false; + if (coveredBranches[kblock->parent].count(kblock) == 0) { + result = true; + } else { + auto &cb = coveredBranches[kblock->parent][kblock]; + if (isa(kblock) && + cast(kblock)->calledFunctions.size() == 1) { + auto calledFunction = *cast(kblock)->calledFunctions.begin(); + KFunction *calledKFunction = + kblock->parent->parent->functionMap[calledFunction]; + result = fullyCoveredFunctions.count(calledKFunction) == 0 && + calledKFunction->numInstructions; + } + result |= + kblock->basicBlock->getTerminator()->getNumSuccessors() > cb.size(); + } + switch (TargetCalculatorMode) { case TargetCalculateBy::Default: { - if (coveredBranches[kblock->parent->function].count(kblock->basicBlock) == - 0) { - result = true; - } else { - auto &cb = coveredBranches[kblock->parent->function][kblock->basicBlock]; - result = - kblock->basicBlock->getTerminator()->getNumSuccessors() > cb.size(); - } break; } case TargetCalculateBy::Blocks: { if (history[kblock->basicBlock].size() != 0) { - result = !differenceIsEmpty(*state, history, kblock); + result |= !differenceIsEmpty(*state, history, kblock); } break; } case TargetCalculateBy::Transitions: { if (history[kblock->basicBlock].size() != 0) { - result = !differenceIsEmpty(*state, transitionHistory, kblock); + result |= !differenceIsEmpty(*state, transitionHistory, kblock); } break; } @@ -146,6 +192,10 @@ TargetHashSet TargetCalculator::calculate(ExecutionState &state) { const KModule &module = *state.pc->parent->parent->parent; KFunction *kf = module.functionMap.at(bb->getParent()); KBlock *kb = kf->blockMap[bb]; + kb = !isa(kb) || (kb->getLastInstruction() != state.pc) + ? kb + : kf->blockMap[state.pc->parent->basicBlock->getTerminator() + ->getSuccessor(0)]; for (auto sfi = state.stack.callStack().rbegin(), sfe = state.stack.callStack().rend(); sfi != sfe; sfi++) { @@ -160,17 +210,30 @@ TargetHashSet TargetCalculator::calculate(ExecutionState &state) { if (!blocks.empty()) { TargetHashSet targets; for (auto block : blocks) { - if (coveredBranches[block->parent->function].count(block->basicBlock) == - 0) { - targets.insert(ReachBlockTarget::create(block, true)); + if (coveredBranches[block->parent].count(block) == 0) { + targets.insert(ReachBlockTarget::create(block, false)); } else { - auto &cb = - coveredBranches[block->parent->function][block->basicBlock]; - for (unsigned index = 0; - index < block->basicBlock->getTerminator()->getNumSuccessors(); - ++index) { - if (!cb.count(index)) - targets.insert(CoverBranchTarget::create(block, index)); + auto &cb = coveredBranches[block->parent][block]; + bool notCoveredFunction = false; + if (isa(block) && + cast(block)->calledFunctions.size() == 1) { + auto calledFunction = + *cast(block)->calledFunctions.begin(); + KFunction *calledKFunction = + block->parent->parent->functionMap[calledFunction]; + notCoveredFunction = + fullyCoveredFunctions.count(calledKFunction) == 0 && + calledKFunction->numInstructions; + } + if (notCoveredFunction) { + targets.insert(ReachBlockTarget::create(block, true)); + } else { + for (unsigned index = 0; + index < block->basicBlock->getTerminator()->getNumSuccessors(); + ++index) { + if (!cb.count(index)) + targets.insert(CoverBranchTarget::create(block, index)); + } } } } @@ -179,6 +242,11 @@ TargetHashSet TargetCalculator::calculate(ExecutionState &state) { if (sfi->caller) { kb = sfi->caller->parent; + + kb = !isa(kb) || (kb->getLastInstruction() != sfi->caller) + ? kb + : kf->blockMap[sfi->caller->parent->basicBlock->getTerminator() + ->getSuccessor(0)]; } } diff --git a/lib/Core/TargetCalculator.h b/lib/Core/TargetCalculator.h index 7369519afd..d3a3937ed5 100644 --- a/lib/Core/TargetCalculator.h +++ b/lib/Core/TargetCalculator.h @@ -42,7 +42,7 @@ typedef std::pair Transition; typedef std::pair Branch; class TargetCalculator { - typedef std::unordered_set VisitedBlocks; + typedef std::unordered_set VisitedBlocks; typedef std::unordered_set VisitedTransitions; typedef std::unordered_set VisitedBranches; @@ -56,11 +56,12 @@ class TargetCalculator { std::unordered_map> TransitionsHistory; - typedef std::unordered_map< - llvm::Function *, - std::unordered_map>> + typedef std::unordered_map>> CoveredBranches; + typedef std::unordered_set CoveredFunctionsBranches; + typedef std::unordered_map CoveredBlocks; public: @@ -76,6 +77,8 @@ class TargetCalculator { BlocksHistory blocksHistory; TransitionsHistory transitionsHistory; CoveredBranches coveredBranches; + CoveredFunctionsBranches coveredFunctionsInBranches; + CoveredFunctionsBranches fullyCoveredFunctions; CoveredBlocks coveredBlocks; bool differenceIsEmpty( diff --git a/lib/Core/TargetManager.cpp b/lib/Core/TargetManager.cpp index 58579130fb..a25ff130e0 100644 --- a/lib/Core/TargetManager.cpp +++ b/lib/Core/TargetManager.cpp @@ -41,7 +41,11 @@ void TargetManager::updateDone(ExecutionState &state, ref target) { setHistory(state, stateTargetForest.getHistory()); if (guidance == Interpreter::GuidanceKind::CoverageGuidance || target->shouldFailOnThisTarget()) { - reachedTargets.insert(target); + if (target->shouldFailOnThisTarget() || + !isa(target->getBlock())) { + reachedTargets.insert(target); + } + for (auto es : states) { if (isTargeted(*es)) { auto &esTargetForest = targetForest(*es); @@ -112,7 +116,7 @@ void TargetManager::updateReached(ExecutionState &state) { if (state.getPrevPCBlock()->getTerminator()->getNumSuccessors() == 0) { target = ReachBlockTarget::create(state.prevPC->parent, true); - } else { + } else if (!isa(state.prevPC->parent)) { unsigned index = 0; for (auto succ : successors(state.getPrevPCBlock())) { if (succ == state.getPCBlock()) { diff --git a/lib/Module/CodeGraphDistance.cpp b/lib/Module/CodeGraphDistance.cpp index 54839c6cd3..988cb4db27 100644 --- a/lib/Module/CodeGraphDistance.cpp +++ b/lib/Module/CodeGraphDistance.cpp @@ -120,6 +120,18 @@ void CodeGraphDistance::calculateBackwardDistance(KFunction *kf) { } } +void CodeGraphDistance::calculateFunctionBranches(KFunction *kf) { + std::map> &fbranches = functionBranches[kf]; + for (auto &kb : kf->blocks) { + fbranches[kb.get()]; + for (unsigned branch = 0; + branch < kb->basicBlock->getTerminator()->getNumSuccessors(); + ++branch) { + fbranches[kb.get()].insert(branch); + } + } +} + const std::unordered_map & CodeGraphDistance::getDistance(KBlock *kb) { if (blockDistance.count(kb) == 0) @@ -200,3 +212,10 @@ void CodeGraphDistance::getNearestPredicateSatisfying( nodes.pop_front(); } } + +const std::map> & +CodeGraphDistance::getFunctionBranches(KFunction *kf) { + if (functionBranches.count(kf) == 0) + calculateFunctionBranches(kf); + return functionBranches.at(kf); +} From 2d8e12b5f07bb98a867eb40a343e39d088c50b17 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Thu, 14 Sep 2023 17:29:51 +0400 Subject: [PATCH 009/103] [refactor] `CodeGraphDistance` -> `CodeGraphInfo` --- .../{CodeGraphDistance.h => CodeGraphInfo.h} | 7 ++-- lib/Core/DistanceCalculator.cpp | 12 +++--- lib/Core/DistanceCalculator.h | 8 ++-- lib/Core/Executor.cpp | 10 ++--- lib/Core/Executor.h | 4 +- lib/Core/TargetCalculator.cpp | 36 ++++++++++-------- lib/Core/TargetCalculator.h | 8 ++-- lib/Core/TargetedExecutionManager.cpp | 12 +++--- lib/Core/TargetedExecutionManager.h | 8 ++-- lib/Module/CMakeLists.txt | 2 +- ...odeGraphDistance.cpp => CodeGraphInfo.cpp} | 38 +++++++++---------- lib/Module/Target.cpp | 2 +- 12 files changed, 76 insertions(+), 71 deletions(-) rename include/klee/Module/{CodeGraphDistance.h => CodeGraphInfo.h} (93%) rename lib/Module/{CodeGraphDistance.cpp => CodeGraphInfo.cpp} (84%) diff --git a/include/klee/Module/CodeGraphDistance.h b/include/klee/Module/CodeGraphInfo.h similarity index 93% rename from include/klee/Module/CodeGraphDistance.h rename to include/klee/Module/CodeGraphInfo.h index 3d8175a1e7..c13a7a0337 100644 --- a/include/klee/Module/CodeGraphDistance.h +++ b/include/klee/Module/CodeGraphInfo.h @@ -1,4 +1,4 @@ -//===-- CodeGraphDistance.h -------------------------------------*- C++ -*-===// +//===-- CodeGraphInfo.h -----------------------------------------*- C++ -*-===// // // The KLEE Symbolic Virtual Machine // @@ -16,7 +16,7 @@ namespace klee { -class CodeGraphDistance { +class CodeGraphInfo { using blockDistanceMap = std::unordered_map>; @@ -76,7 +76,8 @@ class CodeGraphDistance { void getNearestPredicateSatisfying(KBlock *from, KBlockPredicate predicate, std::set &result); - const std::map> &getFunctionBranches(KFunction *kf); + const std::map> & + getFunctionBranches(KFunction *kf); }; } // namespace klee diff --git a/lib/Core/DistanceCalculator.cpp b/lib/Core/DistanceCalculator.cpp index 15cf13be42..ebfdb7eec6 100644 --- a/lib/Core/DistanceCalculator.cpp +++ b/lib/Core/DistanceCalculator.cpp @@ -9,7 +9,7 @@ #include "DistanceCalculator.h" #include "ExecutionState.h" -#include "klee/Module/CodeGraphDistance.h" +#include "klee/Module/CodeGraphInfo.h" #include "klee/Module/KInstruction.h" #include "klee/Module/Target.h" @@ -67,7 +67,7 @@ DistanceResult DistanceCalculator::getDistance(KBlock *kb, TargetKind kind, DistanceResult DistanceCalculator::computeDistance(KBlock *kb, TargetKind kind, KBlock *target) const { const auto &distanceToTargetFunction = - codeGraphDistance.getBackwardDistance(target->parent); + codeGraphInfo.getBackwardDistance(target->parent); weight_type weight = 0; WeightResult res = Miss; bool isInsideFunction = true; @@ -99,7 +99,7 @@ DistanceResult DistanceCalculator::getDistance( KBlock *kb = pc->parent; const auto &distanceToTargetFunction = - codeGraphDistance.getBackwardDistance(target->parent); + codeGraphInfo.getBackwardDistance(target->parent); unsigned int minCallWeight = UINT_MAX, minSfNum = UINT_MAX, sfNum = 0; auto sfi = frames.rbegin(), sfe = frames.rend(); bool strictlyAfterKB = @@ -145,7 +145,7 @@ bool DistanceCalculator::distanceInCallGraph( KBlock *target, bool strictlyAfterKB) const { distance = UINT_MAX; const std::unordered_map &dist = - codeGraphDistance.getDistance(origKB); + codeGraphInfo.getDistance(origKB); KBlock *targetBB = target; KFunction *targetF = targetBB->parent; @@ -176,7 +176,7 @@ bool DistanceCalculator::distanceInCallGraph( KBlock *target) const { distance = UINT_MAX; const std::unordered_map &dist = - codeGraphDistance.getDistance(kb); + codeGraphInfo.getDistance(kb); for (auto &kCallBlock : kf->kCallBlocks) { if (dist.count(kCallBlock) == 0) @@ -199,7 +199,7 @@ DistanceCalculator::tryGetLocalWeight(KBlock *kb, weight_type &weight, KFunction *currentKF = kb->parent; KBlock *currentKB = kb; const std::unordered_map &dist = - codeGraphDistance.getDistance(currentKB); + codeGraphInfo.getDistance(currentKB); weight = UINT_MAX; for (auto &end : localTargets) { if (dist.count(end) > 0) { diff --git a/lib/Core/DistanceCalculator.h b/lib/Core/DistanceCalculator.h index f0fdd15655..77da2254f1 100644 --- a/lib/Core/DistanceCalculator.h +++ b/lib/Core/DistanceCalculator.h @@ -17,7 +17,7 @@ class BasicBlock; } // namespace llvm namespace klee { -class CodeGraphDistance; +class CodeGraphInfo; class Target; enum WeightResult : std::uint8_t { @@ -45,8 +45,8 @@ struct DistanceResult { class DistanceCalculator { public: - explicit DistanceCalculator(CodeGraphDistance &codeGraphDistance_) - : codeGraphDistance(codeGraphDistance_) {} + explicit DistanceCalculator(CodeGraphInfo &codeGraphInfo_) + : codeGraphInfo(codeGraphInfo_) {} DistanceResult getDistance(const ExecutionState &es, KBlock *target); @@ -97,7 +97,7 @@ class DistanceCalculator { using StatesSet = std::unordered_set; - CodeGraphDistance &codeGraphDistance; + CodeGraphInfo &codeGraphInfo; TargetToSpeculativeStateToDistanceResultMap distanceResultCache; StatesSet localStates; diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index 4f9aa76701..3f9d40b984 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -50,7 +50,7 @@ #include "klee/Expr/IndependentSet.h" #include "klee/Expr/Symcrete.h" #include "klee/Module/Cell.h" -#include "klee/Module/CodeGraphDistance.h" +#include "klee/Module/CodeGraphInfo.h" #include "klee/Module/InstructionInfoTable.h" #include "klee/Module/KCallable.h" #include "klee/Module/KInstruction.h" @@ -455,13 +455,13 @@ Executor::Executor(LLVMContext &ctx, const InterpreterOptions &opts, externalDispatcher(new ExternalDispatcher(ctx)), statsTracker(0), pathWriter(0), symPathWriter(0), specialFunctionHandler(0), timers{time::Span(TimerInterval)}, - guidanceKind(opts.Guidance), codeGraphDistance(new CodeGraphDistance()), - distanceCalculator(new DistanceCalculator(*codeGraphDistance)), - targetCalculator(new TargetCalculator(*codeGraphDistance)), + guidanceKind(opts.Guidance), codeGraphInfo(new CodeGraphInfo()), + distanceCalculator(new DistanceCalculator(*codeGraphInfo)), + targetCalculator(new TargetCalculator(*codeGraphInfo)), targetManager(new TargetManager(guidanceKind, *distanceCalculator, *targetCalculator)), targetedExecutionManager( - new TargetedExecutionManager(*codeGraphDistance, *targetManager)), + new TargetedExecutionManager(*codeGraphInfo, *targetManager)), replayKTest(0), replayPath(0), usingSeeds(0), atMemoryLimit(false), inhibitForking(false), haltExecution(HaltExecution::NotHalt), ivcEnabled(false), debugLogBuffer(debugBufferString) { diff --git a/lib/Core/Executor.h b/lib/Core/Executor.h index d66ff5986f..9a89fdcf04 100644 --- a/lib/Core/Executor.h +++ b/lib/Core/Executor.h @@ -72,7 +72,7 @@ namespace klee { class AddressManager; class Array; struct Cell; -class CodeGraphDistance; +class CodeGraphInfo; class DistanceCalculator; class ExecutionState; class ExternalDispatcher; @@ -146,7 +146,7 @@ class Executor : public Interpreter { TimerGroup timers; std::unique_ptr processForest; GuidanceKind guidanceKind; - std::unique_ptr codeGraphDistance; + std::unique_ptr codeGraphInfo; std::unique_ptr distanceCalculator; std::unique_ptr targetCalculator; std::unique_ptr targetManager; diff --git a/lib/Core/TargetCalculator.cpp b/lib/Core/TargetCalculator.cpp index 7116117077..6b6a2f7d3e 100644 --- a/lib/Core/TargetCalculator.cpp +++ b/lib/Core/TargetCalculator.cpp @@ -11,7 +11,7 @@ #include "ExecutionState.h" -#include "klee/Module/CodeGraphDistance.h" +#include "klee/Module/CodeGraphInfo.h" #include "klee/Module/KInstruction.h" #include "klee/Module/Target.h" #include "klee/Module/TargetHash.h" @@ -44,21 +44,24 @@ void TargetCalculator::update(const ExecutionState &state) { coveredBlocks[state.getPrevPCBlock()->getParent()].insert( state.prevPC->parent); } - if (state.prevPC == state.prevPC->parent->getLastInstruction()) { - unsigned index = 0; - coveredBranches[state.prevPC->parent->parent][state.prevPC->parent]; - for (auto succ : successors(state.getPrevPCBlock())) { - if (succ == state.getPCBlock()) { - coveredBranches[state.prevPC->parent->parent][state.prevPC->parent] - .insert(index); - break; + if (state.prevPC == state.prevPC->parent->getLastInstruction() && + !fullyCoveredFunctions.count(state.prevPC->parent->parent)) { + + if (!coveredFunctionsInBranches.count(state.prevPC->parent->parent)) { + unsigned index = 0; + coveredBranches[state.prevPC->parent->parent][state.prevPC->parent]; + for (auto succ : successors(state.getPrevPCBlock())) { + if (succ == state.getPCBlock()) { + coveredBranches[state.prevPC->parent->parent][state.prevPC->parent] + .insert(index); + break; + } + ++index; + } + if (codeGraphInfo.getFunctionBranches(state.prevPC->parent->parent) == + coveredBranches[state.prevPC->parent->parent]) { + coveredFunctionsInBranches.insert(state.prevPC->parent->parent); } - ++index; - } - if (!coveredFunctionsInBranches.count(state.prevPC->parent->parent) && - codeGraphDistance.getFunctionBranches(state.prevPC->parent->parent) == - coveredBranches[state.prevPC->parent->parent]) { - coveredFunctionsInBranches.insert(state.prevPC->parent->parent); } if (!fullyCoveredFunctions.count(state.prevPC->parent->parent) && coveredFunctionsInBranches.count(state.prevPC->parent->parent)) { @@ -205,7 +208,7 @@ TargetHashSet TargetCalculator::calculate(ExecutionState &state) { using std::placeholders::_1; KBlockPredicate func = std::bind(&TargetCalculator::uncoveredBlockPredicate, this, &state, _1); - codeGraphDistance.getNearestPredicateSatisfying(kb, func, blocks); + codeGraphInfo.getNearestPredicateSatisfying(kb, func, blocks); if (!blocks.empty()) { TargetHashSet targets; @@ -237,6 +240,7 @@ TargetHashSet TargetCalculator::calculate(ExecutionState &state) { } } } + assert(!targets.empty()); return targets; } diff --git a/lib/Core/TargetCalculator.h b/lib/Core/TargetCalculator.h index d3a3937ed5..ba78a89f20 100644 --- a/lib/Core/TargetCalculator.h +++ b/lib/Core/TargetCalculator.h @@ -32,7 +32,7 @@ DISABLE_WARNING_POP #include namespace klee { -class CodeGraphDistance; +class CodeGraphInfo; class ExecutionState; struct TransitionHash; @@ -65,15 +65,15 @@ class TargetCalculator { typedef std::unordered_map CoveredBlocks; public: - TargetCalculator(CodeGraphDistance &codeGraphDistance) - : codeGraphDistance(codeGraphDistance) {} + TargetCalculator(CodeGraphInfo &codeGraphInfo) + : codeGraphInfo(codeGraphInfo) {} void update(const ExecutionState &state); TargetHashSet calculate(ExecutionState &state); private: - CodeGraphDistance &codeGraphDistance; + CodeGraphInfo &codeGraphInfo; BlocksHistory blocksHistory; TransitionsHistory transitionsHistory; CoveredBranches coveredBranches; diff --git a/lib/Core/TargetedExecutionManager.cpp b/lib/Core/TargetedExecutionManager.cpp index 25357773ae..3e421a684e 100644 --- a/lib/Core/TargetedExecutionManager.cpp +++ b/lib/Core/TargetedExecutionManager.cpp @@ -14,7 +14,7 @@ #include "ExecutionState.h" #include "klee/Core/TerminationTypes.h" -#include "klee/Module/CodeGraphDistance.h" +#include "klee/Module/CodeGraphInfo.h" #include "klee/Module/KInstruction.h" #include "klee/Support/ErrorHandling.h" @@ -375,18 +375,18 @@ bool TargetedExecutionManager::canReach(const ref &from, return true; } - const auto &blockDist = codeGraphDistance.getDistance(fromBlock); + const auto &blockDist = codeGraphInfo.getDistance(fromBlock); if (blockDist.count(toBlock) != 0) { return true; } } else { - const auto &funcDist = codeGraphDistance.getDistance(fromKf); + const auto &funcDist = codeGraphInfo.getDistance(fromKf); if (funcDist.count(toKf) != 0) { return true; } const auto &backwardFuncDist = - codeGraphDistance.getBackwardDistance(fromKf); + codeGraphInfo.getBackwardDistance(fromKf); if (backwardFuncDist.count(toKf) != 0) { return true; } @@ -449,7 +449,7 @@ KFunction *TargetedExecutionManager::tryResolveEntryFunction( if (i == j) { continue; } - const auto &funcDist = codeGraphDistance.getDistance(resKf); + const auto &funcDist = codeGraphInfo.getDistance(resKf); std::vector currKFs; for (auto block : locToBlocks[result.locations[j]]) { @@ -462,7 +462,7 @@ KFunction *TargetedExecutionManager::tryResolveEntryFunction( for (size_t m = 0; m < currKFs.size() && !curKf; ++m) { curKf = currKFs.at(m); if (funcDist.count(curKf) == 0) { - const auto &curFuncDist = codeGraphDistance.getDistance(curKf); + const auto &curFuncDist = codeGraphInfo.getDistance(curKf); if (curFuncDist.count(resKf) == 0) { curKf = nullptr; } else { diff --git a/lib/Core/TargetedExecutionManager.h b/lib/Core/TargetedExecutionManager.h index 7d5b285d41..e5a66cbf32 100644 --- a/lib/Core/TargetedExecutionManager.h +++ b/lib/Core/TargetedExecutionManager.h @@ -60,7 +60,7 @@ extern llvm::cl::opt TimerInterval; extern llvm::cl::opt MaxCycles; -class CodeGraphDistance; +class CodeGraphInfo; class TargetedHaltsOnTraces { using HaltTypeToConfidence = @@ -116,7 +116,7 @@ class TargetedExecutionManager { KFunction *tryResolveEntryFunction(const Result &result, LocationToBlocks &locToBlocks) const; - CodeGraphDistance &codeGraphDistance; + CodeGraphInfo &codeGraphInfo; TargetManager &targetManager; StatesSet localStates; @@ -127,9 +127,9 @@ class TargetedExecutionManager { } }; - explicit TargetedExecutionManager(CodeGraphDistance &codeGraphDistance_, + explicit TargetedExecutionManager(CodeGraphInfo &codeGraphInfo_, TargetManager &targetManager_) - : codeGraphDistance(codeGraphDistance_), targetManager(targetManager_) {} + : codeGraphInfo(codeGraphInfo_), targetManager(targetManager_) {} ~TargetedExecutionManager() = default; std::map, KFunctionLess> prepareTargets(KModule *kmodule, SarifReport paths); diff --git a/lib/Module/CMakeLists.txt b/lib/Module/CMakeLists.txt index 0bdb2e67eb..81112acbe0 100644 --- a/lib/Module/CMakeLists.txt +++ b/lib/Module/CMakeLists.txt @@ -9,7 +9,7 @@ set(KLEE_MODULE_COMPONENT_SRCS CallSplitter.cpp Checks.cpp - CodeGraphDistance.cpp + CodeGraphInfo.cpp FunctionAlias.cpp InstructionInfoTable.cpp InstructionOperandTypeCheckPass.cpp diff --git a/lib/Module/CodeGraphDistance.cpp b/lib/Module/CodeGraphInfo.cpp similarity index 84% rename from lib/Module/CodeGraphDistance.cpp rename to lib/Module/CodeGraphInfo.cpp index 988cb4db27..045c379932 100644 --- a/lib/Module/CodeGraphDistance.cpp +++ b/lib/Module/CodeGraphInfo.cpp @@ -1,5 +1,4 @@ -//===-- CodeGraphDistance.cpp -//---------------------------------------------------===// +//===-- CodeGraphInfo.cpp -------------------------------------------------===// // // The KLEE Symbolic Virtual Machine // @@ -8,7 +7,7 @@ // //===----------------------------------------------------------------------===// -#include "klee/Module/CodeGraphDistance.h" +#include "klee/Module/CodeGraphInfo.h" #include "klee/Support/CompilerWarning.h" DISABLE_WARNING_PUSH @@ -21,7 +20,7 @@ DISABLE_WARNING_POP using namespace klee; -void CodeGraphDistance::calculateDistance(KBlock *bb) { +void CodeGraphInfo::calculateDistance(KBlock *bb) { auto blockMap = bb->parent->blockMap; std::unordered_map &dist = blockDistance[bb]; std::vector> &sort = blockSortedDistance[bb]; @@ -42,7 +41,7 @@ void CodeGraphDistance::calculateDistance(KBlock *bb) { } } -void CodeGraphDistance::calculateBackwardDistance(KBlock *bb) { +void CodeGraphInfo::calculateBackwardDistance(KBlock *bb) { auto blockMap = bb->parent->blockMap; std::unordered_map &bdist = blockBackwardDistance[bb]; std::vector> &bsort = @@ -64,7 +63,7 @@ void CodeGraphDistance::calculateBackwardDistance(KBlock *bb) { } } -void CodeGraphDistance::calculateDistance(KFunction *kf) { +void CodeGraphInfo::calculateDistance(KFunction *kf) { auto &functionMap = kf->parent->functionMap; std::unordered_map &dist = functionDistance[kf]; std::vector> &sort = @@ -92,7 +91,7 @@ void CodeGraphDistance::calculateDistance(KFunction *kf) { } } -void CodeGraphDistance::calculateBackwardDistance(KFunction *kf) { +void CodeGraphInfo::calculateBackwardDistance(KFunction *kf) { auto &functionMap = kf->parent->functionMap; auto &callMap = kf->parent->callMap; std::unordered_map &bdist = @@ -120,7 +119,7 @@ void CodeGraphDistance::calculateBackwardDistance(KFunction *kf) { } } -void CodeGraphDistance::calculateFunctionBranches(KFunction *kf) { +void CodeGraphInfo::calculateFunctionBranches(KFunction *kf) { std::map> &fbranches = functionBranches[kf]; for (auto &kb : kf->blocks) { fbranches[kb.get()]; @@ -133,63 +132,64 @@ void CodeGraphDistance::calculateFunctionBranches(KFunction *kf) { } const std::unordered_map & -CodeGraphDistance::getDistance(KBlock *kb) { +CodeGraphInfo::getDistance(KBlock *kb) { if (blockDistance.count(kb) == 0) calculateDistance(kb); return blockDistance.at(kb); } const std::unordered_map & -CodeGraphDistance::getBackwardDistance(KBlock *kb) { +CodeGraphInfo::getBackwardDistance(KBlock *kb) { if (blockBackwardDistance.count(kb) == 0) calculateBackwardDistance(kb); return blockBackwardDistance.at(kb); } const std::vector> & -CodeGraphDistance::getSortedDistance(KBlock *kb) { +CodeGraphInfo::getSortedDistance(KBlock *kb) { if (blockDistance.count(kb) == 0) calculateDistance(kb); return blockSortedDistance.at(kb); } const std::vector> & -CodeGraphDistance::getSortedBackwardDistance(KBlock *kb) { +CodeGraphInfo::getSortedBackwardDistance(KBlock *kb) { if (blockBackwardDistance.count(kb) == 0) calculateBackwardDistance(kb); return blockSortedBackwardDistance.at(kb); } const std::unordered_map & -CodeGraphDistance::getDistance(KFunction *kf) { +CodeGraphInfo::getDistance(KFunction *kf) { if (functionDistance.count(kf) == 0) calculateDistance(kf); return functionDistance.at(kf); } const std::unordered_map & -CodeGraphDistance::getBackwardDistance(KFunction *kf) { +CodeGraphInfo::getBackwardDistance(KFunction *kf) { if (functionBackwardDistance.count(kf) == 0) calculateBackwardDistance(kf); return functionBackwardDistance.at(kf); } const std::vector> & -CodeGraphDistance::getSortedDistance(KFunction *kf) { +CodeGraphInfo::getSortedDistance(KFunction *kf) { if (functionDistance.count(kf) == 0) calculateDistance(kf); return functionSortedDistance.at(kf); } const std::vector> & -CodeGraphDistance::getSortedBackwardDistance(KFunction *kf) { +CodeGraphInfo::getSortedBackwardDistance(KFunction *kf) { if (functionBackwardDistance.count(kf) == 0) calculateBackwardDistance(kf); return functionSortedBackwardDistance.at(kf); } -void CodeGraphDistance::getNearestPredicateSatisfying( - KBlock *from, KBlockPredicate predicate, std::set &result) { +void CodeGraphInfo::getNearestPredicateSatisfying(KBlock *from, + KBlockPredicate predicate, + std::set &result) { std::set visited; auto blockMap = from->parent->blockMap; @@ -214,7 +214,7 @@ void CodeGraphDistance::getNearestPredicateSatisfying( } const std::map> & -CodeGraphDistance::getFunctionBranches(KFunction *kf) { +CodeGraphInfo::getFunctionBranches(KFunction *kf) { if (functionBranches.count(kf) == 0) calculateFunctionBranches(kf); return functionBranches.at(kf); diff --git a/lib/Module/Target.cpp b/lib/Module/Target.cpp index 633d27f2a6..916e73f0e8 100644 --- a/lib/Module/Target.cpp +++ b/lib/Module/Target.cpp @@ -10,7 +10,7 @@ #include "klee/Module/Target.h" #include "klee/Module/TargetHash.h" -#include "klee/Module/CodeGraphDistance.h" +#include "klee/Module/CodeGraphInfo.h" #include "klee/Module/KInstruction.h" #include From 448652974210b33a6c3e0791f7936a361e3cb13d Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Fri, 15 Sep 2023 17:47:30 +0400 Subject: [PATCH 010/103] [feat] Improve `only-output-states-covering-new` option --- include/klee/ADT/Ref.h | 12 ++++++++++++ lib/Core/ExecutionState.cpp | 16 +++++++++------- lib/Core/ExecutionState.h | 2 +- lib/Core/Executor.cpp | 8 +++++--- lib/Core/StatsTracker.cpp | 3 --- lib/Core/TargetCalculator.cpp | 17 ++++++++++++++--- 6 files changed, 41 insertions(+), 17 deletions(-) diff --git a/include/klee/ADT/Ref.h b/include/klee/ADT/Ref.h index 45e9632ca2..008580cc7e 100644 --- a/include/klee/ADT/Ref.h +++ b/include/klee/ADT/Ref.h @@ -227,6 +227,18 @@ inline std::stringstream &operator<<(std::stringstream &os, const ref &e) { return os; } +template class box { + friend class ref>; + +private: + /// @brief Required by klee::ref-managed objects + class ReferenceCounter _refCount; + +public: + box(T value_) : value(value_) {} + ReferenceCounter count() { return _refCount; } + T value; +}; } // end namespace klee namespace llvm { diff --git a/lib/Core/ExecutionState.cpp b/lib/Core/ExecutionState.cpp index 5ce9492467..492e22fb9a 100644 --- a/lib/Core/ExecutionState.cpp +++ b/lib/Core/ExecutionState.cpp @@ -128,8 +128,9 @@ ExecutionState::ExecutionState() : initPC(nullptr), pc(nullptr), prevPC(nullptr), incomingBBIndex(-1), depth(0), ptreeNode(nullptr), steppedInstructions(0), steppedMemoryInstructions(0), instsSinceCovNew(0), - roundingMode(llvm::APFloat::rmNearestTiesToEven), coveredNew(false), - forkDisabled(false), prevHistory_(TargetsHistory::create()), + roundingMode(llvm::APFloat::rmNearestTiesToEven), + coveredNew(new box(false)), forkDisabled(false), + prevHistory_(TargetsHistory::create()), history_(TargetsHistory::create()) { setID(); } @@ -138,8 +139,9 @@ ExecutionState::ExecutionState(KFunction *kf) : initPC(kf->instructions), pc(initPC), prevPC(pc), incomingBBIndex(-1), depth(0), ptreeNode(nullptr), steppedInstructions(0), steppedMemoryInstructions(0), instsSinceCovNew(0), - roundingMode(llvm::APFloat::rmNearestTiesToEven), coveredNew(false), - forkDisabled(false), prevHistory_(TargetsHistory::create()), + roundingMode(llvm::APFloat::rmNearestTiesToEven), + coveredNew(new box(false)), forkDisabled(false), + prevHistory_(TargetsHistory::create()), history_(TargetsHistory::create()) { pushFrame(nullptr, kf); setID(); @@ -149,8 +151,9 @@ ExecutionState::ExecutionState(KFunction *kf, KBlock *kb) : initPC(kb->instructions), pc(initPC), prevPC(pc), incomingBBIndex(-1), depth(0), ptreeNode(nullptr), steppedInstructions(0), steppedMemoryInstructions(0), instsSinceCovNew(0), - roundingMode(llvm::APFloat::rmNearestTiesToEven), coveredNew(false), - forkDisabled(false), prevHistory_(TargetsHistory::create()), + roundingMode(llvm::APFloat::rmNearestTiesToEven), + coveredNew(new box(false)), forkDisabled(false), + prevHistory_(TargetsHistory::create()), history_(TargetsHistory::create()) { pushFrame(nullptr, kf); setID(); @@ -191,7 +194,6 @@ ExecutionState *ExecutionState::branch() { auto *falseState = new ExecutionState(*this); falseState->setID(); - falseState->coveredNew = false; falseState->coveredLines.clear(); return falseState; diff --git a/lib/Core/ExecutionState.h b/lib/Core/ExecutionState.h index 575d81f1e8..69e597d278 100644 --- a/lib/Core/ExecutionState.h +++ b/lib/Core/ExecutionState.h @@ -369,7 +369,7 @@ class ExecutionState { std::uint32_t id = 0; /// @brief Whether a new instruction was covered in this state - bool coveredNew = false; + mutable ref> coveredNew; /// @brief Disables forking for this state. Set by user code bool forkDisabled = false; diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index 3f9d40b984..338def4b5c 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -4053,7 +4053,7 @@ bool Executor::checkMemoryUsage() { unsigned idx = theRNG.getInt32() % N; // Make two pulls to try and not hit a state that // covered new code. - if (arr[idx]->coveredNew) + if (arr[idx]->coveredNew->value) idx = theRNG.getInt32() % N; std::swap(arr[idx], arr[N - 1]); @@ -4513,7 +4513,9 @@ void Executor::terminateState(ExecutionState &state, } static bool shouldWriteTest(const ExecutionState &state) { - return !OnlyOutputStatesCoveringNew || state.coveredNew; + bool coveredNew = state.coveredNew->value; + state.coveredNew->value = false; + return !OnlyOutputStatesCoveringNew || coveredNew; } static std::string terminationTypeFileExtension(StateTerminationType type) { @@ -7274,7 +7276,7 @@ void Executor::dumpStates() { *os << "{"; *os << "'depth' : " << es->depth << ", "; *os << "'queryCost' : " << es->queryMetaData.queryCost << ", "; - *os << "'coveredNew' : " << es->coveredNew << ", "; + *os << "'coveredNew' : " << es->coveredNew->value << ", "; *os << "'instsSinceCovNew' : " << es->instsSinceCovNew << ", "; *os << "'md2u' : " << md2u << ", "; *os << "'icnt' : " << icnt << ", "; diff --git a/lib/Core/StatsTracker.cpp b/lib/Core/StatsTracker.cpp index 372c6fc61b..e662644be3 100644 --- a/lib/Core/StatsTracker.cpp +++ b/lib/Core/StatsTracker.cpp @@ -411,7 +411,6 @@ void StatsTracker::stepInstruction(ExecutionState &es) { // FIXME: This trick no longer works, we should fix this in the line // number propogation. es.coveredLines[&ii.file].insert(ii.line); - es.coveredNew = true; es.instsSinceCovNew = 1; ++stats::coveredInstructions; stats::uncoveredInstructions += (uint64_t)-1; @@ -480,7 +479,6 @@ void StatsTracker::markBranchVisited(ExecutionState *visitedTrue, uint64_t hasFalse = theStatisticManager->getIndexedValue(stats::falseBranches, id); if (visitedTrue && !hasTrue) { - visitedTrue->coveredNew = true; visitedTrue->instsSinceCovNew = 1; ++stats::trueBranches; if (hasFalse) { @@ -491,7 +489,6 @@ void StatsTracker::markBranchVisited(ExecutionState *visitedTrue, hasTrue = 1; } if (visitedFalse && !hasFalse) { - visitedFalse->coveredNew = true; visitedFalse->instsSinceCovNew = 1; ++stats::falseBranches; if (hasTrue) { diff --git a/lib/Core/TargetCalculator.cpp b/lib/Core/TargetCalculator.cpp index 6b6a2f7d3e..0c5d72fedb 100644 --- a/lib/Core/TargetCalculator.cpp +++ b/lib/Core/TargetCalculator.cpp @@ -49,11 +49,22 @@ void TargetCalculator::update(const ExecutionState &state) { if (!coveredFunctionsInBranches.count(state.prevPC->parent->parent)) { unsigned index = 0; - coveredBranches[state.prevPC->parent->parent][state.prevPC->parent]; + if (!coveredBranches[state.prevPC->parent->parent].count( + state.prevPC->parent)) { + state.coveredNew->value = false; + state.coveredNew = new box(true); + coveredBranches[state.prevPC->parent->parent][state.prevPC->parent]; + } for (auto succ : successors(state.getPrevPCBlock())) { if (succ == state.getPCBlock()) { - coveredBranches[state.prevPC->parent->parent][state.prevPC->parent] - .insert(index); + if (!coveredBranches[state.prevPC->parent->parent] + [state.prevPC->parent] + .count(index)) { + state.coveredNew->value = false; + state.coveredNew = new box(true); + coveredBranches[state.prevPC->parent->parent][state.prevPC->parent] + .insert(index); + } break; } ++index; From d3344b54ea20c4e20df62c1098cc288720f83e49 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Sat, 16 Sep 2023 13:24:32 +0400 Subject: [PATCH 011/103] [feat] Add `cover-on-the-fly` option --- include/klee/Core/TerminationTypes.h | 3 +- lib/Core/Executor.cpp | 59 +++++++++++++++++++--------- test/Feature/CoverOnTheFly.c | 35 +++++++++++++++++ test/Feature/CoverageCheck.c | 2 +- 4 files changed, 78 insertions(+), 21 deletions(-) create mode 100644 test/Feature/CoverOnTheFly.c diff --git a/include/klee/Core/TerminationTypes.h b/include/klee/Core/TerminationTypes.h index 06d1522923..786cf610d6 100644 --- a/include/klee/Core/TerminationTypes.h +++ b/include/klee/Core/TerminationTypes.h @@ -40,7 +40,8 @@ enum class StateTerminationClass : std::uint8_t { TTYPE(OutOfMemory, 12U, "early") \ TTYPE(OutOfStackMemory, 13U, "early") \ TTYPE(MaxCycles, 14U, "early") \ - TTMARK(EARLY, 14U) \ + TTYPE(CoverOnTheFly, 15U, "early") \ + TTMARK(EARLY, 15U) \ TTYPE(Solver, 20U, "solver.err") \ TTMARK(SOLVERERR, 20U) \ TTYPE(Abort, 30U, "abort.err") \ diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index 338def4b5c..3d5945de3d 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -239,6 +239,18 @@ cl::opt EmitAllErrors( "(default=false, i.e. one per (error,instruction) pair)"), cl::cat(TestGenCat)); +cl::opt CoverOnTheFly( + "cover-on-the-fly", cl::init(false), + cl::desc("Generate tests cases for each new covered block or branch " + "(default=false, i.e. one per (error,instruction) pair)"), + cl::cat(TestGenCat)); + +cl::opt DelayCoverOnTheFly( + "delay-cover-on-the-fly", cl::init(10000), + cl::desc("Start on the fly tests generation after this many instructions " + "(default=10000)"), + cl::cat(TestGenCat)); + /* Constraint solving options */ cl::opt MaxSymArraySize( @@ -4325,8 +4337,36 @@ void Executor::initializeTypeManager() { typeSystemManager->initModule(); } +static bool shouldWriteTest(const ExecutionState &state) { + bool coveredNew = state.coveredNew->value; + state.coveredNew->value = false; + return !OnlyOutputStatesCoveringNew || coveredNew; +} + +static std::string terminationTypeFileExtension(StateTerminationType type) { + std::string ret; +#undef TTYPE +#undef TTMARK +#define TTYPE(N, I, S) \ + case StateTerminationType::N: \ + ret = (S); \ + break; +#define TTMARK(N, I) + switch (type) { TERMINATION_TYPES } + return ret; +}; + void Executor::executeStep(ExecutionState &state) { KInstruction *prevKI = state.prevPC; + + if (CoverOnTheFly && guidanceKind != GuidanceKind::ErrorGuidance && + stats::instructions > DelayCoverOnTheFly && shouldWriteTest(state)) { + interpreterHandler->processTestCase( + state, nullptr, + terminationTypeFileExtension(StateTerminationType::CoverOnTheFly) + .c_str()); + } + if (targetManager->isTargeted(state) && state.targets().empty()) { terminateStateEarlyAlgorithm(state, "State missed all it's targets.", StateTerminationType::MissedAllTargets); @@ -4512,25 +4552,6 @@ void Executor::terminateState(ExecutionState &state, removedStates.push_back(&state); } -static bool shouldWriteTest(const ExecutionState &state) { - bool coveredNew = state.coveredNew->value; - state.coveredNew->value = false; - return !OnlyOutputStatesCoveringNew || coveredNew; -} - -static std::string terminationTypeFileExtension(StateTerminationType type) { - std::string ret; -#undef TTYPE -#undef TTMARK -#define TTYPE(N, I, S) \ - case StateTerminationType::N: \ - ret = (S); \ - break; -#define TTMARK(N, I) - switch (type) { TERMINATION_TYPES } - return ret; -}; - void Executor::terminateStateOnExit(ExecutionState &state) { auto terminationType = StateTerminationType::Exit; ++stats::terminationExit; diff --git a/test/Feature/CoverOnTheFly.c b/test/Feature/CoverOnTheFly.c new file mode 100644 index 0000000000..85c0ead78c --- /dev/null +++ b/test/Feature/CoverOnTheFly.c @@ -0,0 +1,35 @@ +// ASAN fails because KLEE does not cleanup states with -dump-states-on-halt=false +// REQUIRES: not-asan +// RUN: %clang %s -emit-llvm %O0opt -c -o %t.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --only-output-states-covering-new --max-instructions=2000 --delay-cover-on-the-fly=500 --dump-states-on-halt=false --cover-on-the-fly --search=bfs --use-guided-search=none --output-dir=%t.klee-out %t.bc 2>&1 | FileCheck %s + +#include "klee/klee.h" + +#define a (2) +int main() { + int res = 0; + for (;;) { + int n = klee_int("n"); + switch (n) { + case 1: + res += 1; + break; + case 2: + res += 2; + break; + case 3: + res += 3; + break; + case 4: + res += 4; + break; + + default: + break; + } + } +} + +// CHECK: KLEE: done: completed paths = 0 +// CHECK: KLEE: done: generated tests = 5 diff --git a/test/Feature/CoverageCheck.c b/test/Feature/CoverageCheck.c index 4800010350..a9c9eb2b63 100644 --- a/test/Feature/CoverageCheck.c +++ b/test/Feature/CoverageCheck.c @@ -1,6 +1,6 @@ // RUN: %clang %s -emit-llvm %O0opt -c -o %t.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --use-cov-check=instruction-based --output-dir=%t.klee-out %t.bc > %t.log +// RUN: %klee --use-guided-search=none --use-cov-check=instruction-based --output-dir=%t.klee-out %t.bc > %t.log #include "klee/klee.h" #define a (2) From 8d69a9ffa606f4e15e2fd2023e3e9968dccdfd34 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Mon, 18 Sep 2023 12:53:22 +0400 Subject: [PATCH 012/103] [fix] Make `isReachedTarget` consistent with `reportTruePositive` --- lib/Core/TargetManager.cpp | 20 +++++++++++++++++--- lib/Core/TargetedExecutionManager.cpp | 22 +++------------------- test/Industry/if2.c | 2 +- 3 files changed, 21 insertions(+), 23 deletions(-) diff --git a/lib/Core/TargetManager.cpp b/lib/Core/TargetManager.cpp index a25ff130e0..9dcaedcd86 100644 --- a/lib/Core/TargetManager.cpp +++ b/lib/Core/TargetManager.cpp @@ -274,9 +274,23 @@ bool TargetManager::isReachedTarget(const ExecutionState &state, } if (target->shouldFailOnThisTarget()) { - if (state.pc->parent == target->getBlock()) { - if (cast(target)->isTheSameAsIn(state.prevPC) && - cast(target)->isThatError(state.error)) { + bool found = true; + auto possibleInstruction = state.prevPC; + int i = state.stack.size() - 1; + + while (!cast(target)->isTheSameAsIn( + possibleInstruction)) { // TODO: target->getBlock() == + // possibleInstruction should also be checked, + // but more smartly + if (i <= 0) { + found = false; + break; + } + possibleInstruction = state.stack.callStack().at(i).caller; + i--; + } + if (found) { + if (cast(target)->isThatError(state.error)) { result = Done; } else { result = Continue; diff --git a/lib/Core/TargetedExecutionManager.cpp b/lib/Core/TargetedExecutionManager.cpp index 3e421a684e..9f9b498738 100644 --- a/lib/Core/TargetedExecutionManager.cpp +++ b/lib/Core/TargetedExecutionManager.cpp @@ -530,6 +530,7 @@ void TargetedExecutionManager::reportFalseNegative(ExecutionState &state, bool TargetedExecutionManager::reportTruePositive(ExecutionState &state, ReachWithError error) { bool atLeastOneReported = false; + state.error = error; for (auto target : state.targetForest.getTargets()) { if (!target->shouldFailOnThisTarget()) continue; @@ -539,27 +540,10 @@ bool TargetedExecutionManager::reportTruePositive(ExecutionState &state, reportedTraces.count(errorTarget->getId())) continue; - /// The following code checks if target is a `call ...` instruction and we - /// failed somewhere *inside* call - auto possibleInstruction = state.prevPC; - int i = state.stack.size() - 1; - bool found = true; - - while (!errorTarget->isTheSameAsIn( - possibleInstruction)) { // TODO: target->getBlock() == - // possibleInstruction should also be checked, - // but more smartly - if (i <= 0) { - found = false; - break; - } - possibleInstruction = state.stack.callStack().at(i).caller; - i--; - } - if (!found) + if (!targetManager.isReachedTarget(state, errorTarget)) { continue; + } - state.error = error; atLeastOneReported = true; assert(!errorTarget->isReported); if (errorTarget->isThatError(ReachWithError::Reachable)) { diff --git a/test/Industry/if2.c b/test/Industry/if2.c index 27f414ed01..d52edf529f 100644 --- a/test/Industry/if2.c +++ b/test/Industry/if2.c @@ -11,7 +11,7 @@ int main(int x) { // REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --mock-external-calls --skip-not-symbolic-objects --skip-not-lazy-initialized --check-out-of-memory --search=bfs --max-stepped-instructions=19 --max-cycles-before-stuck=0 --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc +// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --mock-external-calls --skip-not-symbolic-objects --skip-not-lazy-initialized --check-out-of-memory --search=bfs --max-stepped-instructions=20 --max-cycles-before-stuck=0 --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc // RUN: FileCheck -input-file=%t.klee-out/warnings.txt %s -check-prefix=CHECK-NONE // CHECK-NONE: KLEE: WARNING: 50.00% NullPointerException False Positive at trace 1 // RUN: FileCheck -input-file=%t.klee-out/messages.txt %s -check-prefix=CHECK-DISTANCE From fcfef9db4bed65f89ebcd212cee54176dce02a41 Mon Sep 17 00:00:00 2001 From: Sergey Morozov Date: Fri, 18 Aug 2023 19:23:04 +0300 Subject: [PATCH 013/103] Created shadow copy of errno in 32bit space to work with 32bit programs. --- lib/Core/Executor.cpp | 29 +++++++++++++++++++++++------ lib/Core/Executor.h | 2 ++ lib/Core/SpecialFunctionHandler.cpp | 3 ++- 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index 3d5945de3d..df73fa953f 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -732,14 +732,32 @@ void Executor::allocateGlobalObjects(ExecutionState &state) { } #ifndef WINDOWS - int *errno_addr = getErrnoLocation(state); + llvm::Type *pointerErrnoAddr = llvm::PointerType::get( llvm::IntegerType::get(m->getContext(), sizeof(*errno_addr) * CHAR_BIT), adressSpaceNum); - MemoryObject *errnoObj = - addExternalObject(state, (void *)errno_addr, - typeSystemManager->getWrappedType(pointerErrnoAddr), - sizeof *errno_addr, false); + MemoryObject *errnoObj = nullptr; + + if (Context::get().getPointerWidth() == 32) { + // This is not working (?) + // errno_addr = (int *)mmap(NULL, sizeof(*errno_addr), PROT_READ | PROT_WRITE, + // MAP_32BIT | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + errnoObj = allocate(state, Expr::createPointer(sizeof(*errno_addr)), false, true, + nullptr, 8); + errnoObj->isFixed = true; + + ObjectState *os = bindObjectInState( + state, errnoObj, typeSystemManager->getWrappedType(pointerErrnoAddr), + false); + errno_addr = reinterpret_cast(errnoObj->address); + } else { + errno_addr = getErrnoLocation(state); + errnoObj = + addExternalObject(state, (void *)errno_addr, + typeSystemManager->getWrappedType(pointerErrnoAddr), + sizeof *errno_addr, false); + } + // Copy values from and to program space explicitly errnoObj->isUserSpecified = true; #endif @@ -4891,7 +4909,6 @@ void Executor::callExternalFunction(ExecutionState &state, KInstruction *target, state.addressSpace.copyOutConcretes(); #ifndef WINDOWS // Update external errno state with local state value - int *errno_addr = getErrnoLocation(state); IDType idResult; llvm::Type *pointerErrnoAddr = llvm::PointerType::get( diff --git a/lib/Core/Executor.h b/lib/Core/Executor.h index 9a89fdcf04..1cd6c1c4a0 100644 --- a/lib/Core/Executor.h +++ b/lib/Core/Executor.h @@ -122,6 +122,8 @@ class Executor : public Interpreter { RNG theRNG; private: + int *errno_addr; + using SetOfStates = std::set; /* Set of Intrinsic::ID. Plain type is used here to avoid including llvm in * the header */ diff --git a/lib/Core/SpecialFunctionHandler.cpp b/lib/Core/SpecialFunctionHandler.cpp index 1d3e07b85f..6138eabe1b 100644 --- a/lib/Core/SpecialFunctionHandler.cpp +++ b/lib/Core/SpecialFunctionHandler.cpp @@ -734,7 +734,8 @@ void SpecialFunctionHandler::handleErrnoLocation( "invalid number of arguments to __errno_location/__error"); #ifndef WINDOWS - int *errno_addr = executor.getErrnoLocation(state); + // int *errno_addr = executor.getErrnoLocation(state); + int *errno_addr = executor.errno_addr; #else int *errno_addr = nullptr; #endif From 0a1674782143d298ef2f5a0d89a3a09628ce8271 Mon Sep 17 00:00:00 2001 From: Sergey Morozov Date: Mon, 21 Aug 2023 19:41:14 +0300 Subject: [PATCH 014/103] Added building of uClibc for 32 and 64-bit archs. --- CMakeLists.txt | 24 +++++++++++++++++------- include/klee/Config/config.h.cmin | 5 ++++- lib/Core/Executor.cpp | 9 +++------ scripts/build/p-uclibc.inc | 20 ++++++++++++++++---- tools/klee/main.cpp | 12 +++++++++++- 5 files changed, 51 insertions(+), 19 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e8317d04c0..18d853e189 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -506,19 +506,29 @@ endif() # KLEE uclibc support ################################################################################ set(KLEE_UCLIBC_PATH "" CACHE PATH "Path to klee-uclibc root directory") -set(KLEE_UCLIBC_BCA_NAME "klee-uclibc.bca") + +set(KLEE_UCLIBC_BCA_32_NAME "klee-uclibc-32.bca") +set(KLEE_UCLIBC_BCA_64_NAME "klee-uclibc-64.bca") + if (NOT KLEE_UCLIBC_PATH STREQUAL "") # Find the C library bitcode archive - set(KLEE_UCLIBC_C_BCA "${KLEE_UCLIBC_PATH}/lib/libc.a") - if (NOT EXISTS "${KLEE_UCLIBC_C_BCA}") + set(KLEE_UCLIBC_C_32_BCA "${KLEE_UCLIBC_PATH}-32/lib/libc.a") + set(KLEE_UCLIBC_C_64_BCA "${KLEE_UCLIBC_PATH}-64/lib/libc.a") + + if (NOT EXISTS "${KLEE_UCLIBC_C_32_BCA}" OR NOT EXISTS "${KLEE_UCLIBC_C_64_BCA}") message(FATAL_ERROR - "klee-uclibc library not found at \"${KLEE_UCLIBC_C_BCA}\". Set KLEE_UCLIBC_PATH to klee-uclibc root directory or empty string.") + "klee-uclibc library not found at \"${KLEE_UCLIBC_C_32_BCA}\" or \"${KLEE_UCLIBC_C_64_BCA}\". Set KLEE_UCLIBC_PATH to klee-uclibc root directory or empty string.") endif() - message(STATUS "Found klee-uclibc library: \"${KLEE_UCLIBC_C_BCA}\"") + message(STATUS "Found klee-uclibc library: \"${KLEE_UCLIBC_C_32_BCA}\" and \"${KLEE_UCLIBC_C_64_BCA}\"") # Copy KLEE_UCLIBC_C_BCA so KLEE can find it where it is expected. + # Create 32 and 64 bit versions + execute_process(COMMAND ${CMAKE_COMMAND} -E copy + "${KLEE_UCLIBC_C_32_BCA}" + "${KLEE_RUNTIME_DIRECTORY}/${KLEE_UCLIBC_BCA_32_NAME}" + ) execute_process(COMMAND ${CMAKE_COMMAND} -E copy - "${KLEE_UCLIBC_C_BCA}" - "${KLEE_RUNTIME_DIRECTORY}/${KLEE_UCLIBC_BCA_NAME}" + "${KLEE_UCLIBC_C_64_BCA}" + "${KLEE_RUNTIME_DIRECTORY}/${KLEE_UCLIBC_BCA_64_NAME}" ) else() message(STATUS "Skipping copying of klee-uclibc runtime") diff --git a/include/klee/Config/config.h.cmin b/include/klee/Config/config.h.cmin index 29a48405b7..91dbaf6868 100644 --- a/include/klee/Config/config.h.cmin +++ b/include/klee/Config/config.h.cmin @@ -102,7 +102,10 @@ #define RUNTIME_CONFIGURATION "@KLEE_RUNTIME_BUILD_TYPE@" /* Configure name of KLEE's uClibc library */ -#cmakedefine KLEE_UCLIBC_BCA_NAME "@KLEE_UCLIBC_BCA_NAME@" +#cmakedefine KLEE_UCLIBC_BCA_32_NAME "@KLEE_UCLIBC_BCA_32_NAME@" + +/* Configure name of KLEE's uClibc library */ +#cmakedefine KLEE_UCLIBC_BCA_64_NAME "@KLEE_UCLIBC_BCA_64_NAME@" /* Configure name of the libCXX bitcode library */ #cmakedefine KLEE_LIBCXX_BC_NAME "@KLEE_LIBCXX_BC_NAME@" diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index df73fa953f..4af041d3ba 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -739,13 +739,10 @@ void Executor::allocateGlobalObjects(ExecutionState &state) { MemoryObject *errnoObj = nullptr; if (Context::get().getPointerWidth() == 32) { - // This is not working (?) - // errno_addr = (int *)mmap(NULL, sizeof(*errno_addr), PROT_READ | PROT_WRITE, - // MAP_32BIT | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); - errnoObj = allocate(state, Expr::createPointer(sizeof(*errno_addr)), false, true, - nullptr, 8); + errnoObj = allocate(state, Expr::createPointer(sizeof(*errno_addr)), false, + true, nullptr, 8); errnoObj->isFixed = true; - + ObjectState *os = bindObjectInState( state, errnoObj, typeSystemManager->getWrappedType(pointerErrnoAddr), false); diff --git a/scripts/build/p-uclibc.inc b/scripts/build/p-uclibc.inc index 95af975137..f7cce95f2d 100644 --- a/scripts/build/p-uclibc.inc +++ b/scripts/build/p-uclibc.inc @@ -6,11 +6,18 @@ setup_build_variables_uclibc() { download_uclibc() { source "${DIR}/common-functions" - git_clone_or_update "${uclibc_url}" "${UCLIBC_PATH}" "${UCLIBC_VERSION}" + git_clone_or_update "${uclibc_url}" "${UCLIBC_PATH}-32" "${UCLIBC_VERSION}" + git_clone_or_update "${uclibc_url}" "${UCLIBC_PATH}-64" "${UCLIBC_VERSION}" } build_uclibc() { - cd "${UCLIBC_PATH}" || return 1 + pushd "${UCLIBC_PATH}-32" || return 1 + ./configure --make-llvm-lib --with-cc "${BITCODE_CC}" --with-llvm-config "${LLVM_CONFIG}" + make KLEE_CFLAGS="-m32" || return 1 + touch .is_installed + popd &>/dev/null + + pushd "${UCLIBC_PATH}-64" || return 1 ./configure --make-llvm-lib --with-cc "${BITCODE_CC}" --with-llvm-config "${LLVM_CONFIG}" make || return 1 touch .is_installed @@ -24,7 +31,11 @@ install_uclibc() { is_installed_uclibc() { ( setup_build_variables_uclibc - [[ -f "${UCLIBC_PATH}"/.is_installed ]] + [[ -f "${UCLIBC_PATH}-32"/.is_installed ]] + ) || return 1 + ( + setup_build_variables_uclibc + [[ -f "${UCLIBC_PATH}-64"/.is_installed ]] ) || return 1 } @@ -40,7 +51,8 @@ get_docker_config_id_uclibc() { get_build_artifacts_uclibc() { ( setup_build_variables_uclibc - echo "${UCLIBC_PATH}" + echo "${UCLIBC_PATH}-32" + echo "${UCLIBC_PATH}-64" ) } diff --git a/tools/klee/main.cpp b/tools/klee/main.cpp index 1099b9da14..b1dee0fb34 100644 --- a/tools/klee/main.cpp +++ b/tools/klee/main.cpp @@ -1221,7 +1221,17 @@ linkWithUclibc(StringRef libDir, std::string opt_suffix, // Ensure that klee-uclibc exists SmallString<128> uclibcBCA(libDir); - llvm::sys::path::append(uclibcBCA, KLEE_UCLIBC_BCA_NAME); + // Hack to find out bitness of .bc file + + if (opt_suffix.substr(0, 2) == "32") { + llvm::sys::path::append(uclibcBCA, KLEE_UCLIBC_BCA_32_NAME); + } else if (opt_suffix.substr(0, 2) == "64") { + llvm::sys::path::append(uclibcBCA, KLEE_UCLIBC_BCA_64_NAME); + } else { + klee_error("Cannot determine bitness of source file from the name %s", + uclibcBCA.c_str()); + } + if (!klee::loadFileAsOneModule(uclibcBCA.c_str(), ctx, libsModules, errorMsg)) klee_error("Cannot find klee-uclibc '%s': %s", uclibcBCA.c_str(), errorMsg.c_str()); From 12c647a96d503b41277c8e801a82851ef579b43a Mon Sep 17 00:00:00 2001 From: Sergey Morozov Date: Tue, 25 Jul 2023 13:26:25 +0300 Subject: [PATCH 015/103] [feat] tc support --- include/klee/Module/Target.h | 3 + include/klee/Support/OptionCategories.h | 1 + lib/Core/Executor.cpp | 41 +- lib/Module/Target.cpp | 9 + lib/Module/TargetForest.cpp | 7 +- ...or2c-lazyMod.adding.1.prop1-back-serstep.c | 565 ++++++++++++++++++ tools/klee/main.cpp | 294 ++++++--- 7 files changed, 831 insertions(+), 89 deletions(-) create mode 100644 test/Industry/wrapped_btor2c-lazyMod.adding.1.prop1-back-serstep.c diff --git a/include/klee/Module/Target.h b/include/klee/Module/Target.h index 80bf7e0c1d..98eb3c900a 100644 --- a/include/klee/Module/Target.h +++ b/include/klee/Module/Target.h @@ -41,6 +41,9 @@ struct ErrorLocation { unsigned int endLine; optional startColumn; optional endColumn; + + ErrorLocation(const klee::ref &loc); + ErrorLocation(const KInstruction *ki); }; class ReproduceErrorTarget; diff --git a/include/klee/Support/OptionCategories.h b/include/klee/Support/OptionCategories.h index c03128f3d9..da1d0d4934 100644 --- a/include/klee/Support/OptionCategories.h +++ b/include/klee/Support/OptionCategories.h @@ -21,6 +21,7 @@ DISABLE_WARNING_DEPRECATED_DECLARATIONS DISABLE_WARNING_POP namespace klee { +extern llvm::cl::OptionCategory TestCompCat; extern llvm::cl::OptionCategory ExecCat; extern llvm::cl::OptionCategory DebugCat; extern llvm::cl::OptionCategory ExecCat; diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index 4af041d3ba..63130c38d8 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -217,6 +217,10 @@ llvm::cl::opt MinNumberElementsLazyInit( "initialization (default 4)"), llvm::cl::init(4), llvm::cl::cat(LazyInitCat)); +cl::opt FunctionCallReproduce( + "function-call-reproduce", cl::init(""), + cl::desc("Marks mentioned function as target for error-guided mode."), + cl::cat(ExecCat)); } // namespace klee namespace { @@ -509,10 +513,6 @@ Executor::Executor(LLVMContext &ctx, const InterpreterOptions &opts, EqualitySubstitution); initializeSearchOptions(); - if (OnlyOutputStatesCoveringNew && !StatsTracker::useIStats()) - klee_error("To use --only-output-states-covering-new, you need to enable " - "--output-istats."); - if (DebugPrintInstructions.isSet(FILE_ALL) || DebugPrintInstructions.isSet(FILE_COMPACT) || DebugPrintInstructions.isSet(FILE_SRC)) { @@ -585,6 +585,13 @@ Executor::setModule(std::vector> &userModules, preservedFunctions.push_back("memcmp"); preservedFunctions.push_back("memmove"); + if (FunctionCallReproduce != "") { + // prevent elimination of the function + auto f = kmodule->module->getFunction(FunctionCallReproduce); + if (f) + f->addFnAttr(Attribute::OptimizeNone); + } + kmodule->optimiseAndPrepare(opts, preservedFunctions); kmodule->checkModule(); @@ -6635,7 +6642,8 @@ void Executor::clearMemory() { void Executor::runFunctionAsMain(Function *f, int argc, char **argv, char **envp) { - if (guidanceKind == GuidanceKind::ErrorGuidance && + if (FunctionCallReproduce == "" && + guidanceKind == GuidanceKind::ErrorGuidance && (!interpreterOpts.Paths.has_value() || interpreterOpts.Paths->empty())) { klee_warning("No targets found in error-guided mode"); return; @@ -6646,9 +6654,26 @@ void Executor::runFunctionAsMain(Function *f, int argc, char **argv, std::vector states; if (guidanceKind == GuidanceKind::ErrorGuidance) { - auto &paths = interpreterOpts.Paths.value(); - auto prepTargets = targetedExecutionManager->prepareTargets( - kmodule.get(), std::move(paths)); + std::map, + klee::TargetedExecutionManager::KFunctionLess> + prepTargets; + if (FunctionCallReproduce == "") { + auto &paths = interpreterOpts.Paths.value(); + prepTargets = targetedExecutionManager->prepareTargets(kmodule.get(), + std::move(paths)); + } else { + /* Find all calls to function specified in .prp file + * and combine them to single target forest */ + KFunction *kEntryFunction = kmodule->functionMap.at(f); + ref forest = new TargetForest(kEntryFunction); + auto kfunction = kmodule->functionNameMap.at(FunctionCallReproduce); + KBlock *kCallBlock = kfunction->entryKBlock; + forest->add(ReproduceErrorTarget::create( + {ReachWithError::Reachable}, "", + ErrorLocation(kCallBlock->getFirstInstruction()), kCallBlock)); + prepTargets.emplace(kEntryFunction, forest); + } + if (prepTargets.empty()) { klee_warning( "No targets found in error-guided mode after prepare targets"); diff --git a/lib/Module/Target.cpp b/lib/Module/Target.cpp index 916e73f0e8..7e6cfab36d 100644 --- a/lib/Module/Target.cpp +++ b/lib/Module/Target.cpp @@ -26,6 +26,15 @@ llvm::cl::opt LocationAccuracy( cl::desc("Check location with line and column accuracy (default=false)")); } +ErrorLocation::ErrorLocation(const klee::ref &loc) + : startLine(loc->startLine), endLine(loc->endLine), + startColumn(loc->startColumn), endColumn(loc->endColumn) {} + +ErrorLocation::ErrorLocation(const KInstruction *ki) { + startLine = (endLine = ki->info->line); + startColumn = (endColumn = ki->info->line); +} + std::string ReproduceErrorTarget::toString() const { std::ostringstream repr; repr << "Target " << getId() << ": "; diff --git a/lib/Module/TargetForest.cpp b/lib/Module/TargetForest.cpp index 0a95f3754f..cb2f8a907e 100644 --- a/lib/Module/TargetForest.cpp +++ b/lib/Module/TargetForest.cpp @@ -117,11 +117,8 @@ void TargetForest::Layer::addTrace( for (auto block : it->second) { ref target = nullptr; if (i == result.locations.size() - 1) { - target = ReproduceErrorTarget::create( - result.errors, result.id, - ErrorLocation{loc->startLine, loc->endLine, loc->startColumn, - loc->endColumn}, - block); + target = ReproduceErrorTarget::create(result.errors, result.id, + ErrorLocation(loc), block); } else { target = ReachBlockTarget::create(block); } diff --git a/test/Industry/wrapped_btor2c-lazyMod.adding.1.prop1-back-serstep.c b/test/Industry/wrapped_btor2c-lazyMod.adding.1.prop1-back-serstep.c new file mode 100644 index 0000000000..7a6d4ff09c --- /dev/null +++ b/test/Industry/wrapped_btor2c-lazyMod.adding.1.prop1-back-serstep.c @@ -0,0 +1,565 @@ +// REQUIRES: z3 +// RUN: %clang %s -emit-llvm %O0opt -g -c -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --use-forked-solver=false --solver-backend=z3 -max-memory=6008 --optimize=true --skip-not-lazy-initialized -output-source=true --output-stats=false --output-istats=false --write-xml-tests --write-ktests=false --xml-metadata-programfile=wrapped_btor2c-lazyMod.adding.1.prop1-back-serstep.c --xml-metadata-programhash=a18daeacf63b42ad6e1cb490555b7cdecd71ad6e58b167ed0f5626c03bc3d772 --use-sym-size-alloc=true --cex-cache-validity-cores --symbolic-allocation-threshold=8192 --function-call-reproduce=reach_error --dump-states-on-halt=false -exit-on-error-type=Assert --search=dfs --search=random-path -max-time=20 %t1.bc 2>&1 | FileCheck -check-prefix=CHECK-VERDICT %s + +// RUN: test -f %t.klee-out/test000001.xml +// RUN: not test -f %t.klee-out/test000001.ktest + +// CHECK-VERDICT: KLEE: WARNING: 100.00% Reachable Reachable at trace + +//RUN: FileCheck %s -input-file=%t.klee-out/assembly.ll +// the only forking br is in __VERIFIER_assert +// that is, all ternary ifs are turned into `select` instructions +// CHECK: {{call.*reach_error}} +// CHECK-COUNT-11: {{ phi }} + + + + + + +// This file is part of the SV-Benchmarks collection of verification tasks: +// https://gitlab.com/sosy-lab/benchmarking/sv-benchmarks +// +// SPDX-FileCopyrightText: 2007 - 2022 Radek Pelánek +// SPDX-FileCopyrightText: 2022 The SV-Benchmarks Community +// +// SPDX-License-Identifier: Apache-2.0 + +// This C program is converted from Btor2 by Btor2C version bfcfb8b +// with arguments: { architecture=64, lazy_modulo=true, use_memmove=false, unroll_inner_loops=false, shortest_type=true, diff_type=true, decimal_constant=true, zero_init=false, sra_extend_sign=true } +// Comments from the original Btor2 file: +// ; source: http://fmv.jku.at/hwmcc19/beem_btor.tar.xz +// ; Model in BTOR format generated by stepout.py 0.41 +#include "klee-test-comp.c" +extern void abort(void); +void reach_error() {} + +extern unsigned char __VERIFIER_nondet_uchar(); +extern unsigned short __VERIFIER_nondet_ushort(); +extern unsigned int __VERIFIER_nondet_uint(); +extern unsigned long __VERIFIER_nondet_ulong(); +void __VERIFIER_assert(int cond) { if (!(cond)) { ERROR: { reach_error(); abort(); } } } +void assume_abort_if_not(int cond) { if (!cond) { abort(); } } +int main() { + // Defining sorts ... + typedef unsigned char SORT_1; // BV with 1 bits + const SORT_1 mask_SORT_1 = (SORT_1)-1 >> (sizeof(SORT_1) * 8 - 1); + const SORT_1 msb_SORT_1 = (SORT_1)1 << (1 - 1); + typedef unsigned char SORT_2; // BV with 5 bits + const SORT_2 mask_SORT_2 = (SORT_2)-1 >> (sizeof(SORT_2) * 8 - 5); + const SORT_2 msb_SORT_2 = (SORT_2)1 << (5 - 1); + typedef unsigned short SORT_3; // BV with 16 bits + const SORT_3 mask_SORT_3 = (SORT_3)-1 >> (sizeof(SORT_3) * 8 - 16); + const SORT_3 msb_SORT_3 = (SORT_3)1 << (16 - 1); + typedef unsigned int SORT_4; // BV with 32 bits + const SORT_4 mask_SORT_4 = (SORT_4)-1 >> (sizeof(SORT_4) * 8 - 32); + const SORT_4 msb_SORT_4 = (SORT_4)1 << (32 - 1); + // Initializing constants ... + const SORT_3 var_5 = 0; + const SORT_1 var_12 = 0; + const SORT_3 var_34 = 1; + const SORT_3 var_37 = 0; + const SORT_1 var_62 = 1; + const SORT_4 var_65 = 20; + const SORT_3 var_66 = 0; + const SORT_4 var_68 = 16; + const SORT_4 var_171 = 17; + // Collecting input declarations ... + SORT_3 input_44; + SORT_3 input_46; + SORT_3 input_48; + SORT_1 input_50; + SORT_1 input_52; + SORT_1 input_54; + SORT_1 input_56; + SORT_1 input_58; + SORT_1 input_60; + SORT_1 input_64; + SORT_1 input_74; + SORT_1 input_78; + SORT_1 input_81; + SORT_1 input_96; + SORT_1 input_100; + // Collecting state declarations ... + SORT_3 state_6 = __VERIFIER_nondet_ushort() & mask_SORT_3; + SORT_3 state_8 = __VERIFIER_nondet_ushort() & mask_SORT_3; + SORT_3 state_10 = __VERIFIER_nondet_ushort() & mask_SORT_3; + SORT_1 state_13 = __VERIFIER_nondet_uchar() & mask_SORT_1; + SORT_1 state_15 = __VERIFIER_nondet_uchar() & mask_SORT_1; + SORT_1 state_17 = __VERIFIER_nondet_uchar() & mask_SORT_1; + SORT_1 state_19 = __VERIFIER_nondet_uchar() & mask_SORT_1; + SORT_1 state_21 = __VERIFIER_nondet_uchar() & mask_SORT_1; + SORT_1 state_23 = __VERIFIER_nondet_uchar() & mask_SORT_1; + SORT_1 state_25 = __VERIFIER_nondet_uchar() & mask_SORT_1; + SORT_1 state_27 = __VERIFIER_nondet_uchar() & mask_SORT_1; + // Initializing states ... + SORT_3 init_7_arg_1 = var_5; + state_6 = init_7_arg_1; + SORT_3 init_9_arg_1 = var_5; + state_8 = init_9_arg_1; + SORT_3 init_11_arg_1 = var_5; + state_10 = init_11_arg_1; + SORT_1 init_14_arg_1 = var_12; + state_13 = init_14_arg_1; + SORT_1 init_16_arg_1 = var_12; + state_15 = init_16_arg_1; + SORT_1 init_18_arg_1 = var_12; + state_17 = init_18_arg_1; + SORT_1 init_20_arg_1 = var_12; + state_19 = init_20_arg_1; + SORT_1 init_22_arg_1 = var_12; + state_21 = init_22_arg_1; + SORT_1 init_24_arg_1 = var_12; + state_23 = init_24_arg_1; + SORT_1 init_26_arg_1 = var_12; + state_25 = init_26_arg_1; + SORT_1 init_28_arg_1 = var_12; + state_27 = init_28_arg_1; + for (;;) { + // Getting external input values ... + input_44 = __VERIFIER_nondet_ushort(); + input_44 = input_44 & mask_SORT_3; + input_46 = __VERIFIER_nondet_ushort(); + input_46 = input_46 & mask_SORT_3; + input_48 = __VERIFIER_nondet_ushort(); + input_48 = input_48 & mask_SORT_3; + input_50 = __VERIFIER_nondet_uchar(); + input_50 = input_50 & mask_SORT_1; + input_52 = __VERIFIER_nondet_uchar(); + input_52 = input_52 & mask_SORT_1; + input_54 = __VERIFIER_nondet_uchar(); + input_54 = input_54 & mask_SORT_1; + input_56 = __VERIFIER_nondet_uchar(); + input_56 = input_56 & mask_SORT_1; + input_58 = __VERIFIER_nondet_uchar(); + input_58 = input_58 & mask_SORT_1; + input_60 = __VERIFIER_nondet_uchar(); + input_60 = input_60 & mask_SORT_1; + input_64 = __VERIFIER_nondet_uchar(); + input_64 = input_64 & mask_SORT_1; + input_74 = __VERIFIER_nondet_uchar(); + input_74 = input_74 & mask_SORT_1; + input_78 = __VERIFIER_nondet_uchar(); + input_78 = input_78 & mask_SORT_1; + input_81 = __VERIFIER_nondet_uchar(); + input_81 = input_81 & mask_SORT_1; + input_96 = __VERIFIER_nondet_uchar(); + input_96 = input_96 & mask_SORT_1; + input_100 = __VERIFIER_nondet_uchar(); + input_100 = input_100 & mask_SORT_1; + // Assuming invariants ... + // Asserting properties ... + SORT_1 var_29_arg_0 = state_13; + SORT_1 var_29_arg_1 = ~state_15; + var_29_arg_1 = var_29_arg_1 & mask_SORT_1; + SORT_1 var_29 = var_29_arg_0 & var_29_arg_1; + SORT_1 var_30_arg_0 = var_29; + SORT_1 var_30_arg_1 = ~state_17; + var_30_arg_1 = var_30_arg_1 & mask_SORT_1; + SORT_1 var_30 = var_30_arg_0 & var_30_arg_1; + SORT_1 var_31_arg_0 = var_30; + SORT_1 var_31_arg_1 = state_19; + SORT_1 var_31 = var_31_arg_0 & var_31_arg_1; + SORT_1 var_32_arg_0 = var_31; + SORT_1 var_32_arg_1 = ~state_21; + var_32_arg_1 = var_32_arg_1 & mask_SORT_1; + SORT_1 var_32 = var_32_arg_0 & var_32_arg_1; + SORT_1 var_33_arg_0 = var_32; + SORT_1 var_33_arg_1 = ~state_23; + var_33_arg_1 = var_33_arg_1 & mask_SORT_1; + SORT_1 var_33 = var_33_arg_0 & var_33_arg_1; + SORT_3 var_35_arg_0 = var_34; + SORT_3 var_35_arg_1 = state_6; + SORT_1 var_35 = var_35_arg_0 == var_35_arg_1; + SORT_1 var_36_arg_0 = var_33; + SORT_1 var_36_arg_1 = var_35; + SORT_1 var_36 = var_36_arg_0 & var_36_arg_1; + SORT_3 var_38_arg_0 = var_37; + SORT_3 var_38_arg_1 = state_8; + SORT_1 var_38 = var_38_arg_0 == var_38_arg_1; + SORT_1 var_39_arg_0 = var_36; + SORT_1 var_39_arg_1 = var_38; + SORT_1 var_39 = var_39_arg_0 & var_39_arg_1; + SORT_3 var_40_arg_0 = var_37; + SORT_3 var_40_arg_1 = state_10; + SORT_1 var_40 = var_40_arg_0 == var_40_arg_1; + SORT_1 var_41_arg_0 = var_39; + SORT_1 var_41_arg_1 = var_40; + SORT_1 var_41 = var_41_arg_0 & var_41_arg_1; + SORT_1 var_42_arg_0 = state_27; + SORT_1 var_42_arg_1 = var_41; + SORT_1 var_42 = var_42_arg_0 & var_42_arg_1; + var_42 = var_42 & mask_SORT_1; + SORT_1 bad_43_arg_0 = var_42; + __VERIFIER_assert(!(bad_43_arg_0)); + // Computing next states ... + SORT_3 next_45_arg_1 = input_44; + SORT_3 next_47_arg_1 = input_46; + SORT_3 next_49_arg_1 = input_48; + SORT_1 next_51_arg_1 = input_50; + SORT_1 next_53_arg_1 = input_52; + SORT_1 next_55_arg_1 = input_54; + SORT_1 next_57_arg_1 = input_56; + SORT_1 next_59_arg_1 = input_58; + SORT_1 next_61_arg_1 = input_60; + SORT_1 next_63_arg_1 = var_62; + SORT_3 var_67_arg_0 = input_44; + SORT_3 var_67_arg_1 = var_66; + SORT_4 var_67 = ((SORT_4)var_67_arg_0 << 16) | var_67_arg_1; + SORT_4 var_69_arg_0 = var_67; + var_69_arg_0 = (var_69_arg_0 & msb_SORT_4) ? (var_69_arg_0 | ~mask_SORT_4) : (var_69_arg_0 & mask_SORT_4); + SORT_4 var_69_arg_1 = var_68; + SORT_4 var_69 = (int)var_69_arg_0 >> var_69_arg_1; + var_69 = (var_69_arg_0 & msb_SORT_4) ? (var_69 | ~(mask_SORT_4 >> var_69_arg_1)) : var_69; + var_69 = var_69 & mask_SORT_4; + SORT_4 var_70_arg_0 = var_65; + SORT_4 var_70_arg_1 = var_69; + SORT_1 var_70 = var_70_arg_0 <= var_70_arg_1; + SORT_1 var_71_arg_0 = input_50; + SORT_1 var_71_arg_1 = ~var_70; + var_71_arg_1 = var_71_arg_1 & mask_SORT_1; + SORT_1 var_71 = var_71_arg_0 & var_71_arg_1; + SORT_1 var_72_arg_0 = ~input_64; + var_72_arg_0 = var_72_arg_0 & mask_SORT_1; + SORT_1 var_72_arg_1 = var_71; + SORT_1 var_72 = var_72_arg_0 | var_72_arg_1; + SORT_1 var_73_arg_0 = input_52; + SORT_1 var_73_arg_1 = input_64; + SORT_1 var_73 = var_73_arg_0 | var_73_arg_1; + SORT_1 var_75_arg_0 = var_73; + SORT_1 var_75_arg_1 = ~input_74; + var_75_arg_1 = var_75_arg_1 & mask_SORT_1; + SORT_1 var_75 = var_75_arg_0 | var_75_arg_1; + SORT_1 var_76_arg_0 = var_72; + SORT_1 var_76_arg_1 = var_75; + SORT_1 var_76 = var_76_arg_0 & var_76_arg_1; + SORT_1 var_77_arg_0 = input_54; + SORT_1 var_77_arg_1 = input_74; + SORT_1 var_77 = var_77_arg_0 | var_77_arg_1; + SORT_1 var_79_arg_0 = var_77; + SORT_1 var_79_arg_1 = ~input_78; + var_79_arg_1 = var_79_arg_1 & mask_SORT_1; + SORT_1 var_79 = var_79_arg_0 | var_79_arg_1; + SORT_1 var_80_arg_0 = var_76; + SORT_1 var_80_arg_1 = var_79; + SORT_1 var_80 = var_80_arg_0 & var_80_arg_1; + SORT_1 var_82_arg_0 = input_64; + SORT_3 var_82_arg_1 = input_44; + SORT_3 var_82_arg_2 = input_46; + SORT_3 var_82 = var_82_arg_0 ? var_82_arg_1 : var_82_arg_2; + SORT_3 var_83_arg_0 = var_82; + SORT_3 var_83_arg_1 = var_66; + SORT_4 var_83 = ((SORT_4)var_83_arg_0 << 16) | var_83_arg_1; + SORT_4 var_84_arg_0 = var_83; + var_84_arg_0 = (var_84_arg_0 & msb_SORT_4) ? (var_84_arg_0 | ~mask_SORT_4) : (var_84_arg_0 & mask_SORT_4); + SORT_4 var_84_arg_1 = var_68; + SORT_4 var_84 = (int)var_84_arg_0 >> var_84_arg_1; + var_84 = (var_84_arg_0 & msb_SORT_4) ? (var_84 | ~(mask_SORT_4 >> var_84_arg_1)) : var_84; + SORT_4 var_85_arg_0 = var_69; + SORT_4 var_85_arg_1 = var_84; + SORT_4 var_85 = var_85_arg_0 + var_85_arg_1; + SORT_4 var_86_arg_0 = var_85; + SORT_3 var_86 = var_86_arg_0 >> 0; + SORT_1 var_87_arg_0 = input_74; + SORT_3 var_87_arg_1 = var_86; + SORT_3 var_87_arg_2 = var_82; + SORT_3 var_87 = var_87_arg_0 ? var_87_arg_1 : var_87_arg_2; + var_87 = var_87 & mask_SORT_3; + SORT_1 var_88_arg_0 = input_78; + SORT_3 var_88_arg_1 = var_87; + SORT_3 var_88_arg_2 = input_44; + SORT_3 var_88 = var_88_arg_0 ? var_88_arg_1 : var_88_arg_2; + SORT_3 var_89_arg_0 = var_88; + SORT_3 var_89_arg_1 = var_66; + SORT_4 var_89 = ((SORT_4)var_89_arg_0 << 16) | var_89_arg_1; + SORT_4 var_90_arg_0 = var_89; + var_90_arg_0 = (var_90_arg_0 & msb_SORT_4) ? (var_90_arg_0 | ~mask_SORT_4) : (var_90_arg_0 & mask_SORT_4); + SORT_4 var_90_arg_1 = var_68; + SORT_4 var_90 = (int)var_90_arg_0 >> var_90_arg_1; + var_90 = (var_90_arg_0 & msb_SORT_4) ? (var_90 | ~(mask_SORT_4 >> var_90_arg_1)) : var_90; + var_90 = var_90 & mask_SORT_4; + SORT_4 var_91_arg_0 = var_65; + SORT_4 var_91_arg_1 = var_90; + SORT_1 var_91 = var_91_arg_0 <= var_91_arg_1; + SORT_1 var_92_arg_0 = input_56; + SORT_1 var_92_arg_1 = ~var_91; + var_92_arg_1 = var_92_arg_1 & mask_SORT_1; + SORT_1 var_92 = var_92_arg_0 & var_92_arg_1; + SORT_1 var_93_arg_0 = ~input_81; + var_93_arg_0 = var_93_arg_0 & mask_SORT_1; + SORT_1 var_93_arg_1 = var_92; + SORT_1 var_93 = var_93_arg_0 | var_93_arg_1; + SORT_1 var_94_arg_0 = var_80; + SORT_1 var_94_arg_1 = var_93; + SORT_1 var_94 = var_94_arg_0 & var_94_arg_1; + SORT_1 var_95_arg_0 = input_58; + SORT_1 var_95_arg_1 = input_81; + SORT_1 var_95 = var_95_arg_0 | var_95_arg_1; + SORT_1 var_97_arg_0 = var_95; + SORT_1 var_97_arg_1 = ~input_96; + var_97_arg_1 = var_97_arg_1 & mask_SORT_1; + SORT_1 var_97 = var_97_arg_0 | var_97_arg_1; + SORT_1 var_98_arg_0 = var_94; + SORT_1 var_98_arg_1 = var_97; + SORT_1 var_98 = var_98_arg_0 & var_98_arg_1; + SORT_1 var_99_arg_0 = input_60; + SORT_1 var_99_arg_1 = input_96; + SORT_1 var_99 = var_99_arg_0 | var_99_arg_1; + SORT_1 var_101_arg_0 = var_99; + SORT_1 var_101_arg_1 = ~input_100; + var_101_arg_1 = var_101_arg_1 & mask_SORT_1; + SORT_1 var_101 = var_101_arg_0 | var_101_arg_1; + SORT_1 var_102_arg_0 = var_98; + SORT_1 var_102_arg_1 = var_101; + SORT_1 var_102 = var_102_arg_0 & var_102_arg_1; + SORT_1 var_103_arg_0 = input_64; + SORT_1 var_103_arg_1 = input_74; + SORT_1 var_103 = var_103_arg_0 | var_103_arg_1; + SORT_1 var_104_arg_0 = input_78; + SORT_1 var_104_arg_1 = var_103; + SORT_1 var_104 = var_104_arg_0 | var_104_arg_1; + SORT_1 var_105_arg_0 = input_81; + SORT_1 var_105_arg_1 = var_104; + SORT_1 var_105 = var_105_arg_0 | var_105_arg_1; + SORT_1 var_106_arg_0 = input_96; + SORT_1 var_106_arg_1 = var_105; + SORT_1 var_106 = var_106_arg_0 | var_106_arg_1; + SORT_1 var_107_arg_0 = input_100; + SORT_1 var_107_arg_1 = var_106; + SORT_1 var_107 = var_107_arg_0 | var_107_arg_1; + SORT_1 var_108_arg_0 = var_102; + SORT_1 var_108_arg_1 = var_107; + SORT_1 var_108 = var_108_arg_0 & var_108_arg_1; + SORT_1 var_109_arg_0 = input_50; + SORT_1 var_109_arg_1 = input_52; + SORT_1 var_109 = var_109_arg_0 & var_109_arg_1; + SORT_1 var_110_arg_0 = input_50; + SORT_1 var_110_arg_1 = input_52; + SORT_1 var_110 = var_110_arg_0 | var_110_arg_1; + SORT_1 var_111_arg_0 = input_54; + SORT_1 var_111_arg_1 = var_110; + SORT_1 var_111 = var_111_arg_0 & var_111_arg_1; + SORT_1 var_112_arg_0 = var_109; + SORT_1 var_112_arg_1 = var_111; + SORT_1 var_112 = var_112_arg_0 | var_112_arg_1; + SORT_1 var_113_arg_0 = input_54; + SORT_1 var_113_arg_1 = var_110; + SORT_1 var_113 = var_113_arg_0 | var_113_arg_1; + SORT_1 var_114_arg_0 = ~var_112; + var_114_arg_0 = var_114_arg_0 & mask_SORT_1; + SORT_1 var_114_arg_1 = var_113; + SORT_1 var_114 = var_114_arg_0 & var_114_arg_1; + SORT_1 var_115_arg_0 = input_56; + SORT_1 var_115_arg_1 = input_58; + SORT_1 var_115 = var_115_arg_0 & var_115_arg_1; + SORT_1 var_116_arg_0 = input_56; + SORT_1 var_116_arg_1 = input_58; + SORT_1 var_116 = var_116_arg_0 | var_116_arg_1; + SORT_1 var_117_arg_0 = input_60; + SORT_1 var_117_arg_1 = var_116; + SORT_1 var_117 = var_117_arg_0 & var_117_arg_1; + SORT_1 var_118_arg_0 = var_115; + SORT_1 var_118_arg_1 = var_117; + SORT_1 var_118 = var_118_arg_0 | var_118_arg_1; + SORT_1 var_119_arg_0 = var_114; + SORT_1 var_119_arg_1 = ~var_118; + var_119_arg_1 = var_119_arg_1 & mask_SORT_1; + SORT_1 var_119 = var_119_arg_0 & var_119_arg_1; + SORT_1 var_120_arg_0 = input_60; + SORT_1 var_120_arg_1 = var_116; + SORT_1 var_120 = var_120_arg_0 | var_120_arg_1; + SORT_1 var_121_arg_0 = var_119; + SORT_1 var_121_arg_1 = var_120; + SORT_1 var_121 = var_121_arg_0 & var_121_arg_1; + SORT_1 var_122_arg_0 = var_108; + SORT_1 var_122_arg_1 = var_121; + SORT_1 var_122 = var_122_arg_0 & var_122_arg_1; + SORT_1 var_123_arg_0 = var_73; + SORT_1 var_123_arg_1 = ~input_74; + var_123_arg_1 = var_123_arg_1 & mask_SORT_1; + SORT_1 var_123 = var_123_arg_0 & var_123_arg_1; + var_123 = var_123 & mask_SORT_1; + SORT_1 var_124_arg_0 = input_50; + SORT_1 var_124_arg_1 = ~input_64; + var_124_arg_1 = var_124_arg_1 & mask_SORT_1; + SORT_1 var_124 = var_124_arg_0 & var_124_arg_1; + SORT_1 var_125_arg_0 = var_124; + SORT_1 var_125_arg_1 = input_78; + SORT_1 var_125 = var_125_arg_0 | var_125_arg_1; + var_125 = var_125 & mask_SORT_1; + SORT_1 var_126_arg_0 = var_123; + SORT_1 var_126_arg_1 = var_125; + SORT_1 var_126 = var_126_arg_0 & var_126_arg_1; + SORT_1 var_127_arg_0 = var_77; + SORT_1 var_127_arg_1 = ~input_78; + var_127_arg_1 = var_127_arg_1 & mask_SORT_1; + SORT_1 var_127 = var_127_arg_0 & var_127_arg_1; + var_127 = var_127 & mask_SORT_1; + SORT_1 var_128_arg_0 = var_123; + SORT_1 var_128_arg_1 = var_125; + SORT_1 var_128 = var_128_arg_0 | var_128_arg_1; + SORT_1 var_129_arg_0 = var_127; + SORT_1 var_129_arg_1 = var_128; + SORT_1 var_129 = var_129_arg_0 & var_129_arg_1; + SORT_1 var_130_arg_0 = var_126; + SORT_1 var_130_arg_1 = var_129; + SORT_1 var_130 = var_130_arg_0 | var_130_arg_1; + SORT_1 var_131_arg_0 = var_127; + SORT_1 var_131_arg_1 = var_128; + SORT_1 var_131 = var_131_arg_0 | var_131_arg_1; + SORT_1 var_132_arg_0 = ~var_130; + var_132_arg_0 = var_132_arg_0 & mask_SORT_1; + SORT_1 var_132_arg_1 = var_131; + SORT_1 var_132 = var_132_arg_0 & var_132_arg_1; + SORT_1 var_133_arg_0 = var_95; + SORT_1 var_133_arg_1 = ~input_96; + var_133_arg_1 = var_133_arg_1 & mask_SORT_1; + SORT_1 var_133 = var_133_arg_0 & var_133_arg_1; + var_133 = var_133 & mask_SORT_1; + SORT_1 var_134_arg_0 = input_56; + SORT_1 var_134_arg_1 = ~input_81; + var_134_arg_1 = var_134_arg_1 & mask_SORT_1; + SORT_1 var_134 = var_134_arg_0 & var_134_arg_1; + SORT_1 var_135_arg_0 = var_134; + SORT_1 var_135_arg_1 = input_100; + SORT_1 var_135 = var_135_arg_0 | var_135_arg_1; + var_135 = var_135 & mask_SORT_1; + SORT_1 var_136_arg_0 = var_133; + SORT_1 var_136_arg_1 = var_135; + SORT_1 var_136 = var_136_arg_0 & var_136_arg_1; + SORT_1 var_137_arg_0 = var_99; + SORT_1 var_137_arg_1 = ~input_100; + var_137_arg_1 = var_137_arg_1 & mask_SORT_1; + SORT_1 var_137 = var_137_arg_0 & var_137_arg_1; + var_137 = var_137 & mask_SORT_1; + SORT_1 var_138_arg_0 = var_133; + SORT_1 var_138_arg_1 = var_135; + SORT_1 var_138 = var_138_arg_0 | var_138_arg_1; + SORT_1 var_139_arg_0 = var_137; + SORT_1 var_139_arg_1 = var_138; + SORT_1 var_139 = var_139_arg_0 & var_139_arg_1; + SORT_1 var_140_arg_0 = var_136; + SORT_1 var_140_arg_1 = var_139; + SORT_1 var_140 = var_140_arg_0 | var_140_arg_1; + SORT_1 var_141_arg_0 = var_132; + SORT_1 var_141_arg_1 = ~var_140; + var_141_arg_1 = var_141_arg_1 & mask_SORT_1; + SORT_1 var_141 = var_141_arg_0 & var_141_arg_1; + SORT_1 var_142_arg_0 = var_137; + SORT_1 var_142_arg_1 = var_138; + SORT_1 var_142 = var_142_arg_0 | var_142_arg_1; + SORT_1 var_143_arg_0 = var_141; + SORT_1 var_143_arg_1 = var_142; + SORT_1 var_143 = var_143_arg_0 & var_143_arg_1; + SORT_1 var_144_arg_0 = var_122; + SORT_1 var_144_arg_1 = var_143; + SORT_1 var_144 = var_144_arg_0 & var_144_arg_1; + SORT_1 var_145_arg_0 = input_81; + SORT_3 var_145_arg_1 = var_88; + SORT_3 var_145_arg_2 = input_48; + SORT_3 var_145 = var_145_arg_0 ? var_145_arg_1 : var_145_arg_2; + SORT_3 var_146_arg_0 = var_145; + SORT_3 var_146_arg_1 = var_66; + SORT_4 var_146 = ((SORT_4)var_146_arg_0 << 16) | var_146_arg_1; + SORT_4 var_147_arg_0 = var_146; + var_147_arg_0 = (var_147_arg_0 & msb_SORT_4) ? (var_147_arg_0 | ~mask_SORT_4) : (var_147_arg_0 & mask_SORT_4); + SORT_4 var_147_arg_1 = var_68; + SORT_4 var_147 = (int)var_147_arg_0 >> var_147_arg_1; + var_147 = (var_147_arg_0 & msb_SORT_4) ? (var_147 | ~(mask_SORT_4 >> var_147_arg_1)) : var_147; + SORT_4 var_148_arg_0 = var_90; + SORT_4 var_148_arg_1 = var_147; + SORT_4 var_148 = var_148_arg_0 + var_148_arg_1; + SORT_4 var_149_arg_0 = var_148; + SORT_3 var_149 = var_149_arg_0 >> 0; + SORT_1 var_150_arg_0 = input_96; + SORT_3 var_150_arg_1 = var_149; + SORT_3 var_150_arg_2 = var_145; + SORT_3 var_150 = var_150_arg_0 ? var_150_arg_1 : var_150_arg_2; + var_150 = var_150 & mask_SORT_3; + SORT_1 var_151_arg_0 = input_100; + SORT_3 var_151_arg_1 = var_150; + SORT_3 var_151_arg_2 = var_88; + SORT_3 var_151 = var_151_arg_0 ? var_151_arg_1 : var_151_arg_2; + var_151 = var_151 & mask_SORT_3; + SORT_3 var_152_arg_0 = var_151; + SORT_3 var_152_arg_1 = state_6; + SORT_1 var_152 = var_152_arg_0 == var_152_arg_1; + SORT_1 var_153_arg_0 = var_144; + SORT_1 var_153_arg_1 = var_152; + SORT_1 var_153 = var_153_arg_0 & var_153_arg_1; + SORT_3 var_154_arg_0 = var_87; + SORT_3 var_154_arg_1 = state_8; + SORT_1 var_154 = var_154_arg_0 == var_154_arg_1; + SORT_1 var_155_arg_0 = var_153; + SORT_1 var_155_arg_1 = var_154; + SORT_1 var_155 = var_155_arg_0 & var_155_arg_1; + SORT_3 var_156_arg_0 = var_150; + SORT_3 var_156_arg_1 = state_10; + SORT_1 var_156 = var_156_arg_0 == var_156_arg_1; + SORT_1 var_157_arg_0 = var_155; + SORT_1 var_157_arg_1 = var_156; + SORT_1 var_157 = var_157_arg_0 & var_157_arg_1; + SORT_1 var_158_arg_0 = var_125; + SORT_1 var_158_arg_1 = state_13; + SORT_1 var_158 = var_158_arg_0 == var_158_arg_1; + SORT_1 var_159_arg_0 = var_157; + SORT_1 var_159_arg_1 = var_158; + SORT_1 var_159 = var_159_arg_0 & var_159_arg_1; + SORT_1 var_160_arg_0 = var_123; + SORT_1 var_160_arg_1 = state_15; + SORT_1 var_160 = var_160_arg_0 == var_160_arg_1; + SORT_1 var_161_arg_0 = var_159; + SORT_1 var_161_arg_1 = var_160; + SORT_1 var_161 = var_161_arg_0 & var_161_arg_1; + SORT_1 var_162_arg_0 = var_127; + SORT_1 var_162_arg_1 = state_17; + SORT_1 var_162 = var_162_arg_0 == var_162_arg_1; + SORT_1 var_163_arg_0 = var_161; + SORT_1 var_163_arg_1 = var_162; + SORT_1 var_163 = var_163_arg_0 & var_163_arg_1; + SORT_1 var_164_arg_0 = var_135; + SORT_1 var_164_arg_1 = state_19; + SORT_1 var_164 = var_164_arg_0 == var_164_arg_1; + SORT_1 var_165_arg_0 = var_163; + SORT_1 var_165_arg_1 = var_164; + SORT_1 var_165 = var_165_arg_0 & var_165_arg_1; + SORT_1 var_166_arg_0 = var_133; + SORT_1 var_166_arg_1 = state_21; + SORT_1 var_166 = var_166_arg_0 == var_166_arg_1; + SORT_1 var_167_arg_0 = var_165; + SORT_1 var_167_arg_1 = var_166; + SORT_1 var_167 = var_167_arg_0 & var_167_arg_1; + SORT_1 var_168_arg_0 = var_137; + SORT_1 var_168_arg_1 = state_23; + SORT_1 var_168 = var_168_arg_0 == var_168_arg_1; + SORT_1 var_169_arg_0 = var_167; + SORT_1 var_169_arg_1 = var_168; + SORT_1 var_169 = var_169_arg_0 & var_169_arg_1; + SORT_1 var_170_arg_0 = var_169; + SORT_1 var_170_arg_1 = state_27; + SORT_1 var_170 = var_170_arg_0 & var_170_arg_1; + SORT_4 var_172_arg_0 = var_171; + SORT_4 var_172_arg_1 = var_69; + SORT_1 var_172 = var_172_arg_0 == var_172_arg_1; + SORT_1 var_173_arg_0 = state_25; + SORT_1 var_173_arg_1 = var_170; + SORT_1 var_173_arg_2 = var_172; + SORT_1 var_173 = var_173_arg_0 ? var_173_arg_1 : var_173_arg_2; + SORT_1 next_174_arg_1 = var_173; + // Assigning next states ... + state_6 = next_45_arg_1; + state_8 = next_47_arg_1; + state_10 = next_49_arg_1; + state_13 = next_51_arg_1; + state_15 = next_53_arg_1; + state_17 = next_55_arg_1; + state_19 = next_57_arg_1; + state_21 = next_59_arg_1; + state_23 = next_61_arg_1; + state_25 = next_63_arg_1; + state_27 = next_174_arg_1; + } + return 0; +} \ No newline at end of file diff --git a/tools/klee/main.cpp b/tools/klee/main.cpp index b1dee0fb34..a0f0e8fd59 100644 --- a/tools/klee/main.cpp +++ b/tools/klee/main.cpp @@ -89,6 +89,11 @@ cl::opt cl::desc("Do not generate any test files (default=false)"), cl::cat(TestCaseCat)); +cl::opt WriteKTests( + "write-ktests", cl::init(true), + cl::desc("Write .ktest files for each test case (default=true)"), + cl::cat(TestCaseCat)); + cl::opt WriteCVCs("write-cvcs", cl::desc("Write .cvc files for each test case (default=false)"), @@ -341,10 +346,30 @@ cl::opt Libcxx( "libcxx", cl::desc("Link the llvm libc++ library into the bitcode (default=false)"), cl::init(false), cl::cat(LinkCat)); + +cl::OptionCategory + TestCompCat("Options specific to Test-Comp", + "These are options specific to the Test-Comp competition."); + +cl::opt WriteXMLTests("write-xml-tests", + cl::desc("Write XML-formated tests"), + cl::init(false), cl::cat(TestCompCat)); + +cl::opt + XMLMetadataProgramFile("xml-metadata-programfile", + cl::desc("Original file name for xml metadata"), + cl::cat(TestCompCat)); + +cl::opt XMLMetadataProgramHash( + "xml-metadata-programhash", + llvm::cl::desc("Test-Comp hash sum of original file for xml metadata"), + llvm::cl::cat(TestCompCat)); + } // namespace namespace klee { extern cl::opt MaxTime; +extern cl::opt FunctionCallReproduce; class ExecutionState; } // namespace klee @@ -384,6 +409,8 @@ class KleeHandler : public InterpreterHandler { void processTestCase(const ExecutionState &state, const char *message, const char *suffix, bool isError = false); + void writeTestCaseXML(bool isError, const KTest &out, unsigned id); + std::string getOutputFilename(const std::string &filename); std::unique_ptr openOutputFile(const std::string &filename); @@ -552,7 +579,9 @@ void KleeHandler::processTestCase(const ExecutionState &state, const char *message, const char *suffix, bool isError) { unsigned id = ++m_numTotalTests; - if (!WriteNone) { + if (!WriteNone && + (FunctionCallReproduce == "" || strcmp(suffix, "assert.err") == 0 || + strcmp(suffix, "reachable.err") == 0)) { KTest ktest; ktest.numArgs = m_argc; ktest.args = m_argv; @@ -566,43 +595,66 @@ void KleeHandler::processTestCase(const ExecutionState &state, const auto start_time = time::getWallTime(); - if (success) { - if (!kTest_toFile( - &ktest, - getOutputFilename(getTestFilename("ktest", id)).c_str())) { - klee_warning("unable to write output test case, losing it"); - } else { - ++m_numGeneratedTests; + if (WriteKTests) { + + if (success) { + if (!kTest_toFile( + &ktest, + getOutputFilename(getTestFilename("ktest", id)).c_str())) { + klee_warning("unable to write output test case, losing it"); + } else { + ++m_numGeneratedTests; + } + + if (WriteStates) { + auto f = openTestFile("state", id); + m_interpreter->logState(state, id, f); + } + } + + if (message) { + auto f = openTestFile(suffix, id); + if (f) + *f << message; } - if (WriteStates) { - auto f = openTestFile("state", id); - m_interpreter->logState(state, id, f); + if (m_pathWriter) { + std::vector concreteBranches; + m_pathWriter->readStream(m_interpreter->getPathStreamID(state), + concreteBranches); + auto f = openTestFile("path", id); + if (f) { + for (const auto &branch : concreteBranches) { + *f << branch << '\n'; + } + } } } - for (unsigned i = 0; i < ktest.numObjects; i++) { - delete[] ktest.objects[i].bytes; - delete[] ktest.objects[i].pointers; + if (message || WriteKQueries) { + std::string constraints; + m_interpreter->getConstraintLog(state, constraints, Interpreter::KQUERY); + auto f = openTestFile("kquery", id); + if (f) + *f << constraints; } - delete[] ktest.objects; - if (message) { - auto f = openTestFile(suffix, id); + if (WriteCVCs) { + // FIXME: If using Z3 as the core solver the emitted file is actually + // SMT-LIBv2 not CVC which is a bit confusing + std::string constraints; + m_interpreter->getConstraintLog(state, constraints, Interpreter::STP); + auto f = openTestFile("cvc", id); if (f) - *f << message; + *f << constraints; } - if (m_pathWriter) { - std::vector concreteBranches; - m_pathWriter->readStream(m_interpreter->getPathStreamID(state), - concreteBranches); - auto f = openTestFile("path", id); - if (f) { - for (const auto &branch : concreteBranches) { - *f << branch << '\n'; - } - } + if (WriteSMT2s) { + std::string constraints; + m_interpreter->getConstraintLog(state, constraints, Interpreter::SMTLIB2); + auto f = openTestFile("smt2", id); + if (f) + *f << constraints; } if (m_symPathWriter) { @@ -617,10 +669,42 @@ void KleeHandler::processTestCase(const ExecutionState &state, } } + if (WriteKPaths) { + std::string blockPath; + m_interpreter->getBlockPath(state, blockPath); + auto f = openTestFile("kpath", id); + if (f) + *f << blockPath; + } + + if (WriteCov) { + std::map> cov; + m_interpreter->getCoveredLines(state, cov); + auto f = openTestFile("cov", id); + if (f) { + for (const auto &entry : cov) { + for (const auto &line : entry.second) { + *f << *entry.first << ':' << line << '\n'; + } + } + } + } + + if (WriteXMLTests) { + writeTestCaseXML(message != nullptr, ktest, id); + ++m_numGeneratedTests; + } + + for (unsigned i = 0; i < ktest.numObjects; i++) { + delete[] ktest.objects[i].bytes; + delete[] ktest.objects[i].pointers; + } + delete[] ktest.objects; + if (m_numGeneratedTests == MaxTests) m_interpreter->setHaltExecution(HaltExecution::MaxTests); - if (WriteTestInfo) { + if (!WriteXMLTests && WriteTestInfo) { time::Span elapsed_time(time::getWallTime() - start_time); auto f = openTestFile("info", id); if (f) @@ -628,57 +712,70 @@ void KleeHandler::processTestCase(const ExecutionState &state, } } // if (!WriteNone) - if (WriteKQueries) { - std::string constraints; - m_interpreter->getConstraintLog(state, constraints, Interpreter::KQUERY); - auto f = openTestFile("kquery", id); - if (f) - *f << constraints; - } - - if (WriteCVCs) { - // FIXME: If using Z3 as the core solver the emitted file is actually - // SMT-LIBv2 not CVC which is a bit confusing - std::string constraints; - m_interpreter->getConstraintLog(state, constraints, Interpreter::STP); - auto f = openTestFile("cvc", id); - if (f) - *f << constraints; + if (isError && OptExitOnError) { + m_interpreter->prepareForEarlyExit(); + klee_error("EXITING ON ERROR:\n%s\n", message); } +} - if (WriteSMT2s) { - std::string constraints; - m_interpreter->getConstraintLog(state, constraints, Interpreter::SMTLIB2); - auto f = openTestFile("smt2", id); - if (f) - *f << constraints; - } +void KleeHandler::writeTestCaseXML(bool isError, const KTest &assignments, + unsigned id) { - if (WriteKPaths) { - std::string blockPath; - m_interpreter->getBlockPath(state, blockPath); - auto f = openTestFile("kpath", id); - if (f) - *f << blockPath; - } + // TODO: This is super specific to test-comp and assumes that the name is the + // type information + auto file = openTestFile("xml", id); + if (!file) + return; - if (WriteCov) { - std::map> cov; - m_interpreter->getCoveredLines(state, cov); - auto f = openTestFile("cov", id); - if (f) { - for (const auto &entry : cov) { - for (const auto &line : entry.second) { - *f << *entry.first << ':' << line << '\n'; - } - } + *file << "\n"; + *file << "\n"; + *file << "\n"; + for (unsigned i = 0; i < assignments.numObjects; i++) { + auto item = assignments.objects[i]; + std::string name(item.name); + + *file << "\t"; + // Ignore the type + auto type_size_bytes = item.numBytes * 8; + llvm::APInt v(type_size_bytes, 0, false); + for (int i = item.numBytes - 1; i >= 0; i--) { + v <<= 8; + v |= item.bytes[i]; } + // print value + + // Check if this is an unsigned type + if (name.find("u") == 0) { + v.print(*file, false); + } else if (name.rfind("*") != std::string::npos) { + // Pointer types + v.print(*file, false); + } else if (name.find("float") == 0) { + llvm::APFloat(APFloatBase::IEEEhalf(), v).print(*file); + } else if (name.find("double") == 0) { + llvm::APFloat(APFloatBase::IEEEdouble(), v).print(*file); + } else if (name.rfind("_t") != std::string::npos) { + // arbitrary type, e.g. sector_t + v.print(*file, false); + } else if (name.find("_") == 0) { + // _Bool + v.print(*file, false); + } else { + // the rest must be signed + v.print(*file, true); + } + *file << "\n"; } - - if (isError && OptExitOnError) { - m_interpreter->prepareForEarlyExit(); - klee_error("EXITING ON ERROR:\n%s\n", message); - } + *file << "\n"; } // load a .path file @@ -1278,6 +1375,47 @@ static int run_klee_on_function(int pArgc, char **pArgv, char **pEnvp, } auto startTime = std::time(nullptr); + + if (WriteXMLTests) { + // Write metadata.xml + auto meta_file = handler->openOutputFile("metadata.xml"); + if (!meta_file) + klee_error("Could not write metadata.xml"); + + *meta_file + << "\n"; + *meta_file + << "\n"; + *meta_file << "\n"; + *meta_file << "\tC\n"; + *meta_file << "\t" << PACKAGE_STRING << "\n"; + + // Assume with early exit a bug finding mode and otherwise coverage + if (OptExitOnError) + *meta_file << "\tCOVER( init(main()), FQL(COVER " + "EDGES(@CALL(__VERIFIER_error))) )\n"; + else + *meta_file << "\tCOVER( init(main()), FQL(COVER " + "EDGES(@DECISIONEDGE)) )\n"; + + // Assume the input file resembles the original source file; just exchange + // extension + *meta_file << "\t" << XMLMetadataProgramFile + << ".c\n"; + *meta_file << "\t" << XMLMetadataProgramHash + << "\n"; + *meta_file << "\t" << EntryPoint << "\n"; + *meta_file << "\t" + << finalModule->getDataLayout().getPointerSizeInBits() + << "bit\n"; + std::stringstream t; + t << std::put_time(std::localtime(&startTime), "%Y-%m-%dT%H:%M:%SZ"); + *meta_file << "\t" << t.str() << "\n"; + *meta_file << "\n"; + } + { // output clock info and start time std::stringstream startInfo; startInfo << time::getClockInfo() << "Started: " @@ -1597,13 +1735,13 @@ int main(int argc, char **argv, char **envp) { module_triple.c_str(), host_triple.c_str()); // Detect architecture - std::string opt_suffix = "64"; // Fall back to 64bit + std::string bit_suffix = "64"; // Fall back to 64bit if (module_triple.find("i686") != std::string::npos || module_triple.find("i586") != std::string::npos || module_triple.find("i486") != std::string::npos || module_triple.find("i386") != std::string::npos || module_triple.find("arm") != std::string::npos) - opt_suffix = "32"; + bit_suffix = "32"; // Add additional user-selected suffix opt_suffix += "_" + RuntimeBuild.getValue(); @@ -1800,6 +1938,10 @@ int main(int argc, char **argv, char **envp) { if (UseGuidedSearch == Interpreter::GuidanceKind::ErrorGuidance) { paths = parseStaticAnalysisInput(); + } else if (FunctionCallReproduce != "") { + klee_warning("Turns on error-guided mode to cover %s function", + FunctionCallReproduce.c_str()); + UseGuidedSearch = Interpreter::GuidanceKind::ErrorGuidance; } Interpreter::InterpreterOptions IOpts(paths); From 97cd0570652dc0d3c03cfd68143e1de249236d83 Mon Sep 17 00:00:00 2001 From: Sergey Morozov Date: Thu, 27 Jul 2023 16:15:56 +0300 Subject: [PATCH 016/103] [fix] float and double symbolics --- include/klee-test-comp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/klee-test-comp.c b/include/klee-test-comp.c index 3abfe2df5d..ecda66ba02 100644 --- a/include/klee-test-comp.c +++ b/include/klee-test-comp.c @@ -82,7 +82,7 @@ unsigned long __VERIFIER_nondet_ulong(void) { } double __VERIFIER_nondet_double(void) { - long x; + double x; klee_make_symbolic(&x, sizeof(x), "double"); return x; } @@ -96,7 +96,7 @@ void *__VERIFIER_nondet_pointer(void) { } float __VERIFIER_nondet_float(void) { - int x; + float x; klee_make_symbolic(&x, sizeof(x), "float"); return x; } From c54358b4fce1d92e2285cd9b439d695db5ab6ee1 Mon Sep 17 00:00:00 2001 From: Yurii Kostyukov Date: Thu, 21 Sep 2023 14:45:46 +0300 Subject: [PATCH 017/103] [fix] z3-tree with 0 size pool --- lib/Solver/CoreSolver.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/lib/Solver/CoreSolver.cpp b/lib/Solver/CoreSolver.cpp index e44e8c37a1..ff6f9cf76e 100644 --- a/lib/Solver/CoreSolver.cpp +++ b/lib/Solver/CoreSolver.cpp @@ -28,7 +28,11 @@ DISABLE_WARNING_POP namespace klee { std::unique_ptr createCoreSolver(CoreSolverType cst) { - bool isTreeSolver = false; + bool isTreeSolver = cst == Z3_TREE_SOLVER; + if (!isTreeSolver && MaxSolversApproxTreeInc > 0) + klee_warning("--%s option is ignored because --%s is not z3-tree", + MaxSolversApproxTreeInc.ArgStr.str().c_str(), + CoreSolverToUse.ArgStr.str().c_str()); switch (cst) { case STP_SOLVER: #ifdef ENABLE_STP @@ -56,7 +60,6 @@ std::unique_ptr createCoreSolver(CoreSolverType cst) { case DUMMY_SOLVER: return createDummySolver(); case Z3_TREE_SOLVER: - isTreeSolver = true; case Z3_SOLVER: #ifdef ENABLE_Z3 klee_message("Using Z3 solver backend"); @@ -68,8 +71,12 @@ std::unique_ptr createCoreSolver(CoreSolverType cst) { klee_message("Using Z3 core builder"); type = KLEE_CORE; #endif - if (isTreeSolver) - return std::make_unique(type, MaxSolversApproxTreeInc); + if (isTreeSolver) { + if (MaxSolversApproxTreeInc > 0) + return std::make_unique(type, MaxSolversApproxTreeInc); + klee_warning("--%s is 0, so falling back to non tree-incremental solver", + MaxSolversApproxTreeInc.ArgStr.str().c_str()); + } return std::make_unique(type); #else klee_message("Not compiled with Z3 support"); From dff6af1c874f4b8f1d73c1087fbbc738586de30c Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Fri, 22 Sep 2023 01:13:41 +0400 Subject: [PATCH 018/103] [refactor] Use `bit_suffix` explicit --- tools/klee/main.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tools/klee/main.cpp b/tools/klee/main.cpp index a0f0e8fd59..e3e87da330 100644 --- a/tools/klee/main.cpp +++ b/tools/klee/main.cpp @@ -1301,7 +1301,7 @@ createLibCWrapper(std::vector> &userModules, } static void -linkWithUclibc(StringRef libDir, std::string opt_suffix, +linkWithUclibc(StringRef libDir, std::string bit_suffix, std::string opt_suffix, std::vector> &userModules, std::vector> &libsModules) { LLVMContext &ctx = userModules[0]->getContext(); @@ -1320,10 +1320,10 @@ linkWithUclibc(StringRef libDir, std::string opt_suffix, SmallString<128> uclibcBCA(libDir); // Hack to find out bitness of .bc file - if (opt_suffix.substr(0, 2) == "32") { - llvm::sys::path::append(uclibcBCA, KLEE_UCLIBC_BCA_32_NAME); - } else if (opt_suffix.substr(0, 2) == "64") { + if (bit_suffix == "64") { llvm::sys::path::append(uclibcBCA, KLEE_UCLIBC_BCA_64_NAME); + } else if (bit_suffix == "32") { + llvm::sys::path::append(uclibcBCA, KLEE_UCLIBC_BCA_32_NAME); } else { klee_error("Cannot determine bitness of source file from the name %s", uclibcBCA.c_str()); @@ -1744,7 +1744,7 @@ int main(int argc, char **argv, char **envp) { bit_suffix = "32"; // Add additional user-selected suffix - opt_suffix += "_" + RuntimeBuild.getValue(); + std::string opt_suffix = bit_suffix + "_" + RuntimeBuild.getValue(); if (UseGuidedSearch == Interpreter::GuidanceKind::ErrorGuidance) { SimplifyModule = false; @@ -1876,7 +1876,7 @@ int main(int argc, char **argv, char **envp) { break; } case LibcType::UcLibc: - linkWithUclibc(LibraryDir, opt_suffix, loadedUserModules, + linkWithUclibc(LibraryDir, bit_suffix, opt_suffix, loadedUserModules, loadedLibsModules); break; } From e1a57bbf87416f021ba36c6097ddf0d0b7d64fb2 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Thu, 21 Sep 2023 02:48:20 +0400 Subject: [PATCH 019/103] [fix] Fix a few bugs --- lib/Core/ExecutionState.cpp | 7 ------- lib/Core/ExecutionState.h | 2 -- lib/Expr/Expr.cpp | 20 -------------------- lib/Solver/IndependentSolver.cpp | 1 - 4 files changed, 30 deletions(-) diff --git a/lib/Core/ExecutionState.cpp b/lib/Core/ExecutionState.cpp index 492e22fb9a..f1152938e7 100644 --- a/lib/Core/ExecutionState.cpp +++ b/lib/Core/ExecutionState.cpp @@ -114,15 +114,8 @@ StackFrame::StackFrame(const StackFrame &s) StackFrame::~StackFrame() { delete[] locals; } -CallStackFrame::CallStackFrame(const CallStackFrame &s) - : caller(s.caller), kf(s.kf) {} - InfoStackFrame::InfoStackFrame(KFunction *kf) : kf(kf) {} -InfoStackFrame::InfoStackFrame(const InfoStackFrame &s) - : kf(s.kf), callPathNode(s.callPathNode), - minDistToUncoveredOnReturn(s.minDistToUncoveredOnReturn) {} - /***/ ExecutionState::ExecutionState() : initPC(nullptr), pc(nullptr), prevPC(nullptr), incomingBBIndex(-1), diff --git a/lib/Core/ExecutionState.h b/lib/Core/ExecutionState.h index 69e597d278..a13b963de7 100644 --- a/lib/Core/ExecutionState.h +++ b/lib/Core/ExecutionState.h @@ -68,7 +68,6 @@ struct CallStackFrame { CallStackFrame(KInstIterator caller_, KFunction *kf_) : caller(caller_), kf(kf_) {} ~CallStackFrame() = default; - CallStackFrame(const CallStackFrame &s); bool equals(const CallStackFrame &other) const; @@ -105,7 +104,6 @@ struct InfoStackFrame { unsigned minDistToUncoveredOnReturn = 0; InfoStackFrame(KFunction *kf); - InfoStackFrame(const InfoStackFrame &s); ~InfoStackFrame() = default; }; diff --git a/lib/Expr/Expr.cpp b/lib/Expr/Expr.cpp index e34239682a..ccf6eab730 100644 --- a/lib/Expr/Expr.cpp +++ b/lib/Expr/Expr.cpp @@ -1635,21 +1635,6 @@ ref ConcatExpr::create(const ref &l, const ref &r) { if (ConstantExpr *rCE = dyn_cast(r)) return lCE->Concat(rCE); - if (isa(l) || isa(r)) { - if (SelectExpr *se = dyn_cast(l)) { - if (isa(se->trueExpr)) { - return SelectExpr::create(se->cond, ConcatExpr::create(se->trueExpr, r), - ConcatExpr::create(se->falseExpr, r)); - } - } - if (SelectExpr *se = dyn_cast(r)) { - if (isa(se->trueExpr)) { - return SelectExpr::create(se->cond, ConcatExpr::create(l, se->trueExpr), - ConcatExpr::create(l, se->falseExpr)); - } - } - } - // Merge contiguous Extracts if (ExtractExpr *ee_left = dyn_cast(l)) { if (ExtractExpr *ee_right = dyn_cast(r)) { @@ -1707,11 +1692,6 @@ ref ExtractExpr::create(ref expr, unsigned off, Width w) { } else if (ConstantExpr *CE = dyn_cast(expr)) { return CE->Extract(off, w); } else if (SelectExpr *se = dyn_cast(expr)) { - if (isa(se->trueExpr)) { - return SelectExpr::create(se->cond, - ExtractExpr::create(se->trueExpr, off, w), - ExtractExpr::create(se->falseExpr, off, w)); - } } else { // Extract(Concat) if (ConcatExpr *ce = dyn_cast(expr)) { diff --git a/lib/Solver/IndependentSolver.cpp b/lib/Solver/IndependentSolver.cpp index 5d16a15a09..50e518fb59 100644 --- a/lib/Solver/IndependentSolver.cpp +++ b/lib/Solver/IndependentSolver.cpp @@ -218,7 +218,6 @@ bool IndependentSolver::computeInitialValues( // satisfy the query. ref arrayConstantSize = dyn_cast(retMap.evaluate(arr->size)); - arrayConstantSize->dump(); assert(arrayConstantSize && "Array of symbolic size had not receive value for size!"); SparseStorage ret(arrayConstantSize->getZExtValue()); From 026da463e728bf4f20d942aee85f10cb6236447b Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Thu, 21 Sep 2023 18:58:00 +0400 Subject: [PATCH 020/103] [fix] Make the tests independent of default search strategies --- test/Solver/CrosscheckCoreStpZ3.c | 6 +++--- test/Solver/CrosscheckZ3AndZ3TreeInc.c | 8 ++++---- test/Solver/DummySolver.c | 2 +- test/Solver/ValidatingSolver.c | 6 +++--- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/test/Solver/CrosscheckCoreStpZ3.c b/test/Solver/CrosscheckCoreStpZ3.c index 471f7d40e3..968cc8a795 100644 --- a/test/Solver/CrosscheckCoreStpZ3.c +++ b/test/Solver/CrosscheckCoreStpZ3.c @@ -2,9 +2,9 @@ // REQUIRES: z3 // RUN: %clang %s -emit-llvm %O0opt -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --solver-backend=stp --use-forked-solver=false --debug-crosscheck-core-solver=z3 %t1.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --solver-backend=stp --use-forked-solver=false --debug-crosscheck-core-solver=z3 --use-guided-search=none %t1.bc 2>&1 | FileCheck %s #include "ExerciseSolver.c.inc" -// CHECK: KLEE: done: completed paths = 9 -// CHECK: KLEE: done: partially completed paths = 5 +// CHECK: KLEE: done: completed paths = 18 +// CHECK: KLEE: done: partially completed paths = 0 diff --git a/test/Solver/CrosscheckZ3AndZ3TreeInc.c b/test/Solver/CrosscheckZ3AndZ3TreeInc.c index 9c4c499a26..b29050cd4a 100644 --- a/test/Solver/CrosscheckZ3AndZ3TreeInc.c +++ b/test/Solver/CrosscheckZ3AndZ3TreeInc.c @@ -1,11 +1,11 @@ // REQUIRES: z3 // RUN: %clang %s -emit-llvm %O0opt -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --search=bfs --solver-backend=z3-tree --max-solvers-approx-tree-inc=4 --debug-crosscheck-core-solver=z3 --debug-z3-validate-models --debug-assignment-validating-solver --use-cex-cache=false %t1.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --search=bfs --solver-backend=z3-tree --max-solvers-approx-tree-inc=4 --debug-crosscheck-core-solver=z3 --debug-z3-validate-models --debug-assignment-validating-solver --use-cex-cache=false --use-guided-search=none %t1.bc 2>&1 | FileCheck %s // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --search=dfs --solver-backend=z3-tree --max-solvers-approx-tree-inc=64 --debug-crosscheck-core-solver=z3 --debug-z3-validate-models --debug-assignment-validating-solver --use-cex-cache=false %t1.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --search=dfs --solver-backend=z3-tree --max-solvers-approx-tree-inc=64 --debug-crosscheck-core-solver=z3 --debug-z3-validate-models --debug-assignment-validating-solver --use-cex-cache=false --use-guided-search=none %t1.bc 2>&1 | FileCheck %s #include "ExerciseSolver.c.inc" -// CHECK: KLEE: done: completed paths = 10 -// CHECK: KLEE: done: partially completed paths = 4 +// CHECK: KLEE: done: completed paths = 18 +// CHECK: KLEE: done: partially completed paths = 0 diff --git a/test/Solver/DummySolver.c b/test/Solver/DummySolver.c index 51c35e936f..9242396854 100644 --- a/test/Solver/DummySolver.c +++ b/test/Solver/DummySolver.c @@ -1,6 +1,6 @@ // RUN: %clang %s -emit-llvm %O0opt -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --solver-backend=dummy %t1.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --search=bfs --solver-backend=dummy --use-guided-search=none %t1.bc 2>&1 | FileCheck %s #include "ExerciseSolver.c.inc" diff --git a/test/Solver/ValidatingSolver.c b/test/Solver/ValidatingSolver.c index d492ff9264..6af3496f82 100644 --- a/test/Solver/ValidatingSolver.c +++ b/test/Solver/ValidatingSolver.c @@ -1,8 +1,8 @@ // RUN: %clang %s -emit-llvm %O0opt -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --debug-validate-solver --debug-assignment-validating-solver %t1.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --search=bfs --debug-validate-solver --debug-assignment-validating-solver --use-guided-search=none %t1.bc 2>&1 | FileCheck %s #include "ExerciseSolver.c.inc" -// CHECK: KLEE: done: completed paths = 9 -// CHECK: KLEE: done: partially completed paths = 5 \ No newline at end of file +// CHECK: KLEE: done: completed paths = 18 +// CHECK: KLEE: done: partially completed paths = 0 \ No newline at end of file From aa7528b558b7f7c34fc47457fd5a12fea4613f56 Mon Sep 17 00:00:00 2001 From: Yurii Kostyukov Date: Tue, 26 Sep 2023 14:36:30 +0300 Subject: [PATCH 021/103] [fix] Incremental DT with no frames --- include/klee/ADT/Incremental.h | 14 +- .../pals_floodmax.5.2.ufo.BOUNDED-10.pals.c | 2775 +++++++++++++++++ 2 files changed, 2783 insertions(+), 6 deletions(-) create mode 100644 test/Solver/pals_floodmax.5.2.ufo.BOUNDED-10.pals.c diff --git a/include/klee/ADT/Incremental.h b/include/klee/ADT/Incremental.h index b2e8417350..6f16fd0867 100644 --- a/include/klee/ADT/Incremental.h +++ b/include/klee/ADT/Incremental.h @@ -28,6 +28,11 @@ void extend(std::vector<_Tp, _Alloc> &ths, ths.insert(ths.end(), other.begin(), other.end()); } +template +void takeAfterv(std::vector<_Tp, _Alloc> &ths, size_t n) { + std::vector<_Tp, _Alloc>(ths.begin() + n, ths.end()).swap(ths); +} + template > class inc_vector { public: @@ -131,12 +136,9 @@ class inc_vector { size_t frames_count, frame_index; take(n, frames_count, frame_index); result = *this; - std::vector<_Tp, _Alloc>(result.v.begin() + n, result.v.end()) - .swap(result.v); - std::vector(result.frame_sizes.begin() + frame_index, - result.frame_sizes.end()) - .swap(result.frame_sizes); - if (frames_count) + takeAfterv(result.v, n); + takeAfterv(result.frame_sizes, frame_index); + if (frames_count && !result.frame_sizes.empty()) result.frame_sizes[0] -= frames_count; } diff --git a/test/Solver/pals_floodmax.5.2.ufo.BOUNDED-10.pals.c b/test/Solver/pals_floodmax.5.2.ufo.BOUNDED-10.pals.c new file mode 100644 index 0000000000..4dd74f1d3c --- /dev/null +++ b/test/Solver/pals_floodmax.5.2.ufo.BOUNDED-10.pals.c @@ -0,0 +1,2775 @@ +// REQUIRES: z3 +// RUN: %clang %s -emit-llvm %O0opt -g -c -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --use-forked-solver=false --solver-backend=z3-tree --max-solvers-approx-tree-inc=16 -max-memory=6008 --optimize --skip-not-lazy-initialized -output-source=false --output-stats=false --use-sym-size-alloc=true --cex-cache-validity-cores --symbolic-allocation-threshold=8192 --function-call-reproduce=reach_error -dump-states-on-halt=true -exit-on-error-type=Assert --search=dfs -max-instructions=6000 --debug-crosscheck-core-solver=z3 --debug-z3-validate-models --debug-assignment-validating-solver --use-cex-cache=false %t1.bc 2>&1 | FileCheck -check-prefix=CHECK-VERDICT %s +// CHECK-VERDICT: KLEE: done: total instructions = 6000 +#include "klee-test-comp.c" + +extern void abort(void); +extern void __assert_fail(const char *, const char *, unsigned int, const char *) __attribute__((__nothrow__, __leaf__)) __attribute__((__noreturn__)); +void reach_error() { __assert_fail("0", "pals_floodmax.5.2.ufo.BOUNDED-10.pals.c", 3, "reach_error"); } + +// This file is part of the SV-Benchmarks collection of verification tasks: +// https://github.com/sosy-lab/sv-benchmarks +// +// SPDX-FileCopyrightText: 2013 Carnegie Mellon University +// SPDX-FileCopyrightText: 2014-2020 The SV-Benchmarks Community +// +// SPDX-License-Identifier: LicenseRef-BSD-3-Clause-Attribution-CMU + +/* Generated by CIL v. 1.6.0 */ +/* print_CIL_Input is true */ + +char __VERIFIER_nondet_char(void); +_Bool __VERIFIER_nondet_bool(void); +void assert(_Bool arg); +void abort(void); +void assume_abort_if_not(int cond) { + if (!cond) { + abort(); + } +} +typedef char msg_t; +typedef int port_t; +extern void read(port_t p, msg_t m); +extern void write(port_t p, msg_t m); +msg_t nomsg = (msg_t)-1; +port_t p12; +char p12_old; +char p12_new; +_Bool ep12; +port_t p13; +char p13_old; +char p13_new; +_Bool ep13; +port_t p14; +char p14_old; +char p14_new; +_Bool ep14; +port_t p15; +char p15_old; +char p15_new; +_Bool ep15; +port_t p21; +char p21_old; +char p21_new; +_Bool ep21; +port_t p23; +char p23_old; +char p23_new; +_Bool ep23; +port_t p24; +char p24_old; +char p24_new; +_Bool ep24; +port_t p25; +char p25_old; +char p25_new; +_Bool ep25; +port_t p31; +char p31_old; +char p31_new; +_Bool ep31; +port_t p32; +char p32_old; +char p32_new; +_Bool ep32; +port_t p34; +char p34_old; +char p34_new; +_Bool ep34; +port_t p35; +char p35_old; +char p35_new; +_Bool ep35; +port_t p41; +char p41_old; +char p41_new; +_Bool ep41; +port_t p42; +char p42_old; +char p42_new; +_Bool ep42; +port_t p43; +char p43_old; +char p43_new; +_Bool ep43; +port_t p45; +char p45_old; +char p45_new; +_Bool ep45; +port_t p51; +char p51_old; +char p51_new; +_Bool ep51; +port_t p52; +char p52_old; +char p52_new; +_Bool ep52; +port_t p53; +char p53_old; +char p53_new; +_Bool ep53; +port_t p54; +char p54_old; +char p54_new; +_Bool ep54; +char id1; +char r1; +char st1; +char nl1; +char m1; +char max1; +_Bool mode1; +char id2; +char r2; +char st2; +char nl2; +char m2; +char max2; +_Bool mode2; +char id3; +char r3; +char st3; +char nl3; +char m3; +char max3; +_Bool mode3; +char id4; +char r4; +char st4; +char nl4; +char m4; +char max4; +_Bool mode4; +char id5; +char r5; +char st5; +char nl5; +char m5; +char max5; +_Bool mode5; +void node1(void) { + + { + if (mode1) { + r1 = (char)((int)r1 + 1); + if (ep21) { + m1 = p21_old; + p21_old = nomsg; + if ((int)m1 > (int)max1) { + max1 = m1; + } + } + if (ep31) { + m1 = p31_old; + p31_old = nomsg; + if ((int)m1 > (int)max1) { + max1 = m1; + } + } + if (ep41) { + m1 = p41_old; + p41_old = nomsg; + if ((int)m1 > (int)max1) { + max1 = m1; + } + } + if (ep51) { + m1 = p51_old; + p51_old = nomsg; + if ((int)m1 > (int)max1) { + max1 = m1; + } + } + if ((int)r1 == 3) { + if ((int)max1 == (int)id1) { + st1 = (char)1; + } else { + nl1 = (char)1; + } + } + mode1 = (_Bool)0; + } else { + if ((int)r1 < 4) { + if (ep12) { + p12_new = max1 != nomsg && p12_new == nomsg ? max1 : p12_new; + } + if (ep13) { + p13_new = max1 != nomsg && p13_new == nomsg ? max1 : p13_new; + } + if (ep14) { + p14_new = max1 != nomsg && p14_new == nomsg ? max1 : p14_new; + } + if (ep15) { + p15_new = max1 != nomsg && p15_new == nomsg ? max1 : p15_new; + } + } + mode1 = (_Bool)1; + } + return; + } +} +void node2(void) { + + { + if (mode2) { + r2 = (char)((int)r2 + 1); + if (ep12) { + m2 = p12_old; + p12_old = nomsg; + if ((int)m2 > (int)max2) { + max2 = m2; + } + } + if (ep32) { + m2 = p32_old; + p32_old = nomsg; + if ((int)m2 > (int)max2) { + max2 = m2; + } + } + if (ep42) { + m2 = p42_old; + p42_old = nomsg; + if ((int)m2 > (int)max2) { + max2 = m2; + } + } + if (ep52) { + m2 = p52_old; + p52_old = nomsg; + if ((int)m2 > (int)max2) { + max2 = m2; + } + } + if ((int)r2 == 4) { + if ((int)max2 == (int)id2) { + st2 = (char)1; + } else { + nl2 = (char)1; + } + } + mode2 = (_Bool)0; + } else { + if ((int)r2 < 4) { + if (ep21) { + p21_new = max2 != nomsg && p21_new == nomsg ? max2 : p21_new; + } + if (ep23) { + p23_new = max2 != nomsg && p23_new == nomsg ? max2 : p23_new; + } + if (ep24) { + p24_new = max2 != nomsg && p24_new == nomsg ? max2 : p24_new; + } + if (ep25) { + p25_new = max2 != nomsg && p25_new == nomsg ? max2 : p25_new; + } + } + mode2 = (_Bool)1; + } + return; + } +} +void node3(void) { + + { + if (mode3) { + r3 = (char)((int)r3 + 1); + if (ep13) { + m3 = p13_old; + p13_old = nomsg; + if ((int)m3 > (int)max3) { + max3 = m3; + } + } + if (ep23) { + m3 = p23_old; + p23_old = nomsg; + if ((int)m3 > (int)max3) { + max3 = m3; + } + } + if (ep43) { + m3 = p43_old; + p43_old = nomsg; + if ((int)m3 > (int)max3) { + max3 = m3; + } + } + if (ep53) { + m3 = p53_old; + p53_old = nomsg; + if ((int)m3 > (int)max3) { + max3 = m3; + } + } + if ((int)r3 == 4) { + if ((int)max3 == (int)id3) { + st3 = (char)1; + } else { + nl3 = (char)1; + } + } + mode3 = (_Bool)0; + } else { + if ((int)r3 < 4) { + if (ep31) { + p31_new = max3 != nomsg && p31_new == nomsg ? max3 : p31_new; + } + if (ep32) { + p32_new = max3 != nomsg && p32_new == nomsg ? max3 : p32_new; + } + if (ep34) { + p34_new = max3 != nomsg && p34_new == nomsg ? max3 : p34_new; + } + if (ep35) { + p35_new = max3 != nomsg && p35_new == nomsg ? max3 : p35_new; + } + } + mode3 = (_Bool)1; + } + return; + } +} +void node4(void) { + + { + if (mode4) { + r4 = (char)((int)r4 + 1); + if (ep14) { + m4 = p14_old; + p14_old = nomsg; + if ((int)m4 > (int)max4) { + max4 = m4; + } + } + if (ep24) { + m4 = p24_old; + p24_old = nomsg; + if ((int)m4 > (int)max4) { + max4 = m4; + } + } + if (ep34) { + m4 = p34_old; + p34_old = nomsg; + if ((int)m4 > (int)max4) { + max4 = m4; + } + } + if (ep54) { + m4 = p54_old; + p54_old = nomsg; + if ((int)m4 > (int)max4) { + max4 = m4; + } + } + if ((int)r4 == 4) { + if ((int)max4 == (int)id4) { + st4 = (char)1; + } else { + nl4 = (char)1; + } + } + mode4 = (_Bool)0; + } else { + if ((int)r4 < 4) { + if (ep41) { + p41_new = max4 != nomsg && p41_new == nomsg ? max4 : p41_new; + } + if (ep42) { + p42_new = max4 != nomsg && p42_new == nomsg ? max4 : p42_new; + } + if (ep43) { + p43_new = max4 != nomsg && p43_new == nomsg ? max4 : p43_new; + } + if (ep45) { + p45_new = max4 != nomsg && p45_new == nomsg ? max4 : p45_new; + } + } + mode4 = (_Bool)1; + } + return; + } +} +void node5(void) { + + { + if (mode5) { + r5 = (char)((int)r5 + 1); + if (ep15) { + m5 = p15_old; + p15_old = nomsg; + if ((int)m5 > (int)max5) { + max5 = m5; + } + } + if (ep25) { + m5 = p25_old; + p25_old = nomsg; + if ((int)m5 > (int)max5) { + max5 = m5; + } + } + if (ep35) { + m5 = p35_old; + p35_old = nomsg; + if ((int)m5 > (int)max5) { + max5 = m5; + } + } + if (ep45) { + m5 = p45_old; + p45_old = nomsg; + if ((int)m5 > (int)max5) { + max5 = m5; + } + } + if ((int)r5 == 4) { + if ((int)max5 == (int)id5) { + st5 = (char)1; + } else { + nl5 = (char)1; + } + } + mode5 = (_Bool)0; + } else { + if ((int)r5 < 4) { + if (ep51) { + p51_new = max5 != nomsg && p51_new == nomsg ? max5 : p51_new; + } + if (ep52) { + p52_new = max5 != nomsg && p52_new == nomsg ? max5 : p52_new; + } + if (ep53) { + p53_new = max5 != nomsg && p53_new == nomsg ? max5 : p53_new; + } + if (ep54) { + p54_new = max5 != nomsg && p54_new == nomsg ? max5 : p54_new; + } + } + mode5 = (_Bool)1; + } + return; + } +} +int init(void) { + _Bool r121; + _Bool r131; + _Bool r141; + _Bool r151; + _Bool r211; + _Bool r231; + _Bool r241; + _Bool r251; + _Bool r311; + _Bool r321; + _Bool r341; + _Bool r351; + _Bool r411; + _Bool r421; + _Bool r431; + _Bool r451; + _Bool r511; + _Bool r521; + _Bool r531; + _Bool r541; + _Bool r122; + int tmp; + _Bool r132; + int tmp___0; + _Bool r142; + int tmp___1; + _Bool r152; + int tmp___2; + _Bool r212; + int tmp___3; + _Bool r232; + int tmp___4; + _Bool r242; + int tmp___5; + _Bool r252; + int tmp___6; + _Bool r312; + int tmp___7; + _Bool r322; + int tmp___8; + _Bool r342; + int tmp___9; + _Bool r352; + int tmp___10; + _Bool r412; + int tmp___11; + _Bool r422; + int tmp___12; + _Bool r432; + int tmp___13; + _Bool r452; + int tmp___14; + _Bool r512; + int tmp___15; + _Bool r522; + int tmp___16; + _Bool r532; + int tmp___17; + _Bool r542; + int tmp___18; + _Bool r123; + int tmp___19; + _Bool r133; + int tmp___20; + _Bool r143; + int tmp___21; + _Bool r153; + int tmp___22; + _Bool r213; + int tmp___23; + _Bool r233; + int tmp___24; + _Bool r243; + int tmp___25; + _Bool r253; + int tmp___26; + _Bool r313; + int tmp___27; + _Bool r323; + int tmp___28; + _Bool r343; + int tmp___29; + _Bool r353; + int tmp___30; + _Bool r413; + int tmp___31; + _Bool r423; + int tmp___32; + _Bool r433; + int tmp___33; + _Bool r453; + int tmp___34; + _Bool r513; + int tmp___35; + _Bool r523; + int tmp___36; + _Bool r533; + int tmp___37; + _Bool r543; + int tmp___38; + _Bool r124; + int tmp___39; + _Bool r134; + int tmp___40; + _Bool r144; + int tmp___41; + _Bool r154; + int tmp___42; + _Bool r214; + int tmp___43; + _Bool r234; + int tmp___44; + _Bool r244; + int tmp___45; + _Bool r254; + int tmp___46; + _Bool r314; + int tmp___47; + _Bool r324; + int tmp___48; + _Bool r344; + int tmp___49; + _Bool r354; + int tmp___50; + _Bool r414; + int tmp___51; + _Bool r424; + int tmp___52; + _Bool r434; + int tmp___53; + _Bool r454; + int tmp___54; + _Bool r514; + int tmp___55; + _Bool r524; + int tmp___56; + _Bool r534; + int tmp___57; + _Bool r544; + int tmp___58; + int tmp___59; + + { + r121 = ep12; + r131 = ep13; + r141 = ep14; + r151 = ep15; + r211 = ep21; + r231 = ep23; + r241 = ep24; + r251 = ep25; + r311 = ep31; + r321 = ep32; + r341 = ep34; + r351 = ep35; + r411 = ep41; + r421 = ep42; + r431 = ep43; + r451 = ep45; + r511 = ep51; + r521 = ep52; + r531 = ep53; + r541 = ep54; + if (r121) { + tmp = 1; + } else if (r131) { + if (ep32) { + tmp = 1; + } else { + goto _L___0; + } + } else + _L___0: /* CIL Label */ + if (r141) { + if (ep42) { + tmp = 1; + } else { + goto _L; + } + } else + _L: /* CIL Label */ + if (r151) { + if (ep52) { + tmp = 1; + } else { + tmp = 0; + } + } else { + tmp = 0; + } + r122 = (_Bool)tmp; + if (r131) { + tmp___0 = 1; + } else if (r121) { + if (ep23) { + tmp___0 = 1; + } else { + goto _L___2; + } + } else + _L___2: /* CIL Label */ + if (r141) { + if (ep43) { + tmp___0 = 1; + } else { + goto _L___1; + } + } else + _L___1: /* CIL Label */ + if (r151) { + if (ep53) { + tmp___0 = 1; + } else { + tmp___0 = 0; + } + } else { + tmp___0 = 0; + } + r132 = (_Bool)tmp___0; + if (r141) { + tmp___1 = 1; + } else if (r121) { + if (ep24) { + tmp___1 = 1; + } else { + goto _L___4; + } + } else + _L___4: /* CIL Label */ + if (r131) { + if (ep34) { + tmp___1 = 1; + } else { + goto _L___3; + } + } else + _L___3: /* CIL Label */ + if (r151) { + if (ep54) { + tmp___1 = 1; + } else { + tmp___1 = 0; + } + } else { + tmp___1 = 0; + } + r142 = (_Bool)tmp___1; + if (r151) { + tmp___2 = 1; + } else if (r121) { + if (ep25) { + tmp___2 = 1; + } else { + goto _L___6; + } + } else + _L___6: /* CIL Label */ + if (r131) { + if (ep35) { + tmp___2 = 1; + } else { + goto _L___5; + } + } else + _L___5: /* CIL Label */ + if (r141) { + if (ep45) { + tmp___2 = 1; + } else { + tmp___2 = 0; + } + } else { + tmp___2 = 0; + } + r152 = (_Bool)tmp___2; + if (r211) { + tmp___3 = 1; + } else if (r231) { + if (ep31) { + tmp___3 = 1; + } else { + goto _L___8; + } + } else + _L___8: /* CIL Label */ + if (r241) { + if (ep41) { + tmp___3 = 1; + } else { + goto _L___7; + } + } else + _L___7: /* CIL Label */ + if (r251) { + if (ep51) { + tmp___3 = 1; + } else { + tmp___3 = 0; + } + } else { + tmp___3 = 0; + } + r212 = (_Bool)tmp___3; + if (r231) { + tmp___4 = 1; + } else if (r211) { + if (ep13) { + tmp___4 = 1; + } else { + goto _L___10; + } + } else + _L___10: /* CIL Label */ + if (r241) { + if (ep43) { + tmp___4 = 1; + } else { + goto _L___9; + } + } else + _L___9: /* CIL Label */ + if (r251) { + if (ep53) { + tmp___4 = 1; + } else { + tmp___4 = 0; + } + } else { + tmp___4 = 0; + } + r232 = (_Bool)tmp___4; + if (r241) { + tmp___5 = 1; + } else if (r211) { + if (ep14) { + tmp___5 = 1; + } else { + goto _L___12; + } + } else + _L___12: /* CIL Label */ + if (r231) { + if (ep34) { + tmp___5 = 1; + } else { + goto _L___11; + } + } else + _L___11: /* CIL Label */ + if (r251) { + if (ep54) { + tmp___5 = 1; + } else { + tmp___5 = 0; + } + } else { + tmp___5 = 0; + } + r242 = (_Bool)tmp___5; + if (r251) { + tmp___6 = 1; + } else if (r211) { + if (ep15) { + tmp___6 = 1; + } else { + goto _L___14; + } + } else + _L___14: /* CIL Label */ + if (r231) { + if (ep35) { + tmp___6 = 1; + } else { + goto _L___13; + } + } else + _L___13: /* CIL Label */ + if (r241) { + if (ep45) { + tmp___6 = 1; + } else { + tmp___6 = 0; + } + } else { + tmp___6 = 0; + } + r252 = (_Bool)tmp___6; + if (r311) { + tmp___7 = 1; + } else if (r321) { + if (ep21) { + tmp___7 = 1; + } else { + goto _L___16; + } + } else + _L___16: /* CIL Label */ + if (r341) { + if (ep41) { + tmp___7 = 1; + } else { + goto _L___15; + } + } else + _L___15: /* CIL Label */ + if (r351) { + if (ep51) { + tmp___7 = 1; + } else { + tmp___7 = 0; + } + } else { + tmp___7 = 0; + } + r312 = (_Bool)tmp___7; + if (r321) { + tmp___8 = 1; + } else if (r311) { + if (ep12) { + tmp___8 = 1; + } else { + goto _L___18; + } + } else + _L___18: /* CIL Label */ + if (r341) { + if (ep42) { + tmp___8 = 1; + } else { + goto _L___17; + } + } else + _L___17: /* CIL Label */ + if (r351) { + if (ep52) { + tmp___8 = 1; + } else { + tmp___8 = 0; + } + } else { + tmp___8 = 0; + } + r322 = (_Bool)tmp___8; + if (r341) { + tmp___9 = 1; + } else if (r311) { + if (ep14) { + tmp___9 = 1; + } else { + goto _L___20; + } + } else + _L___20: /* CIL Label */ + if (r321) { + if (ep24) { + tmp___9 = 1; + } else { + goto _L___19; + } + } else + _L___19: /* CIL Label */ + if (r351) { + if (ep54) { + tmp___9 = 1; + } else { + tmp___9 = 0; + } + } else { + tmp___9 = 0; + } + r342 = (_Bool)tmp___9; + if (r351) { + tmp___10 = 1; + } else if (r311) { + if (ep15) { + tmp___10 = 1; + } else { + goto _L___22; + } + } else + _L___22: /* CIL Label */ + if (r321) { + if (ep25) { + tmp___10 = 1; + } else { + goto _L___21; + } + } else + _L___21: /* CIL Label */ + if (r341) { + if (ep45) { + tmp___10 = 1; + } else { + tmp___10 = 0; + } + } else { + tmp___10 = 0; + } + r352 = (_Bool)tmp___10; + if (r411) { + tmp___11 = 1; + } else if (r421) { + if (ep21) { + tmp___11 = 1; + } else { + goto _L___24; + } + } else + _L___24: /* CIL Label */ + if (r431) { + if (ep31) { + tmp___11 = 1; + } else { + goto _L___23; + } + } else + _L___23: /* CIL Label */ + if (r451) { + if (ep51) { + tmp___11 = 1; + } else { + tmp___11 = 0; + } + } else { + tmp___11 = 0; + } + r412 = (_Bool)tmp___11; + if (r421) { + tmp___12 = 1; + } else if (r411) { + if (ep12) { + tmp___12 = 1; + } else { + goto _L___26; + } + } else + _L___26: /* CIL Label */ + if (r431) { + if (ep32) { + tmp___12 = 1; + } else { + goto _L___25; + } + } else + _L___25: /* CIL Label */ + if (r451) { + if (ep52) { + tmp___12 = 1; + } else { + tmp___12 = 0; + } + } else { + tmp___12 = 0; + } + r422 = (_Bool)tmp___12; + if (r431) { + tmp___13 = 1; + } else if (r411) { + if (ep13) { + tmp___13 = 1; + } else { + goto _L___28; + } + } else + _L___28: /* CIL Label */ + if (r421) { + if (ep23) { + tmp___13 = 1; + } else { + goto _L___27; + } + } else + _L___27: /* CIL Label */ + if (r451) { + if (ep53) { + tmp___13 = 1; + } else { + tmp___13 = 0; + } + } else { + tmp___13 = 0; + } + r432 = (_Bool)tmp___13; + if (r451) { + tmp___14 = 1; + } else if (r411) { + if (ep15) { + tmp___14 = 1; + } else { + goto _L___30; + } + } else + _L___30: /* CIL Label */ + if (r421) { + if (ep25) { + tmp___14 = 1; + } else { + goto _L___29; + } + } else + _L___29: /* CIL Label */ + if (r431) { + if (ep35) { + tmp___14 = 1; + } else { + tmp___14 = 0; + } + } else { + tmp___14 = 0; + } + r452 = (_Bool)tmp___14; + if (r511) { + tmp___15 = 1; + } else if (r521) { + if (ep21) { + tmp___15 = 1; + } else { + goto _L___32; + } + } else + _L___32: /* CIL Label */ + if (r531) { + if (ep31) { + tmp___15 = 1; + } else { + goto _L___31; + } + } else + _L___31: /* CIL Label */ + if (r541) { + if (ep41) { + tmp___15 = 1; + } else { + tmp___15 = 0; + } + } else { + tmp___15 = 0; + } + r512 = (_Bool)tmp___15; + if (r521) { + tmp___16 = 1; + } else if (r511) { + if (ep12) { + tmp___16 = 1; + } else { + goto _L___34; + } + } else + _L___34: /* CIL Label */ + if (r531) { + if (ep32) { + tmp___16 = 1; + } else { + goto _L___33; + } + } else + _L___33: /* CIL Label */ + if (r541) { + if (ep42) { + tmp___16 = 1; + } else { + tmp___16 = 0; + } + } else { + tmp___16 = 0; + } + r522 = (_Bool)tmp___16; + if (r531) { + tmp___17 = 1; + } else if (r511) { + if (ep13) { + tmp___17 = 1; + } else { + goto _L___36; + } + } else + _L___36: /* CIL Label */ + if (r521) { + if (ep23) { + tmp___17 = 1; + } else { + goto _L___35; + } + } else + _L___35: /* CIL Label */ + if (r541) { + if (ep43) { + tmp___17 = 1; + } else { + tmp___17 = 0; + } + } else { + tmp___17 = 0; + } + r532 = (_Bool)tmp___17; + if (r541) { + tmp___18 = 1; + } else if (r511) { + if (ep14) { + tmp___18 = 1; + } else { + goto _L___38; + } + } else + _L___38: /* CIL Label */ + if (r521) { + if (ep24) { + tmp___18 = 1; + } else { + goto _L___37; + } + } else + _L___37: /* CIL Label */ + if (r531) { + if (ep34) { + tmp___18 = 1; + } else { + tmp___18 = 0; + } + } else { + tmp___18 = 0; + } + r542 = (_Bool)tmp___18; + if (r122) { + tmp___19 = 1; + } else if (r132) { + if (ep32) { + tmp___19 = 1; + } else { + goto _L___40; + } + } else + _L___40: /* CIL Label */ + if (r142) { + if (ep42) { + tmp___19 = 1; + } else { + goto _L___39; + } + } else + _L___39: /* CIL Label */ + if (r152) { + if (ep52) { + tmp___19 = 1; + } else { + tmp___19 = 0; + } + } else { + tmp___19 = 0; + } + r123 = (_Bool)tmp___19; + if (r132) { + tmp___20 = 1; + } else if (r122) { + if (ep23) { + tmp___20 = 1; + } else { + goto _L___42; + } + } else + _L___42: /* CIL Label */ + if (r142) { + if (ep43) { + tmp___20 = 1; + } else { + goto _L___41; + } + } else + _L___41: /* CIL Label */ + if (r152) { + if (ep53) { + tmp___20 = 1; + } else { + tmp___20 = 0; + } + } else { + tmp___20 = 0; + } + r133 = (_Bool)tmp___20; + if (r142) { + tmp___21 = 1; + } else if (r122) { + if (ep24) { + tmp___21 = 1; + } else { + goto _L___44; + } + } else + _L___44: /* CIL Label */ + if (r132) { + if (ep34) { + tmp___21 = 1; + } else { + goto _L___43; + } + } else + _L___43: /* CIL Label */ + if (r152) { + if (ep54) { + tmp___21 = 1; + } else { + tmp___21 = 0; + } + } else { + tmp___21 = 0; + } + r143 = (_Bool)tmp___21; + if (r152) { + tmp___22 = 1; + } else if (r122) { + if (ep25) { + tmp___22 = 1; + } else { + goto _L___46; + } + } else + _L___46: /* CIL Label */ + if (r132) { + if (ep35) { + tmp___22 = 1; + } else { + goto _L___45; + } + } else + _L___45: /* CIL Label */ + if (r142) { + if (ep45) { + tmp___22 = 1; + } else { + tmp___22 = 0; + } + } else { + tmp___22 = 0; + } + r153 = (_Bool)tmp___22; + if (r212) { + tmp___23 = 1; + } else if (r232) { + if (ep31) { + tmp___23 = 1; + } else { + goto _L___48; + } + } else + _L___48: /* CIL Label */ + if (r242) { + if (ep41) { + tmp___23 = 1; + } else { + goto _L___47; + } + } else + _L___47: /* CIL Label */ + if (r252) { + if (ep51) { + tmp___23 = 1; + } else { + tmp___23 = 0; + } + } else { + tmp___23 = 0; + } + r213 = (_Bool)tmp___23; + if (r232) { + tmp___24 = 1; + } else if (r212) { + if (ep13) { + tmp___24 = 1; + } else { + goto _L___50; + } + } else + _L___50: /* CIL Label */ + if (r242) { + if (ep43) { + tmp___24 = 1; + } else { + goto _L___49; + } + } else + _L___49: /* CIL Label */ + if (r252) { + if (ep53) { + tmp___24 = 1; + } else { + tmp___24 = 0; + } + } else { + tmp___24 = 0; + } + r233 = (_Bool)tmp___24; + if (r242) { + tmp___25 = 1; + } else if (r212) { + if (ep14) { + tmp___25 = 1; + } else { + goto _L___52; + } + } else + _L___52: /* CIL Label */ + if (r232) { + if (ep34) { + tmp___25 = 1; + } else { + goto _L___51; + } + } else + _L___51: /* CIL Label */ + if (r252) { + if (ep54) { + tmp___25 = 1; + } else { + tmp___25 = 0; + } + } else { + tmp___25 = 0; + } + r243 = (_Bool)tmp___25; + if (r252) { + tmp___26 = 1; + } else if (r212) { + if (ep15) { + tmp___26 = 1; + } else { + goto _L___54; + } + } else + _L___54: /* CIL Label */ + if (r232) { + if (ep35) { + tmp___26 = 1; + } else { + goto _L___53; + } + } else + _L___53: /* CIL Label */ + if (r242) { + if (ep45) { + tmp___26 = 1; + } else { + tmp___26 = 0; + } + } else { + tmp___26 = 0; + } + r253 = (_Bool)tmp___26; + if (r312) { + tmp___27 = 1; + } else if (r322) { + if (ep21) { + tmp___27 = 1; + } else { + goto _L___56; + } + } else + _L___56: /* CIL Label */ + if (r342) { + if (ep41) { + tmp___27 = 1; + } else { + goto _L___55; + } + } else + _L___55: /* CIL Label */ + if (r352) { + if (ep51) { + tmp___27 = 1; + } else { + tmp___27 = 0; + } + } else { + tmp___27 = 0; + } + r313 = (_Bool)tmp___27; + if (r322) { + tmp___28 = 1; + } else if (r312) { + if (ep12) { + tmp___28 = 1; + } else { + goto _L___58; + } + } else + _L___58: /* CIL Label */ + if (r342) { + if (ep42) { + tmp___28 = 1; + } else { + goto _L___57; + } + } else + _L___57: /* CIL Label */ + if (r352) { + if (ep52) { + tmp___28 = 1; + } else { + tmp___28 = 0; + } + } else { + tmp___28 = 0; + } + r323 = (_Bool)tmp___28; + if (r342) { + tmp___29 = 1; + } else if (r312) { + if (ep14) { + tmp___29 = 1; + } else { + goto _L___60; + } + } else + _L___60: /* CIL Label */ + if (r322) { + if (ep24) { + tmp___29 = 1; + } else { + goto _L___59; + } + } else + _L___59: /* CIL Label */ + if (r352) { + if (ep54) { + tmp___29 = 1; + } else { + tmp___29 = 0; + } + } else { + tmp___29 = 0; + } + r343 = (_Bool)tmp___29; + if (r352) { + tmp___30 = 1; + } else if (r312) { + if (ep15) { + tmp___30 = 1; + } else { + goto _L___62; + } + } else + _L___62: /* CIL Label */ + if (r322) { + if (ep25) { + tmp___30 = 1; + } else { + goto _L___61; + } + } else + _L___61: /* CIL Label */ + if (r342) { + if (ep45) { + tmp___30 = 1; + } else { + tmp___30 = 0; + } + } else { + tmp___30 = 0; + } + r353 = (_Bool)tmp___30; + if (r412) { + tmp___31 = 1; + } else if (r422) { + if (ep21) { + tmp___31 = 1; + } else { + goto _L___64; + } + } else + _L___64: /* CIL Label */ + if (r432) { + if (ep31) { + tmp___31 = 1; + } else { + goto _L___63; + } + } else + _L___63: /* CIL Label */ + if (r452) { + if (ep51) { + tmp___31 = 1; + } else { + tmp___31 = 0; + } + } else { + tmp___31 = 0; + } + r413 = (_Bool)tmp___31; + if (r422) { + tmp___32 = 1; + } else if (r412) { + if (ep12) { + tmp___32 = 1; + } else { + goto _L___66; + } + } else + _L___66: /* CIL Label */ + if (r432) { + if (ep32) { + tmp___32 = 1; + } else { + goto _L___65; + } + } else + _L___65: /* CIL Label */ + if (r452) { + if (ep52) { + tmp___32 = 1; + } else { + tmp___32 = 0; + } + } else { + tmp___32 = 0; + } + r423 = (_Bool)tmp___32; + if (r432) { + tmp___33 = 1; + } else if (r412) { + if (ep13) { + tmp___33 = 1; + } else { + goto _L___68; + } + } else + _L___68: /* CIL Label */ + if (r422) { + if (ep23) { + tmp___33 = 1; + } else { + goto _L___67; + } + } else + _L___67: /* CIL Label */ + if (r452) { + if (ep53) { + tmp___33 = 1; + } else { + tmp___33 = 0; + } + } else { + tmp___33 = 0; + } + r433 = (_Bool)tmp___33; + if (r452) { + tmp___34 = 1; + } else if (r412) { + if (ep15) { + tmp___34 = 1; + } else { + goto _L___70; + } + } else + _L___70: /* CIL Label */ + if (r422) { + if (ep25) { + tmp___34 = 1; + } else { + goto _L___69; + } + } else + _L___69: /* CIL Label */ + if (r432) { + if (ep35) { + tmp___34 = 1; + } else { + tmp___34 = 0; + } + } else { + tmp___34 = 0; + } + r453 = (_Bool)tmp___34; + if (r512) { + tmp___35 = 1; + } else if (r522) { + if (ep21) { + tmp___35 = 1; + } else { + goto _L___72; + } + } else + _L___72: /* CIL Label */ + if (r532) { + if (ep31) { + tmp___35 = 1; + } else { + goto _L___71; + } + } else + _L___71: /* CIL Label */ + if (r542) { + if (ep41) { + tmp___35 = 1; + } else { + tmp___35 = 0; + } + } else { + tmp___35 = 0; + } + r513 = (_Bool)tmp___35; + if (r522) { + tmp___36 = 1; + } else if (r512) { + if (ep12) { + tmp___36 = 1; + } else { + goto _L___74; + } + } else + _L___74: /* CIL Label */ + if (r532) { + if (ep32) { + tmp___36 = 1; + } else { + goto _L___73; + } + } else + _L___73: /* CIL Label */ + if (r542) { + if (ep42) { + tmp___36 = 1; + } else { + tmp___36 = 0; + } + } else { + tmp___36 = 0; + } + r523 = (_Bool)tmp___36; + if (r532) { + tmp___37 = 1; + } else if (r512) { + if (ep13) { + tmp___37 = 1; + } else { + goto _L___76; + } + } else + _L___76: /* CIL Label */ + if (r522) { + if (ep23) { + tmp___37 = 1; + } else { + goto _L___75; + } + } else + _L___75: /* CIL Label */ + if (r542) { + if (ep43) { + tmp___37 = 1; + } else { + tmp___37 = 0; + } + } else { + tmp___37 = 0; + } + r533 = (_Bool)tmp___37; + if (r542) { + tmp___38 = 1; + } else if (r512) { + if (ep14) { + tmp___38 = 1; + } else { + goto _L___78; + } + } else + _L___78: /* CIL Label */ + if (r522) { + if (ep24) { + tmp___38 = 1; + } else { + goto _L___77; + } + } else + _L___77: /* CIL Label */ + if (r532) { + if (ep34) { + tmp___38 = 1; + } else { + tmp___38 = 0; + } + } else { + tmp___38 = 0; + } + r543 = (_Bool)tmp___38; + if (r123) { + tmp___39 = 1; + } else if (r133) { + if (ep32) { + tmp___39 = 1; + } else { + goto _L___80; + } + } else + _L___80: /* CIL Label */ + if (r143) { + if (ep42) { + tmp___39 = 1; + } else { + goto _L___79; + } + } else + _L___79: /* CIL Label */ + if (r153) { + if (ep52) { + tmp___39 = 1; + } else { + tmp___39 = 0; + } + } else { + tmp___39 = 0; + } + r124 = (_Bool)tmp___39; + if (r133) { + tmp___40 = 1; + } else if (r123) { + if (ep23) { + tmp___40 = 1; + } else { + goto _L___82; + } + } else + _L___82: /* CIL Label */ + if (r143) { + if (ep43) { + tmp___40 = 1; + } else { + goto _L___81; + } + } else + _L___81: /* CIL Label */ + if (r153) { + if (ep53) { + tmp___40 = 1; + } else { + tmp___40 = 0; + } + } else { + tmp___40 = 0; + } + r134 = (_Bool)tmp___40; + if (r143) { + tmp___41 = 1; + } else if (r123) { + if (ep24) { + tmp___41 = 1; + } else { + goto _L___84; + } + } else + _L___84: /* CIL Label */ + if (r133) { + if (ep34) { + tmp___41 = 1; + } else { + goto _L___83; + } + } else + _L___83: /* CIL Label */ + if (r153) { + if (ep54) { + tmp___41 = 1; + } else { + tmp___41 = 0; + } + } else { + tmp___41 = 0; + } + r144 = (_Bool)tmp___41; + if (r153) { + tmp___42 = 1; + } else if (r123) { + if (ep25) { + tmp___42 = 1; + } else { + goto _L___86; + } + } else + _L___86: /* CIL Label */ + if (r133) { + if (ep35) { + tmp___42 = 1; + } else { + goto _L___85; + } + } else + _L___85: /* CIL Label */ + if (r143) { + if (ep45) { + tmp___42 = 1; + } else { + tmp___42 = 0; + } + } else { + tmp___42 = 0; + } + r154 = (_Bool)tmp___42; + if (r213) { + tmp___43 = 1; + } else if (r233) { + if (ep31) { + tmp___43 = 1; + } else { + goto _L___88; + } + } else + _L___88: /* CIL Label */ + if (r243) { + if (ep41) { + tmp___43 = 1; + } else { + goto _L___87; + } + } else + _L___87: /* CIL Label */ + if (r253) { + if (ep51) { + tmp___43 = 1; + } else { + tmp___43 = 0; + } + } else { + tmp___43 = 0; + } + r214 = (_Bool)tmp___43; + if (r233) { + tmp___44 = 1; + } else if (r213) { + if (ep13) { + tmp___44 = 1; + } else { + goto _L___90; + } + } else + _L___90: /* CIL Label */ + if (r243) { + if (ep43) { + tmp___44 = 1; + } else { + goto _L___89; + } + } else + _L___89: /* CIL Label */ + if (r253) { + if (ep53) { + tmp___44 = 1; + } else { + tmp___44 = 0; + } + } else { + tmp___44 = 0; + } + r234 = (_Bool)tmp___44; + if (r243) { + tmp___45 = 1; + } else if (r213) { + if (ep14) { + tmp___45 = 1; + } else { + goto _L___92; + } + } else + _L___92: /* CIL Label */ + if (r233) { + if (ep34) { + tmp___45 = 1; + } else { + goto _L___91; + } + } else + _L___91: /* CIL Label */ + if (r253) { + if (ep54) { + tmp___45 = 1; + } else { + tmp___45 = 0; + } + } else { + tmp___45 = 0; + } + r244 = (_Bool)tmp___45; + if (r253) { + tmp___46 = 1; + } else if (r213) { + if (ep15) { + tmp___46 = 1; + } else { + goto _L___94; + } + } else + _L___94: /* CIL Label */ + if (r233) { + if (ep35) { + tmp___46 = 1; + } else { + goto _L___93; + } + } else + _L___93: /* CIL Label */ + if (r243) { + if (ep45) { + tmp___46 = 1; + } else { + tmp___46 = 0; + } + } else { + tmp___46 = 0; + } + r254 = (_Bool)tmp___46; + if (r313) { + tmp___47 = 1; + } else if (r323) { + if (ep21) { + tmp___47 = 1; + } else { + goto _L___96; + } + } else + _L___96: /* CIL Label */ + if (r343) { + if (ep41) { + tmp___47 = 1; + } else { + goto _L___95; + } + } else + _L___95: /* CIL Label */ + if (r353) { + if (ep51) { + tmp___47 = 1; + } else { + tmp___47 = 0; + } + } else { + tmp___47 = 0; + } + r314 = (_Bool)tmp___47; + if (r323) { + tmp___48 = 1; + } else if (r313) { + if (ep12) { + tmp___48 = 1; + } else { + goto _L___98; + } + } else + _L___98: /* CIL Label */ + if (r343) { + if (ep42) { + tmp___48 = 1; + } else { + goto _L___97; + } + } else + _L___97: /* CIL Label */ + if (r353) { + if (ep52) { + tmp___48 = 1; + } else { + tmp___48 = 0; + } + } else { + tmp___48 = 0; + } + r324 = (_Bool)tmp___48; + if (r343) { + tmp___49 = 1; + } else if (r313) { + if (ep14) { + tmp___49 = 1; + } else { + goto _L___100; + } + } else + _L___100: /* CIL Label */ + if (r323) { + if (ep24) { + tmp___49 = 1; + } else { + goto _L___99; + } + } else + _L___99: /* CIL Label */ + if (r353) { + if (ep54) { + tmp___49 = 1; + } else { + tmp___49 = 0; + } + } else { + tmp___49 = 0; + } + r344 = (_Bool)tmp___49; + if (r353) { + tmp___50 = 1; + } else if (r313) { + if (ep15) { + tmp___50 = 1; + } else { + goto _L___102; + } + } else + _L___102: /* CIL Label */ + if (r323) { + if (ep25) { + tmp___50 = 1; + } else { + goto _L___101; + } + } else + _L___101: /* CIL Label */ + if (r343) { + if (ep45) { + tmp___50 = 1; + } else { + tmp___50 = 0; + } + } else { + tmp___50 = 0; + } + r354 = (_Bool)tmp___50; + if (r413) { + tmp___51 = 1; + } else if (r423) { + if (ep21) { + tmp___51 = 1; + } else { + goto _L___104; + } + } else + _L___104: /* CIL Label */ + if (r433) { + if (ep31) { + tmp___51 = 1; + } else { + goto _L___103; + } + } else + _L___103: /* CIL Label */ + if (r453) { + if (ep51) { + tmp___51 = 1; + } else { + tmp___51 = 0; + } + } else { + tmp___51 = 0; + } + r414 = (_Bool)tmp___51; + if (r423) { + tmp___52 = 1; + } else if (r413) { + if (ep12) { + tmp___52 = 1; + } else { + goto _L___106; + } + } else + _L___106: /* CIL Label */ + if (r433) { + if (ep32) { + tmp___52 = 1; + } else { + goto _L___105; + } + } else + _L___105: /* CIL Label */ + if (r453) { + if (ep52) { + tmp___52 = 1; + } else { + tmp___52 = 0; + } + } else { + tmp___52 = 0; + } + r424 = (_Bool)tmp___52; + if (r433) { + tmp___53 = 1; + } else if (r413) { + if (ep13) { + tmp___53 = 1; + } else { + goto _L___108; + } + } else + _L___108: /* CIL Label */ + if (r423) { + if (ep23) { + tmp___53 = 1; + } else { + goto _L___107; + } + } else + _L___107: /* CIL Label */ + if (r453) { + if (ep53) { + tmp___53 = 1; + } else { + tmp___53 = 0; + } + } else { + tmp___53 = 0; + } + r434 = (_Bool)tmp___53; + if (r453) { + tmp___54 = 1; + } else if (r413) { + if (ep15) { + tmp___54 = 1; + } else { + goto _L___110; + } + } else + _L___110: /* CIL Label */ + if (r423) { + if (ep25) { + tmp___54 = 1; + } else { + goto _L___109; + } + } else + _L___109: /* CIL Label */ + if (r433) { + if (ep35) { + tmp___54 = 1; + } else { + tmp___54 = 0; + } + } else { + tmp___54 = 0; + } + r454 = (_Bool)tmp___54; + if (r513) { + tmp___55 = 1; + } else if (r523) { + if (ep21) { + tmp___55 = 1; + } else { + goto _L___112; + } + } else + _L___112: /* CIL Label */ + if (r533) { + if (ep31) { + tmp___55 = 1; + } else { + goto _L___111; + } + } else + _L___111: /* CIL Label */ + if (r543) { + if (ep41) { + tmp___55 = 1; + } else { + tmp___55 = 0; + } + } else { + tmp___55 = 0; + } + r514 = (_Bool)tmp___55; + if (r523) { + tmp___56 = 1; + } else if (r513) { + if (ep12) { + tmp___56 = 1; + } else { + goto _L___114; + } + } else + _L___114: /* CIL Label */ + if (r533) { + if (ep32) { + tmp___56 = 1; + } else { + goto _L___113; + } + } else + _L___113: /* CIL Label */ + if (r543) { + if (ep42) { + tmp___56 = 1; + } else { + tmp___56 = 0; + } + } else { + tmp___56 = 0; + } + r524 = (_Bool)tmp___56; + if (r533) { + tmp___57 = 1; + } else if (r513) { + if (ep13) { + tmp___57 = 1; + } else { + goto _L___116; + } + } else + _L___116: /* CIL Label */ + if (r523) { + if (ep23) { + tmp___57 = 1; + } else { + goto _L___115; + } + } else + _L___115: /* CIL Label */ + if (r543) { + if (ep43) { + tmp___57 = 1; + } else { + tmp___57 = 0; + } + } else { + tmp___57 = 0; + } + r534 = (_Bool)tmp___57; + if (r543) { + tmp___58 = 1; + } else if (r513) { + if (ep14) { + tmp___58 = 1; + } else { + goto _L___118; + } + } else + _L___118: /* CIL Label */ + if (r523) { + if (ep24) { + tmp___58 = 1; + } else { + goto _L___117; + } + } else + _L___117: /* CIL Label */ + if (r533) { + if (ep34) { + tmp___58 = 1; + } else { + tmp___58 = 0; + } + } else { + tmp___58 = 0; + } + r544 = (_Bool)tmp___58; + if ((int)id1 != (int)id2) { + if ((int)id1 != (int)id3) { + if ((int)id1 != (int)id4) { + if ((int)id1 != (int)id5) { + if ((int)id2 != (int)id3) { + if ((int)id2 != (int)id4) { + if ((int)id2 != (int)id5) { + if ((int)id3 != (int)id4) { + if ((int)id3 != (int)id5) { + if ((int)id4 != (int)id5) { + if ((int)id1 >= 0) { + if ((int)id2 >= 0) { + if ((int)id3 >= 0) { + if ((int)id4 >= 0) { + if ((int)id5 >= 0) { + if ((int)r1 == 0) { + if ((int)r2 == 0) { + if ((int)r3 == 0) { + if ((int)r4 == 0) { + if ((int)r5 == 0) { + if (r124) { + if (r134) { + if (r144) { + if (r154) { + if (r214) { + if (r234) { + if (r244) { + if (r254) { + if (r314) { + if (r324) { + if (r344) { + if (r354) { + if (r414) { + if (r424) { + if (r434) { + if (r454) { + if (r514) { + if (r524) { + if (r534) { + if (r544) { + if ((int)max1 == (int)id1) { + if ((int)max2 == (int)id2) { + if ((int)max3 == (int)id3) { + if ((int)max4 == (int)id4) { + if ((int)max5 == (int)id5) { + if ((int)st1 == 0) { + if ((int)st2 == 0) { + if ((int)st3 == 0) { + if ((int)st4 == 0) { + if ((int)st5 == 0) { + if ((int)nl1 == 0) { + if ((int)nl2 == 0) { + if ((int)nl3 == 0) { + if ((int)nl4 == 0) { + if ((int)nl5 == 0) { + if ((int)mode1 == 0) { + if ((int)mode2 == 0) { + if ((int)mode3 == 0) { + if ((int)mode4 == 0) { + if ((int)mode5 == 0) { + tmp___59 = 1; + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + } else { + tmp___59 = 0; + } + return (tmp___59); + } +} +int check(void) { + int tmp; + + { + if (((((int)st1 + (int)st2) + (int)st3) + (int)st4) + (int)st5 <= 1) { + if ((int)st1 + (int)nl1 <= 1) { + if ((int)st2 + (int)nl2 <= 1) { + if ((int)st3 + (int)nl3 <= 1) { + if ((int)st4 + (int)nl4 <= 1) { + if ((int)st5 + (int)nl5 <= 1) { + if ((int)r1 >= 4) { + goto _L___1; + } else if (((((int)st1 + (int)st2) + (int)st3) + (int)st4) + (int)st5 == 0) { + _L___1: /* CIL Label */ + if ((int)r1 < 4) { + goto _L___0; + } else if (((((int)st1 + (int)st2) + (int)st3) + (int)st4) + (int)st5 == 1) { + _L___0: /* CIL Label */ + if ((int)r1 >= 4) { + goto _L; + } else if (((((int)nl1 + (int)nl2) + (int)nl3) + (int)nl4) + (int)nl5 == 0) { + _L: /* CIL Label */ + if ((int)r1 < 4) { + tmp = 1; + } else if (((((int)nl1 + (int)nl2) + (int)nl3) + (int)nl4) + (int)nl5 == 4) { + tmp = 1; + } else { + tmp = 0; + } + } else { + tmp = 0; + } + } else { + tmp = 0; + } + } else { + tmp = 0; + } + } else { + tmp = 0; + } + } else { + tmp = 0; + } + } else { + tmp = 0; + } + } else { + tmp = 0; + } + } else { + tmp = 0; + } + } else { + tmp = 0; + } + return (tmp); + } +} +int main(void) { + int c1; + int i2; + + { + c1 = 0; + ep12 = __VERIFIER_nondet_bool(); + ep13 = __VERIFIER_nondet_bool(); + ep14 = __VERIFIER_nondet_bool(); + ep15 = __VERIFIER_nondet_bool(); + ep21 = __VERIFIER_nondet_bool(); + ep23 = __VERIFIER_nondet_bool(); + ep24 = __VERIFIER_nondet_bool(); + ep25 = __VERIFIER_nondet_bool(); + ep31 = __VERIFIER_nondet_bool(); + ep32 = __VERIFIER_nondet_bool(); + ep34 = __VERIFIER_nondet_bool(); + ep35 = __VERIFIER_nondet_bool(); + ep41 = __VERIFIER_nondet_bool(); + ep42 = __VERIFIER_nondet_bool(); + ep43 = __VERIFIER_nondet_bool(); + ep45 = __VERIFIER_nondet_bool(); + ep51 = __VERIFIER_nondet_bool(); + ep52 = __VERIFIER_nondet_bool(); + ep53 = __VERIFIER_nondet_bool(); + ep54 = __VERIFIER_nondet_bool(); + id1 = __VERIFIER_nondet_char(); + r1 = __VERIFIER_nondet_char(); + st1 = __VERIFIER_nondet_char(); + nl1 = __VERIFIER_nondet_char(); + m1 = __VERIFIER_nondet_char(); + max1 = __VERIFIER_nondet_char(); + mode1 = __VERIFIER_nondet_bool(); + id2 = __VERIFIER_nondet_char(); + r2 = __VERIFIER_nondet_char(); + st2 = __VERIFIER_nondet_char(); + nl2 = __VERIFIER_nondet_char(); + m2 = __VERIFIER_nondet_char(); + max2 = __VERIFIER_nondet_char(); + mode2 = __VERIFIER_nondet_bool(); + id3 = __VERIFIER_nondet_char(); + r3 = __VERIFIER_nondet_char(); + st3 = __VERIFIER_nondet_char(); + nl3 = __VERIFIER_nondet_char(); + m3 = __VERIFIER_nondet_char(); + max3 = __VERIFIER_nondet_char(); + mode3 = __VERIFIER_nondet_bool(); + id4 = __VERIFIER_nondet_char(); + r4 = __VERIFIER_nondet_char(); + st4 = __VERIFIER_nondet_char(); + nl4 = __VERIFIER_nondet_char(); + m4 = __VERIFIER_nondet_char(); + max4 = __VERIFIER_nondet_char(); + mode4 = __VERIFIER_nondet_bool(); + id5 = __VERIFIER_nondet_char(); + r5 = __VERIFIER_nondet_char(); + st5 = __VERIFIER_nondet_char(); + nl5 = __VERIFIER_nondet_char(); + m5 = __VERIFIER_nondet_char(); + max5 = __VERIFIER_nondet_char(); + mode5 = __VERIFIER_nondet_bool(); + i2 = init(); + assume_abort_if_not(i2); + p12_old = nomsg; + p12_new = nomsg; + p13_old = nomsg; + p13_new = nomsg; + p14_old = nomsg; + p14_new = nomsg; + p15_old = nomsg; + p15_new = nomsg; + p21_old = nomsg; + p21_new = nomsg; + p23_old = nomsg; + p23_new = nomsg; + p24_old = nomsg; + p24_new = nomsg; + p25_old = nomsg; + p25_new = nomsg; + p31_old = nomsg; + p31_new = nomsg; + p32_old = nomsg; + p32_new = nomsg; + p34_old = nomsg; + p34_new = nomsg; + p35_old = nomsg; + p35_new = nomsg; + p41_old = nomsg; + p41_new = nomsg; + p42_old = nomsg; + p42_new = nomsg; + p43_old = nomsg; + p43_new = nomsg; + p45_old = nomsg; + p45_new = nomsg; + p51_old = nomsg; + p51_new = nomsg; + p52_old = nomsg; + p52_new = nomsg; + p53_old = nomsg; + p53_new = nomsg; + p54_old = nomsg; + p54_new = nomsg; + i2 = 0; + while (i2 < 10) { + { + node1(); + node2(); + node3(); + node4(); + node5(); + p12_old = p12_new; + p12_new = nomsg; + p13_old = p13_new; + p13_new = nomsg; + p14_old = p14_new; + p14_new = nomsg; + p15_old = p15_new; + p15_new = nomsg; + p21_old = p21_new; + p21_new = nomsg; + p23_old = p23_new; + p23_new = nomsg; + p24_old = p24_new; + p24_new = nomsg; + p25_old = p25_new; + p25_new = nomsg; + p31_old = p31_new; + p31_new = nomsg; + p32_old = p32_new; + p32_new = nomsg; + p34_old = p34_new; + p34_new = nomsg; + p35_old = p35_new; + p35_new = nomsg; + p41_old = p41_new; + p41_new = nomsg; + p42_old = p42_new; + p42_new = nomsg; + p43_old = p43_new; + p43_new = nomsg; + p45_old = p45_new; + p45_new = nomsg; + p51_old = p51_new; + p51_new = nomsg; + p52_old = p52_new; + p52_new = nomsg; + p53_old = p53_new; + p53_new = nomsg; + p54_old = p54_new; + p54_new = nomsg; + c1 = check(); + assert(c1); + i2++; + } + } + } + return 0; +} +void assert(_Bool arg) { + + { + if (!arg) { + { + ERROR : { + reach_error(); + abort(); + } + } + } + } +} From 8de31b5bb740c43fcf5435c870107092161d9e74 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Sat, 23 Sep 2023 00:17:25 +0400 Subject: [PATCH 022/103] [fix] Improve `IndependentConstraintSetUnion` --- include/klee/ADT/DisjointSetUnion.h | 29 +++- include/klee/ADT/Either.h | 142 ++++++++++++++++++ .../klee/Expr/IndependentConstraintSetUnion.h | 7 +- include/klee/Expr/IndependentSet.h | 15 +- lib/Core/ExecutionState.h | 2 +- lib/Expr/Constraints.cpp | 12 +- lib/Expr/IndependentConstraintSetUnion.cpp | 74 ++++----- lib/Expr/IndependentSet.cpp | 109 ++++++++------ 8 files changed, 289 insertions(+), 101 deletions(-) create mode 100644 include/klee/ADT/Either.h diff --git a/include/klee/ADT/DisjointSetUnion.h b/include/klee/ADT/DisjointSetUnion.h index 77a41353c2..b479ca0765 100644 --- a/include/klee/ADT/DisjointSetUnion.h +++ b/include/klee/ADT/DisjointSetUnion.h @@ -1,14 +1,27 @@ #ifndef KLEE_DISJOINEDSETUNION_H #define KLEE_DISJOINEDSETUNION_H + +#include "klee/ADT/Either.h" #include "klee/ADT/PersistentMap.h" #include "klee/ADT/PersistentSet.h" #include "klee/ADT/Ref.h" +#include "klee/Expr/Expr.h" +#include "klee/Expr/Symcrete.h" + +#include "klee/Support/CompilerWarning.h" +DISABLE_WARNING_PUSH +DISABLE_WARNING_DEPRECATED_DECLARATIONS +#include "llvm/Support/raw_ostream.h" +DISABLE_WARNING_POP + +#include #include #include #include #include namespace klee { +using ExprEitherSymcrete = either; template > @@ -55,7 +68,7 @@ class DisjointSetUnion { roots.remove(b); disjointSets.replace( {a, SetType::merge(disjointSets.at(a), disjointSets.at(b))}); - disjointSets.replace({b, nullptr}); + disjointSets.remove(b); } bool areJoined(const ValueType &i, const ValueType &j) const { @@ -109,6 +122,8 @@ class DisjointSetUnion { } void add(const DisjointSetUnion &b) { + internalStorage_ty oldRoots = roots; + internalStorage_ty newRoots = b.roots; for (auto it : b.parent) { parent.insert(it); } @@ -124,6 +139,15 @@ class DisjointSetUnion { for (auto it : b.disjointSets) { disjointSets.insert(it); } + for (ValueType nv : newRoots) { + for (ValueType ov : oldRoots) { + if (!areJoined(ov, nv) && + SetType::intersects(disjointSets.at(find(ov)), + disjointSets.at(find(nv)))) { + merge(ov, nv); + } + } + } } DisjointSetUnion() {} @@ -140,4 +164,5 @@ class DisjointSetUnion { disjointSets_ty ds() const { return disjointSets; } }; } // namespace klee -#endif + +#endif /* KLEE_DISJOINEDSETUNION_H */ diff --git a/include/klee/ADT/Either.h b/include/klee/ADT/Either.h new file mode 100644 index 0000000000..cc01bf761e --- /dev/null +++ b/include/klee/ADT/Either.h @@ -0,0 +1,142 @@ +//===-- Either.h ------------------------------------------------*- C++ -*-===// +// +// The KLEE Symbolic Virtual Machine +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef KLEE_EITHER_H +#define KLEE_EITHER_H + +#include "klee/ADT/Ref.h" + +#include "klee/Support/Casting.h" + +#include + +namespace llvm { +class raw_ostream; +} // namespace llvm + +namespace klee { + +template class either_left; +template class either_right; + +template class either { +protected: + friend class ref>; + friend class ref>; + + /// @brief Required by klee::ref-managed objects + class ReferenceCounter _refCount; + +public: + using left = either_left; + using right = either_right; + + enum class EitherKind { Left, Right }; + + virtual ~either() {} + virtual EitherKind getKind() const = 0; + + static bool classof(const either *) { return true; } + // virtual unsigned hash() = 0; + virtual int compare(const either &b) = 0; + virtual bool equals(const either &b) = 0; +}; + +template class either_left : public either { +protected: + friend class ref>; + friend class ref>; + +private: + ref value_; + +public: + either_left(ref leftValue) : value_(leftValue){}; + + ref value() const { return value_; } + operator ref const() { return value_; } + + virtual typename either::EitherKind getKind() const override { + return either::EitherKind::Left; + } + + static bool classof(const either *S) { + return S->getKind() == either::EitherKind::Left; + } + static bool classof(const either_left *) { return true; } + + // virtual unsigned hash() override { return value_->hash(); }; + virtual int compare(const either &b) override { + if (b.getKind() != getKind()) { + return b.getKind() < getKind() ? -1 : 1; + } + const either_left &el = static_cast &>(b); + if (el.value() != value()) { + return el.value() < value() ? -1 : 1; + } + return 0; + } + + virtual bool equals(const either &b) override { + if (b.getKind() != getKind()) { + return false; + } + const either_left &el = static_cast &>(b); + return el.value() == value(); + } +}; + +template class either_right : public either { +protected: + friend class ref>; + friend class ref>; + +private: + ref value_; + +public: + either_right(ref rightValue) : value_(rightValue){}; + + ref value() const { return value_; } + operator ref const() { return value_; } + + virtual typename either::EitherKind getKind() const override { + return either::EitherKind::Right; + } + + static bool classof(const either *S) { + return S->getKind() == either::EitherKind::Right; + } + static bool classof(const either_right *) { return true; } + + // virtual unsigned hash() override { return value_->hash(); }; + virtual int compare(const either &b) override { + if (b.getKind() != getKind()) { + return b.getKind() < getKind() ? -1 : 1; + } + const either_right &el = + static_cast &>(b); + if (el.value() != value()) { + return el.value() < value() ? -1 : 1; + } + return 0; + } + + virtual bool equals(const either &b) override { + if (b.getKind() != getKind()) { + return false; + } + const either_right &el = + static_cast &>(b); + return el.value() == value(); + } +}; +} // end namespace klee + +#endif /* KLEE_EITHER_H */ diff --git a/include/klee/Expr/IndependentConstraintSetUnion.h b/include/klee/Expr/IndependentConstraintSetUnion.h index 3591cd5eff..4ec9e11c5a 100644 --- a/include/klee/Expr/IndependentConstraintSetUnion.h +++ b/include/klee/Expr/IndependentConstraintSetUnion.h @@ -1,12 +1,15 @@ #ifndef KLEE_INDEPENDENTCONSTRAINTSETUNION_H #define KLEE_INDEPENDENTCONSTRAINTSETUNION_H +#include "klee/ADT/Either.h" + #include "klee/Expr/Assignment.h" #include "klee/Expr/IndependentSet.h" namespace klee { class IndependentConstraintSetUnion - : public DisjointSetUnion, IndependentConstraintSet> { + : public DisjointSetUnion, + IndependentConstraintSet> { public: Assignment concretization; @@ -43,4 +46,4 @@ class IndependentConstraintSetUnion }; } // namespace klee -#endif +#endif /* KLEE_INDEPENDENTCONSTRAINTSETUNION_H */ diff --git a/include/klee/Expr/IndependentSet.h b/include/klee/Expr/IndependentSet.h index ef29498f5a..a0878ea6c2 100644 --- a/include/klee/Expr/IndependentSet.h +++ b/include/klee/Expr/IndependentSet.h @@ -2,6 +2,7 @@ #define KLEE_INDEPENDENTSET_H #include "klee/ADT/DisjointSetUnion.h" +#include "klee/ADT/Either.h" #include "klee/ADT/PersistentMap.h" #include "klee/ADT/PersistentSet.h" #include "klee/Expr/Assignment.h" @@ -21,6 +22,7 @@ DISABLE_WARNING_POP #include namespace klee { +using ExprEitherSymcrete = either; template class DenseSet { typedef std::set set_ty; @@ -84,7 +86,11 @@ inline llvm::raw_ostream &operator<<(llvm::raw_ostream &os, class IndependentConstraintSet { private: - using InnerSetUnion = DisjointSetUnion, IndependentConstraintSet>; + using InnerSetUnion = + DisjointSetUnion, IndependentConstraintSet>; + + void initIndependentConstraintSet(ref e); + void initIndependentConstraintSet(ref s); public: // All containers need to become persistent to make fast copy and faster @@ -117,11 +123,8 @@ class IndependentConstraintSet { Assignment &assign) const; IndependentConstraintSet(); - IndependentConstraintSet(ref e); - IndependentConstraintSet(ref s); - IndependentConstraintSet(const ref &ics); - - IndependentConstraintSet &operator=(const IndependentConstraintSet &ies); + explicit IndependentConstraintSet(ref v); + IndependentConstraintSet(const IndependentConstraintSet &ics); void print(llvm::raw_ostream &os) const; diff --git a/lib/Core/ExecutionState.h b/lib/Core/ExecutionState.h index a13b963de7..be63b654bc 100644 --- a/lib/Core/ExecutionState.h +++ b/lib/Core/ExecutionState.h @@ -228,7 +228,7 @@ struct Symbolic { struct MemorySubobject { ref address; unsigned size; - MemorySubobject(ref address, unsigned size) + explicit MemorySubobject(ref address, unsigned size) : address(address), size(size) {} MemorySubobject &operator=(const MemorySubobject &other) = default; }; diff --git a/lib/Expr/Constraints.cpp b/lib/Expr/Constraints.cpp index a1612e9c74..11efeed2b1 100644 --- a/lib/Expr/Constraints.cpp +++ b/lib/Expr/Constraints.cpp @@ -207,12 +207,12 @@ ConstraintSet::ConstraintSet() {} void ConstraintSet::addConstraint(ref e, const Assignment &delta) { _constraints.insert(e); - _independentElements.addExpr(e); // Update bindings for (auto i : delta.bindings) { _concretization.bindings.replace({i.first, i.second}); } _independentElements.updateConcretization(delta); + _independentElements.addExpr(e); } IDType Symcrete::idCounter = 0; @@ -252,8 +252,10 @@ ConstraintSet ConstraintSet::getConcretizedVersion() const { ConstraintSet cs; cs._independentElements = _independentElements.getConcretizedVersion(); - for (ref e : cs._independentElements.is()) { - cs._constraints.insert(e); + for (auto &e : cs._independentElements.is()) { + if (isa(e)) { + cs._constraints.insert(cast(e)->value()); + } } return cs; } @@ -263,8 +265,8 @@ ConstraintSet ConstraintSet::getConcretizedVersion( ConstraintSet cs; cs._independentElements = _independentElements.getConcretizedVersion(newConcretization); - for (ref e : cs._independentElements.is()) { - cs._constraints.insert(e); + for (auto &e : cs._independentElements.is()) { + cs._constraints.insert(cast(e)->value()); } return cs; } diff --git a/lib/Expr/IndependentConstraintSetUnion.cpp b/lib/Expr/IndependentConstraintSetUnion.cpp index 3ec73081cb..01358e2623 100644 --- a/lib/Expr/IndependentConstraintSetUnion.cpp +++ b/lib/Expr/IndependentConstraintSetUnion.cpp @@ -8,7 +8,7 @@ IndependentConstraintSetUnion::IndependentConstraintSetUnion( const constraints_ty &is, const SymcreteOrderedSet &os, const Assignment &c) { for (ref e : is) { - addValue(e); + addExpr(e); } for (ref s : os) { addSymcrete(s); @@ -18,25 +18,25 @@ IndependentConstraintSetUnion::IndependentConstraintSetUnion( IndependentConstraintSetUnion::IndependentConstraintSetUnion( ref ics) { - for (ref e : ics->exprs) { - rank.replace({e, 0}); - internalStorage.insert(e); - disjointSets.replace({e, nullptr}); + auto exprs = ics->exprs; + for (ref e : exprs) { + auto v = ref(new ExprEitherSymcrete::left(e)); + rank.replace({v, 0}); + internalStorage.insert(v); } for (ref s : ics->symcretes) { - ref e = s->symcretized; - rank.replace({e, 0}); - internalStorage.insert(e); - disjointSets.replace({e, nullptr}); + auto v = ref(new ExprEitherSymcrete::right(s)); + rank.replace({v, 0}); + internalStorage.insert(v); } if (internalStorage.size() == 0) { return; } - ref first = *(internalStorage.begin()); - for (ref e : internalStorage) { + auto &first = *(internalStorage.begin()); + for (auto &e : internalStorage) { parent.replace({e, first}); } rank.replace({first, 1}); @@ -53,26 +53,26 @@ void IndependentConstraintSetUnion::addIndependentConstraintSetUnion( void IndependentConstraintSetUnion::updateConcretization( const Assignment &delta) { - for (ref e : roots) { + for (auto &e : roots) { ref ics = disjointSets.at(e); Assignment part = delta.part(ics->getSymcretes()); ics = ics->updateConcretization(part, concretizedExprs); disjointSets.replace({e, ics}); } - for (auto it : delta.bindings) { + for (auto &it : delta.bindings) { concretization.bindings.replace({it.first, it.second}); } } void IndependentConstraintSetUnion::removeConcretization( const Assignment &remove) { - for (ref e : roots) { + for (auto &e : roots) { ref ics = disjointSets.at(e); Assignment part = remove.part(ics->getSymcretes()); ics = ics->removeConcretization(part, concretizedExprs); disjointSets.replace({e, ics}); } - for (auto it : remove.bindings) { + for (auto &it : remove.bindings) { concretization.bindings.remove(it.first); } } @@ -95,8 +95,9 @@ void IndependentConstraintSetUnion::reEvaluateConcretization( void IndependentConstraintSetUnion::getAllIndependentConstraintSets( ref e, std::vector> &result) const { - ref compare = new IndependentConstraintSet(e); - for (ref r : roots) { + ref compare = + new IndependentConstraintSet(new ExprEitherSymcrete::left(e)); + for (auto &r : roots) { ref ics = disjointSets.at(r); if (!IndependentConstraintSet::intersects(ics, compare)) { result.push_back(ics); @@ -107,8 +108,9 @@ void IndependentConstraintSetUnion::getAllIndependentConstraintSets( void IndependentConstraintSetUnion::getAllDependentConstraintSets( ref e, std::vector> &result) const { - ref compare = new IndependentConstraintSet(e); - for (ref r : roots) { + ref compare = + new IndependentConstraintSet(new ExprEitherSymcrete::left(e)); + for (auto &r : roots) { ref ics = disjointSets.at(r); if (IndependentConstraintSet::intersects(ics, compare)) { result.push_back(ics); @@ -117,39 +119,25 @@ void IndependentConstraintSetUnion::getAllDependentConstraintSets( } void IndependentConstraintSetUnion::addExpr(ref e) { - addValue(e); - disjointSets.replace({find(e), disjointSets.at(find(e))->addExpr(e)}); + addValue(new ExprEitherSymcrete::left(e)); } void IndependentConstraintSetUnion::addSymcrete(ref s) { - ref value = s->symcretized; - if (internalStorage.find(value) != internalStorage.end()) { - return; - } - parent.insert({value, value}); - roots.insert(value); - rank.insert({value, 0}); - disjointSets.insert({value, new IndependentConstraintSet(s)}); - - internalStorage.insert(value); - internalStorage_ty oldRoots = roots; - for (ref v : oldRoots) { - if (!areJoined(v, value) && - IndependentConstraintSet::intersects(disjointSets.at(find(v)), - disjointSets.at(find(value)))) { - merge(v, value); - } - } - disjointSets.replace( - {find(value), disjointSets.at(find(value))->addExpr(value)}); + addValue(new ExprEitherSymcrete::right(s)); } IndependentConstraintSetUnion IndependentConstraintSetUnion::getConcretizedVersion() const { IndependentConstraintSetUnion icsu; - for (ref i : roots) { + for (auto &i : roots) { ref root = disjointSets.at(i); - icsu.add(root->concretizedSets); + if (root->concretization.bindings.empty()) { + for (ref expr : root->exprs) { + icsu.addValue(new ExprEitherSymcrete::left(expr)); + } + } else { + icsu.add(root->concretizedSets); + } icsu.concretization.addIndependentAssignment(root->concretization); } icsu.concretizedExprs = concretizedExprs; diff --git a/lib/Expr/IndependentSet.cpp b/lib/Expr/IndependentSet.cpp index ed602599b2..3acca539c9 100644 --- a/lib/Expr/IndependentSet.cpp +++ b/lib/Expr/IndependentSet.cpp @@ -16,18 +16,10 @@ #include namespace klee { - -ref -IndependentConstraintSet::addExpr(ref e) const { - ref ics = new IndependentConstraintSet(this); - ics->concretizedSets.addValue(concretization.evaluate(e)); - return ics; -} - ref IndependentConstraintSet::updateConcretization( const Assignment &delta, ExprHashMap> &concretizedExprs) const { - ref ics = new IndependentConstraintSet(this); + ref ics = new IndependentConstraintSet(*this); if (delta.bindings.size() == 0) { return ics; } @@ -37,12 +29,21 @@ IndependentConstraintSet::updateConcretization( InnerSetUnion DSU; for (ref i : exprs) { ref e = ics->concretization.evaluate(i); + if (auto ce = dyn_cast(e)) { + assert(ce->isTrue() && "Attempt to add invalid constraint"); + continue; + } concretizedExprs[i] = e; - DSU.addValue(e); + DSU.addValue(new ExprEitherSymcrete::left(e)); } for (ref s : symcretes) { - DSU.addValue(EqExpr::create(ics->concretization.evaluate(s->symcretized), - s->symcretized)); + ref e = EqExpr::create(ics->concretization.evaluate(s->symcretized), + s->symcretized); + if (auto ce = dyn_cast(e)) { + assert(ce->isTrue() && "Attempt to add invalid constraint"); + continue; + } + DSU.addValue(new ExprEitherSymcrete::left(e)); } ics->concretizedSets = DSU; return ics; @@ -51,7 +52,7 @@ IndependentConstraintSet::updateConcretization( ref IndependentConstraintSet::removeConcretization( const Assignment &delta, ExprHashMap> &concretizedExprs) const { - ref ics = new IndependentConstraintSet(this); + ref ics = new IndependentConstraintSet(*this); if (delta.bindings.size() == 0) { return ics; } @@ -61,12 +62,21 @@ IndependentConstraintSet::removeConcretization( InnerSetUnion DSU; for (ref i : exprs) { ref e = ics->concretization.evaluate(i); + if (auto ce = dyn_cast(e)) { + assert(ce->isTrue() && "Attempt to add invalid constraint"); + continue; + } concretizedExprs[i] = e; - DSU.addValue(e); + DSU.addValue(new ExprEitherSymcrete::left(e)); } for (ref s : symcretes) { - DSU.addValue(EqExpr::create(ics->concretization.evaluate(s->symcretized), - s->symcretized)); + ref e = EqExpr::create(ics->concretization.evaluate(s->symcretized), + s->symcretized); + if (auto ce = dyn_cast(e)) { + assert(ce->isTrue() && "Attempt to add invalid constraint"); + continue; + } + DSU.addValue(new ExprEitherSymcrete::left(e)); } ics->concretizedSets = DSU; @@ -97,7 +107,15 @@ void IndependentConstraintSet::addValuesToAssignment( IndependentConstraintSet::IndependentConstraintSet() {} -IndependentConstraintSet::IndependentConstraintSet(ref e) { +IndependentConstraintSet::IndependentConstraintSet(ref v) { + if (isa(v)) { + initIndependentConstraintSet(cast(v)->value()); + } else { + initIndependentConstraintSet(cast(v)->value()); + } +} + +void IndependentConstraintSet::initIndependentConstraintSet(ref e) { exprs.insert(e); // Track all reads in the program. Determines whether reads are // concrete or symbolic. If they are symbolic, "collapses" array @@ -134,13 +152,9 @@ IndependentConstraintSet::IndependentConstraintSet(ref e) { } } -IndependentConstraintSet::IndependentConstraintSet(ref s) { +void IndependentConstraintSet::initIndependentConstraintSet(ref s) { symcretes.insert(s); - for (Symcrete &dependentSymcrete : s->dependentSymcretes()) { - symcretes.insert(ref(&dependentSymcrete)); - } - // Track all reads in the program. Determines whether reads are // concrete or symbolic. If they are symbolic, "collapses" array // by adding it to wholeObjects. Otherwise, creates a mapping of @@ -193,22 +207,10 @@ IndependentConstraintSet::IndependentConstraintSet(ref s) { } IndependentConstraintSet::IndependentConstraintSet( - const ref &ics) - : elements(ics->elements), wholeObjects(ics->wholeObjects), - exprs(ics->exprs), symcretes(ics->symcretes), - concretization(ics->concretization), - concretizedSets(ics->concretizedSets) {} - -IndependentConstraintSet & -IndependentConstraintSet::operator=(const IndependentConstraintSet &ics) { - elements = ics.elements; - wholeObjects = ics.wholeObjects; - exprs = ics.exprs; - symcretes = ics.symcretes; - concretization = ics.concretization; - concretizedSets = ics.concretizedSets; - return *this; -} + const IndependentConstraintSet &ics) + : elements(ics.elements), wholeObjects(ics.wholeObjects), exprs(ics.exprs), + symcretes(ics.symcretes), concretization(ics.concretization), + concretizedSets(ics.concretizedSets) {} void IndependentConstraintSet::print(llvm::raw_ostream &os) const { os << "{"; @@ -279,8 +281,8 @@ bool IndependentConstraintSet::intersects( ref IndependentConstraintSet::merge(ref A, ref B) { - ref a = new IndependentConstraintSet(A); - ref b = new IndependentConstraintSet(B); + ref a = new IndependentConstraintSet(*A); + ref b = new IndependentConstraintSet(*B); if (a->wholeObjects.size() + a->elements.size() < b->wholeObjects.size() + b->elements.size()) { @@ -323,7 +325,30 @@ IndependentConstraintSet::merge(ref A, } b->addValuesToAssignment(b->concretization.keys(), b->concretization.values(), a->concretization); - a->concretizedSets.add(b->concretizedSets); + + if (!a->concretization.bindings.empty()) { + InnerSetUnion DSU; + for (ref i : a->exprs) { + ref e = a->concretization.evaluate(i); + if (auto ce = dyn_cast(e)) { + assert(ce->isTrue() && "Attempt to add invalid constraint"); + continue; + } + DSU.addValue(new ExprEitherSymcrete::left(e)); + } + for (ref s : a->symcretes) { + ref e = EqExpr::create(a->concretization.evaluate(s->symcretized), + s->symcretized); + if (auto ce = dyn_cast(e)) { + assert(ce->isTrue() && "Attempt to add invalid constraint"); + continue; + } + DSU.addValue(new ExprEitherSymcrete::left(e)); + } + + a->concretizedSets = DSU; + } + return a; } @@ -355,7 +380,7 @@ void calculateArraysInFactors( } std::vector result; ref queryExprSet = - new IndependentConstraintSet(queryExpr); + new IndependentConstraintSet(new ExprEitherSymcrete::left(queryExpr)); queryExprSet->calculateArrayReferences(result); returnSet.insert(result.begin(), result.end()); returnVector.insert(returnVector.begin(), returnSet.begin(), returnSet.end()); From 847ed62c7315e48bf430ade654665e1b45936a45 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Mon, 25 Sep 2023 16:21:57 +0400 Subject: [PATCH 023/103] [feat] Add optimization in case all constraints are dependent --- lib/Solver/IndependentSolver.cpp | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/lib/Solver/IndependentSolver.cpp b/lib/Solver/IndependentSolver.cpp index 50e518fb59..67c0309335 100644 --- a/lib/Solver/IndependentSolver.cpp +++ b/lib/Solver/IndependentSolver.cpp @@ -152,6 +152,14 @@ bool IndependentSolver::computeInitialValues( Assignment retMap; std::vector> dependentFactors; query.getAllDependentConstraintsSets(dependentFactors); + std::vector> independentFactors; + query.getAllIndependentConstraintsSets(independentFactors); + + if (independentFactors.size() == 0 && dependentFactors.size() == 1) { + return solver->impl->computeInitialValues(query, objects, values, + hasSolution); + } + ConstraintSet dependentConstriants(dependentFactors); std::vector dependentFactorsObjects; @@ -174,9 +182,6 @@ bool IndependentSolver::computeInitialValues( } } - std::vector> independentFactors; - query.getAllIndependentConstraintsSets(independentFactors); - // Used to rearrange all of the answers into the correct order for (ref it : independentFactors) { std::vector arraysInFactor; @@ -242,6 +247,13 @@ bool IndependentSolver::check(const Query &query, ref &result) { Assignment retMap; std::vector> dependentFactors; query.getAllDependentConstraintsSets(dependentFactors); + std::vector> independentFactors; + query.getAllIndependentConstraintsSets(independentFactors); + + if (independentFactors.size() == 0 && dependentFactors.size() == 1) { + return solver->impl->check(query, result); + } + ConstraintSet dependentConstriants(dependentFactors); std::vector dependentFactorsObjects; @@ -266,9 +278,6 @@ bool IndependentSolver::check(const Query &query, ref &result) { } } - std::vector> independentFactors; - query.getAllIndependentConstraintsSets(independentFactors); - // Used to rearrange all of the answers into the correct order for (ref it : independentFactors) { std::vector arraysInFactor; From 3fae575b4c7ac9ccef151ebf1ab8af668adcb968 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Fri, 29 Sep 2023 13:17:40 +0400 Subject: [PATCH 024/103] [fix] Rebuild constraint dsu after constraints simplification --- include/klee/Expr/Constraints.h | 1 + lib/Core/CXXTypeSystem/CXXTypeManager.cpp | 6 ++++-- lib/Expr/Constraints.cpp | 19 ++++++++++++++----- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/include/klee/Expr/Constraints.h b/include/klee/Expr/Constraints.h index a87cd0ce3c..d6f47e3d94 100644 --- a/include/klee/Expr/Constraints.h +++ b/include/klee/Expr/Constraints.h @@ -152,6 +152,7 @@ class Simplificator { struct SetResult { constraints_ty simplified; ExprHashMap dependency; + bool wasSimplified; }; public: diff --git a/lib/Core/CXXTypeSystem/CXXTypeManager.cpp b/lib/Core/CXXTypeSystem/CXXTypeManager.cpp index a171e65a9d..1df8091e9c 100644 --- a/lib/Core/CXXTypeSystem/CXXTypeManager.cpp +++ b/lib/Core/CXXTypeSystem/CXXTypeManager.cpp @@ -201,8 +201,10 @@ static ref getComplexPointerRestrictions( restrictions.addConstraint(innerAlignmentRequirement, {}); } - auto simplified = Simplificator::simplify(restrictions.cs()).simplified; - restrictions.changeCS(simplified); + auto simplified = Simplificator::simplify(restrictions.cs()); + if (simplified.wasSimplified) { + restrictions.changeCS(simplified.simplified); + } for (auto restriction : restrictions.cs()) { if (resultCondition.isNull()) { resultCondition = restriction; diff --git a/lib/Expr/Constraints.cpp b/lib/Expr/Constraints.cpp index 11efeed2b1..f14d612379 100644 --- a/lib/Expr/Constraints.cpp +++ b/lib/Expr/Constraints.cpp @@ -15,6 +15,7 @@ #include "klee/Expr/ExprHashMap.h" #include "klee/Expr/ExprUtil.h" #include "klee/Expr/ExprVisitor.h" +#include "klee/Expr/IndependentSet.h" #include "klee/Expr/Path.h" #include "klee/Expr/Symcrete.h" #include "klee/Module/KModule.h" @@ -289,7 +290,11 @@ void ConstraintSet::print(llvm::raw_ostream &os) const { void ConstraintSet::dump() const { this->print(llvm::errs()); } -void ConstraintSet::changeCS(constraints_ty &cs) { _constraints = cs; } +void ConstraintSet::changeCS(constraints_ty &cs) { + _constraints = cs; + _independentElements = + IndependentConstraintSetUnion(_constraints, _symcretes, _concretization); +} const constraints_ty &ConstraintSet::cs() const { return _constraints; } @@ -355,10 +360,12 @@ ExprHashSet PathConstraints::addConstraint(ref e, const Assignment &delta, if (RewriteEqualities != RewriteEqualitiesPolicy::None) { auto simplified = Simplificator::simplify(constraints.cs(), RewriteEqualities); - constraints.changeCS(simplified.simplified); + if (simplified.wasSimplified) { + constraints.changeCS(simplified.simplified); - _simplificationMap = Simplificator::composeExprDependencies( - _simplificationMap, simplified.dependency); + _simplificationMap = Simplificator::composeExprDependencies( + _simplificationMap, simplified.dependency); + } } return added; @@ -463,6 +470,7 @@ Simplificator::simplify(const constraints_ty &constraints, dependencies.insert({constraint, {constraint}}); } + bool actuallyChanged = false; bool changed = true; while (changed) { changed = false; @@ -495,6 +503,7 @@ Simplificator::simplify(const constraints_ty &constraints, currentDependencies[part].insert(constraint); } if (constraint != simplifiedConstraint || andsSplit.size() > 1) { + actuallyChanged = true; changed = true; } } @@ -508,7 +517,7 @@ Simplificator::simplify(const constraints_ty &constraints, simplified.erase(ConstantExpr::createTrue()); dependencies.erase(ConstantExpr::createTrue()); - return {simplified, dependencies}; + return {simplified, dependencies, actuallyChanged}; } Simplificator::Replacements From a0bb3ca6d339c29cd63ba2bf2d9f99580c2191ab Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Wed, 27 Sep 2023 14:13:44 +0400 Subject: [PATCH 025/103] [fix] Fix MemorySubobject warning --- lib/Core/ExecutionState.h | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/Core/ExecutionState.h b/lib/Core/ExecutionState.h index be63b654bc..a40c6a0982 100644 --- a/lib/Core/ExecutionState.h +++ b/lib/Core/ExecutionState.h @@ -230,7 +230,6 @@ struct MemorySubobject { unsigned size; explicit MemorySubobject(ref address, unsigned size) : address(address), size(size) {} - MemorySubobject &operator=(const MemorySubobject &other) = default; }; struct MemorySubobjectHash { From 390866fab300381ad9def38c4e2160f2993b17c4 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Wed, 27 Sep 2023 14:13:25 +0400 Subject: [PATCH 026/103] [fix] Fix `CachingSolver` --- lib/Solver/CachingSolver.cpp | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/lib/Solver/CachingSolver.cpp b/lib/Solver/CachingSolver.cpp index a84b686474..0bf904a60a 100644 --- a/lib/Solver/CachingSolver.cpp +++ b/lib/Solver/CachingSolver.cpp @@ -223,19 +223,11 @@ bool CachingSolver::computeValidity(const Query &query, if (!solver->impl->computeValidity(query, result)) return false; - switch (result) { - case PValidity::MustBeTrue: - cachedResult = PValidity::MustBeTrue; - break; - case PValidity::MustBeFalse: - cachedResult = PValidity::MustBeFalse; - break; - default: - cachedResult = PValidity::TrueOrFalse; - break; - } + cachedResult = result; + assert(cachedResult != PValidity::None); cacheInsert(query, cachedResult); + return true; } From f5f7574a8f364234cfa4e4c3e8f081473e773c34 Mon Sep 17 00:00:00 2001 From: Yurii Kostyukov Date: Mon, 2 Oct 2023 17:51:25 +0300 Subject: [PATCH 027/103] [fix] Tests for states with mocks --- lib/Core/ExecutionState.cpp | 20 ------ lib/Core/ExecutionState.h | 1 - lib/Core/Executor.cpp | 68 +++++++++++++++---- lib/Core/Executor.h | 1 + .../2023-10-02-test-from-mocked-global.c | 16 +++++ 5 files changed, 70 insertions(+), 36 deletions(-) create mode 100644 test/regression/2023-10-02-test-from-mocked-global.c diff --git a/lib/Core/ExecutionState.cpp b/lib/Core/ExecutionState.cpp index f1152938e7..5ee6b7c8da 100644 --- a/lib/Core/ExecutionState.cpp +++ b/lib/Core/ExecutionState.cpp @@ -363,26 +363,6 @@ void ExecutionState::addUniquePointerResolution(ref address, } } -bool ExecutionState::resolveOnSymbolics(const ref &addr, - IDType &result) const { - uint64_t address = addr->getZExtValue(); - - for (const auto &res : symbolics) { - const auto &mo = res.memoryObject; - // Check if the provided address is between start and end of the object - // [mo->address, mo->address + mo->size) or the object is a 0-sized object. - ref size = cast( - constraints.cs().concretization().evaluate(mo->getSizeExpr())); - if ((size->getZExtValue() == 0 && address == mo->address) || - (address - mo->address < size->getZExtValue())) { - result = mo->id; - return true; - } - } - - return false; -} - /**/ llvm::raw_ostream &klee::operator<<(llvm::raw_ostream &os, diff --git a/lib/Core/ExecutionState.h b/lib/Core/ExecutionState.h index a40c6a0982..424dfc4248 100644 --- a/lib/Core/ExecutionState.h +++ b/lib/Core/ExecutionState.h @@ -428,7 +428,6 @@ class ExecutionState { unsigned size = 0); void addUniquePointerResolution(ref address, const MemoryObject *mo, unsigned size = 0); - bool resolveOnSymbolics(const ref &addr, IDType &result) const; void addConstraint(ref e, const Assignment &c); void addCexPreference(const ref &cond); diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index 63130c38d8..1d0c887e06 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -6949,19 +6949,43 @@ void Executor::logState(const ExecutionState &state, int id, } } -void Executor::setInitializationGraph(const ExecutionState &state, - const Assignment &model, KTest &ktest) { +bool resolveOnSymbolics(const std::vector &symbolics, + const Assignment &assn, + const ref &addr, IDType &result) { + uint64_t address = addr->getZExtValue(); + + for (const auto &res : symbolics) { + const auto &mo = res.memoryObject; + // Check if the provided address is between start and end of the object + // [mo->address, mo->address + mo->size) or the object is a 0-sized object. + ref size = + cast(assn.evaluate(mo->getSizeExpr())); + if ((size->getZExtValue() == 0 && address == mo->address) || + (address - mo->address < size->getZExtValue())) { + result = mo->id; + return true; + } + } + + return false; +} + +void Executor::setInitializationGraph( + const ExecutionState &state, const std::vector &symbolics, + const Assignment &model, KTest &ktest) { std::map> pointers; std::map>> s; ExprHashMap>> resolvedPointers; std::unordered_map> idToSymbolics; - for (const auto &symbolic : state.symbolics) { + for (const auto &symbolic : symbolics) { ref mo = symbolic.memoryObject; idToSymbolics[mo->id] = mo; } - for (const auto &symbolic : state.symbolics) { + const klee::Assignment &assn = state.constraints.cs().concretization(); + + for (const auto &symbolic : symbolics) { KType *symbolicType = symbolic.type; if (!symbolicType->getRawType()) { continue; @@ -6989,7 +7013,7 @@ void Executor::setInitializationGraph(const ExecutionState &state, ref constantAddress = cast(addressInModel); IDType idResult; - if (state.resolveOnSymbolics(constantAddress, idResult)) { + if (resolveOnSymbolics(symbolics, assn, constantAddress, idResult)) { ref mo = idToSymbolics[idResult]; resolvedPointers[address] = std::make_pair(idResult, mo->getOffsetExpr(address)); @@ -7024,12 +7048,12 @@ void Executor::setInitializationGraph(const ExecutionState &state, // The objects have to be symbolic bool pointerFound = false, pointeeFound = false; size_t pointerIndex = 0, pointeeIndex = 0; - for (size_t i = 0; i < state.symbolics.size(); i++) { - if (state.symbolics[i].memoryObject == pointerResolution.first) { + for (size_t i = 0; i < symbolics.size(); i++) { + if (symbolics[i].memoryObject == pointerResolution.first) { pointerIndex = i; pointerFound = true; } - if (state.symbolics[i].memoryObject->id == pointer.second.first) { + if (symbolics[i].memoryObject->id == pointer.second.first) { pointeeIndex = i; pointeeFound = true; } @@ -7081,6 +7105,16 @@ Assignment Executor::computeConcretization(const ConstraintSet &constraints, return concretization; } +bool isReproducible(const klee::Symbolic &symb) { + auto arr = symb.array; + bool bad = IrreproducibleSource::classof(arr->source.get()); + if (bad) + klee_warning_once(arr->source.get(), + "A irreproducible symbolic %s reaches a test", + arr->getIdentifier().c_str()); + return !bad; +} + bool Executor::getSymbolicSolution(const ExecutionState &state, KTest &res) { solver->setTimeout(coreSolverTimeout); @@ -7117,10 +7151,14 @@ bool Executor::getSymbolicSolution(const ExecutionState &state, KTest &res) { } } + std::vector symbolics; + std::copy_if(state.symbolics.begin(), state.symbolics.end(), + std::back_inserter(symbolics), isReproducible); + std::vector> values; std::vector objects; - for (unsigned i = 0; i != state.symbolics.size(); ++i) - objects.push_back(state.symbolics[i].array); + for (unsigned i = 0; i != symbolics.size(); ++i) + objects.push_back(symbolics[i].array); bool success = solver->getInitialValues(extendedConstraints.cs(), objects, values, state.queryMetaData); solver->setTimeout(time::Span()); @@ -7131,11 +7169,11 @@ bool Executor::getSymbolicSolution(const ExecutionState &state, KTest &res) { return false; } - res.objects = new KTestObject[state.symbolics.size()]; - res.numObjects = state.symbolics.size(); + res.objects = new KTestObject[symbolics.size()]; + res.numObjects = symbolics.size(); - for (unsigned i = 0; i != state.symbolics.size(); ++i) { - auto mo = state.symbolics[i].memoryObject; + for (unsigned i = 0; i != symbolics.size(); ++i) { + auto mo = symbolics[i].memoryObject; KTestObject *o = &res.objects[i]; o->name = const_cast(mo->name.c_str()); o->address = mo->address; @@ -7151,7 +7189,7 @@ bool Executor::getSymbolicSolution(const ExecutionState &state, KTest &res) { model.bindings.insert(binding); } - setInitializationGraph(state, model, res); + setInitializationGraph(state, symbolics, model, res); return true; } diff --git a/lib/Core/Executor.h b/lib/Core/Executor.h index 1cd6c1c4a0..26c2e9bba5 100644 --- a/lib/Core/Executor.h +++ b/lib/Core/Executor.h @@ -793,6 +793,7 @@ class Executor : public Interpreter { Interpreter::LogType logFormat = Interpreter::STP) override; void setInitializationGraph(const ExecutionState &state, + const std::vector &symbolics, const Assignment &model, KTest &tc); void logState(const ExecutionState &state, int id, diff --git a/test/regression/2023-10-02-test-from-mocked-global.c b/test/regression/2023-10-02-test-from-mocked-global.c new file mode 100644 index 0000000000..a62eeb9bba --- /dev/null +++ b/test/regression/2023-10-02-test-from-mocked-global.c @@ -0,0 +1,16 @@ +// Darwin does not support section attribute: `argument to 'section' attribute is not valid for this target: mach-o section specifier requires a segment whose length is between 1 and 16 characters` +// REQUIRES: not-darwin +// RUN: %clang %s -g -emit-llvm %O0opt -c -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --mock-all-externals --write-xml-tests --output-dir=%t.klee-out %t1.bc +// RUN: FileCheck --input-file %t.klee-out/test000001.xml %s + +extern void *__crc_mc44s803_attach __attribute__((__weak__)); +static unsigned long const __kcrctab_mc44s803_attach __attribute__((__used__, __unused__, + __section__("___kcrctab+mc44s803_attach"))) = (unsigned long const)((unsigned long)(&__crc_mc44s803_attach)); + +int main() { + return 0; +} + +// CHECK-NOT: Date: Tue, 15 Aug 2023 12:47:55 +0300 Subject: [PATCH 028/103] Memory optimize, remove InstructionInfoTable, add immutable list for symbolics --- include/klee/ADT/ImmutableList.h | 106 + include/klee/Core/Interpreter.h | 15 +- include/klee/Module/InstructionInfoTable.h | 113 - include/klee/Module/KInstruction.h | 56 +- include/klee/Module/KModule.h | 91 +- include/klee/Module/LocationInfo.h | 35 + include/klee/Support/ErrorHandling.h | 2 +- lib/Basic/Statistics.cpp | 2 +- lib/Core/DistanceCalculator.cpp | 3 - lib/Core/ExecutionState.cpp | 40 +- lib/Core/ExecutionState.h | 12 +- lib/Core/Executor.cpp | 157 +- lib/Core/Executor.h | 23 +- lib/Core/ExecutorUtil.cpp | 8 +- lib/Core/Memory.h | 2 +- lib/Core/Searcher.cpp | 5 +- lib/Core/SpecialFunctionHandler.cpp | 2 +- lib/Core/StatsTracker.cpp | 166 +- lib/Core/StatsTracker.h | 1 - lib/Core/TargetedExecutionManager.cpp | 19 +- lib/Core/TargetedExecutionManager.h | 6 - lib/Expr/ExprPPrinter.cpp | 4 +- lib/Expr/Path.cpp | 7 +- lib/Expr/SymbolicSource.cpp | 33 +- lib/Module/CMakeLists.txt | 2 +- lib/Module/InstructionInfoTable.cpp | 230 -- lib/Module/KInstruction.cpp | 90 +- lib/Module/KModule.cpp | 229 +- lib/Module/LocationInfo.cpp | 63 + lib/Module/SarifReport.cpp | 18 +- lib/Module/Target.cpp | 24 +- .../2023-10-04-email_spec0_product16.cil.c | 2794 +++++++++++++++++ tools/klee/main.cpp | 37 +- 33 files changed, 3585 insertions(+), 810 deletions(-) create mode 100644 include/klee/ADT/ImmutableList.h delete mode 100644 include/klee/Module/InstructionInfoTable.h create mode 100644 include/klee/Module/LocationInfo.h delete mode 100644 lib/Module/InstructionInfoTable.cpp create mode 100644 lib/Module/LocationInfo.cpp create mode 100644 test/regression/2023-10-04-email_spec0_product16.cil.c diff --git a/include/klee/ADT/ImmutableList.h b/include/klee/ADT/ImmutableList.h new file mode 100644 index 0000000000..20cb225fd8 --- /dev/null +++ b/include/klee/ADT/ImmutableList.h @@ -0,0 +1,106 @@ +//===---- ImmutableList.h ---------------------------------------*- C++ -*-===// +// +// The KLEE Symbolic Virtual Machine +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef KLEE_IMMUTABLELIST_H +#define KLEE_IMMUTABLELIST_H + +#include +#include + +namespace klee { + +template class ImmutableList { + struct ImmutableListNode { + std::shared_ptr prev; + const size_t prev_len; + std::vector values; + + [[nodiscard]] size_t size() const { return prev_len + values.size(); } + + ImmutableListNode() : prev(nullptr), prev_len(0), values() {} + + explicit ImmutableListNode(const ImmutableList &il) + : prev_len(il.size()), values() { + std::shared_ptr pr = il.node; + while (pr && pr->values.empty()) { + pr = pr->prev; + } + if (pr && pr->size()) { + prev = pr; + } else { + prev = nullptr; + } + } + }; + + std::shared_ptr node; + +public: + [[nodiscard]] size_t size() const { return node ? node->size() : 0; } + + struct iterator { + const ImmutableListNode *rootNode; + std::unique_ptr it; + size_t get; + + public: + explicit iterator(const ImmutableListNode *p) + : rootNode(p), it(nullptr), get(0) { + if (rootNode && rootNode->prev.get()) { + it = std::make_unique(rootNode->prev.get()); + } + } + + bool operator==(const iterator &b) const { + return rootNode == b.rootNode && get == b.get; + } + + bool operator!=(const iterator &b) const { return !(*this == b); } + + iterator &operator++() { + ++get; + if (get < rootNode->prev_len) { + it->operator++(); + } + return *this; + } + + const T &operator*() const { + if (get < rootNode->prev_len) { + return **it; + } + return rootNode->values[get - rootNode->prev_len]; + } + + const T &operator->() const { return **this; } + }; + + [[nodiscard]] iterator begin() const { return iterator(node.get()); } + + [[nodiscard]] iterator end() const { + auto it = iterator(node.get()); + it.get = size(); + return it; + } + + void push_back(T &&value) { + if (!node) { + node = std::make_shared(); + } + node->values.push_back(std::move(value)); + } + + ImmutableList() : node(){}; + ImmutableList(const ImmutableList &il) + : node(std::make_shared(il)) {} +}; + +} // namespace klee + +#endif /* KLEE_IMMUTABLELIST_H */ diff --git a/include/klee/Core/Interpreter.h b/include/klee/Core/Interpreter.h index 6c7ff2f878..766380b486 100644 --- a/include/klee/Core/Interpreter.h +++ b/include/klee/Core/Interpreter.h @@ -41,7 +41,6 @@ class ExecutionState; struct SarifReport; class Interpreter; class TreeStreamWriter; -class InstructionInfoTable; class InterpreterHandler { public: @@ -61,6 +60,12 @@ class InterpreterHandler { const char *suffix, bool isError = false) = 0; }; +/// [File][Line][Column] -> Opcode +using FLCtoOpcode = std::unordered_map< + std::string, + std::unordered_map< + unsigned, std::unordered_map>>>; + class Interpreter { public: enum class GuidanceKind { @@ -140,9 +145,9 @@ class Interpreter { setModule(std::vector> &userModules, std::vector> &libsModules, const ModuleOptions &opts, - const std::unordered_set &mainModuleFunctions, - const std::unordered_set &mainModuleGlobals, - std::unique_ptr origInfos) = 0; + std::set &&mainModuleFunctions, + std::set &&mainModuleGlobals, + FLCtoOpcode &&origInstructions) = 0; // supply a tree stream writer which the interpreter will use // to record the concrete path (as a stream of '0' and '1' bytes). @@ -194,7 +199,7 @@ class Interpreter { virtual void getCoveredLines(const ExecutionState &state, - std::map> &res) = 0; + std::map> &res) = 0; virtual void getBlockPath(const ExecutionState &state, std::string &blockPath) = 0; diff --git a/include/klee/Module/InstructionInfoTable.h b/include/klee/Module/InstructionInfoTable.h deleted file mode 100644 index 8b91c0d8c8..0000000000 --- a/include/klee/Module/InstructionInfoTable.h +++ /dev/null @@ -1,113 +0,0 @@ -//===-- InstructionInfoTable.h ----------------------------------*- C++ -*-===// -// -// The KLEE Symbolic Virtual Machine -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef KLEE_INSTRUCTIONINFOTABLE_H -#define KLEE_INSTRUCTIONINFOTABLE_H - -#include "klee/Support/CompilerWarning.h" -DISABLE_WARNING_PUSH -DISABLE_WARNING_DEPRECATED_DECLARATIONS -#include "llvm/ADT/Optional.h" -#include "llvm/Support/raw_ostream.h" -DISABLE_WARNING_POP - -#include -#include -#include -#include -#include - -namespace llvm { -class Function; -class Instruction; -class Module; -} // namespace llvm - -namespace klee { - -/// @brief InstructionInfo stores debug information for a KInstruction. -struct InstructionInfo { - /// @brief The instruction id. - unsigned id; - /// @brief Line number in source file. - unsigned line; - /// @brief Column number in source file. - unsigned column; - /// @brief Line number in generated assembly.ll. - llvm::Optional assemblyLine; - /// @brief Source file name. - const std::string &file; - -public: - InstructionInfo(unsigned id, const std::string &file, unsigned line, - unsigned column, llvm::Optional assemblyLine) - : id{id}, line{line}, column{column}, - assemblyLine{assemblyLine}, file{file} {} -}; - -/// @brief FunctionInfo stores debug information for a KFunction. -struct FunctionInfo { - /// @brief The function id. - unsigned id; - /// @brief Line number in source file. - unsigned line; - /// @brief Line number in generated assembly.ll. - llvm::Optional assemblyLine; - /// @brief Source file name. - const std::string &file; - -public: - FunctionInfo(unsigned id, const std::string &file, unsigned line, - llvm::Optional assemblyLine) - : id{id}, line{line}, assemblyLine{assemblyLine}, file{file} {} - - FunctionInfo(const FunctionInfo &) = delete; - FunctionInfo &operator=(FunctionInfo const &) = delete; - - FunctionInfo(FunctionInfo &&) = default; -}; - -class InstructionInfoTable { -public: - using Instructions = std::unordered_map< - std::string, - std::unordered_map< - unsigned int, - std::unordered_map>>>; - using LocationToFunctionsMap = - std::unordered_map>; - -private: - std::unordered_map> - infos; - std::unordered_map> - functionInfos; - LocationToFunctionsMap fileNameToFunctions; - std::vector> internedStrings; - std::unordered_set filesNames; - Instructions insts; - -public: - explicit InstructionInfoTable( - const llvm::Module &m, std::unique_ptr assemblyFS, - bool withInstructions = false); - - unsigned getMaxID() const; - const InstructionInfo &getInfo(const llvm::Instruction &) const; - const FunctionInfo &getFunctionInfo(const llvm::Function &) const; - const LocationToFunctionsMap &getFileNameToFunctions() const; - const std::unordered_set &getFilesNames() const; - Instructions getInstructions(); -}; - -} // namespace klee - -#endif /* KLEE_INSTRUCTIONINFOTABLE_H */ diff --git a/include/klee/Module/KInstruction.h b/include/klee/Module/KInstruction.h index 865a752bfd..5c64de152c 100644 --- a/include/klee/Module/KInstruction.h +++ b/include/klee/Module/KInstruction.h @@ -10,16 +10,17 @@ #ifndef KLEE_KINSTRUCTION_H #define KLEE_KINSTRUCTION_H +#include "KModule.h" #include "klee/Config/Version.h" -#include "klee/Module/InstructionInfoTable.h" - #include "klee/Support/CompilerWarning.h" + DISABLE_WARNING_PUSH DISABLE_WARNING_DEPRECATED_DECLARATIONS #include "llvm/Support/DataTypes.h" #include "llvm/Support/raw_ostream.h" DISABLE_WARNING_POP +#include #include namespace llvm { @@ -28,7 +29,6 @@ class Instruction; namespace klee { class Executor; -struct InstructionInfo; class KModule; struct KBlock; @@ -36,26 +36,50 @@ struct KBlock; /// during execution. struct KInstruction { llvm::Instruction *inst; - const InstructionInfo *info; /// Value numbers for each operand. -1 is an invalid value, /// otherwise negative numbers are indices (negated and offset by /// 2) into the module constant table and positive numbers are /// register indices. int *operands; - /// Destination register index. - unsigned dest; KBlock *parent; +private: // Instruction index in the basic block - unsigned index; + const unsigned globalIndex; public: - KInstruction() = default; - explicit KInstruction(const KInstruction &ki); + /// Unique index for KFunction and KInstruction inside KModule + /// from 0 to [KFunction + KInstruction] + [[nodiscard]] unsigned getGlobalIndex() const; + /// Instruction index in the basic block + [[nodiscard]] unsigned getIndex() const; + /// Destination register index. + [[nodiscard]] unsigned getDest() const; + + KInstruction(const std::unordered_map + &_instructionToRegisterMap, + llvm::Instruction *_inst, KModule *_km, KBlock *_kb, + unsigned &_globalIndexInc); + + KInstruction() = delete; + explicit KInstruction(const KInstruction &ki) = delete; virtual ~KInstruction(); - std::string getSourceLocation() const; - std::string toString() const; + + [[nodiscard]] size_t getLine() const; + [[nodiscard]] size_t getColumn() const; + [[nodiscard]] std::string getSourceFilepath() const; + + [[nodiscard]] std::string getSourceLocationString() const; + [[nodiscard]] std::string toString() const; + + [[nodiscard]] inline KBlock *getKBlock() const { return parent; } + [[nodiscard]] inline KFunction *getKFunction() const { + return getKBlock()->parent; + } + [[nodiscard]] inline KModule *getKModule() const { + return getKFunction()->parent; + } }; struct KGEPInstruction : KInstruction { @@ -70,8 +94,14 @@ struct KGEPInstruction : KInstruction { uint64_t offset; public: - KGEPInstruction() = default; - explicit KGEPInstruction(const KGEPInstruction &ki); + KGEPInstruction(const std::unordered_map + &_instructionToRegisterMap, + llvm::Instruction *_inst, KModule *_km, KBlock *_kb, + unsigned &_globalIndexInc) + : KInstruction(_instructionToRegisterMap, _inst, _km, _kb, + _globalIndexInc) {} + KGEPInstruction() = delete; + explicit KGEPInstruction(const KGEPInstruction &ki) = delete; }; } // namespace klee diff --git a/include/klee/Module/KModule.h b/include/klee/Module/KModule.h index e601d91e43..4965f78b27 100644 --- a/include/klee/Module/KModule.h +++ b/include/klee/Module/KModule.h @@ -12,7 +12,6 @@ #include "klee/Config/Version.h" #include "klee/Core/Interpreter.h" -#include "klee/Module/InstructionInfoTable.h" #include "klee/Module/KCallable.h" #include "klee/Support/CompilerWarning.h" @@ -65,16 +64,11 @@ struct KBlock { unsigned numInstructions; KInstruction **instructions; - /// Whether instructions in this function should count as - /// "coverable" for statistics and search heuristics. - bool trackCoverage; - - unsigned id; - public: KBlock(KFunction *, llvm::BasicBlock *, KModule *, - std::unordered_map &, - std::unordered_map &, KInstruction **); + const std::unordered_map &, + KInstruction **, unsigned &globalIndexInc); + KBlock() = delete; KBlock(const KBlock &) = delete; KBlock &operator=(const KBlock &) = delete; virtual ~KBlock() = default; @@ -82,16 +76,15 @@ struct KBlock { virtual KBlockType getKBlockType() const { return KBlockType::Base; } static bool classof(const KBlock *) { return true; } - void handleKInstruction(std::unordered_map - &instructionToRegisterMap, - llvm::Instruction *inst, KModule *km, - KInstruction *ki); KInstruction *getFirstInstruction() const noexcept { return instructions[0]; } KInstruction *getLastInstruction() const noexcept { return instructions[numInstructions - 1]; } std::string getLabel() const; std::string toString() const; + + /// Block number in function + [[nodiscard]] uintptr_t getId() const; }; typedef std::function KBlockPredicate; @@ -101,10 +94,11 @@ struct KCallBlock : KBlock { std::set calledFunctions; public: + KCallBlock() = delete; KCallBlock(KFunction *, llvm::BasicBlock *, KModule *, - std::unordered_map &, - std::unordered_map &, - std::set, KInstruction **); + const std::unordered_map &, + std::set, KInstruction **, + unsigned &globalIndexInc); static bool classof(const KCallBlock *) { return true; } static bool classof(const KBlock *E) { return E->getKBlockType() == KBlockType::Call; @@ -118,9 +112,10 @@ struct KCallBlock : KBlock { struct KReturnBlock : KBlock { public: + KReturnBlock() = delete; KReturnBlock(KFunction *, llvm::BasicBlock *, KModule *, - std::unordered_map &, - std::unordered_map &, KInstruction **); + const std::unordered_map &, + KInstruction **, unsigned &globalIndexInc); static bool classof(const KReturnBlock *) { return true; } static bool classof(const KBlock *E) { return E->getKBlockType() == KBlockType::Return; @@ -131,20 +126,14 @@ struct KReturnBlock : KBlock { struct KFunction : public KCallable { private: std::unordered_map labelMap; + const unsigned globalIndex; public: KModule *parent; llvm::Function *function; - - unsigned numArgs, numRegisters; - unsigned id; - - std::unordered_map registerToInstructionMap; - unsigned numInstructions; - unsigned numBlocks; KInstruction **instructions; - bool kleeHandled = false; + [[nodiscard]] KInstruction *getInstructionByRegister(size_t reg) const; std::unordered_map instructionMap; std::vector> blocks; @@ -153,11 +142,16 @@ struct KFunction : public KCallable { std::vector returnKBlocks; std::vector kCallBlocks; - /// Whether instructions in this function should count as - /// "coverable" for statistics and search heuristics. - bool trackCoverage; + /// count of instructions in function + unsigned numInstructions; + [[nodiscard]] size_t getNumArgs() const; + [[nodiscard]] size_t getNumRegisters() const; + unsigned id; + + bool kleeHandled = false; - explicit KFunction(llvm::Function *, KModule *); + explicit KFunction(llvm::Function *, KModule *, unsigned &); + KFunction() = delete; KFunction(const KFunction &) = delete; KFunction &operator=(const KFunction &) = delete; @@ -187,12 +181,20 @@ struct KFunction : public KCallable { static bool classof(const KCallable *callable) { return callable->getKind() == CK_Function; } + + [[nodiscard]] size_t getLine() const; + [[nodiscard]] std::string getSourceFilepath() const; + + /// Unique index for KFunction and KInstruction inside KModule + /// from 0 to [KFunction + KInstruction] + [[nodiscard]] inline unsigned getGlobalIndex() const { return globalIndex; } }; struct KBlockCompare { bool operator()(const KBlock *a, const KBlock *b) const { - return a->parent->id < b->parent->id || - (a->parent->id == b->parent->id && a->id < b->id); + return a->parent->getGlobalIndex() < b->parent->getGlobalIndex() || + (a->parent->getGlobalIndex() == b->parent->getGlobalIndex() && + a->getId() < b->getId()); } }; @@ -213,7 +215,8 @@ class KConstant { class KModule { private: - bool withPosixRuntime; + bool withPosixRuntime; // TODO move to opts + unsigned maxGlobalIndex; public: std::unique_ptr module; @@ -224,19 +227,16 @@ class KModule { std::unordered_map functionMap; std::unordered_map> callMap; std::unordered_map functionNameMap; - std::unordered_map functionIDMap; + [[nodiscard]] unsigned getFunctionId(const llvm::Function *) const; // Functions which escape (may be called indirectly) // XXX change to KFunction std::set escapingFunctions; - std::unordered_set mainModuleFunctions; + std::set mainModuleFunctions; + std::set mainModuleGlobals; - std::unordered_set mainModuleGlobals; - - InstructionInfoTable::Instructions origInfos; - - std::unique_ptr infos; + FLCtoOpcode origInstructions; std::vector constants; std::unordered_map> @@ -248,6 +248,9 @@ class KModule { // Functions which are part of KLEE runtime std::set internalFunctions; + // instruction to assembly.ll line empty if no statistic enabled + std::unordered_map asmLineMap; + // Mark function with functionName as part of the KLEE runtime void addInternalFunction(const char *functionName); // Replace std functions with KLEE intrinsics @@ -301,6 +304,14 @@ class KModule { bool inMainModule(const llvm::GlobalVariable &v); bool WithPOSIXRuntime() { return withPosixRuntime; } + + std::optional getAsmLine(const uintptr_t ref) const; + std::optional getAsmLine(const llvm::Function *func) const; + std::optional getAsmLine(const llvm::Instruction *inst) const; + + inline unsigned getMaxGlobalIndex() const { return maxGlobalIndex; } + unsigned getGlobalIndex(const llvm::Function *func) const; + unsigned getGlobalIndex(const llvm::Instruction *inst) const; }; } // namespace klee diff --git a/include/klee/Module/LocationInfo.h b/include/klee/Module/LocationInfo.h new file mode 100644 index 0000000000..36ac6bec4d --- /dev/null +++ b/include/klee/Module/LocationInfo.h @@ -0,0 +1,35 @@ +////===-- LocationInfo.h ----------------------------------*- C++ -*-===// +//// +//// The KLEE Symbolic Virtual Machine +//// +//// This file is distributed under the University of Illinois Open Source +//// License. See LICENSE.TXT for details. +//// +////===----------------------------------------------------------------------===// + +#ifndef KLEE_LOCATIONINFO_H +#define KLEE_LOCATIONINFO_H + +#include +#include + +namespace llvm { +class Function; +class Instruction; +class Module; +} // namespace llvm + +namespace klee { + +struct LocationInfo { + std::string file; + size_t line; + size_t column; +}; + +LocationInfo getLocationInfo(const llvm::Function *func); +LocationInfo getLocationInfo(const llvm::Instruction *inst); + +} // namespace klee + +#endif /* KLEE_LOCATIONINFO_H */ diff --git a/include/klee/Support/ErrorHandling.h b/include/klee/Support/ErrorHandling.h index 4cc57c9744..098293d2e5 100644 --- a/include/klee/Support/ErrorHandling.h +++ b/include/klee/Support/ErrorHandling.h @@ -16,7 +16,7 @@ #endif #endif -#include +#include namespace klee { diff --git a/lib/Basic/Statistics.cpp b/lib/Basic/Statistics.cpp index 170ea839e0..50d9e8bf1f 100644 --- a/lib/Basic/Statistics.cpp +++ b/lib/Basic/Statistics.cpp @@ -50,7 +50,7 @@ Statistic *StatisticManager::getStatisticByName(const std::string &name) const { return 0; } -StatisticManager *klee::theStatisticManager = 0; +StatisticManager *klee::theStatisticManager = nullptr; static StatisticManager &getStatisticManager() { static StatisticManager sm; diff --git a/lib/Core/DistanceCalculator.cpp b/lib/Core/DistanceCalculator.cpp index ebfdb7eec6..24d1d47898 100644 --- a/lib/Core/DistanceCalculator.cpp +++ b/lib/Core/DistanceCalculator.cpp @@ -95,8 +95,6 @@ DistanceResult DistanceCalculator::computeDistance(KBlock *kb, TargetKind kind, DistanceResult DistanceCalculator::getDistance( const KInstruction *prevPC, const KInstruction *pc, const ExecutionStack::call_stack_ty &frames, KBlock *target) { - weight_type weight = 0; - KBlock *kb = pc->parent; const auto &distanceToTargetFunction = codeGraphInfo.getBackwardDistance(target->parent); @@ -196,7 +194,6 @@ WeightResult DistanceCalculator::tryGetLocalWeight(KBlock *kb, weight_type &weight, const std::vector &localTargets, KBlock *target) const { - KFunction *currentKF = kb->parent; KBlock *currentKB = kb; const std::unordered_map &dist = codeGraphInfo.getDistance(currentKB); diff --git a/lib/Core/ExecutionState.cpp b/lib/Core/ExecutionState.cpp index 5ee6b7c8da..05142dd2c4 100644 --- a/lib/Core/ExecutionState.cpp +++ b/lib/Core/ExecutionState.cpp @@ -14,7 +14,6 @@ #include "klee/Expr/ArrayExprVisitor.h" #include "klee/Expr/Expr.h" #include "klee/Module/Cell.h" -#include "klee/Module/InstructionInfoTable.h" #include "klee/Module/KInstruction.h" #include "klee/Module/KModule.h" #include "klee/Support/Casting.h" @@ -101,14 +100,14 @@ bool CallStackFrame::equals(const CallStackFrame &other) const { return kf == other.kf && caller == other.caller; } -StackFrame::StackFrame(KFunction *kf) : kf(kf), varargs(0) { - locals = new Cell[kf->numRegisters]; +StackFrame::StackFrame(KFunction *kf) : kf(kf), varargs(nullptr) { + locals = new Cell[kf->getNumRegisters()]; } StackFrame::StackFrame(const StackFrame &s) : kf(s.kf), allocas(s.allocas), varargs(s.varargs) { - locals = new Cell[kf->numRegisters]; - for (unsigned i = 0; i < kf->numRegisters; i++) + locals = new Cell[kf->getNumRegisters()]; + for (unsigned i = 0; i < kf->getNumRegisters(); i++) locals[i] = s.locals[i]; } @@ -119,7 +118,7 @@ InfoStackFrame::InfoStackFrame(KFunction *kf) : kf(kf) {} /***/ ExecutionState::ExecutionState() : initPC(nullptr), pc(nullptr), prevPC(nullptr), incomingBBIndex(-1), - depth(0), ptreeNode(nullptr), steppedInstructions(0), + depth(0), ptreeNode(nullptr), symbolics(), steppedInstructions(0), steppedMemoryInstructions(0), instsSinceCovNew(0), roundingMode(llvm::APFloat::rmNearestTiesToEven), coveredNew(new box(false)), forkDisabled(false), @@ -130,7 +129,7 @@ ExecutionState::ExecutionState() ExecutionState::ExecutionState(KFunction *kf) : initPC(kf->instructions), pc(initPC), prevPC(pc), incomingBBIndex(-1), - depth(0), ptreeNode(nullptr), steppedInstructions(0), + depth(0), ptreeNode(nullptr), symbolics(), steppedInstructions(0), steppedMemoryInstructions(0), instsSinceCovNew(0), roundingMode(llvm::APFloat::rmNearestTiesToEven), coveredNew(new box(false)), forkDisabled(false), @@ -142,7 +141,7 @@ ExecutionState::ExecutionState(KFunction *kf) ExecutionState::ExecutionState(KFunction *kf, KBlock *kb) : initPC(kb->instructions), pc(initPC), prevPC(pc), incomingBBIndex(-1), - depth(0), ptreeNode(nullptr), steppedInstructions(0), + depth(0), ptreeNode(nullptr), symbolics(), steppedInstructions(0), steppedMemoryInstructions(0), instsSinceCovNew(0), roundingMode(llvm::APFloat::rmNearestTiesToEven), coveredNew(new box(false)), forkDisabled(false), @@ -193,8 +192,8 @@ ExecutionState *ExecutionState::branch() { } bool ExecutionState::inSymbolics(const MemoryObject *mo) const { - for (auto i : symbolics) { - if (mo->id == i.memoryObject->id) { + for (const auto &symbolic : symbolics) { + if (mo->id == symbolic.memoryObject->id) { return true; } } @@ -254,13 +253,12 @@ void ExecutionState::popFrame() { void ExecutionState::addSymbolic(const MemoryObject *mo, const Array *array, KType *type) { - symbolics.emplace_back(ref(mo), array, type); + symbolics.push_back({mo, array, type}); } ref ExecutionState::findMemoryObject(const Array *array) const { - for (unsigned i = 0; i != symbolics.size(); ++i) { - const auto &symbolic = symbolics[i]; + for (const auto &symbolic : symbolics) { if (array == symbolic.array) { return symbolic.memoryObject; } @@ -387,13 +385,12 @@ void ExecutionState::dumpStack(llvm::raw_ostream &out) const { const StackFrame &sf = stack.valueStack().at(ri); Function *f = csf.kf->function; - const InstructionInfo &ii = *target->info; out << "\t#" << i; - if (ii.assemblyLine.hasValue()) { - std::stringstream AssStream; - AssStream << std::setw(8) << std::setfill('0') - << ii.assemblyLine.getValue(); - out << AssStream.str(); + auto assemblyLine = target->getKModule()->getAsmLine(target->inst); + if (assemblyLine.has_value()) { + std::stringstream AsmStream; + AsmStream << std::setw(8) << std::setfill('0') << assemblyLine.value(); + out << AsmStream.str(); } out << " in " << f->getName().str() << "("; // Yawn, we could go up and print varargs if we wanted to. @@ -414,8 +411,9 @@ void ExecutionState::dumpStack(llvm::raw_ostream &out) const { } } out << ")"; - if (ii.file != "") - out << " at " << ii.file << ":" << ii.line; + std::string filepath = target->getSourceFilepath(); + if (!filepath.empty()) + out << " at " << filepath << ":" << target->getLine(); out << "\n"; target = csf.caller; } diff --git a/lib/Core/ExecutionState.h b/lib/Core/ExecutionState.h index 424dfc4248..a0aa46619a 100644 --- a/lib/Core/ExecutionState.h +++ b/lib/Core/ExecutionState.h @@ -12,6 +12,7 @@ #include "AddressSpace.h" +#include "klee/ADT/ImmutableList.h" #include "klee/ADT/ImmutableSet.h" #include "klee/ADT/PersistentMap.h" #include "klee/ADT/PersistentSet.h" @@ -53,9 +54,7 @@ struct KBlock; struct KInstruction; class MemoryObject; class PTreeNode; -struct InstructionInfo; class Target; -struct TranstionHash; llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const MemoryMap &mm); @@ -216,7 +215,8 @@ struct Symbolic { const Array *array; KType *type; Symbolic(ref mo, const Array *a, KType *t) - : memoryObject(mo), array(a), type(t) {} + : memoryObject(std::move(mo)), array(a), type(t) {} + Symbolic(const Symbolic &other) = default; Symbolic &operator=(const Symbolic &other) = default; friend bool operator==(const Symbolic &lhs, const Symbolic &rhs) { @@ -317,16 +317,14 @@ class ExecutionState { TreeOStream symPathOS; /// @brief Set containing which lines in which files are covered by this state - std::map> coveredLines; + std::map> coveredLines; /// @brief Pointer to the process tree of the current state /// Copies of ExecutionState should not copy ptreeNode PTreeNode *ptreeNode = nullptr; /// @brief Ordered list of symbolics: used to generate test cases. - // - // FIXME: Move to a shared list structure (not critical). - std::vector symbolics; + ImmutableList symbolics; /// @brief map from memory accesses to accessed objects and access offsets. ExprHashMap> resolvedPointers; diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index 1d0c887e06..c58e1a51ac 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -51,7 +51,6 @@ #include "klee/Expr/Symcrete.h" #include "klee/Module/Cell.h" #include "klee/Module/CodeGraphInfo.h" -#include "klee/Module/InstructionInfoTable.h" #include "klee/Module/KCallable.h" #include "klee/Module/KInstruction.h" #include "klee/Module/KModule.h" @@ -536,13 +535,11 @@ Executor::Executor(LLVMContext &ctx, const InterpreterOptions &opts, } } -llvm::Module * -Executor::setModule(std::vector> &userModules, - std::vector> &libsModules, - const ModuleOptions &opts, - const std::unordered_set &mainModuleFunctions, - const std::unordered_set &mainModuleGlobals, - std::unique_ptr origInfos) { +llvm::Module *Executor::setModule( + std::vector> &userModules, + std::vector> &libsModules, + const ModuleOptions &opts, std::set &&mainModuleFunctions, + std::set &&mainModuleGlobals, FLCtoOpcode &&origInstructions) { assert(!kmodule && !userModules.empty() && "can only register one module"); // XXX gross @@ -596,16 +593,12 @@ Executor::setModule(std::vector> &userModules, kmodule->checkModule(); // 4.) Manifest the module - kmodule->mainModuleFunctions.insert(mainModuleFunctions.begin(), - mainModuleFunctions.end()); - kmodule->mainModuleGlobals.insert(mainModuleGlobals.begin(), - mainModuleGlobals.end()); + std::swap(kmodule->mainModuleFunctions, mainModuleFunctions); + std::swap(kmodule->mainModuleGlobals, mainModuleGlobals); kmodule->manifest(interpreterHandler, interpreterOpts.Guidance, StatsTracker::useStatistics()); - if (origInfos) { - kmodule->origInfos = origInfos->getInstructions(); - } + kmodule->origInstructions = origInstructions; specialFunctionHandler->bind(); @@ -750,6 +743,7 @@ void Executor::allocateGlobalObjects(ExecutionState &state) { true, nullptr, 8); errnoObj->isFixed = true; + // TODO: unused variable ObjectState *os = bindObjectInState( state, errnoObj, typeSystemManager->getWrappedType(pointerErrnoAddr), false); @@ -1108,7 +1102,7 @@ ref Executor::maxStaticPctChecks(ExecutionState ¤t, std::string msg("skipping fork and concretizing condition (MaxStatic*Pct " "limit reached) at "); llvm::raw_string_ostream os(msg); - os << current.prevPC->getSourceLocation(); + os << current.prevPC->getSourceLocationString(); klee_warning_once(0, "%s", os.str().c_str()); addConstraint(current, EqExpr::create(value, condition)); @@ -1526,8 +1520,8 @@ ref Executor::toConstant(ExecutionState &state, ref e, std::string str; llvm::raw_string_ostream os(str); os << "silently concretizing (reason: " << reason << ") expression " << e - << " to value " << value << " (" << (*(state.pc)).info->file << ":" - << (*(state.pc)).info->line << ")"; + << " to value " << value << " (" << state.pc->getSourceFilepath() << ":" + << state.pc->getLine() << ")"; if (AllExternalWarnings) klee_warning("%s", os.str().c_str()); @@ -1606,10 +1600,13 @@ void Executor::printDebugInstructions(ExecutionState &state) { // [src] src location:asm line:state ID if (!DebugPrintInstructions.isSet(STDERR_COMPACT) && !DebugPrintInstructions.isSet(FILE_COMPACT)) { - (*stream) << " " << state.pc->getSourceLocation() << ':'; + (*stream) << " " << state.pc->getSourceLocationString() << ':'; } - if (state.pc->info->assemblyLine.hasValue()) { - (*stream) << state.pc->info->assemblyLine.getValue() << ':'; + { + auto asmLine = state.pc->getKModule()->getAsmLine(state.pc->inst); + if (asmLine.has_value()) { + (*stream) << asmLine.value() << ':'; + } } (*stream) << state.getID() << ":"; (*stream) << "["; @@ -2574,7 +2571,7 @@ void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) { // requires that we still be in the context of the branch // instruction (it reuses its statistic id). Should be cleaned // up with convenient instruction specific data. - if (statsTracker && state.stack.callStack().back().kf->trackCoverage) + if (statsTracker) statsTracker->markBranchVisited(branches.first, branches.second); if (branches.first) @@ -4253,9 +4250,9 @@ void Executor::reportProgressTowardsTargets(std::string prefix, repr << "in function " + target->getBlock()->parent->function->getName().str(); repr << " (lines "; - repr << target->getBlock()->getFirstInstruction()->info->line; + repr << target->getBlock()->getFirstInstruction()->getLine(); repr << " to "; - repr << target->getBlock()->getLastInstruction()->info->line; + repr << target->getBlock()->getLastInstruction()->getLine(); repr << ")"; std::string targetString = repr.str(); klee_message("%s for %s", distance.toString().c_str(), @@ -4620,22 +4617,19 @@ void Executor::terminateStateEarlyUser(ExecutionState &state, terminateStateEarly(state, message, StateTerminationType::SilentExit); } -const InstructionInfo & -Executor::getLastNonKleeInternalInstruction(const ExecutionState &state, - Instruction **lastInstruction) { +const KInstruction * +Executor::getLastNonKleeInternalInstruction(const ExecutionState &state) { // unroll the stack of the applications state and find // the last instruction which is not inside a KLEE internal function - ExecutionStack::call_stack_ty::const_reverse_iterator - it = state.stack.callStack().rbegin(), - itE = state.stack.callStack().rend(); + auto it = state.stack.callStack().rbegin(); + auto itE = state.stack.callStack().rend(); // don't check beyond the outermost function (i.e. main()) itE--; - const InstructionInfo *ii = 0; + const KInstruction *ki = nullptr; if (kmodule->internalFunctions.count(it->kf->function) == 0) { - ii = state.prevPC->info; - *lastInstruction = state.prevPC->inst; + ki = state.prevPC; // Cannot return yet because even though // it->function is not an internal function it might of // been called from an internal function. @@ -4649,21 +4643,19 @@ Executor::getLastNonKleeInternalInstruction(const ExecutionState &state, // function const Function *f = (*it->caller).inst->getParent()->getParent(); if (kmodule->internalFunctions.count(f)) { - ii = 0; + ki = nullptr; continue; } - if (!ii) { - ii = (*it->caller).info; - *lastInstruction = (*it->caller).inst; + if (!ki) { + ki = it->caller; } } - if (!ii) { + if (!ki) { // something went wrong, play safe and return the current instruction info - *lastInstruction = state.prevPC->inst; - return *state.prevPC->info; + return state.prevPC; } - return *ii; + return ki; } bool shouldExitOn(StateTerminationType reason) { @@ -4722,14 +4714,14 @@ void Executor::terminateStateOnError(ExecutionState &state, const char *suffix) { std::string message = messaget.str(); static std::set> emittedErrors; - Instruction *lastInst; - const InstructionInfo &ii = - getLastNonKleeInternalInstruction(state, &lastInst); + const KInstruction *ki = getLastNonKleeInternalInstruction(state); + Instruction *lastInst = ki->inst; if (EmitAllErrors || emittedErrors.insert(std::make_pair(lastInst, message)).second) { - if (!ii.file.empty()) { - klee_message("ERROR: %s:%d: %s", ii.file.c_str(), ii.line, + std::string filepath = ki->getSourceFilepath(); + if (!filepath.empty()) { + klee_message("ERROR: %s:%zu: %s", filepath.c_str(), ki->getLine(), message.c_str()); } else { klee_message("ERROR: (location information missing) %s", message.c_str()); @@ -4740,10 +4732,13 @@ void Executor::terminateStateOnError(ExecutionState &state, std::string MsgString; llvm::raw_string_ostream msg(MsgString); msg << "Error: " << message << '\n'; - if (!ii.file.empty()) { - msg << "File: " << ii.file << '\n' << "Line: " << ii.line << '\n'; - if (ii.assemblyLine.hasValue()) { - msg << "assembly.ll line: " << ii.assemblyLine.getValue() << '\n'; + if (!filepath.empty()) { + msg << "File: " << filepath << '\n' << "Line: " << ki->getLine() << '\n'; + { + auto asmLine = ki->getKModule()->getAsmLine(ki->inst); + if (asmLine.has_value()) { + msg << "assembly.ll line: " << asmLine.value() << '\n'; + } } msg << "State: " << state.getID() << '\n'; } @@ -4832,7 +4827,7 @@ void Executor::callExternalFunction(ExecutionState &state, KInstruction *target, if (i != arguments.size() - 1) os << ", "; } - os << ") at " << state.pc->getSourceLocation(); + os << ") at " << state.pc->getSourceLocationString(); if (AllExternalWarnings) klee_warning("%s", os.str().c_str()); @@ -4950,7 +4945,7 @@ void Executor::callExternalFunction(ExecutionState &state, KInstruction *target, if (i != arguments.size() - 1) os << ", "; } - os << ") at " << state.pc->getSourceLocation(); + os << ") at " << state.pc->getSourceLocationString(); if (AllExternalWarnings) klee_warning("%s", os.str().c_str()); @@ -5875,7 +5870,7 @@ void Executor::collectReads( const std::vector &resolvedMemoryObjects, const std::vector &resolveConcretizations, std::vector> &results) { - ref base = address; + ref base = address; // TODO: unused unsigned size = bytes; if (state.isGEPExpr(address)) { base = state.gepExprBases[address].first; @@ -6852,7 +6847,7 @@ void Executor::prepareSymbolicValue(ExecutionState &state, void Executor::prepareSymbolicRegister(ExecutionState &state, StackFrame &sf, unsigned regNum) { - KInstruction *allocInst = sf.kf->registerToInstructionMap[regNum]; + KInstruction *allocInst = sf.kf->getInstructionByRegister(regNum); prepareSymbolicValue(state, sf, allocInst); } @@ -6935,7 +6930,7 @@ void Executor::logState(const ExecutionState &state, int id, *f << state.symbolics.size() << " symbolics total. " << "Symbolics:\n"; size_t sc = 0; - for (auto &symbolic : state.symbolics) { + for (const auto &symbolic : state.symbolics) { *f << "Symbolic number " << sc++ << "\n"; *f << "Associated memory object: " << symbolic.memoryObject.get()->id << "\n"; @@ -7048,15 +7043,17 @@ void Executor::setInitializationGraph( // The objects have to be symbolic bool pointerFound = false, pointeeFound = false; size_t pointerIndex = 0, pointeeIndex = 0; - for (size_t i = 0; i < symbolics.size(); i++) { - if (symbolics[i].memoryObject == pointerResolution.first) { + size_t i = 0; + for (auto &symbolic : symbolics) { + if (symbolic.memoryObject == pointerResolution.first) { pointerIndex = i; pointerFound = true; } - if (symbolics[i].memoryObject->id == pointer.second.first) { + if (symbolic.memoryObject->id == pointer.second.first) { pointeeIndex = i; pointeeFound = true; } + ++i; } if (pointerFound && pointeeFound) { ref offset = model.evaluate(pointerResolution.second); @@ -7157,8 +7154,9 @@ bool Executor::getSymbolicSolution(const ExecutionState &state, KTest &res) { std::vector> values; std::vector objects; - for (unsigned i = 0; i != symbolics.size(); ++i) - objects.push_back(symbolics[i].array); + for (auto &symbolic : symbolics) { + objects.push_back(symbolic.array); + } bool success = solver->getInitialValues(extendedConstraints.cs(), objects, values, state.queryMetaData); solver->setTimeout(time::Span()); @@ -7169,19 +7167,23 @@ bool Executor::getSymbolicSolution(const ExecutionState &state, KTest &res) { return false; } - res.objects = new KTestObject[symbolics.size()]; res.numObjects = symbolics.size(); + res.objects = new KTestObject[res.numObjects]; - for (unsigned i = 0; i != symbolics.size(); ++i) { - auto mo = symbolics[i].memoryObject; - KTestObject *o = &res.objects[i]; - o->name = const_cast(mo->name.c_str()); - o->address = mo->address; - o->numBytes = values[i].size(); - o->bytes = new unsigned char[o->numBytes]; - std::copy(values[i].begin(), values[i].end(), o->bytes); - o->numPointers = 0; - o->pointers = nullptr; + { + size_t i = 0; + for (auto &symbolic : symbolics) { + auto mo = symbolic.memoryObject; + KTestObject *o = &res.objects[i]; + o->name = const_cast(mo->name.c_str()); + o->address = mo->address; + o->numBytes = values[i].size(); + o->bytes = new unsigned char[o->numBytes]; + std::copy(values[i].begin(), values[i].end(), o->bytes); + o->numPointers = 0; + o->pointers = nullptr; + ++i; + } } Assignment model = Assignment(objects, values); @@ -7194,9 +7196,8 @@ bool Executor::getSymbolicSolution(const ExecutionState &state, KTest &res) { return true; } -void Executor::getCoveredLines( - const ExecutionState &state, - std::map> &res) { +void Executor::getCoveredLines(const ExecutionState &state, + std::map> &res) { res = state.coveredLines; } @@ -7355,9 +7356,9 @@ void Executor::dumpStates() { sfIt != sf_ie; ++sfIt) { *os << "('" << sfIt->kf->function->getName().str() << "',"; if (next == es->stack.callStack().end()) { - *os << es->prevPC->info->line << "), "; + *os << es->prevPC->getLine() << "), "; } else { - *os << next->caller->info->line << "), "; + *os << next->caller->getLine() << "), "; ++next; } } @@ -7366,8 +7367,8 @@ void Executor::dumpStates() { InfoStackFrame &sf = es->stack.infoStack().back(); uint64_t md2u = computeMinDistToUncovered(es->pc, sf.minDistToUncoveredOnReturn); - uint64_t icnt = theStatisticManager->getIndexedValue(stats::instructions, - es->pc->info->id); + uint64_t icnt = theStatisticManager->getIndexedValue( + stats::instructions, es->pc->getGlobalIndex()); uint64_t cpicnt = sf.callPathNode->statistics.getValue(stats::instructions); diff --git a/lib/Core/Executor.h b/lib/Core/Executor.h index 26c2e9bba5..a7e0df7160 100644 --- a/lib/Core/Executor.h +++ b/lib/Core/Executor.h @@ -78,7 +78,6 @@ class ExecutionState; class ExternalDispatcher; class Expr; template class ExprHashMap; -class InstructionInfoTable; class KCallable; struct KFunction; struct KInstruction; @@ -482,7 +481,7 @@ class Executor : public Interpreter { ref readDest(ExecutionState &state, StackFrame &frame, const KInstruction *target) { - unsigned index = target->dest; + unsigned index = target->getDest(); ref reg = frame.locals[index].value; if (!reg) { prepareSymbolicRegister(state, frame, index); @@ -496,7 +495,7 @@ class Executor : public Interpreter { } Cell &getDestCell(const StackFrame &frame, const KInstruction *target) { - return frame.locals[target->dest]; + return frame.locals[target->getDest()]; } const Cell &eval(const KInstruction *ki, unsigned index, @@ -567,10 +566,9 @@ class Executor : public Interpreter { const MemoryObject *mo = nullptr) const; // Determines the \param lastInstruction of the \param state which is not KLEE - // internal and returns its InstructionInfo - const InstructionInfo & - getLastNonKleeInternalInstruction(const ExecutionState &state, - llvm::Instruction **lastInstruction); + // internal and returns its KInstruction + const KInstruction * + getLastNonKleeInternalInstruction(const ExecutionState &state); /// Remove state from queue and delete state void terminateState(ExecutionState &state, @@ -729,9 +727,9 @@ class Executor : public Interpreter { setModule(std::vector> &userModules, std::vector> &libsModules, const ModuleOptions &opts, - const std::unordered_set &mainModuleFunctions, - const std::unordered_set &mainModuleGlobals, - std::unique_ptr origInfos) override; + std::set &&mainModuleFunctions, + std::set &&mainModuleGlobals, + FLCtoOpcode &&origInstructions) override; void useSeeds(const std::vector *seeds) override { usingSeeds = seeds; @@ -801,9 +799,8 @@ class Executor : public Interpreter { bool getSymbolicSolution(const ExecutionState &state, KTest &res) override; - void getCoveredLines( - const ExecutionState &state, - std::map> &res) override; + void getCoveredLines(const ExecutionState &state, + std::map> &res) override; void getBlockPath(const ExecutionState &state, std::string &blockPath) override; diff --git a/lib/Core/ExecutorUtil.cpp b/lib/Core/ExecutorUtil.cpp index 467982c81f..9a4c6054a0 100644 --- a/lib/Core/ExecutorUtil.cpp +++ b/lib/Core/ExecutorUtil.cpp @@ -134,7 +134,7 @@ ref Executor::evalConstant(const Constant *c, std::string msg("Cannot handle constant "); llvm::raw_string_ostream os(msg); os << "'" << *c << "' at location " - << (ki ? ki->getSourceLocation() : "[unknown]"); + << (ki ? ki->getSourceLocationString() : "[unknown]"); klee_error("%s", os.str().c_str()); } } @@ -261,7 +261,7 @@ ref Executor::evalConstantExpr(const llvm::ConstantExpr *ce, std::string msg( "Division/modulo by zero during constant folding at location "); llvm::raw_string_ostream os(msg); - os << (ki ? ki->getSourceLocation() : "[unknown]"); + os << (ki ? ki->getSourceLocationString() : "[unknown]"); klee_error("%s", os.str().c_str()); } break; @@ -271,7 +271,7 @@ ref Executor::evalConstantExpr(const llvm::ConstantExpr *ce, if (op2->getLimitedValue() >= op1->getWidth()) { std::string msg("Overshift during constant folding at location "); llvm::raw_string_ostream os(msg); - os << (ki ? ki->getSourceLocation() : "[unknown]"); + os << (ki ? ki->getSourceLocationString() : "[unknown]"); klee_error("%s", os.str().c_str()); } } @@ -282,7 +282,7 @@ ref Executor::evalConstantExpr(const llvm::ConstantExpr *ce, switch (ce->getOpcode()) { default: os << "'" << *ce << "' at location " - << (ki ? ki->getSourceLocation() : "[unknown]"); + << (ki ? ki->getSourceLocationString() : "[unknown]"); klee_error("%s", os.str().c_str()); case Instruction::Trunc: diff --git a/lib/Core/Memory.h b/lib/Core/Memory.h index e43e4d015b..503faca93a 100644 --- a/lib/Core/Memory.h +++ b/lib/Core/Memory.h @@ -125,7 +125,7 @@ class MemoryObject { /// Get an identifying string for this allocation. void getAllocInfo(std::string &result) const; - void setName(std::string name) const { this->name = name; } + void setName(const std::string &_name) const { this->name = _name; } void updateTimestamp() const { this->timestamp = time++; } diff --git a/lib/Core/Searcher.cpp b/lib/Core/Searcher.cpp index 30adeb8ce7..08e725eacb 100644 --- a/lib/Core/Searcher.cpp +++ b/lib/Core/Searcher.cpp @@ -19,7 +19,6 @@ #include "klee/ADT/DiscretePDF.h" #include "klee/ADT/RNG.h" #include "klee/ADT/WeightedQueue.h" -#include "klee/Module/InstructionInfoTable.h" #include "klee/Module/KInstruction.h" #include "klee/Module/KModule.h" #include "klee/Module/Target.h" @@ -389,8 +388,8 @@ double WeightedRandomSearcher::getWeight(ExecutionState *es) { case RP: return std::pow(0.5, es->depth); case InstCount: { - uint64_t count = theStatisticManager->getIndexedValue(stats::instructions, - es->pc->info->id); + uint64_t count = theStatisticManager->getIndexedValue( + stats::instructions, es->pc->getGlobalIndex()); double inv = 1. / std::max((uint64_t)1, count); return inv * inv; } diff --git a/lib/Core/SpecialFunctionHandler.cpp b/lib/Core/SpecialFunctionHandler.cpp index 6138eabe1b..a9d7457a88 100644 --- a/lib/Core/SpecialFunctionHandler.cpp +++ b/lib/Core/SpecialFunctionHandler.cpp @@ -921,7 +921,7 @@ void SpecialFunctionHandler::handleMakeSymbolic( assert(success && "FIXME: Unhandled solver failure"); if (res) { - uint64_t sid = 0; + uint64_t sid = 0; // TODO: unused variable if (state.arrayNames.count(name)) { sid = state.arrayNames[name]; } diff --git a/lib/Core/StatsTracker.cpp b/lib/Core/StatsTracker.cpp index e662644be3..3a1f3a11f2 100644 --- a/lib/Core/StatsTracker.cpp +++ b/lib/Core/StatsTracker.cpp @@ -13,9 +13,9 @@ #include "klee/Config/Version.h" #include "klee/Core/TerminationTypes.h" -#include "klee/Module/InstructionInfoTable.h" #include "klee/Module/KInstruction.h" #include "klee/Module/KModule.h" +#include "klee/Module/LocationInfo.h" #include "klee/Solver/SolverStats.h" #include "klee/Statistics/Statistics.h" #include "klee/Support/ErrorHandling.h" @@ -233,27 +233,25 @@ StatsTracker::StatsTracker(Executor &_executor, std::string _objectFilename, } if (useStatistics() || userSearcherRequiresMD2U()) - theStatisticManager->useIndexedStats(km->infos->getMaxID()); + theStatisticManager->useIndexedStats(km->getMaxGlobalIndex()); for (auto &kfp : km->functions) { KFunction *kf = kfp.get(); - kf->trackCoverage = 1; for (unsigned i = 0; i < kf->numInstructions; ++i) { KInstruction *ki = kf->instructions[i]; if (OutputIStats) { - unsigned id = ki->info->id; + unsigned id = ki->getGlobalIndex(); theStatisticManager->setIndex(id); - if (kf->trackCoverage && instructionIsCoverable(ki->inst)) + if (instructionIsCoverable(ki->inst)) { ++stats::uncoveredInstructions; + } } - if (kf->trackCoverage) { - if (BranchInst *bi = dyn_cast(ki->inst)) - if (!bi->isUnconditional()) - numBranches++; - } + if (BranchInst *bi = dyn_cast(ki->inst)) + if (!bi->isUnconditional()) + numBranches++; } } @@ -393,24 +391,24 @@ void StatsTracker::stepInstruction(ExecutionState &es) { } Instruction *inst = es.pc->inst; - const InstructionInfo &ii = *es.pc->info; + const KInstruction *ki = es.pc; InfoStackFrame &sf = es.stack.infoStack().back(); - theStatisticManager->setIndex(ii.id); + theStatisticManager->setIndex(ki->getGlobalIndex()); if (UseCallPaths) theStatisticManager->setContext(&sf.callPathNode->statistics); if (es.instsSinceCovNew) ++es.instsSinceCovNew; - if (sf.kf->trackCoverage && instructionIsCoverable(inst)) { + if (instructionIsCoverable(inst)) { if (!theStatisticManager->getIndexedValue(stats::coveredInstructions, - ii.id)) { + ki->getGlobalIndex())) { // Checking for actual stoppoints avoids inconsistencies due // to line number propogation. // // FIXME: This trick no longer works, we should fix this in the line // number propogation. - es.coveredLines[&ii.file].insert(ii.line); + es.coveredLines[ki->getSourceFilepath()].insert(ki->getLine()); es.instsSinceCovNew = 1; ++stats::coveredInstructions; stats::uncoveredInstructions += (uint64_t)-1; @@ -695,8 +693,8 @@ void StatsTracker::updateStateStatistics(uint64_t addend) { ie = executor.states.end(); it != ie; ++it) { ExecutionState &state = **it; - const InstructionInfo &ii = *state.pc->info; - theStatisticManager->incrementIndexedValue(stats::states, ii.id, addend); + theStatisticManager->incrementIndexedValue( + stats::states, state.pc->getGlobalIndex(), addend); if (UseCallPaths) state.stack.infoStack().back().callPathNode->statistics.incrementValue( stats::states, addend); @@ -765,66 +763,70 @@ void StatsTracker::writeIStats() { of << "ob=" << llvm::sys::path::filename(objectFilename).str() << "\n"; - for (Module::iterator fnIt = m->begin(), fn_ie = m->end(); fnIt != fn_ie; - ++fnIt) { - if (!fnIt->isDeclaration()) { + for (auto &fn : *m) { + if (!fn.isDeclaration()) { // Always try to write the filename before the function name, as otherwise // KCachegrind can create two entries for the function, one with an // unnamed file and one without. - Function *fn = &*fnIt; - const FunctionInfo &ii = executor.kmodule->infos->getFunctionInfo(*fn); - if (ii.file != sourceFile) { - of << "fl=" << ii.file << "\n"; - sourceFile = ii.file; + auto fnlFile = getLocationInfo(&fn).file; + if (fnlFile != sourceFile) { + of << "fl=" << fnlFile << "\n"; + sourceFile = fnlFile; } - of << "fn=" << fnIt->getName().str() << "\n"; - for (Function::iterator bbIt = fnIt->begin(), bb_ie = fnIt->end(); - bbIt != bb_ie; ++bbIt) { - for (BasicBlock::iterator it = bbIt->begin(), ie = bbIt->end(); - it != ie; ++it) { - Instruction *instr = &*it; - const InstructionInfo &ii = executor.kmodule->infos->getInfo(*instr); - unsigned index = ii.id; - if (ii.file != sourceFile) { - of << "fl=" << ii.file << "\n"; - sourceFile = ii.file; + of << "fn=" << fn.getName().str() << "\n"; + for (auto &bb : fn) { + for (auto &instr : bb) { + Instruction *instrPtr = &instr; + + auto instrLI = getLocationInfo(instrPtr); + + unsigned index = executor.kmodule->getGlobalIndex(instrPtr); + if (instrLI.file != sourceFile) { + of << "fl=" << instrLI.file << "\n"; + sourceFile = instrLI.file; } - assert(ii.assemblyLine.hasValue()); - of << ii.assemblyLine.getValue() << " "; + { + auto asmLine = executor.kmodule->getAsmLine(instrPtr); + assert(asmLine.has_value()); + of << asmLine.value() << " "; + } - of << ii.line << " "; + of << instrLI.line << " "; for (unsigned i = 0; i < nStats; i++) if (istatsMask.test(i)) of << sm.getIndexedValue(sm.getStatistic(i), index) << " "; of << "\n"; if (UseCallPaths && - (isa(instr) || isa(instr))) { - CallSiteSummaryTable::iterator it = callSiteStats.find(instr); + (isa(instrPtr) || isa(instrPtr))) { + CallSiteSummaryTable::iterator it = callSiteStats.find(instrPtr); if (it != callSiteStats.end()) { - for (auto fit = it->second.begin(), fie = it->second.end(); - fit != fie; ++fit) { - const Function *f = fit->first; - CallSiteInfo &csi = fit->second; - const FunctionInfo &fii = - executor.kmodule->infos->getFunctionInfo(*f); - - if (fii.file != "" && fii.file != sourceFile) - of << "cfl=" << fii.file << "\n"; + for (auto &fit : it->second) { + const Function *f = fit.first; + CallSiteInfo &csi = fit.second; + auto fli = getLocationInfo(f); + if (fli.file != "" && fli.file != sourceFile) + of << "cfl=" << fli.file << "\n"; of << "cfn=" << f->getName().str() << "\n"; of << "calls=" << csi.count << " "; - assert(fii.assemblyLine.hasValue()); - of << fii.assemblyLine.getValue() << " "; + { + auto asmLine = executor.kmodule->getAsmLine(f); + assert(asmLine.has_value()); + of << asmLine.value() << " "; + } - of << fii.line << "\n"; + of << fli.line << "\n"; - assert(ii.assemblyLine.hasValue()); - of << ii.assemblyLine.getValue() << " "; + { + auto asmLine = executor.kmodule->getAsmLine(instrPtr); + assert(asmLine.has_value()); + of << asmLine.value() << " "; + } - of << ii.line << " "; + of << instrLI.line << " "; for (unsigned i = 0; i < nStats; i++) { if (istatsMask.test(i)) { Statistic &s = sm.getStatistic(i); @@ -889,12 +891,12 @@ uint64_t klee::computeMinDistToUncovered(const KInstruction *ki, uint64_t minDistAtRA) { StatisticManager &sm = *theStatisticManager; if (minDistAtRA == 0) { // unreachable on return, best is local - return sm.getIndexedValue(stats::minDistToUncovered, ki->info->id); + return sm.getIndexedValue(stats::minDistToUncovered, ki->getGlobalIndex()); } else { uint64_t minDistLocal = - sm.getIndexedValue(stats::minDistToUncovered, ki->info->id); + sm.getIndexedValue(stats::minDistToUncovered, ki->getGlobalIndex()); uint64_t distToReturn = - sm.getIndexedValue(stats::minDistToReturn, ki->info->id); + sm.getIndexedValue(stats::minDistToReturn, ki->getGlobalIndex()); if (distToReturn == 0) { // return unreachable, best is local return minDistLocal; @@ -910,7 +912,6 @@ void StatsTracker::computeReachableUncovered() { KModule *km = executor.kmodule.get(); const auto m = km->module.get(); static bool init = true; - const InstructionInfoTable &infos = *km->infos; StatisticManager &sm = *theStatisticManager; if (init) { @@ -973,11 +974,10 @@ void StatsTracker::computeReachableUncovered() { // Not sure if I should bother to preorder here. XXX I should. for (Function::iterator bbIt = fnIt->begin(), bb_ie = fnIt->end(); bbIt != bb_ie; ++bbIt) { - for (BasicBlock::iterator it = bbIt->begin(), ie = bbIt->end(); - it != ie; ++it) { - Instruction *inst = &*it; + for (auto &it : *bbIt) { + Instruction *inst = ⁢ instructions.push_back(inst); - unsigned id = infos.getInfo(*inst).id; + unsigned id = km->getGlobalIndex(inst); sm.setIndexedValue(stats::minDistToReturn, id, isa(inst)); } } @@ -989,9 +989,8 @@ void StatsTracker::computeReachableUncovered() { bool changed; do { changed = false; - for (auto it = instructions.begin(), ie = instructions.end(); it != ie; - ++it) { - Instruction *inst = *it; + for (auto &instruction : instructions) { + Instruction *inst = instruction; unsigned bestThrough = 0; if (isa(inst) || isa(inst)) { @@ -1011,15 +1010,15 @@ void StatsTracker::computeReachableUncovered() { } if (bestThrough) { - unsigned id = infos.getInfo(*(*it)).id; + unsigned id = km->getGlobalIndex(instruction); uint64_t best, cur = best = sm.getIndexedValue(stats::minDistToReturn, id); - std::vector succs = getSuccs(*it); + std::vector succs = getSuccs(instruction); for (std::vector::iterator it2 = succs.begin(), ie = succs.end(); it2 != ie; ++it2) { uint64_t dist = sm.getIndexedValue(stats::minDistToReturn, - infos.getInfo(*(*it2)).id); + km->getGlobalIndex(*it2)); if (dist) { uint64_t val = bestThrough + dist; if (best == 0 || val < best) @@ -1055,7 +1054,7 @@ void StatsTracker::computeReachableUncovered() { for (BasicBlock::iterator it = bbIt->begin(), ie = bbIt->end(); it != ie; ++it) { Instruction *inst = &*it; - unsigned id = infos.getInfo(*inst).id; + unsigned id = km->getGlobalIndex(inst); instructions.push_back(inst); sm.setIndexedValue( stats::minDistToUncovered, id, @@ -1070,29 +1069,24 @@ void StatsTracker::computeReachableUncovered() { bool changed; do { changed = false; - for (std::vector::iterator it = instructions.begin(), - ie = instructions.end(); - it != ie; ++it) { - Instruction *inst = *it; + for (auto inst : instructions) { uint64_t best, cur = best = sm.getIndexedValue(stats::minDistToUncovered, - infos.getInfo(*inst).id); + km->getGlobalIndex(inst)); unsigned bestThrough = 0; if (isa(inst) || isa(inst)) { std::vector &targets = callTargets[inst]; - for (std::vector::iterator fnIt = targets.begin(), - ie = targets.end(); - fnIt != ie; ++fnIt) { - uint64_t dist = functionShortestPath[*fnIt]; + for (auto &target : targets) { + uint64_t dist = functionShortestPath[target]; if (dist) { dist = 1 + dist; // count instruction itself if (bestThrough == 0 || dist < bestThrough) bestThrough = dist; } - if (!(*fnIt)->isDeclaration()) { + if (!target->isDeclaration()) { uint64_t calleeDist = sm.getIndexedValue( - stats::minDistToUncovered, infos.getFunctionInfo(*(*fnIt)).id); + stats::minDistToUncovered, km->getGlobalIndex(target)); if (calleeDist) { calleeDist = 1 + calleeDist; // count instruction itself if (best == 0 || calleeDist < best) @@ -1106,11 +1100,9 @@ void StatsTracker::computeReachableUncovered() { if (bestThrough) { std::vector succs = getSuccs(inst); - for (std::vector::iterator it2 = succs.begin(), - ie = succs.end(); - it2 != ie; ++it2) { + for (auto &succ : succs) { uint64_t dist = sm.getIndexedValue(stats::minDistToUncovered, - infos.getInfo(*(*it2)).id); + km->getGlobalIndex(succ)); if (dist) { uint64_t val = bestThrough + dist; if (best == 0 || val < best) @@ -1120,7 +1112,7 @@ void StatsTracker::computeReachableUncovered() { } if (best != cur) { - sm.setIndexedValue(stats::minDistToUncovered, infos.getInfo(*inst).id, + sm.setIndexedValue(stats::minDistToUncovered, km->getGlobalIndex(inst), best); changed = true; } diff --git a/lib/Core/StatsTracker.h b/lib/Core/StatsTracker.h index be0f39ae5b..52a85d560c 100644 --- a/lib/Core/StatsTracker.h +++ b/lib/Core/StatsTracker.h @@ -27,7 +27,6 @@ class raw_fd_ostream; namespace klee { class ExecutionState; class Executor; -class InstructionInfoTable; class InterpreterHandler; struct KInstruction; struct InfoStackFrame; diff --git a/lib/Core/TargetedExecutionManager.cpp b/lib/Core/TargetedExecutionManager.cpp index 9f9b498738..a46a12e3c9 100644 --- a/lib/Core/TargetedExecutionManager.cpp +++ b/lib/Core/TargetedExecutionManager.cpp @@ -318,24 +318,27 @@ TargetedExecutionManager::LocationToBlocks TargetedExecutionManager::prepareAllLocations(KModule *kmodule, Locations &locations) const { LocationToBlocks locToBlocks; - const auto &infos = kmodule->infos; + std::unordered_map> + fileNameToFunctions; + + for (const auto &kfunc : kmodule->functions) { + fileNameToFunctions[kfunc->getSourceFilepath()].insert(kfunc->function); + } + for (auto it = locations.begin(); it != locations.end(); ++it) { auto loc = *it; - for (const auto &fileName : infos->getFilesNames()) { - if (kmodule->origInfos.count(fileName) == 0) { + for (const auto &[fileName, origInstsInFile] : kmodule->origInstructions) { + if (kmodule->origInstructions.count(fileName) == 0) { continue; } if (!loc->isInside(fileName)) { continue; } - const auto &relatedFunctions = - infos->getFileNameToFunctions().at(fileName); + const auto &relatedFunctions = fileNameToFunctions.at(fileName); for (const auto func : relatedFunctions) { const auto kfunc = kmodule->functionMap[func]; - const auto &fi = infos->getFunctionInfo(*kfunc->function); - const auto &origInstsInFile = kmodule->origInfos.at(fi.file); for (const auto &kblock : kfunc->blocks) { auto b = kblock.get(); @@ -524,7 +527,7 @@ TargetedExecutionManager::prepareTargets(KModule *kmodule, SarifReport paths) { void TargetedExecutionManager::reportFalseNegative(ExecutionState &state, ReachWithError error) { klee_warning("100.00%% %s False Negative at: %s", getErrorString(error), - state.prevPC->getSourceLocation().c_str()); + state.prevPC->getSourceLocationString().c_str()); } bool TargetedExecutionManager::reportTruePositive(ExecutionState &state, diff --git a/lib/Core/TargetedExecutionManager.h b/lib/Core/TargetedExecutionManager.h index e5a66cbf32..93ea108a07 100644 --- a/lib/Core/TargetedExecutionManager.h +++ b/lib/Core/TargetedExecutionManager.h @@ -96,12 +96,6 @@ class TargetedExecutionManager { using StatesSet = std::unordered_set; using TargetToStateUnorderedSetMap = TargetHashMap; - using Instructions = std::unordered_map< - std::string, - std::unordered_map< - unsigned int, - std::unordered_map>>>; - std::unordered_set brokenTraces; std::unordered_set reportedTraces; diff --git a/lib/Expr/ExprPPrinter.cpp b/lib/Expr/ExprPPrinter.cpp index bde8d30d6d..165b438025 100644 --- a/lib/Expr/ExprPPrinter.cpp +++ b/lib/Expr/ExprPPrinter.cpp @@ -409,8 +409,8 @@ class PPrinter : public ExprPPrinter { auto kf = s->km->functionMap.at(s->allocSite.getFunction()); auto ki = kf->instructionMap.at(&s->allocSite); auto kb = ki->parent; - PC << ki->index << " " << kb->getLabel() << " " << kf->getName().str() - << " " << s->index; + PC << ki->getIndex() << " " << kb->getLabel() << " " + << kf->getName().str() << " " << s->index; } else if (auto s = dyn_cast(source)) { PC << s->name; } else { diff --git a/lib/Expr/Path.cpp b/lib/Expr/Path.cpp index 7b578aa30c..e67abd51b4 100644 --- a/lib/Expr/Path.cpp +++ b/lib/Expr/Path.cpp @@ -15,8 +15,8 @@ using namespace llvm; void Path::advance(KInstruction *ki) { if (KBlocks.empty()) { - firstInstruction = ki->index; - lastInstruction = ki->index; + firstInstruction = ki->getIndex(); + lastInstruction = ki->getIndex(); KBlocks.push_back(ki->parent); return; } @@ -24,8 +24,7 @@ void Path::advance(KInstruction *ki) { if (ki->parent != lastBlock) { KBlocks.push_back(ki->parent); } - lastInstruction = ki->index; - return; + lastInstruction = ki->getIndex(); } unsigned Path::KBlockSize() const { return KBlocks.size(); } diff --git a/lib/Expr/SymbolicSource.cpp b/lib/Expr/SymbolicSource.cpp index 0e7f8b1086..9d8d3b6e58 100644 --- a/lib/Expr/SymbolicSource.cpp +++ b/lib/Expr/SymbolicSource.cpp @@ -98,9 +98,8 @@ int ArgumentSource::internalCompare(const SymbolicSource &b) const { assert(km == ab.km); auto parent = allocSite.getParent(); auto bParent = ab.allocSite.getParent(); - if (km->functionIDMap.at(parent) != km->functionIDMap.at(bParent)) { - return km->functionIDMap.at(parent) < km->functionIDMap.at(bParent) ? -1 - : 1; + if (km->getFunctionId(parent) != km->getFunctionId(bParent)) { + return km->getFunctionId(parent) < km->getFunctionId(bParent) ? -1 : 1; } if (allocSite.getArgNo() != ab.allocSite.getArgNo()) { return allocSite.getArgNo() < ab.allocSite.getArgNo() ? -1 : 1; @@ -119,20 +118,20 @@ int InstructionSource::internalCompare(const SymbolicSource &b) const { assert(km == ib.km); auto function = allocSite.getParent()->getParent(); auto bFunction = ib.allocSite.getParent()->getParent(); - if (km->functionIDMap.at(function) != km->functionIDMap.at(bFunction)) { - return km->functionIDMap.at(function) < km->functionIDMap.at(bFunction) ? -1 - : 1; + if (km->getFunctionId(function) != km->getFunctionId(bFunction)) { + return km->getFunctionId(function) < km->getFunctionId(bFunction) ? -1 : 1; } auto kf = km->functionMap.at(function); auto block = allocSite.getParent(); auto bBlock = ib.allocSite.getParent(); - if (kf->blockMap[block]->id != kf->blockMap[bBlock]->id) { - return kf->blockMap[block]->id < kf->blockMap[bBlock]->id ? -1 : 1; + if (kf->blockMap[block]->getId() != kf->blockMap[bBlock]->getId()) { + return kf->blockMap[block]->getId() < kf->blockMap[bBlock]->getId() ? -1 + : 1; } - if (kf->instructionMap[&allocSite]->index != - kf->instructionMap[&ib.allocSite]->index) { - return kf->instructionMap[&allocSite]->index < - kf->instructionMap[&ib.allocSite]->index + if (kf->instructionMap[&allocSite]->getIndex() != + kf->instructionMap[&ib.allocSite]->getIndex()) { + return kf->instructionMap[&allocSite]->getIndex() < + kf->instructionMap[&ib.allocSite]->getIndex() ? -1 : 1; } @@ -142,8 +141,7 @@ int InstructionSource::internalCompare(const SymbolicSource &b) const { unsigned ArgumentSource::computeHash() { unsigned res = (getKind() * SymbolicSource::MAGIC_HASH_CONSTANT) + index; auto parent = allocSite.getParent(); - res = (res * SymbolicSource::MAGIC_HASH_CONSTANT) + - km->functionIDMap.at(parent); + res = (res * SymbolicSource::MAGIC_HASH_CONSTANT) + km->getFunctionId(parent); res = (res * SymbolicSource::MAGIC_HASH_CONSTANT) + allocSite.getArgNo(); hashValue = res; return hashValue; @@ -154,11 +152,12 @@ unsigned InstructionSource::computeHash() { auto function = allocSite.getParent()->getParent(); auto kf = km->functionMap.at(function); auto block = allocSite.getParent(); + res = + (res * SymbolicSource::MAGIC_HASH_CONSTANT) + km->getFunctionId(function); res = (res * SymbolicSource::MAGIC_HASH_CONSTANT) + - km->functionIDMap.at(function); - res = (res * SymbolicSource::MAGIC_HASH_CONSTANT) + kf->blockMap[block]->id; + kf->blockMap[block]->getId(); res = (res * SymbolicSource::MAGIC_HASH_CONSTANT) + - kf->instructionMap[&allocSite]->index; + kf->instructionMap[&allocSite]->getIndex(); hashValue = res; return hashValue; } diff --git a/lib/Module/CMakeLists.txt b/lib/Module/CMakeLists.txt index 81112acbe0..42ef35556b 100644 --- a/lib/Module/CMakeLists.txt +++ b/lib/Module/CMakeLists.txt @@ -11,7 +11,7 @@ set(KLEE_MODULE_COMPONENT_SRCS Checks.cpp CodeGraphInfo.cpp FunctionAlias.cpp - InstructionInfoTable.cpp + LocationInfo.cpp InstructionOperandTypeCheckPass.cpp IntrinsicCleaner.cpp KInstruction.cpp diff --git a/lib/Module/InstructionInfoTable.cpp b/lib/Module/InstructionInfoTable.cpp deleted file mode 100644 index ee66e91cbf..0000000000 --- a/lib/Module/InstructionInfoTable.cpp +++ /dev/null @@ -1,230 +0,0 @@ -//===-- InstructionInfoTable.cpp ------------------------------------------===// -// -// The KLEE Symbolic Virtual Machine -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "klee/Module/InstructionInfoTable.h" -#include "klee/Config/Version.h" - -#include "klee/Support/CompilerWarning.h" -DISABLE_WARNING_PUSH -DISABLE_WARNING_DEPRECATED_DECLARATIONS -#include "llvm/Analysis/ValueTracking.h" -#include "llvm/IR/AssemblyAnnotationWriter.h" -#include "llvm/IR/DebugInfo.h" -#include "llvm/IR/DebugInfoMetadata.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/InstIterator.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/IntrinsicInst.h" -#include "llvm/IR/LLVMContext.h" -#include "llvm/IR/Module.h" -#include "llvm/Linker/Linker.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/FormattedStream.h" -#include "llvm/Support/Path.h" -#include "llvm/Support/raw_ostream.h" -DISABLE_WARNING_POP - -#include -#include -#include - -using namespace klee; - -class InstructionToLineAnnotator : public llvm::AssemblyAnnotationWriter { -private: - std::unordered_map mapping = {}; - -public: - void emitInstructionAnnot(const llvm::Instruction *i, - llvm::formatted_raw_ostream &os) override { - os.flush(); - mapping.emplace(reinterpret_cast(i), os.getLine() + 1); - } - - void emitFunctionAnnot(const llvm::Function *f, - llvm::formatted_raw_ostream &os) override { - os.flush(); - mapping.emplace(reinterpret_cast(f), os.getLine() + 1); - } - - std::unordered_map getMapping() const { return mapping; } -}; - -static std::unordered_map -buildInstructionToLineMap(const llvm::Module &m, - std::unique_ptr assemblyFS) { - - InstructionToLineAnnotator a; - - m.print(*assemblyFS, &a); - assemblyFS->flush(); - - return a.getMapping(); -} - -class DebugInfoExtractor { - std::vector> &internedStrings; - std::unordered_map lineTable; - - const llvm::Module &module; - bool withAsm = false; - -public: - DebugInfoExtractor( - std::vector> &_internedStrings, - const llvm::Module &_module, - std::unique_ptr assemblyFS) - : internedStrings(_internedStrings), module(_module) { - if (assemblyFS) { - withAsm = true; - lineTable = buildInstructionToLineMap(module, std::move(assemblyFS)); - } - } - - std::string &getInternedString(const std::string &s) { - auto found = std::find_if(internedStrings.begin(), internedStrings.end(), - [&s](const std::unique_ptr &item) { - return *item.get() == s; - }); - if (found != internedStrings.end()) - return *found->get(); - - auto newItem = std::unique_ptr(new std::string(s)); - auto result = newItem.get(); - - internedStrings.emplace_back(std::move(newItem)); - return *result; - } - - std::unique_ptr getFunctionInfo(const llvm::Function &Func) { - llvm::Optional asmLine; - if (withAsm) { - asmLine = lineTable.at(reinterpret_cast(&Func)); - } - auto dsub = Func.getSubprogram(); - - if (dsub != nullptr) { - auto path = dsub->getFilename(); - return std::make_unique(FunctionInfo( - 0, getInternedString(path.str()), dsub->getLine(), asmLine)); - } - - // Fallback: Mark as unknown - return std::make_unique( - FunctionInfo(0, getInternedString(""), 0, asmLine)); - } - - std::unique_ptr - getInstructionInfo(const llvm::Instruction &Inst, const FunctionInfo *f) { - llvm::Optional asmLine; - if (withAsm) { - asmLine = lineTable.at(reinterpret_cast(&Inst)); - } - - // Retrieve debug information associated with instruction - auto dl = Inst.getDebugLoc(); - - // Check if a valid debug location is assigned to the instruction. - if (dl.get() != nullptr) { - auto full_path = dl.get()->getFilename(); - auto line = dl.getLine(); - auto column = dl.getCol(); - - // Still, if the line is unknown, take the context of the instruction to - // narrow it down - if (line == 0) { - if (auto LexicalBlock = - llvm::dyn_cast(dl.getScope())) { - line = LexicalBlock->getLine(); - column = LexicalBlock->getColumn(); - } - } - return std::make_unique(InstructionInfo( - 0, getInternedString(full_path.str()), line, column, asmLine)); - } - - if (f != nullptr) - // If nothing found, use the surrounding function - return std::make_unique( - InstructionInfo(0, f->file, f->line, 0, asmLine)); - // If nothing found, use the surrounding function - return std::make_unique( - InstructionInfo(0, getInternedString(""), 0, 0, asmLine)); - } -}; - -InstructionInfoTable::InstructionInfoTable( - const llvm::Module &m, std::unique_ptr assemblyFS, - bool withInstructions) { - // Generate all debug instruction information - DebugInfoExtractor DI(internedStrings, m, std::move(assemblyFS)); - - for (const auto &Func : m) { - auto F = DI.getFunctionInfo(Func); - auto FR = F.get(); - functionInfos.emplace(&Func, std::move(F)); - - for (auto it = llvm::inst_begin(Func), ie = llvm::inst_end(Func); it != ie; - ++it) { - auto instr = &*it; - auto instInfo = DI.getInstructionInfo(*instr, FR); - if (withInstructions) { - insts[instInfo->file][instInfo->line][instInfo->column].insert( - instr->getOpcode()); - } - filesNames.insert(instInfo->file); - fileNameToFunctions[instInfo->file].insert(&Func); - infos.emplace(instr, std::move(instInfo)); - } - } - - // Make sure that every item has a unique ID - size_t idCounter = 0; - for (auto &item : infos) - item.second->id = idCounter++; - for (auto &item : functionInfos) - item.second->id = idCounter++; -} - -unsigned InstructionInfoTable::getMaxID() const { - return infos.size() + functionInfos.size(); -} - -const InstructionInfo & -InstructionInfoTable::getInfo(const llvm::Instruction &inst) const { - auto it = infos.find(&inst); - if (it == infos.end()) - llvm::report_fatal_error("invalid instruction, not present in " - "initial module!"); - return *it->second.get(); -} - -const FunctionInfo & -InstructionInfoTable::getFunctionInfo(const llvm::Function &f) const { - auto found = functionInfos.find(&f); - if (found == functionInfos.end()) - llvm::report_fatal_error("invalid instruction, not present in " - "initial module!"); - - return *found->second.get(); -} - -const InstructionInfoTable::LocationToFunctionsMap & -InstructionInfoTable::getFileNameToFunctions() const { - return fileNameToFunctions; -} - -const std::unordered_set & -InstructionInfoTable::getFilesNames() const { - return filesNames; -} - -InstructionInfoTable::Instructions InstructionInfoTable::getInstructions() { - return std::move(insts); -} diff --git a/lib/Module/KInstruction.cpp b/lib/Module/KInstruction.cpp index f7159c4bd6..b5c33fe41d 100644 --- a/lib/Module/KInstruction.cpp +++ b/lib/Module/KInstruction.cpp @@ -9,11 +9,15 @@ #include "klee/Module/KInstruction.h" #include "klee/Module/KModule.h" +#include "klee/Module/LocationInfo.h" #include "klee/Support/CompilerWarning.h" DISABLE_WARNING_PUSH DISABLE_WARNING_DEPRECATED_DECLARATIONS #include "llvm/ADT/StringExtras.h" +#include "llvm/IR/DebugInfoMetadata.h" +#include +#include DISABLE_WARNING_POP #include @@ -23,17 +27,91 @@ using namespace klee; /***/ +static int getOperandNum( + Value *v, + const std::unordered_map &instructionToRegisterMap, + KModule *km, KInstruction *ki) { + if (Instruction *inst = dyn_cast(v)) { + return instructionToRegisterMap.at(inst); + } else if (Argument *a = dyn_cast(v)) { + return a->getArgNo(); + } else if (isa(v) || isa(v) || + isa(v)) { + return -1; + } else { + assert(isa(v)); + Constant *c = cast(v); + return -(km->getConstantID(c, ki) + 2); + } +} + +KInstruction::KInstruction( + const std::unordered_map + &_instructionToRegisterMap, + llvm::Instruction *_inst, KModule *_km, KBlock *_kb, + unsigned &_globalIndexInc) + : inst(_inst), parent(_kb), globalIndex(_globalIndexInc++) { + if (isa(inst) || isa(inst)) { + const llvm::CallBase &cs = cast(*inst); + Value *val = cs.getCalledOperand(); + unsigned numArgs = cs.arg_size(); + operands = new int[numArgs + 1]; + operands[0] = getOperandNum(val, _instructionToRegisterMap, _km, this); + for (unsigned j = 0; j < numArgs; j++) { + Value *v = cs.getArgOperand(j); + operands[j + 1] = getOperandNum(v, _instructionToRegisterMap, _km, this); + } + } else { + unsigned numOperands = inst->getNumOperands(); + operands = new int[numOperands]; + for (unsigned j = 0; j < numOperands; j++) { + Value *v = inst->getOperand(j); + operands[j] = getOperandNum(v, _instructionToRegisterMap, _km, this); + } + } +} + KInstruction::~KInstruction() { delete[] operands; } -std::string KInstruction::getSourceLocation() const { - if (!info->file.empty()) - return info->file + ":" + std::to_string(info->line) + " " + - std::to_string(info->column); - else +size_t KInstruction::getLine() const { + auto locationInfo = getLocationInfo(inst); + return locationInfo.line; +} + +size_t KInstruction::getColumn() const { + auto locationInfo = getLocationInfo(inst); + return locationInfo.column; +} + +std::string KInstruction::getSourceFilepath() const { + auto locationInfo = getLocationInfo(inst); + return locationInfo.file; +} + +std::string KInstruction::getSourceLocationString() const { + std::string filePath = getSourceFilepath(); + if (!filePath.empty()) { + // TODO change format to file:line:column + return filePath + ":" + std::to_string(getLine()) + " " + + std::to_string(getColumn()); + } else { return "[no debug info]"; + } } std::string KInstruction::toString() const { - return llvm::utostr(index) + " at " + parent->toString() + " (" + + return llvm::utostr(getIndex()) + " at " + parent->toString() + " (" + inst->getOpcodeName() + ")"; } + +unsigned KInstruction::getGlobalIndex() const { return globalIndex; } + +unsigned KInstruction::getIndex() const { + return getGlobalIndex() - getKFunction()->getGlobalIndex() - + getKBlock()->getId() - 1; +} + +unsigned KInstruction::getDest() const { + return parent->parent->getNumArgs() + getIndex() + + (parent->instructions - parent->parent->instructions); +} diff --git a/lib/Module/KModule.cpp b/lib/Module/KModule.cpp index 2ab1059a8f..7bfb8433f3 100644 --- a/lib/Module/KModule.cpp +++ b/lib/Module/KModule.cpp @@ -14,9 +14,9 @@ #include "klee/Config/Version.h" #include "klee/Core/Interpreter.h" #include "klee/Module/Cell.h" -#include "klee/Module/InstructionInfoTable.h" #include "klee/Module/KInstruction.h" #include "klee/Module/KModule.h" +#include "klee/Module/LocationInfo.h" #include "klee/Support/Debug.h" #include "klee/Support/ErrorHandling.h" #include "klee/Support/ModuleUtil.h" @@ -26,6 +26,7 @@ DISABLE_WARNING_PUSH DISABLE_WARNING_DEPRECATED_DECLARATIONS #include "llvm/Bitcode/BitcodeWriter.h" +#include "llvm/IR/AssemblyAnnotationWriter.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/Function.h" #include "llvm/IR/IRBuilder.h" @@ -37,6 +38,7 @@ DISABLE_WARNING_DEPRECATED_DECLARATIONS #include "llvm/IR/Verifier.h" #include "llvm/Linker/Linker.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/FormattedStream.h" #include "llvm/Support/Path.h" #include "llvm/Support/raw_os_ostream.h" #include "llvm/Support/raw_ostream.h" @@ -46,7 +48,9 @@ DISABLE_WARNING_DEPRECATED_DECLARATIONS #include "llvm/Transforms/Utils/Cloning.h" DISABLE_WARNING_POP +#include #include +#include using namespace llvm; using namespace klee; @@ -337,6 +341,38 @@ void KModule::optimiseAndPrepare( pm3.run(*module); } +class InstructionToLineAnnotator : public llvm::AssemblyAnnotationWriter { +private: + std::unordered_map mapping = {}; + +public: + void emitInstructionAnnot(const llvm::Instruction *i, + llvm::formatted_raw_ostream &os) override { + os.flush(); + mapping.emplace(reinterpret_cast(i), os.getLine() + 1); + } + + void emitFunctionAnnot(const llvm::Function *f, + llvm::formatted_raw_ostream &os) override { + os.flush(); + mapping.emplace(reinterpret_cast(f), os.getLine() + 1); + } + + std::unordered_map getMapping() const { return mapping; } +}; + +static std::unordered_map +buildInstructionToLineMap(const llvm::Module &m, + std::unique_ptr assemblyFS) { + + InstructionToLineAnnotator a; + + m.print(*assemblyFS, &a); + assemblyFS->flush(); + + return a.getMapping(); +} + void KModule::manifest(InterpreterHandler *ih, Interpreter::GuidanceKind guidance, bool forceSourceOutput) { @@ -351,32 +387,21 @@ void KModule::manifest(InterpreterHandler *ih, std::unique_ptr assemblyFS; if (OutputSource || forceSourceOutput) { assemblyFS = ih->openOutputFile("assembly.ll"); + asmLineMap = buildInstructionToLineMap(*module, std::move(assemblyFS)); } - infos = - std::make_unique(*module, std::move(assemblyFS)); } std::vector declarations; unsigned functionID = 0; + maxGlobalIndex = 0; for (auto &Function : module->functions()) { if (Function.isDeclaration()) { declarations.push_back(&Function); } - auto kf = std::unique_ptr(new KFunction(&Function, this)); - - llvm::Function *function = &Function; - for (auto &BasicBlock : *function) { - unsigned numInstructions = kf->blockMap[&BasicBlock]->numInstructions; - KBlock *kb = kf->blockMap[&BasicBlock]; - for (unsigned i = 0; i < numInstructions; ++i) { - KInstruction *ki = kb->instructions[i]; - ki->info = &infos->getInfo(*ki->inst); - } - } + auto kf = std::make_unique(&Function, this, maxGlobalIndex); - functionIDMap.insert({&Function, functionID}); kf->id = functionID; functionID++; functionNameMap.insert({kf->getName().str(), kf.get()}); @@ -426,6 +451,19 @@ void KModule::manifest(InterpreterHandler *ih, } } +std::optional KModule::getAsmLine(const uintptr_t ref) const { + if (!asmLineMap.empty()) { + return asmLineMap.at(ref); + } + return std::nullopt; +} +std::optional KModule::getAsmLine(const llvm::Function *func) const { + return getAsmLine(reinterpret_cast(func)); +} +std::optional KModule::getAsmLine(const llvm::Instruction *inst) const { + return getAsmLine(reinterpret_cast(inst)); +} + void KModule::checkModule() { InstructionOperandTypeCheckPass *operandTypeCheckPass = new InstructionOperandTypeCheckPass(); @@ -502,6 +540,18 @@ unsigned KModule::getConstantID(Constant *c, KInstruction *ki) { return id; } +unsigned KModule::getFunctionId(const llvm::Function *func) const { + return functionMap.at(func)->id; +} +unsigned KModule::getGlobalIndex(const llvm::Function *func) const { + return functionMap.at(func)->getGlobalIndex(); +} +unsigned KModule::getGlobalIndex(const llvm::Instruction *inst) const { + return functionMap.at(inst->getFunction()) + ->instructionMap.at(inst) + ->getGlobalIndex(); +} + /***/ KConstant::KConstant(llvm::Constant *_ct, unsigned _id, KInstruction *_ki) { @@ -510,76 +560,25 @@ KConstant::KConstant(llvm::Constant *_ct, unsigned _id, KInstruction *_ki) { ki = _ki; } -/***/ - -static int getOperandNum( - Value *v, - std::unordered_map &instructionToRegisterMap, - KModule *km, KInstruction *ki) { - if (Instruction *inst = dyn_cast(v)) { - return instructionToRegisterMap[inst]; - } else if (Argument *a = dyn_cast(v)) { - return a->getArgNo(); - } else if (isa(v) || isa(v) || - isa(v)) { - return -1; - } else { - assert(isa(v)); - Constant *c = cast(v); - return -(km->getConstantID(c, ki) + 2); - } -} - -void KBlock::handleKInstruction( - std::unordered_map &instructionToRegisterMap, - llvm::Instruction *inst, KModule *km, KInstruction *ki) { - ki->parent = this; - ki->inst = inst; - ki->dest = instructionToRegisterMap[inst]; - if (isa(inst) || isa(inst)) { - const CallBase &cs = cast(*inst); - Value *val = cs.getCalledOperand(); - unsigned numArgs = cs.arg_size(); - ki->operands = new int[numArgs + 1]; - ki->operands[0] = getOperandNum(val, instructionToRegisterMap, km, ki); - for (unsigned j = 0; j < numArgs; j++) { - Value *v = cs.getArgOperand(j); - ki->operands[j + 1] = getOperandNum(v, instructionToRegisterMap, km, ki); - } - } else { - unsigned numOperands = inst->getNumOperands(); - ki->operands = new int[numOperands]; - for (unsigned j = 0; j < numOperands; j++) { - Value *v = inst->getOperand(j); - ki->operands[j] = getOperandNum(v, instructionToRegisterMap, km, ki); - } - } -} - -KFunction::KFunction(llvm::Function *_function, KModule *_km) - : KCallable(CK_Function), parent(_km), function(_function), - numArgs(function->arg_size()), numInstructions(0), numBlocks(0), - entryKBlock(nullptr), trackCoverage(true) { +KFunction::KFunction(llvm::Function *_function, KModule *_km, + unsigned &globalIndexInc) + : KCallable(CK_Function), globalIndex(globalIndexInc++), parent(_km), + function(_function), entryKBlock(nullptr), numInstructions(0) { for (auto &BasicBlock : *function) { numInstructions += BasicBlock.size(); - numBlocks++; } instructions = new KInstruction *[numInstructions]; std::unordered_map instructionToRegisterMap; // Assign unique instruction IDs to each basic block unsigned n = 0; // The first arg_size() registers are reserved for formals. - unsigned rnum = numArgs; - for (llvm::Function::iterator bbit = function->begin(), - bbie = function->end(); - bbit != bbie; ++bbit) { - for (llvm::BasicBlock::iterator it = bbit->begin(), ie = bbit->end(); - it != ie; ++it) - instructionToRegisterMap[&*it] = rnum++; + unsigned rnum = getNumArgs(); + for (auto &bb : *function) { + for (auto &instr : bb) { + instructionToRegisterMap[&instr] = rnum++; + } } - numRegisters = rnum; - unsigned blockID = 0; for (llvm::Function::iterator bbit = function->begin(), bbie = function->end(); bbit != bbie; ++bbit) { @@ -594,32 +593,42 @@ KFunction::KFunction(llvm::Function *_function, KModule *_km) if (f) { calledFunctions.insert(f); } - KCallBlock *ckb = new KCallBlock( - this, &*bbit, parent, instructionToRegisterMap, - registerToInstructionMap, calledFunctions, &instructions[n]); + auto *ckb = + new KCallBlock(this, &*bbit, parent, instructionToRegisterMap, + calledFunctions, &instructions[n], globalIndexInc); kCallBlocks.push_back(ckb); kb = ckb; } else if (SplitReturns && isa(lit)) { kb = new KReturnBlock(this, &*bbit, parent, instructionToRegisterMap, - registerToInstructionMap, &instructions[n]); + &instructions[n], globalIndexInc); returnKBlocks.push_back(kb); - } else + } else { kb = new KBlock(this, &*bbit, parent, instructionToRegisterMap, - registerToInstructionMap, &instructions[n]); + &instructions[n], globalIndexInc); + } for (unsigned i = 0; i < kb->numInstructions; i++, n++) { instructionMap[instructions[n]->inst] = instructions[n]; } - kb->id = blockID++; blockMap[&*bbit] = kb; blocks.push_back(std::unique_ptr(kb)); } - if (numBlocks > 0) { + if (blocks.size() > 0) { assert(function->begin() != function->end()); entryKBlock = blockMap[&*function->begin()]; } } +size_t KFunction::getLine() const { + auto locationInfo = getLocationInfo(function); + return locationInfo.line; +} + +std::string KFunction::getSourceFilepath() const { + auto locationInfo = getLocationInfo(function); + return locationInfo.file; +} + KFunction::~KFunction() { for (unsigned i = 0; i < numInstructions; ++i) delete instructions[i]; @@ -628,47 +637,40 @@ KFunction::~KFunction() { KBlock::KBlock( KFunction *_kfunction, llvm::BasicBlock *block, KModule *km, - std::unordered_map &instructionToRegisterMap, - std::unordered_map ®isterToInstructionMap, - KInstruction **instructionsKF) - : parent(_kfunction), basicBlock(block), numInstructions(0), - trackCoverage(true) { + const std::unordered_map &instructionToRegisterMap, + KInstruction **instructionsKF, unsigned &globalIndexInc) + : parent(_kfunction), basicBlock(block), numInstructions(0) { numInstructions += block->size(); instructions = instructionsKF; - unsigned i = 0; - for (llvm::BasicBlock::iterator it = block->begin(), ie = block->end(); - it != ie; ++it) { + for (auto &it : *block) { KInstruction *ki; - switch (it->getOpcode()) { + switch (it.getOpcode()) { case Instruction::GetElementPtr: case Instruction::InsertValue: case Instruction::ExtractValue: - ki = new KGEPInstruction(); + ki = new KGEPInstruction(instructionToRegisterMap, &it, km, this, + globalIndexInc); break; default: - ki = new KInstruction(); + ki = new KInstruction(instructionToRegisterMap, &it, km, this, + globalIndexInc); break; } - - Instruction *inst = &*it; - handleKInstruction(instructionToRegisterMap, inst, km, ki); - ki->index = i; - instructions[i++] = ki; - registerToInstructionMap[instructionToRegisterMap[&*it]] = ki; + instructions[ki->getIndex()] = ki; } } KCallBlock::KCallBlock( KFunction *_kfunction, llvm::BasicBlock *block, KModule *km, - std::unordered_map &instructionToRegisterMap, - std::unordered_map ®isterToInstructionMap, - std::set _calledFunctions, KInstruction **instructionsKF) + const std::unordered_map &instructionToRegisterMap, + std::set _calledFunctions, KInstruction **instructionsKF, + unsigned &globalIndexInc) : KBlock::KBlock(_kfunction, block, km, instructionToRegisterMap, - registerToInstructionMap, instructionsKF), + instructionsKF, globalIndexInc), kcallInstruction(this->instructions[0]), - calledFunctions(_calledFunctions) {} + calledFunctions(std::move(_calledFunctions)) {} bool KCallBlock::intrinsic() const { if (calledFunctions.size() != 1) { @@ -695,11 +697,10 @@ KFunction *KCallBlock::getKFunction() const { KReturnBlock::KReturnBlock( KFunction *_kfunction, llvm::BasicBlock *block, KModule *km, - std::unordered_map &instructionToRegisterMap, - std::unordered_map ®isterToInstructionMap, - KInstruction **instructionsKF) + const std::unordered_map &instructionToRegisterMap, + KInstruction **instructionsKF, unsigned &globalIndexInc) : KBlock::KBlock(_kfunction, block, km, instructionToRegisterMap, - registerToInstructionMap, instructionsKF) {} + instructionsKF, globalIndexInc) {} std::string KBlock::getLabel() const { std::string _label; @@ -712,3 +713,13 @@ std::string KBlock::getLabel() const { std::string KBlock::toString() const { return getLabel() + " in function " + parent->function->getName().str(); } + +uintptr_t KBlock::getId() const { return instructions - parent->instructions; } + +KInstruction *KFunction::getInstructionByRegister(size_t reg) const { + return instructions[reg - function->arg_size()]; +} +size_t KFunction::getNumArgs() const { return function->arg_size(); } +size_t KFunction::getNumRegisters() const { + return function->arg_size() + numInstructions; +} diff --git a/lib/Module/LocationInfo.cpp b/lib/Module/LocationInfo.cpp new file mode 100644 index 0000000000..274a55e25d --- /dev/null +++ b/lib/Module/LocationInfo.cpp @@ -0,0 +1,63 @@ +//===-- LocationInfo.cpp ------------------------------------------===// +// +// The KLEE Symbolic Virtual Machine +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "klee/Module/LocationInfo.h" +#include "klee/Support/CompilerWarning.h" + +DISABLE_WARNING_PUSH +DISABLE_WARNING_DEPRECATED_DECLARATIONS +#include "llvm/Analysis/ValueTracking.h" +#include "llvm/IR/AssemblyAnnotationWriter.h" +#include "llvm/IR/DebugInfoMetadata.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/Support/FormattedStream.h" +DISABLE_WARNING_POP + +namespace klee { + +LocationInfo getLocationInfo(const llvm::Function *func) { + const auto dsub = func->getSubprogram(); + + if (dsub != nullptr) { + auto path = dsub->getFilename(); + return {path.str(), dsub->getLine(), 0}; // TODO why not use column here? + } + + return {"", 0, 0}; +} + +LocationInfo getLocationInfo(const llvm::Instruction *inst) { + // Retrieve debug information associated with instruction + const auto &dl = inst->getDebugLoc(); + + // Check if a valid debug location is assigned to the instruction. + if (dl.get() != nullptr) { + auto full_path = dl->getFilename(); + auto line = dl.getLine(); + auto column = dl.getCol(); + + // Still, if the line is unknown, take the context of the instruction to + // narrow it down + if (line == 0) { + if (auto LexicalBlock = + llvm::dyn_cast(dl.getScope())) { + line = LexicalBlock->getLine(); + column = LexicalBlock->getColumn(); + } + } + return {full_path.str(), line, column}; + } + + return getLocationInfo(inst->getParent()->getParent()); +} + +} // namespace klee diff --git a/lib/Module/SarifReport.cpp b/lib/Module/SarifReport.cpp index 075ce32417..3923d32ead 100644 --- a/lib/Module/SarifReport.cpp +++ b/lib/Module/SarifReport.cpp @@ -326,20 +326,22 @@ bool Location::isInside(const std::string &name) const { } bool Location::isInside(KBlock *block, const Instructions &origInsts) const { - auto first = block->getFirstInstruction()->info; - auto last = block->getLastInstruction()->info; + auto first = block->getFirstInstruction(); + auto last = block->getLastInstruction(); if (!startColumn.has_value()) { - if (first->line > endLine) + if (first->getLine() > endLine) return false; - return startLine <= last->line; // and `first <= line` from above + return startLine <= last->getLine(); // and `first <= line` from above } else { for (size_t i = 0; i < block->numInstructions; ++i) { - auto inst = block->instructions[i]->info; + auto inst = block->instructions[i]; auto opCode = block->instructions[i]->inst->getOpcode(); if (!isa(block->instructions[i]->inst) && - inst->line <= endLine && inst->line >= startLine && - inst->column <= *endColumn && inst->column >= *startColumn && - origInsts.at(inst->line).at(inst->column).count(opCode) != 0) { + inst->getLine() <= endLine && inst->getLine() >= startLine && + inst->getColumn() <= *endColumn && + inst->getColumn() >= *startColumn && + origInsts.at(inst->getLine()).at(inst->getColumn()).count(opCode) != + 0) { return true; } } diff --git a/lib/Module/Target.cpp b/lib/Module/Target.cpp index 7e6cfab36d..d2dde07919 100644 --- a/lib/Module/Target.cpp +++ b/lib/Module/Target.cpp @@ -31,8 +31,8 @@ ErrorLocation::ErrorLocation(const klee::ref &loc) startColumn(loc->startColumn), endColumn(loc->endColumn) {} ErrorLocation::ErrorLocation(const KInstruction *ki) { - startLine = (endLine = ki->info->line); - startColumn = (endColumn = ki->info->line); + startLine = (endLine = ki->getLine()); + startColumn = (endColumn = ki->getLine()); } std::string ReproduceErrorTarget::toString() const { @@ -102,11 +102,11 @@ ref CoverBranchTarget::create(KBlock *_block, unsigned _branchCase) { bool ReproduceErrorTarget::isTheSameAsIn(const KInstruction *instr) const { const auto &errLoc = loc; - return instr->info->line >= errLoc.startLine && - instr->info->line <= errLoc.endLine && + return instr->getLine() >= errLoc.startLine && + instr->getLine() <= errLoc.endLine && (!LocationAccuracy || !errLoc.startColumn.has_value() || - (instr->info->column >= *errLoc.startColumn && - instr->info->column <= *errLoc.endColumn)); + (instr->getColumn() >= *errLoc.startColumn && + instr->getColumn() <= *errLoc.endColumn)); } int Target::compare(const Target &b) const { return internalCompare(b); } @@ -126,8 +126,8 @@ int ReachBlockTarget::internalCompare(const Target &b) const { if (block->parent->id != other.block->parent->id) { return block->parent->id < other.block->parent->id ? -1 : 1; } - if (block->id != other.block->id) { - return block->id < other.block->id ? -1 : 1; + if (block->getId() != other.block->getId()) { + return block->getId() < other.block->getId() ? -1 : 1; } if (atEnd != other.atEnd) { @@ -146,8 +146,8 @@ int CoverBranchTarget::internalCompare(const Target &b) const { if (block->parent->id != other.block->parent->id) { return block->parent->id < other.block->parent->id ? -1 : 1; } - if (block->id != other.block->id) { - return block->id < other.block->id ? -1 : 1; + if (block->getId() != other.block->getId()) { + return block->getId() < other.block->getId() ? -1 : 1; } if (branchCase != other.branchCase) { @@ -170,8 +170,8 @@ int ReproduceErrorTarget::internalCompare(const Target &b) const { if (block->parent->id != other.block->parent->id) { return block->parent->id < other.block->parent->id ? -1 : 1; } - if (block->id != other.block->id) { - return block->id < other.block->id ? -1 : 1; + if (block->getId() != other.block->getId()) { + return block->getId() < other.block->getId() ? -1 : 1; } if (errors.size() != other.errors.size()) { diff --git a/test/regression/2023-10-04-email_spec0_product16.cil.c b/test/regression/2023-10-04-email_spec0_product16.cil.c new file mode 100644 index 0000000000..8a4acd5c58 --- /dev/null +++ b/test/regression/2023-10-04-email_spec0_product16.cil.c @@ -0,0 +1,2794 @@ +// REQUIRES: z3 +// RUN: %clang -Wno-everything %s -emit-llvm %O0opt -g -c -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --use-forked-solver=false --solver-backend=z3 -max-memory=6008 --optimize --skip-not-lazy-initialized -istats-write-interval=90s -exit-on-error-type=Assert --search=dfs -max-time=10s %t1.bc 2>&1 | FileCheck -check-prefix=CHECK %s + +// RUN find %t.klee-out -type f -name "*.assert.err" | sed 's/assert\.err/ktest/' | xargs %ktest-tool | FileCheck -check-prefix=CHECK-TEST %s +// CHECK-TEST-NOT: object 20 + +#include "klee-test-comp.c" + +// This file is part of the SV-Benchmarks collection of verification tasks: +// https://gitlab.com/sosy-lab/benchmarking/sv-benchmarks +// +// SPDX-FileCopyrightText: 2011-2013 Alexander von Rhein, University of Passau +// SPDX-FileCopyrightText: 2011-2021 The SV-Benchmarks Community +// +// SPDX-License-Identifier: Apache-2.0 + +extern void abort(void); +extern void __assert_fail(const char *, const char *, unsigned int, const char *) __attribute__((__nothrow__, __leaf__)) __attribute__((__noreturn__)); +// CHECK: email_spec0_product16.cil.c:[[@LINE+1]]: ASSERTION FAIL: 0 +void reach_error() { __assert_fail("0", "email_spec0_product16.cil.c", 3, "reach_error"); } + +extern int __VERIFIER_nondet_int(void); +/* Generated by CIL v. 1.3.7 */ +/* print_CIL_Input is true */ + +struct JoinPoint { + void **(*fp)(struct JoinPoint *); + void **args; + int argsCount; + char const **argsType; + void *(*arg)(int, struct JoinPoint *); + char const *(*argType)(int, struct JoinPoint *); + void **retValue; + char const *retType; + char const *funcName; + char const *targetName; + char const *fileName; + char const *kind; + void *excep_return; +}; +struct __UTAC__CFLOW_FUNC { + int (*func)(int, int); + int val; + struct __UTAC__CFLOW_FUNC *next; +}; +struct __UTAC__EXCEPTION { + void *jumpbuf; + unsigned long long prtValue; + int pops; + struct __UTAC__CFLOW_FUNC *cflowfuncs; +}; +typedef unsigned int size_t; +struct __ACC__ERR { + void *v; + struct __ACC__ERR *next; +}; +#pragma merger(0, "featureselect.i", "") +int __SELECTED_FEATURE_Base; +int __SELECTED_FEATURE_Keys; +int __SELECTED_FEATURE_Encrypt; +int __SELECTED_FEATURE_AutoResponder; +int __SELECTED_FEATURE_AddressBook; +int __SELECTED_FEATURE_Sign; +int __SELECTED_FEATURE_Forward; +int __SELECTED_FEATURE_Verify; +int __SELECTED_FEATURE_Decrypt; +int __GUIDSL_ROOT_PRODUCTION; +int __GUIDSL_NON_TERMINAL_main; +int select_one(void); +void select_features(void); +void select_helpers(void); +int valid_product(void); +int select_one(void) { + int retValue_acc; + int choice = __VERIFIER_nondet_int(); + + { + retValue_acc = choice; + return (retValue_acc); + return (retValue_acc); + } +} +void select_features(void) { + + { + return; + } +} +void select_helpers(void) { + + { + return; + } +} +int valid_product(void) { + int retValue_acc; + + { + retValue_acc = 1; + return (retValue_acc); + return (retValue_acc); + } +} +#pragma merger(0, "Test.i", "") +extern int printf(char const *__restrict __format, ...); +extern int puts(char const *__s); +void setClientPrivateKey(int handle, int value); +int createClientKeyringEntry(int handle); +int getClientKeyringUser(int handle, int index); +void setClientKeyringUser(int handle, int index, int value); +int getClientKeyringPublicKey(int handle, int index); +void setClientKeyringPublicKey(int handle, int index, int value); +void setClientForwardReceiver(int handle, int value); +void setClientId(int handle, int value); +int is_queue_empty(void); +int get_queued_client(void); +int get_queued_email(void); +void outgoing(int client, int msg); +void sendEmail(int sender, int receiver); +void generateKeyPair(int client, int seed); +int bob; +int rjh; +int chuck; +void setup_bob(int bob___0); +void setup_rjh(int rjh___0); +void setup_chuck(int chuck___0); +void bobToRjh(void); +void rjhToBob(void); +void test(void); +void setup(void); +int main(void); +void bobKeyAdd(void); +void bobKeyAddChuck(void); +void rjhKeyAdd(void); +void rjhKeyAddChuck(void); +void chuckKeyAdd(void); +void bobKeyChange(void); +void rjhKeyChange(void); +void rjhDeletePrivateKey(void); +void chuckKeyAddRjh(void); +void rjhEnableForwarding(void); +void setup_bob__wrappee__Base(int bob___0) { + + { + { + setClientId(bob___0, bob___0); + } + return; + } +} +void setup_bob(int bob___0) { + + { + { + setup_bob__wrappee__Base(bob___0); + setClientPrivateKey(bob___0, 123); + } + return; + } +} +void setup_rjh__wrappee__Base(int rjh___0) { + + { + { + setClientId(rjh___0, rjh___0); + } + return; + } +} +void setup_rjh(int rjh___0) { + + { + { + setup_rjh__wrappee__Base(rjh___0); + setClientPrivateKey(rjh___0, 456); + } + return; + } +} +void setup_chuck__wrappee__Base(int chuck___0) { + + { + { + setClientId(chuck___0, chuck___0); + } + return; + } +} +void setup_chuck(int chuck___0) { + + { + { + setup_chuck__wrappee__Base(chuck___0); + setClientPrivateKey(chuck___0, 789); + } + return; + } +} +void bobToRjh(void) { + int tmp; + int tmp___0; + int tmp___1; + + { + { + puts("Please enter a subject and a message body.\n"); + sendEmail(bob, rjh); + tmp___1 = is_queue_empty(); + } + if (tmp___1) { + + } else { + { + tmp = get_queued_email(); + tmp___0 = get_queued_client(); + outgoing(tmp___0, tmp); + } + } + return; + } +} +void rjhToBob(void) { + + { + { + puts("Please enter a subject and a message body.\n"); + sendEmail(rjh, bob); + } + return; + } +} +void setup(void) { + char const *__restrict __cil_tmp1; + char const *__restrict __cil_tmp2; + char const *__restrict __cil_tmp3; + + { + { + bob = 1; + setup_bob(bob); + __cil_tmp1 = (char const *__restrict)"bob: %d\n"; + printf(__cil_tmp1, bob); + rjh = 2; + setup_rjh(rjh); + __cil_tmp2 = (char const *__restrict)"rjh: %d\n"; + printf(__cil_tmp2, rjh); + chuck = 3; + setup_chuck(chuck); + __cil_tmp3 = (char const *__restrict)"chuck: %d\n"; + printf(__cil_tmp3, chuck); + } + return; + } +} +int main(void) { + int retValue_acc; + int tmp; + + { + { + select_helpers(); + select_features(); + tmp = valid_product(); + } + if (tmp) { + { + setup(); + test(); + } + } else { + } + return (retValue_acc); + } +} +void bobKeyAdd(void) { + int tmp; + int tmp___0; + char const *__restrict __cil_tmp3; + char const *__restrict __cil_tmp4; + + { + { + createClientKeyringEntry(bob); + setClientKeyringUser(bob, 0, 2); + setClientKeyringPublicKey(bob, 0, 456); + puts("bob added rjhs key"); + tmp = getClientKeyringUser(bob, 0); + __cil_tmp3 = (char const *__restrict)"%d\n"; + printf(__cil_tmp3, tmp); + tmp___0 = getClientKeyringPublicKey(bob, 0); + __cil_tmp4 = (char const *__restrict)"%d\n"; + printf(__cil_tmp4, tmp___0); + } + return; + } +} +void rjhKeyAdd(void) { + + { + { + createClientKeyringEntry(rjh); + setClientKeyringUser(rjh, 0, 1); + setClientKeyringPublicKey(rjh, 0, 123); + } + return; + } +} +void rjhKeyAddChuck(void) { + + { + { + createClientKeyringEntry(rjh); + setClientKeyringUser(rjh, 0, 3); + setClientKeyringPublicKey(rjh, 0, 789); + } + return; + } +} +void bobKeyAddChuck(void) { + + { + { + createClientKeyringEntry(bob); + setClientKeyringUser(bob, 1, 3); + setClientKeyringPublicKey(bob, 1, 789); + } + return; + } +} +void chuckKeyAdd(void) { + + { + { + createClientKeyringEntry(chuck); + setClientKeyringUser(chuck, 0, 1); + setClientKeyringPublicKey(chuck, 0, 123); + } + return; + } +} +void chuckKeyAddRjh(void) { + + { + { + createClientKeyringEntry(chuck); + setClientKeyringUser(chuck, 0, 2); + setClientKeyringPublicKey(chuck, 0, 456); + } + return; + } +} +void rjhDeletePrivateKey(void) { + + { + { + setClientPrivateKey(rjh, 0); + } + return; + } +} +void bobKeyChange(void) { + + { + { + generateKeyPair(bob, 777); + } + return; + } +} +void rjhKeyChange(void) { + + { + { + generateKeyPair(rjh, 666); + } + return; + } +} +void rjhEnableForwarding(void) { + + { + { + setClientForwardReceiver(rjh, chuck); + } + return; + } +} +#pragma merger(0, "wsllib_check.i", "") +void __automaton_fail(void) { + + { + ERROR : { + reach_error(); + abort(); + } + return; + } +} +#pragma merger(0, "Email.i", "") +int getEmailId(int handle); +int getEmailFrom(int handle); +void setEmailFrom(int handle, int value); +int getEmailTo(int handle); +void setEmailTo(int handle, int value); +int isEncrypted(int handle); +int getEmailEncryptionKey(int handle); +void printMail(int msg); +int isReadable(int msg); +int createEmail(int from, int to); +int cloneEmail(int msg); +void printMail__wrappee__Keys(int msg) { + int tmp; + int tmp___0; + int tmp___1; + int tmp___2; + char const *__restrict __cil_tmp6; + char const *__restrict __cil_tmp7; + char const *__restrict __cil_tmp8; + char const *__restrict __cil_tmp9; + + { + { + tmp = getEmailId(msg); + __cil_tmp6 = (char const *__restrict)"ID:\n %i\n"; + printf(__cil_tmp6, tmp); + tmp___0 = getEmailFrom(msg); + __cil_tmp7 = (char const *__restrict)"FROM:\n %i\n"; + printf(__cil_tmp7, tmp___0); + tmp___1 = getEmailTo(msg); + __cil_tmp8 = (char const *__restrict)"TO:\n %i\n"; + printf(__cil_tmp8, tmp___1); + tmp___2 = isReadable(msg); + __cil_tmp9 = (char const *__restrict)"IS_READABLE\n %i\n"; + printf(__cil_tmp9, tmp___2); + } + return; + } +} +void printMail(int msg) { + int tmp; + int tmp___0; + char const *__restrict __cil_tmp4; + char const *__restrict __cil_tmp5; + + { + { + printMail__wrappee__Keys(msg); + tmp = isEncrypted(msg); + __cil_tmp4 = (char const *__restrict)"ENCRYPTED\n %d\n"; + printf(__cil_tmp4, tmp); + tmp___0 = getEmailEncryptionKey(msg); + __cil_tmp5 = (char const *__restrict)"ENCRYPTION KEY\n %d\n"; + printf(__cil_tmp5, tmp___0); + } + return; + } +} +int isReadable__wrappee__Keys(int msg) { + int retValue_acc; + + { + retValue_acc = 1; + return (retValue_acc); + return (retValue_acc); + } +} +int isReadable(int msg) { + int retValue_acc; + int tmp; + + { + { + tmp = isEncrypted(msg); + } + if (tmp) { + retValue_acc = 0; + return (retValue_acc); + } else { + { + retValue_acc = isReadable__wrappee__Keys(msg); + } + return (retValue_acc); + } + return (retValue_acc); + } +} +int cloneEmail(int msg) { + int retValue_acc; + + { + retValue_acc = msg; + return (retValue_acc); + return (retValue_acc); + } +} +int createEmail(int from, int to) { + int retValue_acc; + int msg; + + { + { + msg = 1; + setEmailFrom(msg, from); + setEmailTo(msg, to); + retValue_acc = msg; + } + return (retValue_acc); + return (retValue_acc); + } +} +#pragma merger(0, "scenario.i", "") +void test(void) { + int op1; + int op2; + int op3; + int op4; + int op5; + int op6; + int op7; + int op8; + int op9; + int op10; + int op11; + int splverifierCounter; + int tmp; + int tmp___0; + int tmp___1; + int tmp___2; + int tmp___3; + int tmp___4; + int tmp___5; + int tmp___6; + int tmp___7; + int tmp___8; + int tmp___9; + + { + op1 = 0; + op2 = 0; + op3 = 0; + op4 = 0; + op5 = 0; + op6 = 0; + op7 = 0; + op8 = 0; + op9 = 0; + op10 = 0; + op11 = 0; + splverifierCounter = 0; + { + while (1) { + while_0_continue: /* CIL Label */; + if (splverifierCounter < 4) { + + } else { + goto while_0_break; + } + splverifierCounter = splverifierCounter + 1; + if (!op1) { + { + tmp___9 = __VERIFIER_nondet_int(); + } + if (tmp___9) { + { + bobKeyAdd(); + op1 = 1; + } + } else { + goto _L___8; + } + } else { + _L___8: /* CIL Label */ + if (!op2) { + { + tmp___8 = __VERIFIER_nondet_int(); + } + if (tmp___8) { + op2 = 1; + } else { + goto _L___7; + } + } else { + _L___7: /* CIL Label */ + if (!op3) { + { + tmp___7 = __VERIFIER_nondet_int(); + } + if (tmp___7) { + { + rjhDeletePrivateKey(); + op3 = 1; + } + } else { + goto _L___6; + } + } else { + _L___6: /* CIL Label */ + if (!op4) { + { + tmp___6 = __VERIFIER_nondet_int(); + } + if (tmp___6) { + { + rjhKeyAdd(); + op4 = 1; + } + } else { + goto _L___5; + } + } else { + _L___5: /* CIL Label */ + if (!op5) { + { + tmp___5 = __VERIFIER_nondet_int(); + } + if (tmp___5) { + { + chuckKeyAddRjh(); + op5 = 1; + } + } else { + goto _L___4; + } + } else { + _L___4: /* CIL Label */ + if (!op6) { + { + tmp___4 = __VERIFIER_nondet_int(); + } + if (tmp___4) { + { + rjhEnableForwarding(); + op6 = 1; + } + } else { + goto _L___3; + } + } else { + _L___3: /* CIL Label */ + if (!op7) { + { + tmp___3 = __VERIFIER_nondet_int(); + } + if (tmp___3) { + { + rjhKeyChange(); + op7 = 1; + } + } else { + goto _L___2; + } + } else { + _L___2: /* CIL Label */ + if (!op8) { + { + tmp___2 = __VERIFIER_nondet_int(); + } + if (tmp___2) { + op8 = 1; + } else { + goto _L___1; + } + } else { + _L___1: /* CIL Label */ + if (!op9) { + { + tmp___1 = __VERIFIER_nondet_int(); + } + if (tmp___1) { + { + chuckKeyAdd(); + op9 = 1; + } + } else { + goto _L___0; + } + } else { + _L___0: /* CIL Label */ + if (!op10) { + { + tmp___0 = __VERIFIER_nondet_int(); + } + if (tmp___0) { + { + bobKeyChange(); + op10 = 1; + } + } else { + goto _L; + } + } else { + _L: /* CIL Label */ + if (!op11) { + { + tmp = __VERIFIER_nondet_int(); + } + if (tmp) { + { + chuckKeyAdd(); + op11 = 1; + } + } else { + goto while_0_break; + } + } else { + goto while_0_break; + } + } + } + } + } + } + } + } + } + } + } + } + while_0_break: /* CIL Label */; + } + { + bobToRjh(); + } + return; + } +} +#pragma merger(0, "libacc.i", "") +extern __attribute__((__nothrow__, __noreturn__)) void __assert_fail(char const *__assertion, + char const *__file, + unsigned int __line, + char const *__function); +extern __attribute__((__nothrow__)) void *malloc(size_t __size) __attribute__((__malloc__)); +extern __attribute__((__nothrow__)) void free(void *__ptr); +void __utac__exception__cf_handler_set(void *exception, int (*cflow_func)(int, int), + int val) { + struct __UTAC__EXCEPTION *excep; + struct __UTAC__CFLOW_FUNC *cf; + void *tmp; + unsigned long __cil_tmp7; + unsigned long __cil_tmp8; + unsigned long __cil_tmp9; + unsigned long __cil_tmp10; + unsigned long __cil_tmp11; + unsigned long __cil_tmp12; + unsigned long __cil_tmp13; + unsigned long __cil_tmp14; + int (**mem_15)(int, int); + int *mem_16; + struct __UTAC__CFLOW_FUNC **mem_17; + struct __UTAC__CFLOW_FUNC **mem_18; + struct __UTAC__CFLOW_FUNC **mem_19; + + { + { + excep = (struct __UTAC__EXCEPTION *)exception; + tmp = malloc(24UL); + cf = (struct __UTAC__CFLOW_FUNC *)tmp; + mem_15 = (int (**)(int, int))cf; + *mem_15 = cflow_func; + __cil_tmp7 = (unsigned long)cf; + __cil_tmp8 = __cil_tmp7 + 8; + mem_16 = (int *)__cil_tmp8; + *mem_16 = val; + __cil_tmp9 = (unsigned long)cf; + __cil_tmp10 = __cil_tmp9 + 16; + __cil_tmp11 = (unsigned long)excep; + __cil_tmp12 = __cil_tmp11 + 24; + mem_17 = (struct __UTAC__CFLOW_FUNC **)__cil_tmp10; + mem_18 = (struct __UTAC__CFLOW_FUNC **)__cil_tmp12; + *mem_17 = *mem_18; + __cil_tmp13 = (unsigned long)excep; + __cil_tmp14 = __cil_tmp13 + 24; + mem_19 = (struct __UTAC__CFLOW_FUNC **)__cil_tmp14; + *mem_19 = cf; + } + return; + } +} +void __utac__exception__cf_handler_free(void *exception) { + struct __UTAC__EXCEPTION *excep; + struct __UTAC__CFLOW_FUNC *cf; + struct __UTAC__CFLOW_FUNC *tmp; + unsigned long __cil_tmp5; + unsigned long __cil_tmp6; + struct __UTAC__CFLOW_FUNC *__cil_tmp7; + unsigned long __cil_tmp8; + unsigned long __cil_tmp9; + unsigned long __cil_tmp10; + unsigned long __cil_tmp11; + void *__cil_tmp12; + unsigned long __cil_tmp13; + unsigned long __cil_tmp14; + struct __UTAC__CFLOW_FUNC **mem_15; + struct __UTAC__CFLOW_FUNC **mem_16; + struct __UTAC__CFLOW_FUNC **mem_17; + + { + excep = (struct __UTAC__EXCEPTION *)exception; + __cil_tmp5 = (unsigned long)excep; + __cil_tmp6 = __cil_tmp5 + 24; + mem_15 = (struct __UTAC__CFLOW_FUNC **)__cil_tmp6; + cf = *mem_15; + { + while (1) { + while_1_continue: /* CIL Label */; + { + __cil_tmp7 = (struct __UTAC__CFLOW_FUNC *)0; + __cil_tmp8 = (unsigned long)__cil_tmp7; + __cil_tmp9 = (unsigned long)cf; + if (__cil_tmp9 != __cil_tmp8) { + + } else { + goto while_1_break; + } + } + { + tmp = cf; + __cil_tmp10 = (unsigned long)cf; + __cil_tmp11 = __cil_tmp10 + 16; + mem_16 = (struct __UTAC__CFLOW_FUNC **)__cil_tmp11; + cf = *mem_16; + __cil_tmp12 = (void *)tmp; + free(__cil_tmp12); + } + } + while_1_break: /* CIL Label */; + } + __cil_tmp13 = (unsigned long)excep; + __cil_tmp14 = __cil_tmp13 + 24; + mem_17 = (struct __UTAC__CFLOW_FUNC **)__cil_tmp14; + *mem_17 = (struct __UTAC__CFLOW_FUNC *)0; + return; + } +} +void __utac__exception__cf_handler_reset(void *exception) { + struct __UTAC__EXCEPTION *excep; + struct __UTAC__CFLOW_FUNC *cf; + unsigned long __cil_tmp5; + unsigned long __cil_tmp6; + struct __UTAC__CFLOW_FUNC *__cil_tmp7; + unsigned long __cil_tmp8; + unsigned long __cil_tmp9; + int (*__cil_tmp10)(int, int); + unsigned long __cil_tmp11; + unsigned long __cil_tmp12; + int __cil_tmp13; + unsigned long __cil_tmp14; + unsigned long __cil_tmp15; + struct __UTAC__CFLOW_FUNC **mem_16; + int (**mem_17)(int, int); + int *mem_18; + struct __UTAC__CFLOW_FUNC **mem_19; + + { + excep = (struct __UTAC__EXCEPTION *)exception; + __cil_tmp5 = (unsigned long)excep; + __cil_tmp6 = __cil_tmp5 + 24; + mem_16 = (struct __UTAC__CFLOW_FUNC **)__cil_tmp6; + cf = *mem_16; + { + while (1) { + while_2_continue: /* CIL Label */; + { + __cil_tmp7 = (struct __UTAC__CFLOW_FUNC *)0; + __cil_tmp8 = (unsigned long)__cil_tmp7; + __cil_tmp9 = (unsigned long)cf; + if (__cil_tmp9 != __cil_tmp8) { + + } else { + goto while_2_break; + } + } + { + mem_17 = (int (**)(int, int))cf; + __cil_tmp10 = *mem_17; + __cil_tmp11 = (unsigned long)cf; + __cil_tmp12 = __cil_tmp11 + 8; + mem_18 = (int *)__cil_tmp12; + __cil_tmp13 = *mem_18; + (*__cil_tmp10)(4, __cil_tmp13); + __cil_tmp14 = (unsigned long)cf; + __cil_tmp15 = __cil_tmp14 + 16; + mem_19 = (struct __UTAC__CFLOW_FUNC **)__cil_tmp15; + cf = *mem_19; + } + } + while_2_break: /* CIL Label */; + } + { + __utac__exception__cf_handler_free(exception); + } + return; + } +} +void *__utac__error_stack_mgt(void *env, int mode, int count); +static struct __ACC__ERR *head = (struct __ACC__ERR *)0; +void *__utac__error_stack_mgt(void *env, int mode, int count) { + void *retValue_acc; + struct __ACC__ERR *new; + void *tmp; + struct __ACC__ERR *temp; + struct __ACC__ERR *next; + void *excep; + unsigned long __cil_tmp10; + unsigned long __cil_tmp11; + unsigned long __cil_tmp12; + unsigned long __cil_tmp13; + void *__cil_tmp14; + unsigned long __cil_tmp15; + unsigned long __cil_tmp16; + void *__cil_tmp17; + void **mem_18; + struct __ACC__ERR **mem_19; + struct __ACC__ERR **mem_20; + void **mem_21; + struct __ACC__ERR **mem_22; + void **mem_23; + void **mem_24; + + { + if (count == 0) { + return (retValue_acc); + } else { + } + if (mode == 0) { + { + tmp = malloc(16UL); + new = (struct __ACC__ERR *)tmp; + mem_18 = (void **)new; + *mem_18 = env; + __cil_tmp10 = (unsigned long)new; + __cil_tmp11 = __cil_tmp10 + 8; + mem_19 = (struct __ACC__ERR **)__cil_tmp11; + *mem_19 = head; + head = new; + retValue_acc = (void *)new; + } + return (retValue_acc); + } else { + } + if (mode == 1) { + temp = head; + { + while (1) { + while_3_continue: /* CIL Label */; + if (count > 1) { + + } else { + goto while_3_break; + } + { + __cil_tmp12 = (unsigned long)temp; + __cil_tmp13 = __cil_tmp12 + 8; + mem_20 = (struct __ACC__ERR **)__cil_tmp13; + next = *mem_20; + mem_21 = (void **)temp; + excep = *mem_21; + __cil_tmp14 = (void *)temp; + free(__cil_tmp14); + __utac__exception__cf_handler_reset(excep); + temp = next; + count = count - 1; + } + } + while_3_break: /* CIL Label */; + } + { + __cil_tmp15 = (unsigned long)temp; + __cil_tmp16 = __cil_tmp15 + 8; + mem_22 = (struct __ACC__ERR **)__cil_tmp16; + head = *mem_22; + mem_23 = (void **)temp; + excep = *mem_23; + __cil_tmp17 = (void *)temp; + free(__cil_tmp17); + __utac__exception__cf_handler_reset(excep); + retValue_acc = excep; + } + return (retValue_acc); + } else { + } + if (mode == 2) { + if (head) { + mem_24 = (void **)head; + retValue_acc = *mem_24; + return (retValue_acc); + } else { + retValue_acc = (void *)0; + return (retValue_acc); + } + } else { + } + return (retValue_acc); + } +} +void *__utac__get_this_arg(int i, struct JoinPoint *this) { + void *retValue_acc; + unsigned long __cil_tmp4; + unsigned long __cil_tmp5; + int __cil_tmp6; + int __cil_tmp7; + unsigned long __cil_tmp8; + unsigned long __cil_tmp9; + void **__cil_tmp10; + void **__cil_tmp11; + int *mem_12; + void ***mem_13; + + { + if (i > 0) { + { + __cil_tmp4 = (unsigned long)this; + __cil_tmp5 = __cil_tmp4 + 16; + mem_12 = (int *)__cil_tmp5; + __cil_tmp6 = *mem_12; + if (i <= __cil_tmp6) { + + } else { + { + __assert_fail("i > 0 && i <= this->argsCount", "libacc.c", + 123U, "__utac__get_this_arg"); + } + } + } + } else { + { + __assert_fail("i > 0 && i <= this->argsCount", "libacc.c", + 123U, "__utac__get_this_arg"); + } + } + __cil_tmp7 = i - 1; + __cil_tmp8 = (unsigned long)this; + __cil_tmp9 = __cil_tmp8 + 8; + mem_13 = (void ***)__cil_tmp9; + __cil_tmp10 = *mem_13; + __cil_tmp11 = __cil_tmp10 + __cil_tmp7; + retValue_acc = *__cil_tmp11; + return (retValue_acc); + return (retValue_acc); + } +} +char const *__utac__get_this_argtype(int i, struct JoinPoint *this) { + char const *retValue_acc; + unsigned long __cil_tmp4; + unsigned long __cil_tmp5; + int __cil_tmp6; + int __cil_tmp7; + unsigned long __cil_tmp8; + unsigned long __cil_tmp9; + char const **__cil_tmp10; + char const **__cil_tmp11; + int *mem_12; + char const ***mem_13; + + { + if (i > 0) { + { + __cil_tmp4 = (unsigned long)this; + __cil_tmp5 = __cil_tmp4 + 16; + mem_12 = (int *)__cil_tmp5; + __cil_tmp6 = *mem_12; + if (i <= __cil_tmp6) { + + } else { + { + __assert_fail("i > 0 && i <= this->argsCount", "libacc.c", + 131U, "__utac__get_this_argtype"); + } + } + } + } else { + { + __assert_fail("i > 0 && i <= this->argsCount", "libacc.c", + 131U, "__utac__get_this_argtype"); + } + } + __cil_tmp7 = i - 1; + __cil_tmp8 = (unsigned long)this; + __cil_tmp9 = __cil_tmp8 + 24; + mem_13 = (char const ***)__cil_tmp9; + __cil_tmp10 = *mem_13; + __cil_tmp11 = __cil_tmp10 + __cil_tmp7; + retValue_acc = *__cil_tmp11; + return (retValue_acc); + return (retValue_acc); + } +} +#pragma merger(0, "ClientLib.i", "") +int initClient(void); +char *getClientName(int handle); +void setClientName(int handle, char *value); +int getClientOutbuffer(int handle); +void setClientOutbuffer(int handle, int value); +int getClientAddressBookSize(int handle); +void setClientAddressBookSize(int handle, int value); +int createClientAddressBookEntry(int handle); +int getClientAddressBookAlias(int handle, int index); +void setClientAddressBookAlias(int handle, int index, int value); +int getClientAddressBookAddress(int handle, int index); +void setClientAddressBookAddress(int handle, int index, int value); +int getClientAutoResponse(int handle); +void setClientAutoResponse(int handle, int value); +int getClientPrivateKey(int handle); +int getClientKeyringSize(int handle); +int getClientForwardReceiver(int handle); +int getClientId(int handle); +int findPublicKey(int handle, int userid); +int findClientAddressBookAlias(int handle, int userid); +int __ste_Client_counter = 0; +int initClient(void) { + int retValue_acc; + + { + if (__ste_Client_counter < 3) { + __ste_Client_counter = __ste_Client_counter + 1; + retValue_acc = __ste_Client_counter; + return (retValue_acc); + } else { + retValue_acc = -1; + return (retValue_acc); + } + return (retValue_acc); + } +} +char *__ste_client_name0 = (char *)0; +char *__ste_client_name1 = (char *)0; +char *__ste_client_name2 = (char *)0; +char *getClientName(int handle) { + char *retValue_acc; + void *__cil_tmp3; + + { + if (handle == 1) { + retValue_acc = __ste_client_name0; + return (retValue_acc); + } else { + if (handle == 2) { + retValue_acc = __ste_client_name1; + return (retValue_acc); + } else { + if (handle == 3) { + retValue_acc = __ste_client_name2; + return (retValue_acc); + } else { + __cil_tmp3 = (void *)0; + retValue_acc = (char *)__cil_tmp3; + return (retValue_acc); + } + } + } + return (retValue_acc); + } +} +void setClientName(int handle, char *value) { + + { + if (handle == 1) { + __ste_client_name0 = value; + } else { + if (handle == 2) { + __ste_client_name1 = value; + } else { + if (handle == 3) { + __ste_client_name2 = value; + } else { + } + } + } + return; + } +} +int __ste_client_outbuffer0 = 0; +int __ste_client_outbuffer1 = 0; +int __ste_client_outbuffer2 = 0; +int __ste_client_outbuffer3 = 0; +int getClientOutbuffer(int handle) { + int retValue_acc; + + { + if (handle == 1) { + retValue_acc = __ste_client_outbuffer0; + return (retValue_acc); + } else { + if (handle == 2) { + retValue_acc = __ste_client_outbuffer1; + return (retValue_acc); + } else { + if (handle == 3) { + retValue_acc = __ste_client_outbuffer2; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } + return (retValue_acc); + } +} +void setClientOutbuffer(int handle, int value) { + + { + if (handle == 1) { + __ste_client_outbuffer0 = value; + } else { + if (handle == 2) { + __ste_client_outbuffer1 = value; + } else { + if (handle == 3) { + __ste_client_outbuffer2 = value; + } else { + } + } + } + return; + } +} +int __ste_ClientAddressBook_size0 = 0; +int __ste_ClientAddressBook_size1 = 0; +int __ste_ClientAddressBook_size2 = 0; +int getClientAddressBookSize(int handle) { + int retValue_acc; + + { + if (handle == 1) { + retValue_acc = __ste_ClientAddressBook_size0; + return (retValue_acc); + } else { + if (handle == 2) { + retValue_acc = __ste_ClientAddressBook_size1; + return (retValue_acc); + } else { + if (handle == 3) { + retValue_acc = __ste_ClientAddressBook_size2; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } + return (retValue_acc); + } +} +void setClientAddressBookSize(int handle, int value) { + + { + if (handle == 1) { + __ste_ClientAddressBook_size0 = value; + } else { + if (handle == 2) { + __ste_ClientAddressBook_size1 = value; + } else { + if (handle == 3) { + __ste_ClientAddressBook_size2 = value; + } else { + } + } + } + return; + } +} +int createClientAddressBookEntry(int handle) { + int retValue_acc; + int size; + int tmp; + int __cil_tmp5; + + { + { + tmp = getClientAddressBookSize(handle); + size = tmp; + } + if (size < 3) { + { + __cil_tmp5 = size + 1; + setClientAddressBookSize(handle, __cil_tmp5); + retValue_acc = size + 1; + } + return (retValue_acc); + } else { + retValue_acc = -1; + return (retValue_acc); + } + return (retValue_acc); + } +} +int __ste_Client_AddressBook0_Alias0 = 0; +int __ste_Client_AddressBook0_Alias1 = 0; +int __ste_Client_AddressBook0_Alias2 = 0; +int __ste_Client_AddressBook1_Alias0 = 0; +int __ste_Client_AddressBook1_Alias1 = 0; +int __ste_Client_AddressBook1_Alias2 = 0; +int __ste_Client_AddressBook2_Alias0 = 0; +int __ste_Client_AddressBook2_Alias1 = 0; +int __ste_Client_AddressBook2_Alias2 = 0; +int getClientAddressBookAlias(int handle, int index) { + int retValue_acc; + + { + if (handle == 1) { + if (index == 0) { + retValue_acc = __ste_Client_AddressBook0_Alias0; + return (retValue_acc); + } else { + if (index == 1) { + retValue_acc = __ste_Client_AddressBook0_Alias1; + return (retValue_acc); + } else { + if (index == 2) { + retValue_acc = __ste_Client_AddressBook0_Alias2; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } + } else { + if (handle == 2) { + if (index == 0) { + retValue_acc = __ste_Client_AddressBook1_Alias0; + return (retValue_acc); + } else { + if (index == 1) { + retValue_acc = __ste_Client_AddressBook1_Alias1; + return (retValue_acc); + } else { + if (index == 2) { + retValue_acc = __ste_Client_AddressBook1_Alias2; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } + } else { + if (handle == 3) { + if (index == 0) { + retValue_acc = __ste_Client_AddressBook2_Alias0; + return (retValue_acc); + } else { + if (index == 1) { + retValue_acc = __ste_Client_AddressBook2_Alias1; + return (retValue_acc); + } else { + if (index == 2) { + retValue_acc = __ste_Client_AddressBook2_Alias2; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } + return (retValue_acc); + } +} +int findClientAddressBookAlias(int handle, int userid) { + int retValue_acc; + + { + if (handle == 1) { + if (userid == __ste_Client_AddressBook0_Alias0) { + retValue_acc = 0; + return (retValue_acc); + } else { + if (userid == __ste_Client_AddressBook0_Alias1) { + retValue_acc = 1; + return (retValue_acc); + } else { + if (userid == __ste_Client_AddressBook0_Alias2) { + retValue_acc = 2; + return (retValue_acc); + } else { + retValue_acc = -1; + return (retValue_acc); + } + } + } + } else { + if (handle == 2) { + if (userid == __ste_Client_AddressBook1_Alias0) { + retValue_acc = 0; + return (retValue_acc); + } else { + if (userid == __ste_Client_AddressBook1_Alias1) { + retValue_acc = 1; + return (retValue_acc); + } else { + if (userid == __ste_Client_AddressBook1_Alias2) { + retValue_acc = 2; + return (retValue_acc); + } else { + retValue_acc = -1; + return (retValue_acc); + } + } + } + } else { + if (handle == 3) { + if (userid == __ste_Client_AddressBook2_Alias0) { + retValue_acc = 0; + return (retValue_acc); + } else { + if (userid == __ste_Client_AddressBook2_Alias1) { + retValue_acc = 1; + return (retValue_acc); + } else { + if (userid == __ste_Client_AddressBook2_Alias2) { + retValue_acc = 2; + return (retValue_acc); + } else { + retValue_acc = -1; + return (retValue_acc); + } + } + } + } else { + retValue_acc = -1; + return (retValue_acc); + } + } + } + return (retValue_acc); + } +} +void setClientAddressBookAlias(int handle, int index, int value) { + + { + if (handle == 1) { + if (index == 0) { + __ste_Client_AddressBook0_Alias0 = value; + } else { + if (index == 1) { + __ste_Client_AddressBook0_Alias1 = value; + } else { + if (index == 2) { + __ste_Client_AddressBook0_Alias2 = value; + } else { + } + } + } + } else { + if (handle == 2) { + if (index == 0) { + __ste_Client_AddressBook1_Alias0 = value; + } else { + if (index == 1) { + __ste_Client_AddressBook1_Alias1 = value; + } else { + if (index == 2) { + __ste_Client_AddressBook1_Alias2 = value; + } else { + } + } + } + } else { + if (handle == 3) { + if (index == 0) { + __ste_Client_AddressBook2_Alias0 = value; + } else { + if (index == 1) { + __ste_Client_AddressBook2_Alias1 = value; + } else { + if (index == 2) { + __ste_Client_AddressBook2_Alias2 = value; + } else { + } + } + } + } else { + } + } + } + return; + } +} +int __ste_Client_AddressBook0_Address0 = 0; +int __ste_Client_AddressBook0_Address1 = 0; +int __ste_Client_AddressBook0_Address2 = 0; +int __ste_Client_AddressBook1_Address0 = 0; +int __ste_Client_AddressBook1_Address1 = 0; +int __ste_Client_AddressBook1_Address2 = 0; +int __ste_Client_AddressBook2_Address0 = 0; +int __ste_Client_AddressBook2_Address1 = 0; +int __ste_Client_AddressBook2_Address2 = 0; +int getClientAddressBookAddress(int handle, int index) { + int retValue_acc; + + { + if (handle == 1) { + if (index == 0) { + retValue_acc = __ste_Client_AddressBook0_Address0; + return (retValue_acc); + } else { + if (index == 1) { + retValue_acc = __ste_Client_AddressBook0_Address1; + return (retValue_acc); + } else { + if (index == 2) { + retValue_acc = __ste_Client_AddressBook0_Address2; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } + } else { + if (handle == 2) { + if (index == 0) { + retValue_acc = __ste_Client_AddressBook1_Address0; + return (retValue_acc); + } else { + if (index == 1) { + retValue_acc = __ste_Client_AddressBook1_Address1; + return (retValue_acc); + } else { + if (index == 2) { + retValue_acc = __ste_Client_AddressBook1_Address2; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } + } else { + if (handle == 3) { + if (index == 0) { + retValue_acc = __ste_Client_AddressBook2_Address0; + return (retValue_acc); + } else { + if (index == 1) { + retValue_acc = __ste_Client_AddressBook2_Address1; + return (retValue_acc); + } else { + if (index == 2) { + retValue_acc = __ste_Client_AddressBook2_Address2; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } + return (retValue_acc); + } +} +void setClientAddressBookAddress(int handle, int index, int value) { + + { + if (handle == 1) { + if (index == 0) { + __ste_Client_AddressBook0_Address0 = value; + } else { + if (index == 1) { + __ste_Client_AddressBook0_Address1 = value; + } else { + if (index == 2) { + __ste_Client_AddressBook0_Address2 = value; + } else { + } + } + } + } else { + if (handle == 2) { + if (index == 0) { + __ste_Client_AddressBook1_Address0 = value; + } else { + if (index == 1) { + __ste_Client_AddressBook1_Address1 = value; + } else { + if (index == 2) { + __ste_Client_AddressBook1_Address2 = value; + } else { + } + } + } + } else { + if (handle == 3) { + if (index == 0) { + __ste_Client_AddressBook2_Address0 = value; + } else { + if (index == 1) { + __ste_Client_AddressBook2_Address1 = value; + } else { + if (index == 2) { + __ste_Client_AddressBook2_Address2 = value; + } else { + } + } + } + } else { + } + } + } + return; + } +} +int __ste_client_autoResponse0 = 0; +int __ste_client_autoResponse1 = 0; +int __ste_client_autoResponse2 = 0; +int getClientAutoResponse(int handle) { + int retValue_acc; + + { + if (handle == 1) { + retValue_acc = __ste_client_autoResponse0; + return (retValue_acc); + } else { + if (handle == 2) { + retValue_acc = __ste_client_autoResponse1; + return (retValue_acc); + } else { + if (handle == 3) { + retValue_acc = __ste_client_autoResponse2; + return (retValue_acc); + } else { + retValue_acc = -1; + return (retValue_acc); + } + } + } + return (retValue_acc); + } +} +void setClientAutoResponse(int handle, int value) { + + { + if (handle == 1) { + __ste_client_autoResponse0 = value; + } else { + if (handle == 2) { + __ste_client_autoResponse1 = value; + } else { + if (handle == 3) { + __ste_client_autoResponse2 = value; + } else { + } + } + } + return; + } +} +int __ste_client_privateKey0 = 0; +int __ste_client_privateKey1 = 0; +int __ste_client_privateKey2 = 0; +int getClientPrivateKey(int handle) { + int retValue_acc; + + { + if (handle == 1) { + retValue_acc = __ste_client_privateKey0; + return (retValue_acc); + } else { + if (handle == 2) { + retValue_acc = __ste_client_privateKey1; + return (retValue_acc); + } else { + if (handle == 3) { + retValue_acc = __ste_client_privateKey2; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } + return (retValue_acc); + } +} +void setClientPrivateKey(int handle, int value) { + + { + if (handle == 1) { + __ste_client_privateKey0 = value; + } else { + if (handle == 2) { + __ste_client_privateKey1 = value; + } else { + if (handle == 3) { + __ste_client_privateKey2 = value; + } else { + } + } + } + return; + } +} +int __ste_ClientKeyring_size0 = 0; +int __ste_ClientKeyring_size1 = 0; +int __ste_ClientKeyring_size2 = 0; +int getClientKeyringSize(int handle) { + int retValue_acc; + + { + if (handle == 1) { + retValue_acc = __ste_ClientKeyring_size0; + return (retValue_acc); + } else { + if (handle == 2) { + retValue_acc = __ste_ClientKeyring_size1; + return (retValue_acc); + } else { + if (handle == 3) { + retValue_acc = __ste_ClientKeyring_size2; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } + return (retValue_acc); + } +} +void setClientKeyringSize(int handle, int value) { + + { + if (handle == 1) { + __ste_ClientKeyring_size0 = value; + } else { + if (handle == 2) { + __ste_ClientKeyring_size1 = value; + } else { + if (handle == 3) { + __ste_ClientKeyring_size2 = value; + } else { + } + } + } + return; + } +} +int createClientKeyringEntry(int handle) { + int retValue_acc; + int size; + int tmp; + int __cil_tmp5; + + { + { + tmp = getClientKeyringSize(handle); + size = tmp; + } + if (size < 2) { + { + __cil_tmp5 = size + 1; + setClientKeyringSize(handle, __cil_tmp5); + retValue_acc = size + 1; + } + return (retValue_acc); + } else { + retValue_acc = -1; + return (retValue_acc); + } + return (retValue_acc); + } +} +int __ste_Client_Keyring0_User0 = 0; +int __ste_Client_Keyring0_User1 = 0; +int __ste_Client_Keyring0_User2 = 0; +int __ste_Client_Keyring1_User0 = 0; +int __ste_Client_Keyring1_User1 = 0; +int __ste_Client_Keyring1_User2 = 0; +int __ste_Client_Keyring2_User0 = 0; +int __ste_Client_Keyring2_User1 = 0; +int __ste_Client_Keyring2_User2 = 0; +int getClientKeyringUser(int handle, int index) { + int retValue_acc; + + { + if (handle == 1) { + if (index == 0) { + retValue_acc = __ste_Client_Keyring0_User0; + return (retValue_acc); + } else { + if (index == 1) { + retValue_acc = __ste_Client_Keyring0_User1; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } else { + if (handle == 2) { + if (index == 0) { + retValue_acc = __ste_Client_Keyring1_User0; + return (retValue_acc); + } else { + if (index == 1) { + retValue_acc = __ste_Client_Keyring1_User1; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } else { + if (handle == 3) { + if (index == 0) { + retValue_acc = __ste_Client_Keyring2_User0; + return (retValue_acc); + } else { + if (index == 1) { + retValue_acc = __ste_Client_Keyring2_User1; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } + return (retValue_acc); + } +} +void setClientKeyringUser(int handle, int index, int value) { + + { + if (handle == 1) { + if (index == 0) { + __ste_Client_Keyring0_User0 = value; + } else { + if (index == 1) { + __ste_Client_Keyring0_User1 = value; + } else { + } + } + } else { + if (handle == 2) { + if (index == 0) { + __ste_Client_Keyring1_User0 = value; + } else { + if (index == 1) { + __ste_Client_Keyring1_User1 = value; + } else { + } + } + } else { + if (handle == 3) { + if (index == 0) { + __ste_Client_Keyring2_User0 = value; + } else { + if (index == 1) { + __ste_Client_Keyring2_User1 = value; + } else { + } + } + } else { + } + } + } + return; + } +} +int __ste_Client_Keyring0_PublicKey0 = 0; +int __ste_Client_Keyring0_PublicKey1 = 0; +int __ste_Client_Keyring0_PublicKey2 = 0; +int __ste_Client_Keyring1_PublicKey0 = 0; +int __ste_Client_Keyring1_PublicKey1 = 0; +int __ste_Client_Keyring1_PublicKey2 = 0; +int __ste_Client_Keyring2_PublicKey0 = 0; +int __ste_Client_Keyring2_PublicKey1 = 0; +int __ste_Client_Keyring2_PublicKey2 = 0; +int getClientKeyringPublicKey(int handle, int index) { + int retValue_acc; + + { + if (handle == 1) { + if (index == 0) { + retValue_acc = __ste_Client_Keyring0_PublicKey0; + return (retValue_acc); + } else { + if (index == 1) { + retValue_acc = __ste_Client_Keyring0_PublicKey1; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } else { + if (handle == 2) { + if (index == 0) { + retValue_acc = __ste_Client_Keyring1_PublicKey0; + return (retValue_acc); + } else { + if (index == 1) { + retValue_acc = __ste_Client_Keyring1_PublicKey1; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } else { + if (handle == 3) { + if (index == 0) { + retValue_acc = __ste_Client_Keyring2_PublicKey0; + return (retValue_acc); + } else { + if (index == 1) { + retValue_acc = __ste_Client_Keyring2_PublicKey1; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } + return (retValue_acc); + } +} +int findPublicKey(int handle, int userid) { + int retValue_acc; + + { + if (handle == 1) { + if (userid == __ste_Client_Keyring0_User0) { + retValue_acc = __ste_Client_Keyring0_PublicKey0; + return (retValue_acc); + } else { + if (userid == __ste_Client_Keyring0_User1) { + retValue_acc = __ste_Client_Keyring0_PublicKey1; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } else { + if (handle == 2) { + if (userid == __ste_Client_Keyring1_User0) { + retValue_acc = __ste_Client_Keyring1_PublicKey0; + return (retValue_acc); + } else { + if (userid == __ste_Client_Keyring1_User1) { + retValue_acc = __ste_Client_Keyring1_PublicKey1; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } else { + if (handle == 3) { + if (userid == __ste_Client_Keyring2_User0) { + retValue_acc = __ste_Client_Keyring2_PublicKey0; + return (retValue_acc); + } else { + if (userid == __ste_Client_Keyring2_User1) { + retValue_acc = __ste_Client_Keyring2_PublicKey1; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } + return (retValue_acc); + } +} +void setClientKeyringPublicKey(int handle, int index, int value) { + + { + if (handle == 1) { + if (index == 0) { + __ste_Client_Keyring0_PublicKey0 = value; + } else { + if (index == 1) { + __ste_Client_Keyring0_PublicKey1 = value; + } else { + } + } + } else { + if (handle == 2) { + if (index == 0) { + __ste_Client_Keyring1_PublicKey0 = value; + } else { + if (index == 1) { + __ste_Client_Keyring1_PublicKey1 = value; + } else { + } + } + } else { + if (handle == 3) { + if (index == 0) { + __ste_Client_Keyring2_PublicKey0 = value; + } else { + if (index == 1) { + __ste_Client_Keyring2_PublicKey1 = value; + } else { + } + } + } else { + } + } + } + return; + } +} +int __ste_client_forwardReceiver0 = 0; +int __ste_client_forwardReceiver1 = 0; +int __ste_client_forwardReceiver2 = 0; +int __ste_client_forwardReceiver3 = 0; +int getClientForwardReceiver(int handle) { + int retValue_acc; + + { + if (handle == 1) { + retValue_acc = __ste_client_forwardReceiver0; + return (retValue_acc); + } else { + if (handle == 2) { + retValue_acc = __ste_client_forwardReceiver1; + return (retValue_acc); + } else { + if (handle == 3) { + retValue_acc = __ste_client_forwardReceiver2; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } + return (retValue_acc); + } +} +void setClientForwardReceiver(int handle, int value) { + + { + if (handle == 1) { + __ste_client_forwardReceiver0 = value; + } else { + if (handle == 2) { + __ste_client_forwardReceiver1 = value; + } else { + if (handle == 3) { + __ste_client_forwardReceiver2 = value; + } else { + } + } + } + return; + } +} +int __ste_client_idCounter0 = 0; +int __ste_client_idCounter1 = 0; +int __ste_client_idCounter2 = 0; +int getClientId(int handle) { + int retValue_acc; + + { + if (handle == 1) { + retValue_acc = __ste_client_idCounter0; + return (retValue_acc); + } else { + if (handle == 2) { + retValue_acc = __ste_client_idCounter1; + return (retValue_acc); + } else { + if (handle == 3) { + retValue_acc = __ste_client_idCounter2; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + } + return (retValue_acc); + } +} +void setClientId(int handle, int value) { + + { + if (handle == 1) { + __ste_client_idCounter0 = value; + } else { + if (handle == 2) { + __ste_client_idCounter1 = value; + } else { + if (handle == 3) { + __ste_client_idCounter2 = value; + } else { + } + } + } + return; + } +} +#pragma merger(0, "EmailLib.i", "") +int initEmail(void); +void setEmailId(int handle, int value); +char *getEmailSubject(int handle); +void setEmailSubject(int handle, char *value); +char *getEmailBody(int handle); +void setEmailBody(int handle, char *value); +void setEmailIsEncrypted(int handle, int value); +void setEmailEncryptionKey(int handle, int value); +int isSigned(int handle); +void setEmailIsSigned(int handle, int value); +int getEmailSignKey(int handle); +void setEmailSignKey(int handle, int value); +int isVerified(int handle); +void setEmailIsSignatureVerified(int handle, int value); +int __ste_Email_counter = 0; +int initEmail(void) { + int retValue_acc; + + { + if (__ste_Email_counter < 2) { + __ste_Email_counter = __ste_Email_counter + 1; + retValue_acc = __ste_Email_counter; + return (retValue_acc); + } else { + retValue_acc = -1; + return (retValue_acc); + } + return (retValue_acc); + } +} +int __ste_email_id0 = 0; +int __ste_email_id1 = 0; +int getEmailId(int handle) { + int retValue_acc; + + { + if (handle == 1) { + retValue_acc = __ste_email_id0; + return (retValue_acc); + } else { + if (handle == 2) { + retValue_acc = __ste_email_id1; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + return (retValue_acc); + } +} +void setEmailId(int handle, int value) { + + { + if (handle == 1) { + __ste_email_id0 = value; + } else { + if (handle == 2) { + __ste_email_id1 = value; + } else { + } + } + return; + } +} +int __ste_email_from0 = 0; +int __ste_email_from1 = 0; +int getEmailFrom(int handle) { + int retValue_acc; + + { + if (handle == 1) { + retValue_acc = __ste_email_from0; + return (retValue_acc); + } else { + if (handle == 2) { + retValue_acc = __ste_email_from1; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + return (retValue_acc); + } +} +void setEmailFrom(int handle, int value) { + + { + if (handle == 1) { + __ste_email_from0 = value; + } else { + if (handle == 2) { + __ste_email_from1 = value; + } else { + } + } + return; + } +} +int __ste_email_to0 = 0; +int __ste_email_to1 = 0; +int getEmailTo(int handle) { + int retValue_acc; + + { + if (handle == 1) { + retValue_acc = __ste_email_to0; + return (retValue_acc); + } else { + if (handle == 2) { + retValue_acc = __ste_email_to1; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + return (retValue_acc); + } +} +void setEmailTo(int handle, int value) { + + { + if (handle == 1) { + __ste_email_to0 = value; + } else { + if (handle == 2) { + __ste_email_to1 = value; + } else { + } + } + return; + } +} +char *__ste_email_subject0; +char *__ste_email_subject1; +char *getEmailSubject(int handle) { + char *retValue_acc; + void *__cil_tmp3; + + { + if (handle == 1) { + retValue_acc = __ste_email_subject0; + return (retValue_acc); + } else { + if (handle == 2) { + retValue_acc = __ste_email_subject1; + return (retValue_acc); + } else { + __cil_tmp3 = (void *)0; + retValue_acc = (char *)__cil_tmp3; + return (retValue_acc); + } + } + return (retValue_acc); + } +} +void setEmailSubject(int handle, char *value) { + + { + if (handle == 1) { + __ste_email_subject0 = value; + } else { + if (handle == 2) { + __ste_email_subject1 = value; + } else { + } + } + return; + } +} +char *__ste_email_body0 = (char *)0; +char *__ste_email_body1 = (char *)0; +char *getEmailBody(int handle) { + char *retValue_acc; + void *__cil_tmp3; + + { + if (handle == 1) { + retValue_acc = __ste_email_body0; + return (retValue_acc); + } else { + if (handle == 2) { + retValue_acc = __ste_email_body1; + return (retValue_acc); + } else { + __cil_tmp3 = (void *)0; + retValue_acc = (char *)__cil_tmp3; + return (retValue_acc); + } + } + return (retValue_acc); + } +} +void setEmailBody(int handle, char *value) { + + { + if (handle == 1) { + __ste_email_body0 = value; + } else { + if (handle == 2) { + __ste_email_body1 = value; + } else { + } + } + return; + } +} +int __ste_email_isEncrypted0 = 0; +int __ste_email_isEncrypted1 = 0; +int isEncrypted(int handle) { + int retValue_acc; + + { + if (handle == 1) { + retValue_acc = __ste_email_isEncrypted0; + return (retValue_acc); + } else { + if (handle == 2) { + retValue_acc = __ste_email_isEncrypted1; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + return (retValue_acc); + } +} +void setEmailIsEncrypted(int handle, int value) { + + { + if (handle == 1) { + __ste_email_isEncrypted0 = value; + } else { + if (handle == 2) { + __ste_email_isEncrypted1 = value; + } else { + } + } + return; + } +} +int __ste_email_encryptionKey0 = 0; +int __ste_email_encryptionKey1 = 0; +int getEmailEncryptionKey(int handle) { + int retValue_acc; + + { + if (handle == 1) { + retValue_acc = __ste_email_encryptionKey0; + return (retValue_acc); + } else { + if (handle == 2) { + retValue_acc = __ste_email_encryptionKey1; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + return (retValue_acc); + } +} +void setEmailEncryptionKey(int handle, int value) { + + { + if (handle == 1) { + __ste_email_encryptionKey0 = value; + } else { + if (handle == 2) { + __ste_email_encryptionKey1 = value; + } else { + } + } + return; + } +} +int __ste_email_isSigned0 = 0; +int __ste_email_isSigned1 = 0; +int isSigned(int handle) { + int retValue_acc; + + { + if (handle == 1) { + retValue_acc = __ste_email_isSigned0; + return (retValue_acc); + } else { + if (handle == 2) { + retValue_acc = __ste_email_isSigned1; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + return (retValue_acc); + } +} +void setEmailIsSigned(int handle, int value) { + + { + if (handle == 1) { + __ste_email_isSigned0 = value; + } else { + if (handle == 2) { + __ste_email_isSigned1 = value; + } else { + } + } + return; + } +} +int __ste_email_signKey0 = 0; +int __ste_email_signKey1 = 0; +int getEmailSignKey(int handle) { + int retValue_acc; + + { + if (handle == 1) { + retValue_acc = __ste_email_signKey0; + return (retValue_acc); + } else { + if (handle == 2) { + retValue_acc = __ste_email_signKey1; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + return (retValue_acc); + } +} +void setEmailSignKey(int handle, int value) { + + { + if (handle == 1) { + __ste_email_signKey0 = value; + } else { + if (handle == 2) { + __ste_email_signKey1 = value; + } else { + } + } + return; + } +} +int __ste_email_isSignatureVerified0; +int __ste_email_isSignatureVerified1; +int isVerified(int handle) { + int retValue_acc; + + { + if (handle == 1) { + retValue_acc = __ste_email_isSignatureVerified0; + return (retValue_acc); + } else { + if (handle == 2) { + retValue_acc = __ste_email_isSignatureVerified1; + return (retValue_acc); + } else { + retValue_acc = 0; + return (retValue_acc); + } + } + return (retValue_acc); + } +} +void setEmailIsSignatureVerified(int handle, int value) { + + { + if (handle == 1) { + __ste_email_isSignatureVerified0 = value; + } else { + if (handle == 2) { + __ste_email_isSignatureVerified1 = value; + } else { + } + } + return; + } +} +#pragma merger(0, "DecryptForward_spec.i", "") +inline static void __utac_acc__DecryptForward_spec__1(int msg) { + int tmp; + + { + { + puts("before forward\n"); + tmp = isReadable(msg); + } + if (tmp) { + + } else { + { + __automaton_fail(); + } + } + return; + } +} +#pragma merger(0, "Util.i", "") +int prompt(char *msg); +int prompt(char *msg) { + int retValue_acc; + int retval; + char const *__restrict __cil_tmp4; + + { + { + __cil_tmp4 = (char const *__restrict)"%s\n"; + printf(__cil_tmp4, msg); + retValue_acc = retval; + } + return (retValue_acc); + return (retValue_acc); + } +} +#pragma merger(0, "Client.i", "") +void queue(int client, int msg); +void mail(int client, int msg); +void deliver(int client, int msg); +void incoming(int client, int msg); +int createClient(char *name); +int isKeyPairValid(int publicKey, int privateKey); +void forward(int client, int msg); +int queue_empty = 1; +int queued_message; +int queued_client; +void mail(int client, int msg) { + int tmp; + + { + { + puts("mail sent"); + tmp = getEmailTo(msg); + incoming(tmp, msg); + } + return; + } +} +void outgoing__wrappee__Keys(int client, int msg) { + int tmp; + + { + { + tmp = getClientId(client); + setEmailFrom(msg, tmp); + mail(client, msg); + } + return; + } +} +void outgoing(int client, int msg) { + int receiver; + int tmp; + int pubkey; + int tmp___0; + + { + { + tmp = getEmailTo(msg); + receiver = tmp; + tmp___0 = findPublicKey(client, receiver); + pubkey = tmp___0; + } + if (pubkey) { + { + setEmailEncryptionKey(msg, pubkey); + setEmailIsEncrypted(msg, 1); + } + } else { + } + { + outgoing__wrappee__Keys(client, msg); + } + return; + } +} +void deliver(int client, int msg) { + + { + { + puts("mail delivered\n"); + } + return; + } +} +void incoming__wrappee__Encrypt(int client, int msg) { + + { + { + deliver(client, msg); + } + return; + } +} +void incoming__wrappee__Forward(int client, int msg) { + int fwreceiver; + int tmp; + + { + { + incoming__wrappee__Encrypt(client, msg); + tmp = getClientForwardReceiver(client); + fwreceiver = tmp; + } + if (fwreceiver) { + { + setEmailTo(msg, fwreceiver); + forward(client, msg); + } + } else { + } + return; + } +} +void incoming(int client, int msg) { + int privkey; + int tmp; + int tmp___0; + int tmp___1; + int tmp___2; + + { + { + tmp = getClientPrivateKey(client); + privkey = tmp; + } + if (privkey) { + { + tmp___0 = isEncrypted(msg); + } + if (tmp___0) { + { + tmp___1 = getEmailEncryptionKey(msg); + tmp___2 = isKeyPairValid(tmp___1, privkey); + } + if (tmp___2) { + { + setEmailIsEncrypted(msg, 0); + setEmailEncryptionKey(msg, 0); + } + } else { + } + } else { + } + } else { + } + { + incoming__wrappee__Forward(client, msg); + } + return; + } +} +int createClient(char *name) { + int retValue_acc; + int client; + int tmp; + + { + { + tmp = initClient(); + client = tmp; + retValue_acc = client; + } + return (retValue_acc); + return (retValue_acc); + } +} +void sendEmail(int sender, int receiver) { + int email; + int tmp; + + { + { + tmp = createEmail(0, receiver); + email = tmp; + outgoing(sender, email); + } + return; + } +} +void queue(int client, int msg) { + + { + queue_empty = 0; + queued_message = msg; + queued_client = client; + return; + } +} +int is_queue_empty(void) { + int retValue_acc; + + { + retValue_acc = queue_empty; + return (retValue_acc); + return (retValue_acc); + } +} +int get_queued_client(void) { + int retValue_acc; + + { + retValue_acc = queued_client; + return (retValue_acc); + return (retValue_acc); + } +} +int get_queued_email(void) { + int retValue_acc; + + { + retValue_acc = queued_message; + return (retValue_acc); + return (retValue_acc); + } +} +int isKeyPairValid(int publicKey, int privateKey) { + int retValue_acc; + char const *__restrict __cil_tmp4; + + { + { + __cil_tmp4 = (char const *__restrict)"keypair valid %d %d"; + printf(__cil_tmp4, publicKey, privateKey); + } + if (!publicKey) { + retValue_acc = 0; + return (retValue_acc); + } else { + if (!privateKey) { + retValue_acc = 0; + return (retValue_acc); + } else { + } + } + retValue_acc = privateKey == publicKey; + return (retValue_acc); + return (retValue_acc); + } +} +void generateKeyPair(int client, int seed) { + + { + { + setClientPrivateKey(client, seed); + } + return; + } +} +void forward(int client, int msg) { + int __utac__ad__arg1; + + { + { + __utac__ad__arg1 = msg; + __utac_acc__DecryptForward_spec__1(__utac__ad__arg1); + puts("Forwarding message.\n"); + printMail(msg); + queue(client, msg); + } + return; + } +} diff --git a/tools/klee/main.cpp b/tools/klee/main.cpp index e3e87da330..364254f278 100644 --- a/tools/klee/main.cpp +++ b/tools/klee/main.cpp @@ -15,7 +15,7 @@ #include "klee/Core/Context.h" #include "klee/Core/Interpreter.h" #include "klee/Core/TargetedExecutionReporter.h" -#include "klee/Expr/Expr.h" +#include "klee/Module/LocationInfo.h" #include "klee/Module/SarifReport.h" #include "klee/Module/TargetForest.h" #include "klee/Solver/SolverCmdLine.h" @@ -34,9 +34,7 @@ DISABLE_WARNING_DEPRECATED_DECLARATIONS #include "llvm/Bitcode/BitcodeReader.h" #include "llvm/IR/Constants.h" #include "llvm/IR/IRBuilder.h" -#include "llvm/IR/InstrTypes.h" #include "llvm/IR/Instruction.h" -#include "llvm/IR/Instructions.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Type.h" #include "llvm/Support/CommandLine.h" @@ -52,8 +50,8 @@ DISABLE_WARNING_DEPRECATED_DECLARATIONS #include "llvm/Support/TargetSelect.h" DISABLE_WARNING_POP +#include #include -#include #include #include #include @@ -64,6 +62,7 @@ DISABLE_WARNING_POP #include #include #include +#include #include using json = nlohmann::json; @@ -678,13 +677,13 @@ void KleeHandler::processTestCase(const ExecutionState &state, } if (WriteCov) { - std::map> cov; + std::map> cov; m_interpreter->getCoveredLines(state, cov); auto f = openTestFile("cov", id); if (f) { for (const auto &entry : cov) { for (const auto &line : entry.second) { - *f << *entry.first << ':' << line << '\n'; + *f << entry.first << ':' << line << '\n'; } } } @@ -1691,13 +1690,19 @@ int main(int argc, char **argv, char **envp) { } llvm::Module *mainModule = loadedUserModules.front().get(); - std::unique_ptr origInfos; - std::unique_ptr assemblyFS; + FLCtoOpcode origInstructions; if (UseGuidedSearch == Interpreter::GuidanceKind::ErrorGuidance) { + for (const auto &Func : *mainModule) { + for (const auto &instr : llvm::instructions(Func)) { + auto locationInfo = getLocationInfo(&instr); + origInstructions[locationInfo.file][locationInfo.line] + [locationInfo.column] + .insert(instr.getOpcode()); + } + } + std::vector args; - origInfos = std::make_unique( - *mainModule, std::move(assemblyFS), true); args.push_back(llvm::Type::getInt32Ty(ctx)); // argc args.push_back(llvm::PointerType::get( Type::getInt8PtrTy(ctx), @@ -1716,15 +1721,16 @@ int main(int argc, char **argv, char **envp) { EntryPoint = stubEntryPoint; } - std::unordered_set mainModuleFunctions; + std::set mainModuleFunctions; for (auto &Function : *mainModule) { if (!Function.isDeclaration()) { mainModuleFunctions.insert(Function.getName().str()); } } - std::unordered_set mainModuleGlobals; - for (const auto &gv : mainModule->globals()) + std::set mainModuleGlobals; + for (const auto &gv : mainModule->globals()) { mainModuleGlobals.insert(gv.getName().str()); + } const std::string &module_triple = mainModule->getTargetTriple(); std::string host_triple = llvm::sys::getDefaultTargetTriple(); @@ -1962,8 +1968,9 @@ int main(int argc, char **argv, char **envp) { // locale and other data and then calls main. auto finalModule = interpreter->setModule( - loadedUserModules, loadedLibsModules, Opts, mainModuleFunctions, - mainModuleGlobals, std::move(origInfos)); + loadedUserModules, loadedLibsModules, Opts, + std::move(mainModuleFunctions), std::move(mainModuleGlobals), + std::move(origInstructions)); externalsAndGlobalsCheck(finalModule); if (InteractiveMode) { From 90e8cbf417e5b0521f35379e71d4f4dbf67620a5 Mon Sep 17 00:00:00 2001 From: Yurii Kostyukov Date: Wed, 4 Oct 2023 13:59:21 +0300 Subject: [PATCH 029/103] [feat] uint128 --- include/klee-test-comp.c | 6 ++++++ test/Feature/uint128.c | 11 +++++++++++ 2 files changed, 17 insertions(+) create mode 100644 test/Feature/uint128.c diff --git a/include/klee-test-comp.c b/include/klee-test-comp.c index ecda66ba02..bad3b783d0 100644 --- a/include/klee-test-comp.c +++ b/include/klee-test-comp.c @@ -33,6 +33,12 @@ unsigned int __VERIFIER_nondet_uint(void) { return x; } +unsigned __int128 __VERIFIER_nondet_uint128(void) { + unsigned __int128 x; + klee_make_symbolic(&x, sizeof(x), "unsigned __int128"); + return x; +} + unsigned __VERIFIER_nondet_unsigned(void) { unsigned x; klee_make_symbolic(&x, sizeof(x), "unsigned"); diff --git a/test/Feature/uint128.c b/test/Feature/uint128.c new file mode 100644 index 0000000000..efa5915beb --- /dev/null +++ b/test/Feature/uint128.c @@ -0,0 +1,11 @@ +// RUN: %clang %s -emit-llvm %O0opt -c -g -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out %t1.bc 2>&1 | FileCheck %s +// CHECK-NOT: failed external call +#include "klee-test-comp.c" +extern unsigned __int128 __VERIFIER_nondet_uint128(); + +int main() { + __int128 x = __VERIFIER_nondet_uint128(); + return x > 0; +} From 27b6ed17f27256c9f381124d40c5f09f382796bb Mon Sep 17 00:00:00 2001 From: Yurii Kostyukov Date: Thu, 5 Oct 2023 14:38:54 +0300 Subject: [PATCH 030/103] [chore] Optimized KBlock mem --- include/klee/Module/KModule.h | 5 ++--- lib/Core/Searcher.cpp | 2 +- lib/Core/TypeManager.cpp | 13 +++---------- lib/Module/KModule.cpp | 5 ++--- lib/Module/SarifReport.cpp | 2 +- 5 files changed, 9 insertions(+), 18 deletions(-) diff --git a/include/klee/Module/KModule.h b/include/klee/Module/KModule.h index 4965f78b27..50949908b6 100644 --- a/include/klee/Module/KModule.h +++ b/include/klee/Module/KModule.h @@ -60,8 +60,6 @@ enum KBlockType { Base, Call, Return }; struct KBlock { KFunction *parent; llvm::BasicBlock *basicBlock; - - unsigned numInstructions; KInstruction **instructions; public: @@ -76,9 +74,10 @@ struct KBlock { virtual KBlockType getKBlockType() const { return KBlockType::Base; } static bool classof(const KBlock *) { return true; } + unsigned getNumInstructions() const noexcept { return basicBlock->size(); } KInstruction *getFirstInstruction() const noexcept { return instructions[0]; } KInstruction *getLastInstruction() const noexcept { - return instructions[numInstructions - 1]; + return instructions[getNumInstructions() - 1]; } std::string getLabel() const; std::string toString() const; diff --git a/lib/Core/Searcher.cpp b/lib/Core/Searcher.cpp index 08e725eacb..644d5904a0 100644 --- a/lib/Core/Searcher.cpp +++ b/lib/Core/Searcher.cpp @@ -189,7 +189,7 @@ weight_type TargetedSearcher::getWeight(ExecutionState *es) { KBlock *kb = es->pc->parent; KInstruction *ki = es->pc; weight_type weight; - if (!target->shouldFailOnThisTarget() && kb->numInstructions && + if (!target->shouldFailOnThisTarget() && kb->getNumInstructions() && !isa(kb) && kb->getFirstInstruction() != ki && states->tryGetWeight(es, weight)) { return weight; diff --git a/lib/Core/TypeManager.cpp b/lib/Core/TypeManager.cpp index c6e00f2f82..0ba8f8ffb1 100644 --- a/lib/Core/TypeManager.cpp +++ b/lib/Core/TypeManager.cpp @@ -141,20 +141,13 @@ void TypeManager::initTypesFromGlobals() { */ void TypeManager::initTypesFromInstructions() { for (auto &function : *(parent->module)) { - auto kf = parent->functionMap[&function]; - for (auto &BasicBlock : function) { - unsigned numInstructions = kf->blockMap[&BasicBlock]->numInstructions; - KBlock *kb = kf->blockMap[&BasicBlock]; - - for (unsigned i = 0; i < numInstructions; ++i) { - llvm::Instruction *inst = kb->instructions[i]->inst; - + for (auto &inst : BasicBlock) { /* Register return type */ - getWrappedType(inst->getType()); + getWrappedType(inst.getType()); /* Register types for arguments */ - for (auto opb = inst->op_begin(), ope = inst->op_end(); opb != ope; + for (auto opb = inst.op_begin(), ope = inst.op_end(); opb != ope; ++opb) { getWrappedType((*opb)->getType()); } diff --git a/lib/Module/KModule.cpp b/lib/Module/KModule.cpp index 7bfb8433f3..946fd2f087 100644 --- a/lib/Module/KModule.cpp +++ b/lib/Module/KModule.cpp @@ -606,7 +606,7 @@ KFunction::KFunction(llvm::Function *_function, KModule *_km, kb = new KBlock(this, &*bbit, parent, instructionToRegisterMap, &instructions[n], globalIndexInc); } - for (unsigned i = 0; i < kb->numInstructions; i++, n++) { + for (unsigned i = 0, ie = kb->getNumInstructions(); i < ie; i++, n++) { instructionMap[instructions[n]->inst] = instructions[n]; } blockMap[&*bbit] = kb; @@ -639,8 +639,7 @@ KBlock::KBlock( KFunction *_kfunction, llvm::BasicBlock *block, KModule *km, const std::unordered_map &instructionToRegisterMap, KInstruction **instructionsKF, unsigned &globalIndexInc) - : parent(_kfunction), basicBlock(block), numInstructions(0) { - numInstructions += block->size(); + : parent(_kfunction), basicBlock(block) { instructions = instructionsKF; for (auto &it : *block) { diff --git a/lib/Module/SarifReport.cpp b/lib/Module/SarifReport.cpp index 3923d32ead..6cc323a87a 100644 --- a/lib/Module/SarifReport.cpp +++ b/lib/Module/SarifReport.cpp @@ -333,7 +333,7 @@ bool Location::isInside(KBlock *block, const Instructions &origInsts) const { return false; return startLine <= last->getLine(); // and `first <= line` from above } else { - for (size_t i = 0; i < block->numInstructions; ++i) { + for (unsigned i = 0, ie = block->getNumInstructions(); i < ie; ++i) { auto inst = block->instructions[i]; auto opCode = block->instructions[i]->inst->getOpcode(); if (!isa(block->instructions[i]->inst) && From 2dc5efad3028e9bdc33ea705433ccc0abd75aa6f Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Thu, 5 Oct 2023 18:03:24 +0400 Subject: [PATCH 031/103] [fix] Error testcase processing doesn't affect `coveredNew` --- lib/Core/ExecutionState.cpp | 15 ++++++--------- lib/Core/ExecutionState.h | 19 ++++++++++++++++++- lib/Core/Executor.cpp | 29 ++++++++++++++++------------- lib/Core/TargetCalculator.cpp | 30 ++++++++++++++++++++++++++---- lib/Core/TargetCalculator.h | 8 +++++++- 5 files changed, 73 insertions(+), 28 deletions(-) diff --git a/lib/Core/ExecutionState.cpp b/lib/Core/ExecutionState.cpp index 05142dd2c4..e1b4cde6f8 100644 --- a/lib/Core/ExecutionState.cpp +++ b/lib/Core/ExecutionState.cpp @@ -120,9 +120,8 @@ ExecutionState::ExecutionState() : initPC(nullptr), pc(nullptr), prevPC(nullptr), incomingBBIndex(-1), depth(0), ptreeNode(nullptr), symbolics(), steppedInstructions(0), steppedMemoryInstructions(0), instsSinceCovNew(0), - roundingMode(llvm::APFloat::rmNearestTiesToEven), - coveredNew(new box(false)), forkDisabled(false), - prevHistory_(TargetsHistory::create()), + roundingMode(llvm::APFloat::rmNearestTiesToEven), coveredNew({}), + forkDisabled(false), prevHistory_(TargetsHistory::create()), history_(TargetsHistory::create()) { setID(); } @@ -131,9 +130,8 @@ ExecutionState::ExecutionState(KFunction *kf) : initPC(kf->instructions), pc(initPC), prevPC(pc), incomingBBIndex(-1), depth(0), ptreeNode(nullptr), symbolics(), steppedInstructions(0), steppedMemoryInstructions(0), instsSinceCovNew(0), - roundingMode(llvm::APFloat::rmNearestTiesToEven), - coveredNew(new box(false)), forkDisabled(false), - prevHistory_(TargetsHistory::create()), + roundingMode(llvm::APFloat::rmNearestTiesToEven), coveredNew({}), + forkDisabled(false), prevHistory_(TargetsHistory::create()), history_(TargetsHistory::create()) { pushFrame(nullptr, kf); setID(); @@ -143,9 +141,8 @@ ExecutionState::ExecutionState(KFunction *kf, KBlock *kb) : initPC(kb->instructions), pc(initPC), prevPC(pc), incomingBBIndex(-1), depth(0), ptreeNode(nullptr), symbolics(), steppedInstructions(0), steppedMemoryInstructions(0), instsSinceCovNew(0), - roundingMode(llvm::APFloat::rmNearestTiesToEven), - coveredNew(new box(false)), forkDisabled(false), - prevHistory_(TargetsHistory::create()), + roundingMode(llvm::APFloat::rmNearestTiesToEven), coveredNew({}), + forkDisabled(false), prevHistory_(TargetsHistory::create()), history_(TargetsHistory::create()) { pushFrame(nullptr, kf); setID(); diff --git a/lib/Core/ExecutionState.h b/lib/Core/ExecutionState.h index a0aa46619a..f8cc093489 100644 --- a/lib/Core/ExecutionState.h +++ b/lib/Core/ExecutionState.h @@ -36,6 +36,7 @@ DISABLE_WARNING_DEPRECATED_DECLARATIONS #include "llvm/IR/Function.h" DISABLE_WARNING_POP +#include #include #include #include @@ -364,7 +365,7 @@ class ExecutionState { std::uint32_t id = 0; /// @brief Whether a new instruction was covered in this state - mutable ref> coveredNew; + mutable std::deque>> coveredNew; /// @brief Disables forking for this state. Set by user code bool forkDisabled = false; @@ -502,6 +503,22 @@ class ExecutionState { } return false; } + + bool isCoveredNew() const { + return !coveredNew.empty() && coveredNew.back()->value; + } + void coverNew() const { coveredNew.push_back(new box(true)); } + void updateCoveredNew() const { + while (!coveredNew.empty() && !coveredNew.front()->value) { + coveredNew.pop_front(); + } + } + void clearCoveredNew() const { + for (auto signal : coveredNew) { + signal->value = false; + } + coveredNew.clear(); + } }; struct ExecutionStateIDCompare { diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index c58e1a51ac..e3c8cce344 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -3953,6 +3953,10 @@ void Executor::updateStates(ExecutionState *current) { targetedExecutionManager->update(current, addedStates, removedStates); } + if (targetCalculator) { + targetCalculator->update(current, addedStates, removedStates); + } + if (searcher) { searcher->update(current, addedStates, removedStates); } @@ -4084,7 +4088,7 @@ bool Executor::checkMemoryUsage() { unsigned idx = theRNG.getInt32() % N; // Make two pulls to try and not hit a state that // covered new code. - if (arr[idx]->coveredNew->value) + if (arr[idx]->isCoveredNew()) idx = theRNG.getInt32() % N; std::swap(arr[idx], arr[N - 1]); @@ -4294,11 +4298,6 @@ void Executor::run(std::vector initialStates) { KInstruction *prevKI = state.prevPC; KFunction *kf = prevKI->parent->parent; - if (prevKI->inst->isTerminator() && - kmodule->inMainModule(*kf->function)) { - targetCalculator->update(state); - } - executeStep(state); } @@ -4357,8 +4356,8 @@ void Executor::initializeTypeManager() { } static bool shouldWriteTest(const ExecutionState &state) { - bool coveredNew = state.coveredNew->value; - state.coveredNew->value = false; + state.updateCoveredNew(); + bool coveredNew = state.isCoveredNew(); return !OnlyOutputStatesCoveringNew || coveredNew; } @@ -4380,6 +4379,7 @@ void Executor::executeStep(ExecutionState &state) { if (CoverOnTheFly && guidanceKind != GuidanceKind::ErrorGuidance && stats::instructions > DelayCoverOnTheFly && shouldWriteTest(state)) { + state.clearCoveredNew(); interpreterHandler->processTestCase( state, nullptr, terminationTypeFileExtension(StateTerminationType::CoverOnTheFly) @@ -4565,7 +4565,6 @@ void Executor::terminateState(ExecutionState &state, interpreterHandler->incPathsExplored(); state.pc = state.prevPC; - targetCalculator->update(state); solver->notifyStateTermination(state.id); removedStates.push_back(&state); @@ -4574,9 +4573,11 @@ void Executor::terminateState(ExecutionState &state, void Executor::terminateStateOnExit(ExecutionState &state) { auto terminationType = StateTerminationType::Exit; ++stats::terminationExit; - if (shouldWriteTest(state) || (AlwaysOutputSeeds && seedMap.count(&state))) + if (shouldWriteTest(state) || (AlwaysOutputSeeds && seedMap.count(&state))) { + state.clearCoveredNew(); interpreterHandler->processTestCase( state, nullptr, terminationTypeFileExtension(terminationType).c_str()); + } interpreterHandler->incPathsCompleted(); terminateState(state, terminationType); @@ -4593,6 +4594,7 @@ void Executor::terminateStateEarly(ExecutionState &state, const Twine &message, reason == StateTerminationType::MissedAllTargets) && shouldWriteTest(state)) || (AlwaysOutputSeeds && seedMap.count(&state))) { + state.clearCoveredNew(); interpreterHandler->processTestCase( state, (message + "\n").str().c_str(), terminationTypeFileExtension(reason).c_str(), @@ -4717,8 +4719,9 @@ void Executor::terminateStateOnError(ExecutionState &state, const KInstruction *ki = getLastNonKleeInternalInstruction(state); Instruction *lastInst = ki->inst; - if (EmitAllErrors || - emittedErrors.insert(std::make_pair(lastInst, message)).second) { + if ((EmitAllErrors || + emittedErrors.insert(std::make_pair(lastInst, message)).second) && + shouldWriteTest(state)) { std::string filepath = ki->getSourceFilepath(); if (!filepath.empty()) { klee_message("ERROR: %s:%zu: %s", filepath.c_str(), ki->getLine(), @@ -7375,7 +7378,7 @@ void Executor::dumpStates() { *os << "{"; *os << "'depth' : " << es->depth << ", "; *os << "'queryCost' : " << es->queryMetaData.queryCost << ", "; - *os << "'coveredNew' : " << es->coveredNew->value << ", "; + *os << "'coveredNew' : " << es->isCoveredNew() << ", "; *os << "'instsSinceCovNew' : " << es->instsSinceCovNew << ", "; *os << "'md2u' : " << md2u << ", "; *os << "'icnt' : " << icnt << ", "; diff --git a/lib/Core/TargetCalculator.cpp b/lib/Core/TargetCalculator.cpp index 0c5d72fedb..e6a8f8834c 100644 --- a/lib/Core/TargetCalculator.cpp +++ b/lib/Core/TargetCalculator.cpp @@ -51,8 +51,7 @@ void TargetCalculator::update(const ExecutionState &state) { unsigned index = 0; if (!coveredBranches[state.prevPC->parent->parent].count( state.prevPC->parent)) { - state.coveredNew->value = false; - state.coveredNew = new box(true); + state.coverNew(); coveredBranches[state.prevPC->parent->parent][state.prevPC->parent]; } for (auto succ : successors(state.getPrevPCBlock())) { @@ -60,8 +59,7 @@ void TargetCalculator::update(const ExecutionState &state) { if (!coveredBranches[state.prevPC->parent->parent] [state.prevPC->parent] .count(index)) { - state.coveredNew->value = false; - state.coveredNew = new box(true); + state.coverNew(); coveredBranches[state.prevPC->parent->parent][state.prevPC->parent] .insert(index); } @@ -129,6 +127,30 @@ void TargetCalculator::update(const ExecutionState &state) { } } +void TargetCalculator::update( + ExecutionState *current, const std::vector &addedStates, + const std::vector &removedStates) { + if (current && (std::find(removedStates.begin(), removedStates.end(), + current) == removedStates.end())) { + localStates.insert(current); + } + for (const auto state : addedStates) { + localStates.insert(state); + } + for (const auto state : removedStates) { + localStates.insert(state); + } + for (auto state : localStates) { + KFunction *kf = state->prevPC->parent->parent; + KModule *km = kf->parent; + if (state->prevPC->inst->isTerminator() && + km->inMainModule(*kf->function)) { + update(*state); + } + } + localStates.clear(); +} + bool TargetCalculator::differenceIsEmpty( const ExecutionState &state, const std::unordered_map &history, diff --git a/lib/Core/TargetCalculator.h b/lib/Core/TargetCalculator.h index ba78a89f20..75bd8413d8 100644 --- a/lib/Core/TargetCalculator.h +++ b/lib/Core/TargetCalculator.h @@ -42,6 +42,8 @@ typedef std::pair Transition; typedef std::pair Branch; class TargetCalculator { + using StatesSet = std::unordered_set; + typedef std::unordered_set VisitedBlocks; typedef std::unordered_set VisitedTransitions; typedef std::unordered_set VisitedBranches; @@ -63,12 +65,15 @@ class TargetCalculator { typedef std::unordered_set CoveredFunctionsBranches; typedef std::unordered_map CoveredBlocks; + void update(const ExecutionState &state); public: TargetCalculator(CodeGraphInfo &codeGraphInfo) : codeGraphInfo(codeGraphInfo) {} - void update(const ExecutionState &state); + void update(ExecutionState *current, + const std::vector &addedStates, + const std::vector &removedStates); TargetHashSet calculate(ExecutionState &state); @@ -80,6 +85,7 @@ class TargetCalculator { CoveredFunctionsBranches coveredFunctionsInBranches; CoveredFunctionsBranches fullyCoveredFunctions; CoveredBlocks coveredBlocks; + StatesSet localStates; bool differenceIsEmpty( const ExecutionState &state, From 16155cdeca65810413d9f08b7d956b8775f0061e Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Thu, 5 Oct 2023 18:18:07 +0400 Subject: [PATCH 032/103] [fix] Fix `computeValidity` in partial response case --- lib/Solver/CachingSolver.cpp | 110 +++++--------------------------- lib/Solver/CexCachingSolver.cpp | 43 +++++++++---- lib/Solver/SolverImpl.cpp | 38 +++++++---- test/Feature/SolverTimeout.c | 4 +- test/Solver/DummySolver.c | 2 +- 5 files changed, 78 insertions(+), 119 deletions(-) diff --git a/lib/Solver/CachingSolver.cpp b/lib/Solver/CachingSolver.cpp index 0bf904a60a..75dbe1dfec 100644 --- a/lib/Solver/CachingSolver.cpp +++ b/lib/Solver/CachingSolver.cpp @@ -187,30 +187,36 @@ bool CachingSolver::computeValidity(const Query &query, return true; case PValidity::MayBeTrue: { ++stats::queryCacheMisses; - if (!solver->impl->computeTruth(query, tmp)) - return false; - if (tmp) { + bool success = solver->impl->computeTruth(query, tmp); + if (success && tmp) { cacheInsert(query, PValidity::MustBeTrue); result = PValidity::MustBeTrue; return true; - } else { + } else if (success && !tmp) { cacheInsert(query, PValidity::TrueOrFalse); result = PValidity::TrueOrFalse; return true; + } else { + cacheInsert(query, PValidity::MayBeTrue); + result = PValidity::MayBeTrue; + return true; } } case PValidity::MayBeFalse: { ++stats::queryCacheMisses; - if (!solver->impl->computeTruth(query.negateExpr(), tmp)) - return false; - if (tmp) { + bool success = solver->impl->computeTruth(query.negateExpr(), tmp); + if (success && tmp) { cacheInsert(query, PValidity::MustBeFalse); result = PValidity::MustBeFalse; return true; - } else { + } else if (success && !tmp) { cacheInsert(query, PValidity::TrueOrFalse); result = PValidity::TrueOrFalse; return true; + } else { + cacheInsert(query, PValidity::MayBeFalse); + result = PValidity::MayBeFalse; + return true; } } default: @@ -267,50 +273,8 @@ bool CachingSolver::computeTruth(const Query &query, bool &isValid) { bool CachingSolver::computeValidityCore(const Query &query, ValidityCore &validityCore, bool &isValid) { - PartialValidity cachedResult; - bool tmp, cacheHit = cacheLookup(query, cachedResult); - - // a cached result of MayBeTrue forces us to check whether - // a False assignment exists. - if (cacheHit && cachedResult != PValidity::MayBeTrue) { - ValidityCore cachedValidityCore; - cacheHit = validityCoreCacheLookup(query, cachedValidityCore); - if (cacheHit && cachedResult == PValidity::MustBeTrue) { - ++stats::queryCacheHits; - validityCore = cachedValidityCore; - } else if (cachedResult == PValidity::MustBeTrue) { - ++stats::queryCacheMisses; - if (!solver->impl->computeValidityCore(query, validityCore, tmp)) - return false; - assert(tmp && "Query must be true!"); - validityCoreCacheInsert(query, validityCore); - } else { - ++stats::queryCacheHits; - } - isValid = (cachedResult == PValidity::MustBeTrue); - return true; - } - ++stats::queryCacheMisses; - - // cache miss: query solver - if (!solver->impl->computeValidityCore(query, validityCore, isValid)) - return false; - - if (isValid) { - cachedResult = PValidity::MustBeTrue; - validityCoreCacheInsert(query, validityCore); - } else if (cacheHit) { - // We know a true assignment exists, and query isn't valid, so - // must be TrueOrFalse. - assert(cachedResult == PValidity::MayBeTrue); - cachedResult = PValidity::TrueOrFalse; - } else { - cachedResult = PValidity::MayBeFalse; - } - - cacheInsert(query, cachedResult); - return true; + return solver->impl->computeValidityCore(query, validityCore, isValid); } bool CachingSolver::computeInitialValues( @@ -322,50 +286,8 @@ bool CachingSolver::computeInitialValues( } bool CachingSolver::check(const Query &query, ref &result) { - PartialValidity cachedResult; - bool tmp, cacheHit = cacheLookup(query, cachedResult); - - // a cached result of MayBeTrue forces us to check whether - // a False assignment exists. - if (cacheHit && cachedResult != PValidity::MayBeTrue) { - ValidityCore cachedValidityCore; - cacheHit = validityCoreCacheLookup(query, cachedValidityCore); - if (cacheHit && cachedResult == PValidity::MustBeTrue) { - ++stats::queryCacheHits; - result = new ValidResponse(cachedValidityCore); - } else if (cachedResult == PValidity::MustBeTrue) { - ++stats::queryCacheMisses; - if (!solver->impl->computeValidityCore(query, cachedValidityCore, tmp)) - return false; - result = new ValidResponse(cachedValidityCore); - assert(tmp && "Query must be true!"); - } else { - ++stats::queryCacheMisses; - if (!solver->impl->check(query, result)) - return false; - } - return true; - } - ++stats::queryCacheMisses; - - // cache miss: query solver - if (!solver->impl->check(query, result)) - return false; - - if (isa(result)) { - cachedResult = PValidity::MustBeTrue; - } else if (cacheHit) { - // We know a true assignment exists, and query isn't valid, so - // must be TrueOrFalse. - assert(cachedResult == PValidity::MayBeTrue); - cachedResult = PValidity::TrueOrFalse; - } else { - cachedResult = PValidity::MayBeFalse; - } - - cacheInsert(query, cachedResult); - return true; + return solver->impl->check(query, result); } SolverImpl::SolverRunStatus CachingSolver::getOperationStatusCode() { diff --git a/lib/Solver/CexCachingSolver.cpp b/lib/Solver/CexCachingSolver.cpp index 92a209e4f9..98a9f58149 100644 --- a/lib/Solver/CexCachingSolver.cpp +++ b/lib/Solver/CexCachingSolver.cpp @@ -180,13 +180,25 @@ bool CexCachingSolver::searchForResponse(KeyType &key, return true; } + KeyType booleanKey; + KeyType nonBooleanKey; + for (auto i : key) { + if (i->getWidth() == Expr::Bool) { + booleanKey.insert(i); + } else { + nonBooleanKey.insert(i); + } + } + // Otherwise, iterate through the set of current solver responses to see if // one of them satisfies the query. for (responseTable_ty::iterator it = responseTable.begin(), ie = responseTable.end(); it != ie; ++it) { ref a = *it; - if (isa(a) && cast(a)->satisfies(key)) { + if (isa(a) && + cast(a)->satisfies(booleanKey) && + cast(a)->satisfiesNonBoolean(nonBooleanKey)) { result = a; return true; } @@ -270,12 +282,23 @@ bool CexCachingSolver::getResponse(const Query &query, result = *res.first; } - if (DebugCexCacheCheckBinding) - if (!cast(result)->satisfies(key)) { + if (DebugCexCacheCheckBinding) { + KeyType booleanKey; + KeyType nonBooleanKey; + for (auto i : key) { + if (i->getWidth() == Expr::Bool) { + booleanKey.insert(i); + } else { + nonBooleanKey.insert(i); + } + } + if (!cast(result)->satisfies(booleanKey) || + !cast(result)->satisfiesNonBoolean(nonBooleanKey)) { query.dump(); result->dump(); klee_error("Generated assignment doesn't match query"); } + } } ValidityCore resultCore; @@ -307,21 +330,19 @@ bool CexCachingSolver::computeValidity(const Query &query, return false; if (cast(q)->isTrue()) { - if (!getResponse(query, a)) - return false; - if (isa(a)) { + bool success = getResponse(query, a); + if (success && isa(a)) { result = PValidity::MustBeTrue; - } else if (isa(a)) { + } else if (success && isa(a)) { result = PValidity::TrueOrFalse; } else { result = PValidity::MayBeTrue; } } else { - if (!getResponse(query.negateExpr(), a)) - return false; - if (isa(a)) { + bool success = getResponse(query.negateExpr(), a); + if (success && isa(a)) { result = PValidity::MustBeFalse; - } else if (isa(a)) { + } else if (success && isa(a)) { result = PValidity::TrueOrFalse; } else { result = PValidity::MayBeFalse; diff --git a/lib/Solver/SolverImpl.cpp b/lib/Solver/SolverImpl.cpp index 2768ce3ce9..e1d3ab3513 100644 --- a/lib/Solver/SolverImpl.cpp +++ b/lib/Solver/SolverImpl.cpp @@ -18,27 +18,41 @@ using namespace klee; SolverImpl::~SolverImpl() {} bool SolverImpl::computeValidity(const Query &query, PartialValidity &result) { + bool trueSuccess, falseSuccess; bool isTrue, isFalse; - if (!computeTruth(query, isTrue)) - return false; - if (isTrue) { + trueSuccess = computeTruth(query, isTrue); + if (trueSuccess && isTrue) { result = PValidity::MustBeTrue; } else { - if (!computeTruth(query.negateExpr(), isFalse)) - return false; - result = isFalse ? PValidity::MustBeFalse : PValidity::TrueOrFalse; + falseSuccess = computeTruth(query.negateExpr(), isFalse); + if (falseSuccess && isFalse) { + result = PValidity::MustBeFalse; + } else { + if (trueSuccess && falseSuccess) { + result = PValidity::TrueOrFalse; + } else if (!trueSuccess) { + result = PValidity::MayBeTrue; + } else if (!falseSuccess) { + result = PValidity::MayBeFalse; + } else { + result = PValidity::None; + } + } } - return true; + return result != PValidity::None; } bool SolverImpl::computeValidity(const Query &query, ref &queryResult, ref &negatedQueryResult) { - if (!check(query, queryResult)) - return false; - if (!check(query.negateExpr(), negatedQueryResult)) - return false; - return true; + if (!check(query, queryResult)) { + queryResult = new UnknownResponse(); + } + if (!check(query.negateExpr(), negatedQueryResult)) { + negatedQueryResult = new UnknownResponse(); + } + return !isa(queryResult) || + !isa(negatedQueryResult); } bool SolverImpl::check(const Query &query, ref &result) { diff --git a/test/Feature/SolverTimeout.c b/test/Feature/SolverTimeout.c index af449cebd0..41049f5b34 100644 --- a/test/Feature/SolverTimeout.c +++ b/test/Feature/SolverTimeout.c @@ -1,6 +1,6 @@ // RUN: %clang %s -emit-llvm %O0opt -c -o %t.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --max-solver-time=1 %t.bc +// RUN: %klee --output-dir=%t.klee-out --max-solver-time=1 %t.bc 2>&1 | FileCheck %s // // Note: This test occasionally fails when using Z3 4.4.1 @@ -11,6 +11,8 @@ int main() { klee_make_symbolic(&x, sizeof(x), "x"); + // CHECK-NOT: Yes + // CHECK: No if (x * x * x * x * x * x * x * x * x * x * x * x * x * x * x * x + (x * x % (x + 12)) == y * y * y * y * y * y * y * y * y * y * y * y * y * y * y * y % i) printf("Yes\n"); else diff --git a/test/Solver/DummySolver.c b/test/Solver/DummySolver.c index 9242396854..54d94b5b2c 100644 --- a/test/Solver/DummySolver.c +++ b/test/Solver/DummySolver.c @@ -1,6 +1,6 @@ // RUN: %clang %s -emit-llvm %O0opt -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --search=bfs --solver-backend=dummy --use-guided-search=none %t1.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --search=bfs --solver-backend=dummy --use-guided-search=none --use-cex-cache=false %t1.bc 2>&1 | FileCheck %s #include "ExerciseSolver.c.inc" From c934eb7300819210fe60089d904607939ceb5442 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Thu, 5 Oct 2023 18:27:47 +0400 Subject: [PATCH 033/103] [chore] Disable test --- test/InteractiveMode/interactive_mode.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/InteractiveMode/interactive_mode.c b/test/InteractiveMode/interactive_mode.c index 1adb5e01f2..8ae3cb75c1 100644 --- a/test/InteractiveMode/interactive_mode.c +++ b/test/InteractiveMode/interactive_mode.c @@ -1,4 +1,5 @@ -// REQUIRES: not-ubsan +/* The test is flaky and the feature isn't importatnt now */ +// REQUIRES: not-ubsan, not-darwin // RUN: %clang %s -emit-llvm -g %O0opt -c -o %t.bc // RUN: rm -rf %t.klee-out %t.entrypoints // RUN: echo sign_sum >> %t.entrypoints From 4ac916348ee90a542c2285f3a3b913e9e23fa151 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Thu, 5 Oct 2023 23:31:23 +0400 Subject: [PATCH 034/103] [chore] Add a test --- test/Solver/CexCacheCheckBinding.c | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 test/Solver/CexCacheCheckBinding.c diff --git a/test/Solver/CexCacheCheckBinding.c b/test/Solver/CexCacheCheckBinding.c new file mode 100644 index 0000000000..4743ef1027 --- /dev/null +++ b/test/Solver/CexCacheCheckBinding.c @@ -0,0 +1,8 @@ +// RUN: %clang %s -emit-llvm %O0opt -c -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --debug-cex-cache-check-binding --search=bfs --use-guided-search=none --use-cex-cache=false %t1.bc 2>&1 | FileCheck %s + +#include "ExerciseSolver.c.inc" + +// CHECK: KLEE: done: completed paths = 18 +// CHECK: KLEE: done: partially completed paths = 0 From 532bcff042edb3c419bcd45054fe76eb9a6b46a7 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Fri, 6 Oct 2023 01:01:25 +0400 Subject: [PATCH 035/103] [chore] Add an option to disable loop deletion pass --- lib/Module/Optimize.cpp | 9 +++++-- ...ChenFlurMukhopadhyay-2012SAS-Fig1-alloca.c | 25 +++++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) create mode 100644 test/regression/2023-10-06-ChenFlurMukhopadhyay-2012SAS-Fig1-alloca.c diff --git a/lib/Module/Optimize.cpp b/lib/Module/Optimize.cpp index dd97353391..cda430bd96 100644 --- a/lib/Module/Optimize.cpp +++ b/lib/Module/Optimize.cpp @@ -75,6 +75,10 @@ static cl::opt static cl::alias A1("S", cl::desc("Alias for --strip-debug"), cl::aliasopt(StripDebug)); +static cl::opt DeleteDeadLoops("delete-dead-loops", + cl::desc("Use LoopDeletionPass"), + cl::init(true), cl::cat(klee::ModuleCat)); + // A utility function that adds a pass to the pass manager but will also add // a verifier pass after if we're supposed to verify. static inline void addPass(legacy::PassManager &PM, Pass *P) { @@ -131,8 +135,9 @@ static void AddStandardCompilePasses(legacy::PassManager &PM) { addPass(PM, createLoopUnswitchPass()); // Unswitch loops. // FIXME : Removing instcombine causes nestedloop regression. addPass(PM, createInstructionCombiningPass()); - addPass(PM, createIndVarSimplifyPass()); // Canonicalize indvars - addPass(PM, createLoopDeletionPass()); // Delete dead loops + addPass(PM, createIndVarSimplifyPass()); // Canonicalize indvars + if (DeleteDeadLoops) + addPass(PM, createLoopDeletionPass()); // Delete dead loops addPass(PM, createLoopUnrollPass()); // Unroll small loops addPass(PM, createInstructionCombiningPass()); // Clean up after the unroller addPass(PM, createGVNPass()); // Remove redundancies diff --git a/test/regression/2023-10-06-ChenFlurMukhopadhyay-2012SAS-Fig1-alloca.c b/test/regression/2023-10-06-ChenFlurMukhopadhyay-2012SAS-Fig1-alloca.c new file mode 100644 index 0000000000..9b27688a42 --- /dev/null +++ b/test/regression/2023-10-06-ChenFlurMukhopadhyay-2012SAS-Fig1-alloca.c @@ -0,0 +1,25 @@ +// REQUIRES: z3 +// RUN: %clang -Wno-everything %s -emit-llvm %O0opt -g -c -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --optimize=true --delete-dead-loops=false --use-forked-solver=false -max-memory=6008 --cex-cache-validity-cores --only-output-states-covering-new=true --dump-states-on-halt=true %t1.bc 2>&1 | FileCheck -check-prefix=CHECK %s + +#include "klee-test-comp.c" + +extern int __VERIFIER_nondet_int(void); + +int main() { + int *x = alloca(sizeof(int)); + int *y = alloca(sizeof(int)); + int *z = alloca(sizeof(int)); + *x = __VERIFIER_nondet_int(); + *y = __VERIFIER_nondet_int(); + *z = __VERIFIER_nondet_int(); + + while (*x > 0) { + *x = *x + *y; + *y = *z; + *z = -(*z) - 1; + } +} + +// CHECK: generated tests = 3 From 8798ea5753642f8dca3bc5dca9f44db453517414 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Fri, 6 Oct 2023 01:01:38 +0400 Subject: [PATCH 036/103] [fix] Fix stats --- tools/klee/main.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tools/klee/main.cpp b/tools/klee/main.cpp index 364254f278..e9bb118371 100644 --- a/tools/klee/main.cpp +++ b/tools/klee/main.cpp @@ -593,6 +593,7 @@ void KleeHandler::processTestCase(const ExecutionState &state, klee_warning("unable to get symbolic solution, losing test case"); const auto start_time = time::getWallTime(); + bool atLeastOneGenerated = false; if (WriteKTests) { @@ -602,7 +603,7 @@ void KleeHandler::processTestCase(const ExecutionState &state, getOutputFilename(getTestFilename("ktest", id)).c_str())) { klee_warning("unable to write output test case, losing it"); } else { - ++m_numGeneratedTests; + atLeastOneGenerated = true; } if (WriteStates) { @@ -691,6 +692,10 @@ void KleeHandler::processTestCase(const ExecutionState &state, if (WriteXMLTests) { writeTestCaseXML(message != nullptr, ktest, id); + atLeastOneGenerated = true; + } + + if (atLeastOneGenerated) { ++m_numGeneratedTests; } From d5095be34033c1ebb97b55247487a20bbee22689 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Fri, 6 Oct 2023 18:52:19 +0400 Subject: [PATCH 037/103] [feat] Differentiate `isCoveredNew` and `isCoveredNewError` --- lib/Core/ExecutionState.cpp | 19 +- lib/Core/ExecutionState.h | 9 +- lib/Core/Executor.cpp | 8 +- test/regression/2023-10-06-Dubois-015.c | 351 ++++++++++++++++++++++++ 4 files changed, 375 insertions(+), 12 deletions(-) create mode 100644 test/regression/2023-10-06-Dubois-015.c diff --git a/lib/Core/ExecutionState.cpp b/lib/Core/ExecutionState.cpp index e1b4cde6f8..9b7667ee62 100644 --- a/lib/Core/ExecutionState.cpp +++ b/lib/Core/ExecutionState.cpp @@ -121,7 +121,8 @@ ExecutionState::ExecutionState() depth(0), ptreeNode(nullptr), symbolics(), steppedInstructions(0), steppedMemoryInstructions(0), instsSinceCovNew(0), roundingMode(llvm::APFloat::rmNearestTiesToEven), coveredNew({}), - forkDisabled(false), prevHistory_(TargetsHistory::create()), + coveredNewError(new box(false)), forkDisabled(false), + prevHistory_(TargetsHistory::create()), history_(TargetsHistory::create()) { setID(); } @@ -131,7 +132,8 @@ ExecutionState::ExecutionState(KFunction *kf) depth(0), ptreeNode(nullptr), symbolics(), steppedInstructions(0), steppedMemoryInstructions(0), instsSinceCovNew(0), roundingMode(llvm::APFloat::rmNearestTiesToEven), coveredNew({}), - forkDisabled(false), prevHistory_(TargetsHistory::create()), + coveredNewError(new box(false)), forkDisabled(false), + prevHistory_(TargetsHistory::create()), history_(TargetsHistory::create()) { pushFrame(nullptr, kf); setID(); @@ -142,7 +144,8 @@ ExecutionState::ExecutionState(KFunction *kf, KBlock *kb) depth(0), ptreeNode(nullptr), symbolics(), steppedInstructions(0), steppedMemoryInstructions(0), instsSinceCovNew(0), roundingMode(llvm::APFloat::rmNearestTiesToEven), coveredNew({}), - forkDisabled(false), prevHistory_(TargetsHistory::create()), + coveredNewError(new box(false)), forkDisabled(false), + prevHistory_(TargetsHistory::create()), history_(TargetsHistory::create()) { pushFrame(nullptr, kf); setID(); @@ -170,11 +173,11 @@ ExecutionState::ExecutionState(const ExecutionState &state) unwindingInformation(state.unwindingInformation ? state.unwindingInformation->clone() : nullptr), - coveredNew(state.coveredNew), forkDisabled(state.forkDisabled), - returnValue(state.returnValue), gepExprBases(state.gepExprBases), - prevTargets_(state.prevTargets_), targets_(state.targets_), - prevHistory_(state.prevHistory_), history_(state.history_), - isTargeted_(state.isTargeted_) { + coveredNew(state.coveredNew), coveredNewError(state.coveredNewError), + forkDisabled(state.forkDisabled), returnValue(state.returnValue), + gepExprBases(state.gepExprBases), prevTargets_(state.prevTargets_), + targets_(state.targets_), prevHistory_(state.prevHistory_), + history_(state.history_), isTargeted_(state.isTargeted_) { queryMetaData.id = state.id; } diff --git a/lib/Core/ExecutionState.h b/lib/Core/ExecutionState.h index f8cc093489..9492e1ce02 100644 --- a/lib/Core/ExecutionState.h +++ b/lib/Core/ExecutionState.h @@ -366,6 +366,7 @@ class ExecutionState { /// @brief Whether a new instruction was covered in this state mutable std::deque>> coveredNew; + mutable ref> coveredNewError; /// @brief Disables forking for this state. Set by user code bool forkDisabled = false; @@ -507,7 +508,12 @@ class ExecutionState { bool isCoveredNew() const { return !coveredNew.empty() && coveredNew.back()->value; } - void coverNew() const { coveredNew.push_back(new box(true)); } + bool isCoveredNewError() const { return coveredNewError->value; } + void coverNew() const { + coveredNew.push_back(new box(true)); + coveredNewError->value = false; + coveredNewError = new box(true); + } void updateCoveredNew() const { while (!coveredNew.empty() && !coveredNew.front()->value) { coveredNew.pop_front(); @@ -519,6 +525,7 @@ class ExecutionState { } coveredNew.clear(); } + void clearCoveredNewError() const { coveredNewError->value = false; } }; struct ExecutionStateIDCompare { diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index e3c8cce344..e30001d601 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -4355,9 +4355,9 @@ void Executor::initializeTypeManager() { typeSystemManager->initModule(); } -static bool shouldWriteTest(const ExecutionState &state) { +static bool shouldWriteTest(const ExecutionState &state, bool isError = false) { state.updateCoveredNew(); - bool coveredNew = state.isCoveredNew(); + bool coveredNew = isError ? state.isCoveredNewError() : state.isCoveredNew(); return !OnlyOutputStatesCoveringNew || coveredNew; } @@ -4721,7 +4721,7 @@ void Executor::terminateStateOnError(ExecutionState &state, if ((EmitAllErrors || emittedErrors.insert(std::make_pair(lastInst, message)).second) && - shouldWriteTest(state)) { + shouldWriteTest(state, true)) { std::string filepath = ki->getSourceFilepath(); if (!filepath.empty()) { klee_message("ERROR: %s:%zu: %s", filepath.c_str(), ki->getLine(), @@ -4752,6 +4752,8 @@ void Executor::terminateStateOnError(ExecutionState &state, if (!info_str.empty()) msg << "Info: \n" << info_str; + state.clearCoveredNewError(); + const std::string ext = terminationTypeFileExtension(terminationType); // use user provided suffix from klee_report_error() const char *file_suffix = suffix ? suffix : ext.c_str(); diff --git a/test/regression/2023-10-06-Dubois-015.c b/test/regression/2023-10-06-Dubois-015.c new file mode 100644 index 0000000000..f70af983b4 --- /dev/null +++ b/test/regression/2023-10-06-Dubois-015.c @@ -0,0 +1,351 @@ +// RUN: %clang -Wno-everything %s -emit-llvm %O0opt -g -c -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --optimize=true --emit-all-errors --only-output-states-covering-new=true --dump-states-on-halt=true --search=dfs %t1.bc 2>&1 | FileCheck -check-prefix=CHECK %s + +#include "klee-test-comp.c" + +// This file is part of the SV-Benchmarks collection of verification tasks: +// https://github.com/sosy-lab/sv-benchmarks +// +// SPDX-FileCopyrightText: 2016 Gilles Audemard +// SPDX-FileCopyrightText: 2020 Dirk Beyer +// SPDX-FileCopyrightText: 2020 The SV-Benchmarks Community +// +// SPDX-License-Identifier: MIT + +extern void abort(void) __attribute__((__nothrow__, __leaf__)) +__attribute__((__noreturn__)); +extern void __assert_fail(const char *, const char *, unsigned int, + const char *) __attribute__((__nothrow__, __leaf__)) +__attribute__((__noreturn__)); +#ifdef GCOV +extern void __gcov_dump(void); +#endif + +void abort_prog() { +#ifdef GCOV + __gcov_dump(); +#endif + abort(); +} +int __VERIFIER_nondet_int(); +void reach_error() { abort_prog(); __assert_fail("0", "Dubois-015.c", 5, "reach_error"); } +void assume(int cond) { + if (!cond) + abort_prog(); +} +int main() { + int cond0; + int dummy = 0; + int N; + int var0; + var0 = __VERIFIER_nondet_int(); + assume(var0 >= 0); + assume(var0 <= 1); + int var1; + var1 = __VERIFIER_nondet_int(); + assume(var1 >= 0); + assume(var1 <= 1); + int var2; + var2 = __VERIFIER_nondet_int(); + assume(var2 >= 0); + assume(var2 <= 1); + int var3; + var3 = __VERIFIER_nondet_int(); + assume(var3 >= 0); + assume(var3 <= 1); + int var4; + var4 = __VERIFIER_nondet_int(); + assume(var4 >= 0); + assume(var4 <= 1); + int var5; + var5 = __VERIFIER_nondet_int(); + assume(var5 >= 0); + assume(var5 <= 1); + int var6; + var6 = __VERIFIER_nondet_int(); + assume(var6 >= 0); + assume(var6 <= 1); + int var7; + var7 = __VERIFIER_nondet_int(); + assume(var7 >= 0); + assume(var7 <= 1); + int var8; + var8 = __VERIFIER_nondet_int(); + assume(var8 >= 0); + assume(var8 <= 1); + int var9; + var9 = __VERIFIER_nondet_int(); + assume(var9 >= 0); + assume(var9 <= 1); + int var10; + var10 = __VERIFIER_nondet_int(); + assume(var10 >= 0); + assume(var10 <= 1); + int var11; + var11 = __VERIFIER_nondet_int(); + assume(var11 >= 0); + assume(var11 <= 1); + int var12; + var12 = __VERIFIER_nondet_int(); + assume(var12 >= 0); + assume(var12 <= 1); + int var13; + var13 = __VERIFIER_nondet_int(); + assume(var13 >= 0); + assume(var13 <= 1); + int var14; + var14 = __VERIFIER_nondet_int(); + assume(var14 >= 0); + assume(var14 <= 1); + int var15; + var15 = __VERIFIER_nondet_int(); + assume(var15 >= 0); + assume(var15 <= 1); + int var16; + var16 = __VERIFIER_nondet_int(); + assume(var16 >= 0); + assume(var16 <= 1); + int var17; + var17 = __VERIFIER_nondet_int(); + assume(var17 >= 0); + assume(var17 <= 1); + int var18; + var18 = __VERIFIER_nondet_int(); + assume(var18 >= 0); + assume(var18 <= 1); + int var19; + var19 = __VERIFIER_nondet_int(); + assume(var19 >= 0); + assume(var19 <= 1); + int var20; + var20 = __VERIFIER_nondet_int(); + assume(var20 >= 0); + assume(var20 <= 1); + int var21; + var21 = __VERIFIER_nondet_int(); + assume(var21 >= 0); + assume(var21 <= 1); + int var22; + var22 = __VERIFIER_nondet_int(); + assume(var22 >= 0); + assume(var22 <= 1); + int var23; + var23 = __VERIFIER_nondet_int(); + assume(var23 >= 0); + assume(var23 <= 1); + int var24; + var24 = __VERIFIER_nondet_int(); + assume(var24 >= 0); + assume(var24 <= 1); + int var25; + var25 = __VERIFIER_nondet_int(); + assume(var25 >= 0); + assume(var25 <= 1); + int var26; + var26 = __VERIFIER_nondet_int(); + assume(var26 >= 0); + assume(var26 <= 1); + int var27; + var27 = __VERIFIER_nondet_int(); + assume(var27 >= 0); + assume(var27 <= 1); + int var28; + var28 = __VERIFIER_nondet_int(); + assume(var28 >= 0); + assume(var28 <= 1); + int var29; + var29 = __VERIFIER_nondet_int(); + assume(var29 >= 0); + assume(var29 <= 1); + int var30; + var30 = __VERIFIER_nondet_int(); + assume(var30 >= 0); + assume(var30 <= 1); + int var31; + var31 = __VERIFIER_nondet_int(); + assume(var31 >= 0); + assume(var31 <= 1); + int var32; + var32 = __VERIFIER_nondet_int(); + assume(var32 >= 0); + assume(var32 <= 1); + int var33; + var33 = __VERIFIER_nondet_int(); + assume(var33 >= 0); + assume(var33 <= 1); + int var34; + var34 = __VERIFIER_nondet_int(); + assume(var34 >= 0); + assume(var34 <= 1); + int var35; + var35 = __VERIFIER_nondet_int(); + assume(var35 >= 0); + assume(var35 <= 1); + int var36; + var36 = __VERIFIER_nondet_int(); + assume(var36 >= 0); + assume(var36 <= 1); + int var37; + var37 = __VERIFIER_nondet_int(); + assume(var37 >= 0); + assume(var37 <= 1); + int var38; + var38 = __VERIFIER_nondet_int(); + assume(var38 >= 0); + assume(var38 <= 1); + int var39; + var39 = __VERIFIER_nondet_int(); + assume(var39 >= 0); + assume(var39 <= 1); + int var40; + var40 = __VERIFIER_nondet_int(); + assume(var40 >= 0); + assume(var40 <= 1); + int var41; + var41 = __VERIFIER_nondet_int(); + assume(var41 >= 0); + assume(var41 <= 1); + int var42; + var42 = __VERIFIER_nondet_int(); + assume(var42 >= 0); + assume(var42 <= 1); + int var43; + var43 = __VERIFIER_nondet_int(); + assume(var43 >= 0); + assume(var43 <= 1); + int var44; + var44 = __VERIFIER_nondet_int(); + assume(var44 >= 0); + assume(var44 <= 1); + int myvar0 = 1; + assume((var28 == 0 & var29 == 0 & var0 == 1) | + (var28 == 0 & var29 == 1 & var0 == 0) | + (var28 == 1 & var29 == 0 & var0 == 0) | + (var28 == 1 & var29 == 1 & var0 == 1) | 0); + assume((var1 == 0 & var31 == 0 & var2 == 1) | + (var1 == 0 & var31 == 1 & var2 == 0) | + (var1 == 1 & var31 == 0 & var2 == 0) | + (var1 == 1 & var31 == 1 & var2 == 1) | 0); + assume((var2 == 0 & var32 == 0 & var3 == 1) | + (var2 == 0 & var32 == 1 & var3 == 0) | + (var2 == 1 & var32 == 0 & var3 == 0) | + (var2 == 1 & var32 == 1 & var3 == 1) | 0); + assume((var3 == 0 & var33 == 0 & var4 == 1) | + (var3 == 0 & var33 == 1 & var4 == 0) | + (var3 == 1 & var33 == 0 & var4 == 0) | + (var3 == 1 & var33 == 1 & var4 == 1) | 0); + assume((var4 == 0 & var34 == 0 & var5 == 1) | + (var4 == 0 & var34 == 1 & var5 == 0) | + (var4 == 1 & var34 == 0 & var5 == 0) | + (var4 == 1 & var34 == 1 & var5 == 1) | 0); + assume((var5 == 0 & var35 == 0 & var6 == 1) | + (var5 == 0 & var35 == 1 & var6 == 0) | + (var5 == 1 & var35 == 0 & var6 == 0) | + (var5 == 1 & var35 == 1 & var6 == 1) | 0); + assume((var6 == 0 & var36 == 0 & var7 == 1) | + (var6 == 0 & var36 == 1 & var7 == 0) | + (var6 == 1 & var36 == 0 & var7 == 0) | + (var6 == 1 & var36 == 1 & var7 == 1) | 0); + assume((var7 == 0 & var37 == 0 & var8 == 1) | + (var7 == 0 & var37 == 1 & var8 == 0) | + (var7 == 1 & var37 == 0 & var8 == 0) | + (var7 == 1 & var37 == 1 & var8 == 1) | 0); + assume((var8 == 0 & var38 == 0 & var9 == 1) | + (var8 == 0 & var38 == 1 & var9 == 0) | + (var8 == 1 & var38 == 0 & var9 == 0) | + (var8 == 1 & var38 == 1 & var9 == 1) | 0); + assume((var9 == 0 & var39 == 0 & var10 == 1) | + (var9 == 0 & var39 == 1 & var10 == 0) | + (var9 == 1 & var39 == 0 & var10 == 0) | + (var9 == 1 & var39 == 1 & var10 == 1) | 0); + assume((var10 == 0 & var40 == 0 & var11 == 1) | + (var10 == 0 & var40 == 1 & var11 == 0) | + (var10 == 1 & var40 == 0 & var11 == 0) | + (var10 == 1 & var40 == 1 & var11 == 1) | 0); + assume((var11 == 0 & var41 == 0 & var12 == 1) | + (var11 == 0 & var41 == 1 & var12 == 0) | + (var11 == 1 & var41 == 0 & var12 == 0) | + (var11 == 1 & var41 == 1 & var12 == 1) | 0); + assume((var12 == 0 & var42 == 0 & var13 == 1) | + (var12 == 0 & var42 == 1 & var13 == 0) | + (var12 == 1 & var42 == 0 & var13 == 0) | + (var12 == 1 & var42 == 1 & var13 == 1) | 0); + assume((var0 == 0 & var30 == 0 & var1 == 1) | + (var0 == 0 & var30 == 1 & var1 == 0) | + (var0 == 1 & var30 == 0 & var1 == 0) | + (var0 == 1 & var30 == 1 & var1 == 1) | 0); + assume((var14 == 0 & var43 == 0 & var44 == 1) | + (var14 == 0 & var43 == 1 & var44 == 0) | + (var14 == 1 & var43 == 0 & var44 == 0) | + (var14 == 1 & var43 == 1 & var44 == 1) | 0); + assume((var13 == 0 & var43 == 0 & var44 == 1) | + (var13 == 0 & var43 == 1 & var44 == 0) | + (var13 == 1 & var43 == 0 & var44 == 0) | + (var13 == 1 & var43 == 1 & var44 == 1) | 0); + assume((var16 == 0 & var41 == 0 & var15 == 1) | + (var16 == 0 & var41 == 1 & var15 == 0) | + (var16 == 1 & var41 == 0 & var15 == 0) | + (var16 == 1 & var41 == 1 & var15 == 1) | 0); + assume((var17 == 0 & var40 == 0 & var16 == 1) | + (var17 == 0 & var40 == 1 & var16 == 0) | + (var17 == 1 & var40 == 0 & var16 == 0) | + (var17 == 1 & var40 == 1 & var16 == 1) | 0); + assume((var18 == 0 & var39 == 0 & var17 == 1) | + (var18 == 0 & var39 == 1 & var17 == 0) | + (var18 == 1 & var39 == 0 & var17 == 0) | + (var18 == 1 & var39 == 1 & var17 == 1) | 0); + assume((var19 == 0 & var38 == 0 & var18 == 1) | + (var19 == 0 & var38 == 1 & var18 == 0) | + (var19 == 1 & var38 == 0 & var18 == 0) | + (var19 == 1 & var38 == 1 & var18 == 1) | 0); + assume((var20 == 0 & var37 == 0 & var19 == 1) | + (var20 == 0 & var37 == 1 & var19 == 0) | + (var20 == 1 & var37 == 0 & var19 == 0) | + (var20 == 1 & var37 == 1 & var19 == 1) | 0); + assume((var21 == 0 & var36 == 0 & var20 == 1) | + (var21 == 0 & var36 == 1 & var20 == 0) | + (var21 == 1 & var36 == 0 & var20 == 0) | + (var21 == 1 & var36 == 1 & var20 == 1) | 0); + assume((var22 == 0 & var35 == 0 & var21 == 1) | + (var22 == 0 & var35 == 1 & var21 == 0) | + (var22 == 1 & var35 == 0 & var21 == 0) | + (var22 == 1 & var35 == 1 & var21 == 1) | 0); + assume((var23 == 0 & var34 == 0 & var22 == 1) | + (var23 == 0 & var34 == 1 & var22 == 0) | + (var23 == 1 & var34 == 0 & var22 == 0) | + (var23 == 1 & var34 == 1 & var22 == 1) | 0); + assume((var24 == 0 & var33 == 0 & var23 == 1) | + (var24 == 0 & var33 == 1 & var23 == 0) | + (var24 == 1 & var33 == 0 & var23 == 0) | + (var24 == 1 & var33 == 1 & var23 == 1) | 0); + assume((var25 == 0 & var32 == 0 & var24 == 1) | + (var25 == 0 & var32 == 1 & var24 == 0) | + (var25 == 1 & var32 == 0 & var24 == 0) | + (var25 == 1 & var32 == 1 & var24 == 1) | 0); + assume((var26 == 0 & var31 == 0 & var25 == 1) | + (var26 == 0 & var31 == 1 & var25 == 0) | + (var26 == 1 & var31 == 0 & var25 == 0) | + (var26 == 1 & var31 == 1 & var25 == 1) | 0); + assume((var27 == 0 & var30 == 0 & var26 == 1) | + (var27 == 0 & var30 == 1 & var26 == 0) | + (var27 == 1 & var30 == 0 & var26 == 0) | + (var27 == 1 & var30 == 1 & var26 == 1) | 0); + assume((var15 == 0 & var42 == 0 & var14 == 1) | + (var15 == 0 & var42 == 1 & var14 == 0) | + (var15 == 1 & var42 == 0 & var14 == 0) | + (var15 == 1 & var42 == 1 & var14 == 1) | 0); + assume((var28 == 0 & var29 == 0 & var27 == 0) | + (var28 == 0 & var29 == 1 & var27 == 1) | + (var28 == 1 & var29 == 0 & var27 == 1) | + (var28 == 1 & var29 == 1 & var27 == 0) | 0); + reach_error(); + return 0; /* 0 x[0]1 x[1]2 x[2]3 x[3]4 x[4]5 x[5]6 x[6]7 x[7]8 x[8]9 x[9]10 + x[10]11 x[11]12 x[12]13 x[13]14 x[14]15 x[15]16 x[16]17 x[17]18 + x[18]19 x[19]20 x[20]21 x[21]22 x[22]23 x[23]24 x[24]25 x[25]26 + x[26]27 x[27]28 x[28]29 x[29]30 x[30]31 x[31]32 x[32]33 x[33]34 + x[34]35 x[35]36 x[36]37 x[37]38 x[38]39 x[39]40 x[40]41 x[41]42 + x[42]43 x[43]44 x[44] */ +} + +// CHECK: generated tests = 2 \ No newline at end of file From c9c14199edc93c5c74d184501dc52184becda0ad Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Sat, 7 Oct 2023 00:42:55 +0400 Subject: [PATCH 038/103] [chore] Z3 is not required in a lot of tests, so remove the requirements --- .../LazyInitialization/DerefSymbolicPointer.c | 3 +-- .../ImpossibleAddressForLI.c | 3 +-- .../LazyInitialization/LazyInitialization.c | 3 +-- test/Feature/LazyInitialization/LinkedList.c | 3 +-- .../LazyInitialization/PointerOffset.c | 3 +-- .../SingleInitializationAndAccess.c | 3 +-- .../TwoObjectsInitialization.c | 3 +-- test/Industry/AssignNull_Scene_BadCase02.c | 1 - test/Industry/AssignNull_Scene_BadCase04.c | 1 - test/Industry/BadCase01_SecB_ForwardNull.c | 1 - test/Industry/CheckNull_Scene_BadCase02.c | 1 - test/Industry/CheckNull_Scene_BadCase04.c | 1 - test/Industry/FN_SecB_ForwardNull_filed.c | 12 +++++------ .../Industry/FN_SecB_ForwardNull_filed.c.json | 6 +++--- ...Var_Alloc_in_Loop_Exit_in_Loop_BadCase01.c | 1 - test/Industry/NullReturn_BadCase_WhiteBox01.c | 10 +++++----- .../NullReturn_BadCase_WhiteBox01.c.json | 20 +++++++++---------- test/Industry/NullReturn_Scene_BadCase01.c | 1 - test/Industry/NullReturn_Scene_BadCase02.c | 1 - test/Industry/NullReturn_Scene_BadCase03.c | 1 - test/Industry/NullReturn_Scene_BadCase04.c | 1 - test/Industry/NullReturn_Scene_BadCase06.c | 1 - test/Industry/NullReturn_Scene_BadCase08.cpp | 1 - test/Industry/SecB_ForwardNull.c | 10 +++++----- test/Industry/SecB_ForwardNull.c.json | 6 +++--- .../UseAfterFree/Double_Free_BadCase01.c | 3 +-- .../UseAfterFree/Double_Free_BadCase02.c | 3 +-- .../Free_Not_Set_Null_BadCase02.cpp | 3 +-- .../Prod_Dereference_After_Free_BadCase01.c | 1 - test/Industry/ZeroDeref_Scene_BadCase02.c | 1 - test/Industry/ZeroDeref_Scene_BadCase05.c | 1 - test/Industry/fn_reverse_null.c | 1 - test/Industry/fp_forward_null_address.c | 1 - test/Industry/fp_null_returns_self_define.c | 1 - test/Industry/fp_null_returns_self_define2.c | 1 - test/Industry/if2.c | 1 - test/Industry/test.c | 1 - test/Industry/while_true.c | 1 - ...or2c-lazyMod.adding.1.prop1-back-serstep.c | 5 +++-- ...eplay-test-with-lazy-initialized-objects.c | 4 ++-- .../2023-10-04-email_spec0_product16.cil.c | 3 +-- ...ChenFlurMukhopadhyay-2012SAS-Fig1-alloca.c | 1 - test/regression/2023-10-06-Dubois-015.c | 5 ++++- 43 files changed, 52 insertions(+), 82 deletions(-) diff --git a/test/Feature/LazyInitialization/DerefSymbolicPointer.c b/test/Feature/LazyInitialization/DerefSymbolicPointer.c index 27fd4d1d42..b0919d56a3 100644 --- a/test/Feature/LazyInitialization/DerefSymbolicPointer.c +++ b/test/Feature/LazyInitialization/DerefSymbolicPointer.c @@ -1,7 +1,6 @@ -// REQUIRES: z3 // RUN: %clang %s -emit-llvm %O0opt -c -o %t.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --write-kqueries --output-dir=%t.klee-out --solver-backend=z3 --skip-not-symbolic-objects %t.bc > %t.log +// RUN: %klee --write-kqueries --output-dir=%t.klee-out --skip-not-symbolic-objects %t.bc > %t.log // RUN: FileCheck %s -input-file=%t.log #include "klee/klee.h" diff --git a/test/Feature/LazyInitialization/ImpossibleAddressForLI.c b/test/Feature/LazyInitialization/ImpossibleAddressForLI.c index abc643eb05..f0d9f25bf6 100644 --- a/test/Feature/LazyInitialization/ImpossibleAddressForLI.c +++ b/test/Feature/LazyInitialization/ImpossibleAddressForLI.c @@ -1,7 +1,6 @@ -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -g -c -o %t.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --solver-backend=z3 --skip-not-symbolic-objects %t.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --skip-not-symbolic-objects %t.bc 2>&1 | FileCheck %s #include "klee/klee.h" diff --git a/test/Feature/LazyInitialization/LazyInitialization.c b/test/Feature/LazyInitialization/LazyInitialization.c index 74356f31b3..31e82a124e 100644 --- a/test/Feature/LazyInitialization/LazyInitialization.c +++ b/test/Feature/LazyInitialization/LazyInitialization.c @@ -1,7 +1,6 @@ -// REQUIRES: z3 // RUN: %clang %s -emit-llvm %O0opt -c -o %t.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --solver-backend=z3 --skip-not-symbolic-objects --use-timestamps=false --use-guided-search=none %t.bc > %t.log +// RUN: %klee --output-dir=%t.klee-out --skip-not-symbolic-objects --use-timestamps=false --use-guided-search=none %t.bc > %t.log // RUN: FileCheck %s -input-file=%t.log struct Node { diff --git a/test/Feature/LazyInitialization/LinkedList.c b/test/Feature/LazyInitialization/LinkedList.c index 9431e4ffc3..191ce3103b 100644 --- a/test/Feature/LazyInitialization/LinkedList.c +++ b/test/Feature/LazyInitialization/LinkedList.c @@ -1,7 +1,6 @@ -// REQUIRES: z3 // RUN: %clang %s -emit-llvm %O0opt -g -c -o %t.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --write-kqueries --solver-backend=z3 --output-dir=%t.klee-out --skip-not-symbolic-objects %t.bc > %t.log +// RUN: %klee --write-kqueries --output-dir=%t.klee-out --skip-not-symbolic-objects %t.bc > %t.log // RUN: FileCheck %s -input-file=%t.log #include "klee/klee.h" diff --git a/test/Feature/LazyInitialization/PointerOffset.c b/test/Feature/LazyInitialization/PointerOffset.c index aaf3694e1c..2d0b7a4321 100644 --- a/test/Feature/LazyInitialization/PointerOffset.c +++ b/test/Feature/LazyInitialization/PointerOffset.c @@ -1,7 +1,6 @@ -// REQUIRES: z3 // RUN: %clang %s -emit-llvm %O0opt -c -o %t.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --solver-backend=z3 --skip-not-symbolic-objects --use-timestamps=false --skip-local=false %t.bc +// RUN: %klee --output-dir=%t.klee-out --skip-not-symbolic-objects --use-timestamps=false --skip-local=false %t.bc // RUN: %ktest-tool %t.klee-out/test*.ktest > %t.log // RUN: FileCheck %s -input-file=%t.log // CHECK: pointers: [(0, 1, 4)] diff --git a/test/Feature/LazyInitialization/SingleInitializationAndAccess.c b/test/Feature/LazyInitialization/SingleInitializationAndAccess.c index 1def3a9876..4c2413aa9e 100644 --- a/test/Feature/LazyInitialization/SingleInitializationAndAccess.c +++ b/test/Feature/LazyInitialization/SingleInitializationAndAccess.c @@ -1,7 +1,6 @@ -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -g -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --solver-backend=z3 --skip-not-symbolic-objects --skip-local=false --use-sym-size-li --min-number-elements-li=1 %t1.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --skip-not-symbolic-objects --skip-local=false --use-sym-size-li --min-number-elements-li=1 %t1.bc 2>&1 | FileCheck %s #include "klee/klee.h" #include diff --git a/test/Feature/LazyInitialization/TwoObjectsInitialization.c b/test/Feature/LazyInitialization/TwoObjectsInitialization.c index ab67462f3d..957f4bd7da 100644 --- a/test/Feature/LazyInitialization/TwoObjectsInitialization.c +++ b/test/Feature/LazyInitialization/TwoObjectsInitialization.c @@ -1,7 +1,6 @@ -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -g -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --solver-backend=z3 --skip-not-symbolic-objects %t1.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --skip-not-symbolic-objects %t1.bc 2>&1 | FileCheck %s #include "klee/klee.h" #include diff --git a/test/Industry/AssignNull_Scene_BadCase02.c b/test/Industry/AssignNull_Scene_BadCase02.c index ecb898b0b2..55fb4b7989 100644 --- a/test/Industry/AssignNull_Scene_BadCase02.c +++ b/test/Industry/AssignNull_Scene_BadCase02.c @@ -49,7 +49,6 @@ void TestBad5(struct STU *pdev, const char *buf, unsigned int count) printf("teacher id is %ud", teacherID); } -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --location-accuracy --mock-external-calls --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc diff --git a/test/Industry/AssignNull_Scene_BadCase04.c b/test/Industry/AssignNull_Scene_BadCase04.c index 757479e40d..6a0979278f 100644 --- a/test/Industry/AssignNull_Scene_BadCase04.c +++ b/test/Industry/AssignNull_Scene_BadCase04.c @@ -50,7 +50,6 @@ int TestBad7(char *arg, unsigned int count) return 1; } -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --mock-external-calls --check-out-of-memory --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --smart-resolve-entry-function --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc diff --git a/test/Industry/BadCase01_SecB_ForwardNull.c b/test/Industry/BadCase01_SecB_ForwardNull.c index 38431719b3..f72959d73c 100644 --- a/test/Industry/BadCase01_SecB_ForwardNull.c +++ b/test/Industry/BadCase01_SecB_ForwardNull.c @@ -140,7 +140,6 @@ void badbad(char *ptr) } #endif -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --mock-external-calls --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --check-out-of-memory --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc diff --git a/test/Industry/CheckNull_Scene_BadCase02.c b/test/Industry/CheckNull_Scene_BadCase02.c index fc27954a53..3effb46f57 100644 --- a/test/Industry/CheckNull_Scene_BadCase02.c +++ b/test/Industry/CheckNull_Scene_BadCase02.c @@ -41,7 +41,6 @@ void TestBad2() free(errMsg); } -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --mock-external-calls --check-out-of-memory --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc diff --git a/test/Industry/CheckNull_Scene_BadCase04.c b/test/Industry/CheckNull_Scene_BadCase04.c index dba74dd82a..0e9038201d 100644 --- a/test/Industry/CheckNull_Scene_BadCase04.c +++ b/test/Industry/CheckNull_Scene_BadCase04.c @@ -56,7 +56,6 @@ void TestBad12(int cond1, int cond2) } } -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --mock-external-calls --check-out-of-memory --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc diff --git a/test/Industry/FN_SecB_ForwardNull_filed.c b/test/Industry/FN_SecB_ForwardNull_filed.c index fad10a2644..6faaf136b9 100644 --- a/test/Industry/FN_SecB_ForwardNull_filed.c +++ b/test/Industry/FN_SecB_ForwardNull_filed.c @@ -1,8 +1,3 @@ -// REQUIRES: z3 -// RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc -// RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --mock-external-calls --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc -// RUN: FileCheck -input-file=%t.klee-out/warnings.txt %s /* * Copyright (c) Huawei Technologies Co., Ltd. 2021-2021. All rights reserved. * @description 空指针解引用 验收失败 @@ -44,8 +39,13 @@ void WB_BadCase_Field(UINT32 inputNum1, UINT32 inputNum2) void WB_BadCase_field2(DataInfo *data) { data->dataBuff = NULL; - *data->dataBuff = 'c'; // CHECK: KLEE: WARNING: 100.00% NullPointerException False Negative at: {{.*}}test/Industry/FN_SecB_ForwardNull_filed.c:47 19 + *data->dataBuff = 'c'; // CHECK: KLEE: WARNING: 100.00% NullPointerException False Negative at: {{.*}}test/Industry/FN_SecB_ForwardNull_filed.c:42 19 char *ptr = NULL; *ptr = 'c'; // CHECK: KLEE: WARNING: 100.00% NullPointerException False Positive at trace 1 } + +// RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --mock-external-calls --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc +// RUN: FileCheck -input-file=%t.klee-out/warnings.txt %s \ No newline at end of file diff --git a/test/Industry/FN_SecB_ForwardNull_filed.c.json b/test/Industry/FN_SecB_ForwardNull_filed.c.json index b54baa91f9..ec0f7d3101 100644 --- a/test/Industry/FN_SecB_ForwardNull_filed.c.json +++ b/test/Industry/FN_SecB_ForwardNull_filed.c.json @@ -20,7 +20,7 @@ "uri": "/mnt/d/wsl-ubuntu/test2/forward_null/./FN_SecB_ForwardNull_filed.c" }, "region": { - "startLine": 49, + "startLine": 44, "startColumn": null } } @@ -33,7 +33,7 @@ "uri": "/mnt/d/wsl-ubuntu/test2/forward_null/./FN_SecB_ForwardNull_filed.c" }, "region": { - "startLine": 50, + "startLine": 45, "startColumn": null } } @@ -52,7 +52,7 @@ "uri": "/mnt/d/wsl-ubuntu/test2/forward_null/./FN_SecB_ForwardNull_filed.c" }, "region": { - "startLine": 50, + "startLine": 45, "startColumn": null } } diff --git a/test/Industry/MemoryLeak/LocalVar_Alloc_in_Loop_Exit_in_Loop_BadCase01.c b/test/Industry/MemoryLeak/LocalVar_Alloc_in_Loop_Exit_in_Loop_BadCase01.c index 4b77bd1b66..9a04367627 100644 --- a/test/Industry/MemoryLeak/LocalVar_Alloc_in_Loop_Exit_in_Loop_BadCase01.c +++ b/test/Industry/MemoryLeak/LocalVar_Alloc_in_Loop_Exit_in_Loop_BadCase01.c @@ -53,7 +53,6 @@ void call_func(int num) ResourceLeak_bad01(num); } -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --write-kqueries --max-cycles-before-stuck=0 --use-guided-search=error --check-out-of-memory --mock-external-calls --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc diff --git a/test/Industry/NullReturn_BadCase_WhiteBox01.c b/test/Industry/NullReturn_BadCase_WhiteBox01.c index 8ee8261adb..666c470216 100644 --- a/test/Industry/NullReturn_BadCase_WhiteBox01.c +++ b/test/Industry/NullReturn_BadCase_WhiteBox01.c @@ -1,8 +1,3 @@ -// REQUIRES: z3 -// RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc -// RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --smart-resolve-entry-function --use-guided-search=error --mock-external-calls --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc -// RUN: FileCheck -input-file=%t.klee-out/warnings.txt %s /* * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved. * @@ -68,3 +63,8 @@ void NullReturn_BadCase_WhiteBox01(UINT8 index, SchedHarqStru *harqInfo) SendMsg(index, usrId, resultInfo); // (3) } } + +// RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --smart-resolve-entry-function --use-guided-search=error --mock-external-calls --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc +// RUN: FileCheck -input-file=%t.klee-out/warnings.txt %s \ No newline at end of file diff --git a/test/Industry/NullReturn_BadCase_WhiteBox01.c.json b/test/Industry/NullReturn_BadCase_WhiteBox01.c.json index 3372239023..42a4b510f1 100644 --- a/test/Industry/NullReturn_BadCase_WhiteBox01.c.json +++ b/test/Industry/NullReturn_BadCase_WhiteBox01.c.json @@ -20,7 +20,7 @@ "uri": "/mnt/d/wsl-ubuntu/test2/null_returns/NullReturn_BadCase_WhiteBox01.c" }, "region": { - "startLine": 45, + "startLine": 40, "startColumn": 9 } } @@ -33,7 +33,7 @@ "uri": "/mnt/d/wsl-ubuntu/test2/null_returns/NullReturn_BadCase_WhiteBox01.c" }, "region": { - "startLine": 66, + "startLine": 61, "startColumn": 34 } } @@ -46,7 +46,7 @@ "uri": "/mnt/d/wsl-ubuntu/test2/null_returns/NullReturn_BadCase_WhiteBox01.c" }, "region": { - "startLine": 68, + "startLine": 63, "startColumn": 9 } } @@ -59,7 +59,7 @@ "uri": "/mnt/d/wsl-ubuntu/test2/null_returns/NullReturn_BadCase_WhiteBox01.c" }, "region": { - "startLine": 56, + "startLine": 51, "startColumn": 30 } } @@ -78,7 +78,7 @@ "uri": "/mnt/d/wsl-ubuntu/test2/null_returns/NullReturn_BadCase_WhiteBox01.c" }, "region": { - "startLine": 56, + "startLine": 51, "startColumn": 30 } } @@ -98,7 +98,7 @@ "uri": "/mnt/d/wsl-ubuntu/test2/null_returns/NullReturn_BadCase_WhiteBox01.c" }, "region": { - "startLine": 45, + "startLine": 40, "startColumn": 9 } } @@ -111,7 +111,7 @@ "uri": "/mnt/d/wsl-ubuntu/test2/null_returns/NullReturn_BadCase_WhiteBox01.c" }, "region": { - "startLine": 66, + "startLine": 61, "startColumn": 34 } } @@ -124,7 +124,7 @@ "uri": "/mnt/d/wsl-ubuntu/test2/null_returns/NullReturn_BadCase_WhiteBox01.c" }, "region": { - "startLine": 68, + "startLine": 63, "startColumn": 9 } } @@ -137,7 +137,7 @@ "uri": "/mnt/d/wsl-ubuntu/test2/null_returns/NullReturn_BadCase_WhiteBox01.c" }, "region": { - "startLine": 54, + "startLine": 49, "startColumn": 30 } } @@ -156,7 +156,7 @@ "uri": "/mnt/d/wsl-ubuntu/test2/null_returns/NullReturn_BadCase_WhiteBox01.c" }, "region": { - "startLine": 54, + "startLine": 49, "startColumn": 30 } } diff --git a/test/Industry/NullReturn_Scene_BadCase01.c b/test/Industry/NullReturn_Scene_BadCase01.c index cfab0db844..45b8240318 100644 --- a/test/Industry/NullReturn_Scene_BadCase01.c +++ b/test/Industry/NullReturn_Scene_BadCase01.c @@ -39,7 +39,6 @@ void TestBad1() free(buf); } -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --mock-external-calls --external-calls=all --check-out-of-memory --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc diff --git a/test/Industry/NullReturn_Scene_BadCase02.c b/test/Industry/NullReturn_Scene_BadCase02.c index 7042eb01b1..d25af79653 100644 --- a/test/Industry/NullReturn_Scene_BadCase02.c +++ b/test/Industry/NullReturn_Scene_BadCase02.c @@ -38,7 +38,6 @@ void TestBad2() printf("The second is %d", info->tm_sec); // CHECK: KLEE: WARNING: 100.00% NullPointerException True Positive at trace 1 } -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --location-accuracy --mock-external-calls --check-out-of-memory --skip-not-symbolic-objects --skip-not-lazy-initialized --extern-calls-can-return-null --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc diff --git a/test/Industry/NullReturn_Scene_BadCase03.c b/test/Industry/NullReturn_Scene_BadCase03.c index f24ef754b6..c4190f9bb2 100644 --- a/test/Industry/NullReturn_Scene_BadCase03.c +++ b/test/Industry/NullReturn_Scene_BadCase03.c @@ -40,7 +40,6 @@ void TestBad3() free(buf); } -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --mock-external-calls --check-out-of-memory --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc diff --git a/test/Industry/NullReturn_Scene_BadCase04.c b/test/Industry/NullReturn_Scene_BadCase04.c index d7054e5af2..377e4b9e19 100644 --- a/test/Industry/NullReturn_Scene_BadCase04.c +++ b/test/Industry/NullReturn_Scene_BadCase04.c @@ -44,7 +44,6 @@ void TestBad4() free(buf); } -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --check-out-of-memory --mock-external-calls --libc=klee --external-calls=all --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc diff --git a/test/Industry/NullReturn_Scene_BadCase06.c b/test/Industry/NullReturn_Scene_BadCase06.c index 8ad07ac540..19b11d341b 100644 --- a/test/Industry/NullReturn_Scene_BadCase06.c +++ b/test/Industry/NullReturn_Scene_BadCase06.c @@ -52,7 +52,6 @@ void TestBad6(unsigned int count) free(buf); } -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --mock-external-calls --check-out-of-memory --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc diff --git a/test/Industry/NullReturn_Scene_BadCase08.cpp b/test/Industry/NullReturn_Scene_BadCase08.cpp index 07870565a0..91e6dccdf8 100644 --- a/test/Industry/NullReturn_Scene_BadCase08.cpp +++ b/test/Industry/NullReturn_Scene_BadCase08.cpp @@ -37,7 +37,6 @@ void TestBad9() printf("the current integer is: %d", *p); // CHECK: KLEE: WARNING: 100.00% NullPointerException True Positive at trace 1 } -// REQUIRES: z3 // RUN: %clangxx %s -emit-llvm %O0opt -c -g -o %t1.bc // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --write-kqueries --use-guided-search=error --location-accuracy --mock-external-calls --check-out-of-memory --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc diff --git a/test/Industry/SecB_ForwardNull.c b/test/Industry/SecB_ForwardNull.c index ef5866afbc..e3a8334c82 100644 --- a/test/Industry/SecB_ForwardNull.c +++ b/test/Industry/SecB_ForwardNull.c @@ -1,8 +1,3 @@ -// REQUIRES: z3 -// RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc -// RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --mock-external-calls --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc -// RUN: FileCheck -input-file=%t.klee-out/warnings.txt %s /* * Copyright (c) Huawei Technologies Co., Ltd. 2021-2021. All rights reserved. * @description 空指针解引用 验收失败 @@ -133,3 +128,8 @@ void badbad(char *ptr) ptr = NULL; *ptr = 'a'; // CHECK: KLEE: WARNING: 100.00% NullPointerException True Positive at trace 1 } + +// RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --mock-external-calls --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc +// RUN: FileCheck -input-file=%t.klee-out/warnings.txt %s \ No newline at end of file diff --git a/test/Industry/SecB_ForwardNull.c.json b/test/Industry/SecB_ForwardNull.c.json index d26344534b..ee8294c266 100644 --- a/test/Industry/SecB_ForwardNull.c.json +++ b/test/Industry/SecB_ForwardNull.c.json @@ -20,7 +20,7 @@ "uri": "/mnt/d/wsl-ubuntu/test2/forward_null/SecB_ForwardNull.c" }, "region": { - "startLine": 133, + "startLine": 128, "startColumn": null } } @@ -33,7 +33,7 @@ "uri": "/mnt/d/wsl-ubuntu/test2/forward_null/SecB_ForwardNull.c" }, "region": { - "startLine": 134, + "startLine": 129, "startColumn": null } } @@ -52,7 +52,7 @@ "uri": "/mnt/d/wsl-ubuntu/test2/forward_null/SecB_ForwardNull.c" }, "region": { - "startLine": 134, + "startLine": 129, "startColumn": null } } diff --git a/test/Industry/UseAfterFree/Double_Free_BadCase01.c b/test/Industry/UseAfterFree/Double_Free_BadCase01.c index cece04e8a7..57d3600faa 100644 --- a/test/Industry/UseAfterFree/Double_Free_BadCase01.c +++ b/test/Industry/UseAfterFree/Double_Free_BadCase01.c @@ -16,8 +16,8 @@ * @author xwx356597;x00407107 * */ + #include -#include //@scene 指针释放后未置空导致双重释放 void DoubleFreeBad01() @@ -36,7 +36,6 @@ void DoubleFreeBad01() free(p); // CHECK: KLEE: WARNING: 100.00% DoubleFree True Positive at trace 1 } -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --mock-external-calls --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc diff --git a/test/Industry/UseAfterFree/Double_Free_BadCase02.c b/test/Industry/UseAfterFree/Double_Free_BadCase02.c index e6e93818d8..be8f1c52c1 100644 --- a/test/Industry/UseAfterFree/Double_Free_BadCase02.c +++ b/test/Industry/UseAfterFree/Double_Free_BadCase02.c @@ -16,8 +16,8 @@ * @author xwx356597;x00407107 * */ + #include -#include //@scene 指针释放后未置空,有条件地再再次释放导致双重释放 void DoubleFreeBad02(int flag) @@ -39,7 +39,6 @@ void DoubleFreeBad02(int flag) } } -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --mock-external-calls --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc diff --git a/test/Industry/UseAfterFree/Free_Not_Set_Null_BadCase02.cpp b/test/Industry/UseAfterFree/Free_Not_Set_Null_BadCase02.cpp index 6c15434bf4..90a32d9903 100644 --- a/test/Industry/UseAfterFree/Free_Not_Set_Null_BadCase02.cpp +++ b/test/Industry/UseAfterFree/Free_Not_Set_Null_BadCase02.cpp @@ -17,7 +17,6 @@ * */ -#include #include #include @@ -34,6 +33,7 @@ typedef struct { int a; char *pname; }Data; + //全局变量 分支结束前要重新赋值 char *MSG = (char*)malloc(1000); @@ -75,7 +75,6 @@ int main() return 0; } -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --mock-external-calls --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc diff --git a/test/Industry/UseAfterFree/Prod_Dereference_After_Free_BadCase01.c b/test/Industry/UseAfterFree/Prod_Dereference_After_Free_BadCase01.c index 9c171549e9..7742d31afd 100644 --- a/test/Industry/UseAfterFree/Prod_Dereference_After_Free_BadCase01.c +++ b/test/Industry/UseAfterFree/Prod_Dereference_After_Free_BadCase01.c @@ -33,7 +33,6 @@ void UseAfterFree() return; } -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --mock-external-calls --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc diff --git a/test/Industry/ZeroDeref_Scene_BadCase02.c b/test/Industry/ZeroDeref_Scene_BadCase02.c index 0e65b66155..dd0fe063ac 100644 --- a/test/Industry/ZeroDeref_Scene_BadCase02.c +++ b/test/Industry/ZeroDeref_Scene_BadCase02.c @@ -38,7 +38,6 @@ void TestBad9() memcpy(pDest, p, BUFFERSIZE); // CHECK-DAG: KLEE: WARNING: 100.00% NullPointerException True Positive at trace 1 } -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --mock-external-calls --check-out-of-memory --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc diff --git a/test/Industry/ZeroDeref_Scene_BadCase05.c b/test/Industry/ZeroDeref_Scene_BadCase05.c index d094cea77b..3afb67837e 100644 --- a/test/Industry/ZeroDeref_Scene_BadCase05.c +++ b/test/Industry/ZeroDeref_Scene_BadCase05.c @@ -62,7 +62,6 @@ void TestBad18(struct STU *stu) HelpBadTest1(NULL); } -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --check-out-of-memory --mock-external-calls --libc=klee --external-calls=all --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc diff --git a/test/Industry/fn_reverse_null.c b/test/Industry/fn_reverse_null.c index 0e02ebc842..aff52b8f68 100644 --- a/test/Industry/fn_reverse_null.c +++ b/test/Industry/fn_reverse_null.c @@ -53,7 +53,6 @@ void TestErr4(TreeNode *head) return; } -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --external-calls=all --mock-external-calls --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --check-out-of-memory --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc diff --git a/test/Industry/fp_forward_null_address.c b/test/Industry/fp_forward_null_address.c index f39297d2a4..e090051722 100644 --- a/test/Industry/fp_forward_null_address.c +++ b/test/Industry/fp_forward_null_address.c @@ -22,7 +22,6 @@ void foo() int v = *p; // CHECK: KLEE: WARNING: 100.00% NullPointerException False Positive at trace 1 } -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --max-cycles-before-stuck=150 --use-guided-search=error --mock-external-calls --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc diff --git a/test/Industry/fp_null_returns_self_define.c b/test/Industry/fp_null_returns_self_define.c index 2ed62cfb68..fa331108b6 100644 --- a/test/Industry/fp_null_returns_self_define.c +++ b/test/Industry/fp_null_returns_self_define.c @@ -1,4 +1,3 @@ -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --mock-external-calls --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc diff --git a/test/Industry/fp_null_returns_self_define2.c b/test/Industry/fp_null_returns_self_define2.c index f737f18cc5..6606140676 100644 --- a/test/Industry/fp_null_returns_self_define2.c +++ b/test/Industry/fp_null_returns_self_define2.c @@ -26,7 +26,6 @@ void TEST_NullReturns004(unsigned short index) sink(value); } -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --mock-external-calls --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc diff --git a/test/Industry/if2.c b/test/Industry/if2.c index d52edf529f..e41a4a0a0e 100644 --- a/test/Industry/if2.c +++ b/test/Industry/if2.c @@ -8,7 +8,6 @@ int main(int x) { return *p; } -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --mock-external-calls --skip-not-symbolic-objects --skip-not-lazy-initialized --check-out-of-memory --search=bfs --max-stepped-instructions=20 --max-cycles-before-stuck=0 --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc diff --git a/test/Industry/test.c b/test/Industry/test.c index 9d84770da0..5b08e0cd97 100644 --- a/test/Industry/test.c +++ b/test/Industry/test.c @@ -19,7 +19,6 @@ void TestBad8(int len) buf[0] = 'a'; // CHECK-NUM: KLEE: WARNING: 100.00% NullPointerException True Positive at trace 1 } // CHECK-UID: KLEE: WARNING: 100.00% NullPointerException True Positive at trace 8389b1896658d867c9e15267acfe8c32 -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --mock-external-calls --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --check-out-of-memory --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc diff --git a/test/Industry/while_true.c b/test/Industry/while_true.c index a2eebdcc0a..f0566cce12 100644 --- a/test/Industry/while_true.c +++ b/test/Industry/while_true.c @@ -8,7 +8,6 @@ int main() { return *p; } -// REQUIRES: z3 // RUN: %clang %s -emit-llvm -c -g -O0 -Xclang -disable-O0-optnone -o %t1.bc // RUN: rm -rf %t.klee-out-1 // RUN: %klee --output-dir=%t.klee-out-1 --use-guided-search=error --mock-external-calls --skip-not-symbolic-objects --skip-not-lazy-initialized --check-out-of-memory --max-stepped-instructions=10 --max-cycles-before-stuck=0 --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc diff --git a/test/Industry/wrapped_btor2c-lazyMod.adding.1.prop1-back-serstep.c b/test/Industry/wrapped_btor2c-lazyMod.adding.1.prop1-back-serstep.c index 7a6d4ff09c..6048923249 100644 --- a/test/Industry/wrapped_btor2c-lazyMod.adding.1.prop1-back-serstep.c +++ b/test/Industry/wrapped_btor2c-lazyMod.adding.1.prop1-back-serstep.c @@ -1,7 +1,8 @@ -// REQUIRES: z3 +// REQUIRES: not-msan +// Disabling msan because it times out on CI // RUN: %clang %s -emit-llvm %O0opt -g -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --use-forked-solver=false --solver-backend=z3 -max-memory=6008 --optimize=true --skip-not-lazy-initialized -output-source=true --output-stats=false --output-istats=false --write-xml-tests --write-ktests=false --xml-metadata-programfile=wrapped_btor2c-lazyMod.adding.1.prop1-back-serstep.c --xml-metadata-programhash=a18daeacf63b42ad6e1cb490555b7cdecd71ad6e58b167ed0f5626c03bc3d772 --use-sym-size-alloc=true --cex-cache-validity-cores --symbolic-allocation-threshold=8192 --function-call-reproduce=reach_error --dump-states-on-halt=false -exit-on-error-type=Assert --search=dfs --search=random-path -max-time=20 %t1.bc 2>&1 | FileCheck -check-prefix=CHECK-VERDICT %s +// RUN: %klee --output-dir=%t.klee-out --use-forked-solver=false -max-memory=6008 --optimize=true --skip-not-lazy-initialized -output-source=true --output-stats=false --output-istats=false --write-xml-tests --write-ktests=false --xml-metadata-programfile=wrapped_btor2c-lazyMod.adding.1.prop1-back-serstep.c --xml-metadata-programhash=a18daeacf63b42ad6e1cb490555b7cdecd71ad6e58b167ed0f5626c03bc3d772 --use-sym-size-alloc=true --cex-cache-validity-cores --symbolic-allocation-threshold=8192 --function-call-reproduce=reach_error --dump-states-on-halt=false -exit-on-error-type=Assert --search=dfs --search=random-path -max-time=20 %t1.bc 2>&1 | FileCheck -check-prefix=CHECK-VERDICT %s // RUN: test -f %t.klee-out/test000001.xml // RUN: not test -f %t.klee-out/test000001.ktest diff --git a/test/regression/2023-02-01-replay-test-with-lazy-initialized-objects.c b/test/regression/2023-02-01-replay-test-with-lazy-initialized-objects.c index ec58f72187..66edca58dc 100644 --- a/test/regression/2023-02-01-replay-test-with-lazy-initialized-objects.c +++ b/test/regression/2023-02-01-replay-test-with-lazy-initialized-objects.c @@ -1,7 +1,7 @@ -// REQUIRES: not-darwin, z3 +// REQUIRES: not-darwin // RUN: %clang %s -emit-llvm %O0opt -c -o %t.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --libc=klee --posix-runtime --solver-backend=z3 --skip-not-lazy-initialized --skip-not-symbolic-objects %t.bc > %t.log +// RUN: %klee --output-dir=%t.klee-out --libc=klee --posix-runtime --skip-not-lazy-initialized --skip-not-symbolic-objects %t.bc > %t.log // RUN: test -f %t.klee-out/test000006.ktest diff --git a/test/regression/2023-10-04-email_spec0_product16.cil.c b/test/regression/2023-10-04-email_spec0_product16.cil.c index 8a4acd5c58..e407b7bbb2 100644 --- a/test/regression/2023-10-04-email_spec0_product16.cil.c +++ b/test/regression/2023-10-04-email_spec0_product16.cil.c @@ -1,7 +1,6 @@ -// REQUIRES: z3 // RUN: %clang -Wno-everything %s -emit-llvm %O0opt -g -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --use-forked-solver=false --solver-backend=z3 -max-memory=6008 --optimize --skip-not-lazy-initialized -istats-write-interval=90s -exit-on-error-type=Assert --search=dfs -max-time=10s %t1.bc 2>&1 | FileCheck -check-prefix=CHECK %s +// RUN: %klee --output-dir=%t.klee-out --use-forked-solver=false --max-memory=6008 --optimize --skip-not-lazy-initialized --istats-write-interval=90s --exit-on-error-type=Assert --search=dfs --max-time=10s %t1.bc 2>&1 | FileCheck -check-prefix=CHECK %s // RUN find %t.klee-out -type f -name "*.assert.err" | sed 's/assert\.err/ktest/' | xargs %ktest-tool | FileCheck -check-prefix=CHECK-TEST %s // CHECK-TEST-NOT: object 20 diff --git a/test/regression/2023-10-06-ChenFlurMukhopadhyay-2012SAS-Fig1-alloca.c b/test/regression/2023-10-06-ChenFlurMukhopadhyay-2012SAS-Fig1-alloca.c index 9b27688a42..d08c61d74a 100644 --- a/test/regression/2023-10-06-ChenFlurMukhopadhyay-2012SAS-Fig1-alloca.c +++ b/test/regression/2023-10-06-ChenFlurMukhopadhyay-2012SAS-Fig1-alloca.c @@ -1,4 +1,3 @@ -// REQUIRES: z3 // RUN: %clang -Wno-everything %s -emit-llvm %O0opt -g -c -o %t1.bc // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --optimize=true --delete-dead-loops=false --use-forked-solver=false -max-memory=6008 --cex-cache-validity-cores --only-output-states-covering-new=true --dump-states-on-halt=true %t1.bc 2>&1 | FileCheck -check-prefix=CHECK %s diff --git a/test/regression/2023-10-06-Dubois-015.c b/test/regression/2023-10-06-Dubois-015.c index f70af983b4..fccb9acd93 100644 --- a/test/regression/2023-10-06-Dubois-015.c +++ b/test/regression/2023-10-06-Dubois-015.c @@ -29,7 +29,10 @@ void abort_prog() { abort(); } int __VERIFIER_nondet_int(); -void reach_error() { abort_prog(); __assert_fail("0", "Dubois-015.c", 5, "reach_error"); } +void reach_error() { + abort_prog(); + __assert_fail("0", "Dubois-015.c", 5, "reach_error"); +} void assume(int cond) { if (!cond) abort_prog(); From f1e87206cae546fcf62208ad58c5b124ec6f2a40 Mon Sep 17 00:00:00 2001 From: Yurii Kostyukov Date: Tue, 10 Oct 2023 16:28:14 +0300 Subject: [PATCH 039/103] [feat] Improved Iterative Deepening Searcher --- lib/Core/ExecutionState.h | 17 +- lib/Core/Executor.cpp | 12 +- lib/Core/Searcher.cpp | 110 +- lib/Core/Searcher.h | 42 +- lib/Core/StatsTracker.cpp | 2 +- lib/Core/TargetManager.h | 20 +- lib/Core/UserSearcher.cpp | 32 +- test/Feature/Searchers.c | 8 +- ...r.3.ufo.UNBOUNDED.pals+Problem12_label00.c | 5147 +++++++++++++++++ 9 files changed, 5303 insertions(+), 87 deletions(-) create mode 100644 test/Industry/pals_lcr.3.ufo.UNBOUNDED.pals+Problem12_label00.c diff --git a/lib/Core/ExecutionState.h b/lib/Core/ExecutionState.h index 9492e1ce02..d10afb7072 100644 --- a/lib/Core/ExecutionState.h +++ b/lib/Core/ExecutionState.h @@ -127,6 +127,7 @@ struct ExecutionStack { inline value_stack_ty &valueStack() { return valueStack_; } inline const value_stack_ty &valueStack() const { return valueStack_; } inline const call_stack_ty &callStack() const { return callStack_; } + inline const info_stack_ty &infoStack() const { return infoStack_; } inline info_stack_ty &infoStack() { return infoStack_; } inline const call_stack_ty &uniqueFrames() const { return uniqueFrames_; } @@ -491,16 +492,18 @@ class ExecutionState { bool reachedTarget(ref target) const; static std::uint32_t getLastID() { return nextID - 1; }; - inline bool isStuck(unsigned long long bound) { - KInstruction *prevKI = prevPC; - if (prevKI->inst->isTerminator() && stack.size() > 0) { - auto level = stack.infoStack().back().multilevel[getPCBlock()].second; - return bound && level > bound; + inline bool isStuck(unsigned long long bound) const { + if (bound == 0) + return false; + if (prevPC->inst->isTerminator() && stack.size() > 0) { + auto &ml = stack.infoStack().back().multilevel; + auto level = ml.find(getPCBlock()); + return level != ml.end() && level->second > bound; } if (pc == pc->parent->getFirstInstruction() && pc->parent == pc->parent->parent->entryKBlock) { - auto level = stack.multilevel[stack.callStack().back().kf].second; - return bound && level > bound; + auto level = stack.multilevel.at(stack.callStack().back().kf); + return level > bound; } return false; } diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index e30001d601..0705439d90 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -4295,8 +4295,6 @@ void Executor::run(std::vector initialStates) { while (!states.empty() && !haltExecution) { while (!searcher->empty() && !haltExecution) { ExecutionState &state = searcher->selectState(); - KInstruction *prevKI = state.prevPC; - KFunction *kf = prevKI->parent->parent; executeStep(state); } @@ -4375,8 +4373,6 @@ static std::string terminationTypeFileExtension(StateTerminationType type) { }; void Executor::executeStep(ExecutionState &state) { - KInstruction *prevKI = state.prevPC; - if (CoverOnTheFly && guidanceKind != GuidanceKind::ErrorGuidance && stats::instructions > DelayCoverOnTheFly && shouldWriteTest(state)) { state.clearCoveredNew(); @@ -4389,13 +4385,7 @@ void Executor::executeStep(ExecutionState &state) { if (targetManager->isTargeted(state) && state.targets().empty()) { terminateStateEarlyAlgorithm(state, "State missed all it's targets.", StateTerminationType::MissedAllTargets); - } else if (prevKI->inst->isTerminator() && MaxCycles && - (state.stack.infoStack() - .back() - .multilevel[state.getPCBlock()] - .second > MaxCycles || - state.stack.multilevel[state.stack.callStack().back().kf].second > - MaxCycles)) { + } else if (state.isStuck(MaxCycles)) { terminateStateEarly(state, "max-cycles exceeded.", StateTerminationType::MaxCycles); } else { diff --git a/lib/Core/Searcher.cpp b/lib/Core/Searcher.cpp index 644d5904a0..d9762e752d 100644 --- a/lib/Core/Searcher.cpp +++ b/lib/Core/Searcher.cpp @@ -640,33 +640,94 @@ void BatchingSearcher::printName(llvm::raw_ostream &os) { /// -IterativeDeepeningTimeSearcher::IterativeDeepeningTimeSearcher( - Searcher *baseSearcher) - : baseSearcher{baseSearcher} {}; +class TimeMetric final : public IterativeDeepeningSearcher::Metric { + time::Point startTime; + time::Span time{time::seconds(1)}; -ExecutionState &IterativeDeepeningTimeSearcher::selectState() { +public: + void selectState() final { startTime = time::getWallTime(); } + bool exceeds(const ExecutionState &state) const final { + return time::getWallTime() - startTime > time; + } + void increaseLimit() final { + time *= 2U; + klee_message("increased time budget to %f seconds", time.toSeconds()); + } +}; + +class MaxCyclesMetric final : public IterativeDeepeningSearcher::Metric { +public: + using ty = unsigned long long; + +private: + ty maxCycles; + +public: + explicit MaxCyclesMetric(ty maxCycles) : maxCycles(maxCycles){}; + explicit MaxCyclesMetric() : MaxCyclesMetric(1ULL){}; + + bool exceeds(const ExecutionState &state) const final { + return state.isStuck(maxCycles); + } + void increaseLimit() final { + maxCycles *= 2ULL; + klee_message("increased max-cycles to %llu", maxCycles); + } +}; + +IterativeDeepeningSearcher::IterativeDeepeningSearcher( + Searcher *baseSearcher, TargetManagerSubscriber *tms, + HaltExecution::Reason m) + : baseSearcher{baseSearcher}, tms{tms} { + switch (m) { + case HaltExecution::Reason::MaxTime: + metric = std::make_unique(); + return; + case HaltExecution::Reason::MaxCycles: + metric = std::make_unique(); + return; + default: + klee_error("Illegal metric for iterative deepening searcher: %d", m); + } +} + +ExecutionState &IterativeDeepeningSearcher::selectState() { ExecutionState &res = baseSearcher->selectState(); - startTime = time::getWallTime(); + metric->selectState(); return res; } -void IterativeDeepeningTimeSearcher::update( - ExecutionState *current, const std::vector &addedStates, - const std::vector &removedStates) { +void IterativeDeepeningSearcher::filter(const StatesVector &states, + StatesVector &result) const { + StatesVector states1(states); + std::sort(states1.begin(), states1.end()); + std::set_difference(states1.begin(), states1.end(), pausedStates.begin(), + pausedStates.end(), std::back_inserter(result)); +} - const auto elapsed = time::getWallTime() - startTime; +void IterativeDeepeningSearcher::update( + const TargetHistoryTargetPairToStatesMap &added, + const TargetHistoryTargetPairToStatesMap &removed) { + if (!tms) + return; + TargetHistoryTargetPairToStatesMap removedRefined(removed.size()); + for (const auto &pair : removed) { + StatesVector refined; + IterativeDeepeningSearcher::filter(pair.second, refined); + removedRefined.emplace(pair.first, std::move(refined)); + } + tms->update(added, removedRefined); +} + +void IterativeDeepeningSearcher::update(ExecutionState *current, + const StatesVector &addedStates, + const StatesVector &removedStates) { // update underlying searcher (filter paused states unknown to underlying // searcher) if (!removedStates.empty()) { - std::vector alt = removedStates; - for (const auto state : removedStates) { - auto it = pausedStates.find(state); - if (it != pausedStates.end()) { - pausedStates.erase(it); - alt.erase(std::remove(alt.begin(), alt.end(), state), alt.end()); - } - } + StatesVector alt; + IterativeDeepeningSearcher::filter(removedStates, alt); baseSearcher->update(current, addedStates, alt); } else { baseSearcher->update(current, addedStates, removedStates); @@ -676,27 +737,26 @@ void IterativeDeepeningTimeSearcher::update( if (current && std::find(removedStates.begin(), removedStates.end(), current) == removedStates.end() && - elapsed > time) { + metric->exceeds(*current)) { pausedStates.insert(current); baseSearcher->update(nullptr, {}, {current}); } // no states left in underlying searcher: fill with paused states if (baseSearcher->empty()) { - time *= 2U; - klee_message("increased time budget to %f\n", time.toSeconds()); - std::vector ps(pausedStates.begin(), pausedStates.end()); - baseSearcher->update(nullptr, ps, std::vector()); + metric->increaseLimit(); + StatesVector ps(pausedStates.begin(), pausedStates.end()); + baseSearcher->update(nullptr, ps, {}); pausedStates.clear(); } } -bool IterativeDeepeningTimeSearcher::empty() { +bool IterativeDeepeningSearcher::empty() { return baseSearcher->empty() && pausedStates.empty(); } -void IterativeDeepeningTimeSearcher::printName(llvm::raw_ostream &os) { - os << "IterativeDeepeningTimeSearcher\n"; +void IterativeDeepeningSearcher::printName(llvm::raw_ostream &os) { + os << "IterativeDeepeningSearcher\n"; } /// diff --git a/lib/Core/Searcher.h b/lib/Core/Searcher.h index 0a6c734f73..957ca3d18f 100644 --- a/lib/Core/Searcher.h +++ b/lib/Core/Searcher.h @@ -160,17 +160,10 @@ class GuidedSearcher final : public Searcher, public TargetManagerSubscriber { using TargetHistoryTargetPairHashMap = std::unordered_map; - - using TargetHistoryTargetPair = - std::pair, ref>; using TargetHistoryTargetPairToSearcherMap = std::unordered_map, TargetHistoryTargetHash, TargetHistoryTargetCmp>; - using StatesVector = std::vector; - using TargetHistoryTargetPairToStatesMap = - std::unordered_map; using TargetForestHisoryTargetVector = std::vector; using TargetForestHistoryTargetSet = std::unordered_set baseSearcher; - time::Point startTime; - time::Span time{time::seconds(1)}; + TargetManagerSubscriber *tms; + std::unique_ptr metric; std::set pausedStates; + void filter(const std::vector &states, + std::vector &result) const; + public: /// \param baseSearcher The underlying searcher (takes ownership). - explicit IterativeDeepeningTimeSearcher(Searcher *baseSearcher); - ~IterativeDeepeningTimeSearcher() override = default; + explicit IterativeDeepeningSearcher(Searcher *baseSearcher, + TargetManagerSubscriber *tms, + HaltExecution::Reason metric); + ~IterativeDeepeningSearcher() override = default; ExecutionState &selectState() override; void update(ExecutionState *current, const std::vector &addedStates, const std::vector &removedStates) override; + void update(const TargetHistoryTargetPairToStatesMap &added, + const TargetHistoryTargetPairToStatesMap &removed) override; bool empty() override; void printName(llvm::raw_ostream &os) override; }; diff --git a/lib/Core/StatsTracker.cpp b/lib/Core/StatsTracker.cpp index 3a1f3a11f2..c2b9b4769d 100644 --- a/lib/Core/StatsTracker.cpp +++ b/lib/Core/StatsTracker.cpp @@ -392,7 +392,7 @@ void StatsTracker::stepInstruction(ExecutionState &es) { Instruction *inst = es.pc->inst; const KInstruction *ki = es.pc; - InfoStackFrame &sf = es.stack.infoStack().back(); + auto &sf = es.stack.infoStack().back(); theStatisticManager->setIndex(ki->getGlobalIndex()); if (UseCallPaths) theStatisticManager->setContext(&sf.callPathNode->statistics); diff --git a/lib/Core/TargetManager.h b/lib/Core/TargetManager.h index 3d3188b1f6..5e65834140 100644 --- a/lib/Core/TargetManager.h +++ b/lib/Core/TargetManager.h @@ -25,15 +25,15 @@ namespace klee { class TargetCalculator; +using TargetHistoryTargetPair = + std::pair, ref>; +using StatesVector = std::vector; +using TargetHistoryTargetPairToStatesMap = + std::unordered_map; + class TargetManagerSubscriber { public: - using TargetHistoryTargetPair = - std::pair, ref>; - using StatesVector = std::vector; - using TargetHistoryTargetPairToStatesMap = - std::unordered_map; - virtual ~TargetManagerSubscriber() = default; /// Selects a state for further exploration. @@ -47,12 +47,6 @@ class TargetManager { using StatesSet = std::unordered_set; using StateToDistanceMap = std::unordered_map>; - using TargetHistoryTargetPair = - std::pair, ref>; - using StatesVector = std::vector; - using TargetHistoryTargetPairToStatesMap = - std::unordered_map; using TargetForestHistoryTargetSet = std::unordered_set; diff --git a/lib/Core/UserSearcher.cpp b/lib/Core/UserSearcher.cpp index 8de5273052..59674a84f7 100644 --- a/lib/Core/UserSearcher.cpp +++ b/lib/Core/UserSearcher.cpp @@ -55,11 +55,17 @@ cl::list CoreSearch( clEnumValN(Searcher::NURS_QC, "nurs:qc", "use NURS with Query-Cost")), cl::cat(SearchCat)); -cl::opt UseIterativeDeepeningTimeSearch( - "use-iterative-deepening-time-search", - cl::desc( - "Use iterative deepening time search (experimental) (default=false)"), - cl::init(false), cl::cat(SearchCat)); +cl::opt UseIterativeDeepeningSearch( + "use-iterative-deepening-search", + cl::desc("Use iterative deepening search based on metric (experimental) " + "(default=unspecified)"), + cl::values(clEnumValN(HaltExecution::Reason::Unspecified, "unspecified", + "Do not use iterative deepening search (default)"), + clEnumValN(HaltExecution::Reason::MaxTime, "max-time", + "metric is maximum time"), + clEnumValN(HaltExecution::Reason::MaxCycles, "max-cycles", + "metric is maximum cycles")), + cl::init(HaltExecution::Reason::Unspecified), cl::cat(SearchCat)); cl::opt UseBatchingSearch( "use-batching-search", @@ -172,16 +178,22 @@ Searcher *klee::constructUserSearcher(Executor &executor, BatchInstructions); } - if (UseIterativeDeepeningTimeSearch) { - searcher = new IterativeDeepeningTimeSearcher(searcher); - } - + TargetManagerSubscriber *tms = nullptr; if (executor.guidanceKind != Interpreter::GuidanceKind::NoGuidance) { searcher = new GuidedSearcher(searcher, *executor.distanceCalculator, executor.theRNG); - executor.targetManager->subscribe(*static_cast(searcher)); + tms = static_cast(searcher); } + if (UseIterativeDeepeningSearch != HaltExecution::Reason::Unspecified) { + searcher = new IterativeDeepeningSearcher(searcher, tms, + UseIterativeDeepeningSearch); + tms = static_cast(searcher); + } + + if (tms) + executor.targetManager->subscribe(*tms); + llvm::raw_ostream &os = executor.getHandler().getInfoStream(); os << "BEGIN searcher description\n"; diff --git a/test/Feature/Searchers.c b/test/Feature/Searchers.c index 84abd378d1..aacb09de59 100644 --- a/test/Feature/Searchers.c +++ b/test/Feature/Searchers.c @@ -18,13 +18,13 @@ // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --search=random-path --search=nurs:qc %t2.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --use-iterative-deepening-time-search --use-batching-search %t2.bc +// RUN: %klee --output-dir=%t.klee-out --use-iterative-deepening-search=max-time --use-batching-search %t2.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --use-iterative-deepening-time-search --use-batching-search --search=random-state %t2.bc +// RUN: %klee --output-dir=%t.klee-out --use-iterative-deepening-search=max-time --use-batching-search --search=random-state %t2.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --use-iterative-deepening-time-search --use-batching-search --search=nurs:depth %t2.bc +// RUN: %klee --output-dir=%t.klee-out --use-iterative-deepening-search=max-time --use-batching-search --search=nurs:depth %t2.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --use-iterative-deepening-time-search --use-batching-search --search=nurs:qc %t2.bc +// RUN: %klee --output-dir=%t.klee-out --use-iterative-deepening-search=max-time --use-batching-search --search=nurs:qc %t2.bc /* this test is basically just for coverage and doesn't really do any correctness check (aside from testing that the various combinations diff --git a/test/Industry/pals_lcr.3.ufo.UNBOUNDED.pals+Problem12_label00.c b/test/Industry/pals_lcr.3.ufo.UNBOUNDED.pals+Problem12_label00.c new file mode 100644 index 0000000000..36a3bb4ab7 --- /dev/null +++ b/test/Industry/pals_lcr.3.ufo.UNBOUNDED.pals+Problem12_label00.c @@ -0,0 +1,5147 @@ +// REQUIRES: geq-llvm-14.0 +// RUN: %clang %s -emit-llvm %O0opt -g -c -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --delete-dead-loops=false --emit-all-errors --mock-all-externals --use-forked-solver=false --optimize --skip-not-lazy-initialized --output-source=false --output-stats=true --output-istats=true -istats-write-interval=3s --use-sym-size-alloc=true --cex-cache-validity-cores --symbolic-allocation-threshold=8192 --cover-on-the-fly=false --delay-cover-on-the-fly=400000 --only-output-states-covering-new --dump-states-on-halt=true --search=dfs --search=random-state --use-iterative-deepening-search=max-cycles --max-cycles=4 %t1.bc +// RUN: %klee-stats --print-columns 'BCov(%)' --table-format=csv %t.klee-out > %t.stats +// RUN: FileCheck -input-file=%t.stats %s + +// Branch coverage at least 94%: +// CHECK: BCov(%) +// CHECK-NEXT: {{(9[4-9]|100)\.}} + +// This file is part of the SV-Benchmarks collection of verification tasks: +// https://gitlab.com/sosy-lab/benchmarking/sv-benchmarks +// +// SPDX-FileCopyrightText: 2012 The RERS Challenge +// SPDX-FileCopyrightText: 2013 Carnegie Mellon University +// SPDX-FileCopyrightText: 2014-2020 The SV-Benchmarks Community +// +// SPDX-License-Identifier: Apache-2.0 +// SPDX-License-Identifier: LicenseRef-BSD-3-Clause-Attribution-CMU +#include "klee-test-comp.c" + +extern unsigned int __VERIFIER_nondet_uint(); +extern char __VERIFIER_nondet_char(); +extern int __VERIFIER_nondet_int(); +extern long __VERIFIER_nondet_long(); +extern unsigned long __VERIFIER_nondet_ulong(); +extern float __VERIFIER_nondet_float(); +extern void exit(int); +extern void abort(void); +extern void __assert_fail(const char *, const char *, unsigned int, const char *) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__noreturn__)); +void reach_error() { __assert_fail("0", "pals_lcr.3.ufo.UNBOUNDED.pals.c", 3, "reach_error"); } + + +/* Generated by CIL v. 1.6.0 */ +/* print_CIL_Input is true */ + +_Bool __VERIFIER_nondet_bool(void) ; +char __VERIFIER_nondet_char(void) ; +unsigned char __VERIFIER_nondet_uchar(void) ; +void assert(_Bool arg ) ; +void abort(void); +void assume_abort_if_not(int cond) { + if(!cond) {abort();} +} +typedef char msg_t; +typedef int port_t; +extern void read(port_t p , msg_t m ) ; +extern void write(port_t p , msg_t m ) ; +msg_t nomsg = (msg_t )-1; +unsigned char r1 ; +port_t p1 ; +char p1_old ; +char p1_new ; +char id1 ; +char st1 ; +msg_t send1 ; +_Bool mode1 ; +port_t p2 ; +char p2_old ; +char p2_new ; +char id2 ; +char st2 ; +msg_t send2 ; +_Bool mode2 ; +port_t p3 ; +char p3_old ; +char p3_new ; +char id3 ; +char st3 ; +msg_t send3 ; +_Bool mode3 ; +void node1(void) +{ + msg_t m1 ; + + { + m1 = nomsg; + if (mode1) { + if (r1 == 255) { + r1 = 2; + } + r1 = r1 + 1; + m1 = p3_old; + p3_old = nomsg; + if ((int )m1 != (int )nomsg) { + if ((int )m1 > (int )id1) { + send1 = m1; + } else + if ((int )m1 == (int )id1) { + st1 = (char)1; + } + } + mode1 = (_Bool)0; + } else { + p1_new = send1 != nomsg && p1_new == nomsg ? send1 : p1_new; + mode1 = (_Bool)1; + } + return; +} +} +void node2(void) +{ + msg_t m2 ; + + { + m2 = nomsg; + if (mode2) { + m2 = p1_old; + p1_old = nomsg; + if ((int )m2 != (int )nomsg) { + if ((int )m2 > (int )id2) { + send2 = m2; + } else + if ((int )m2 == (int )id2) { + st2 = (char)1; + } + } + mode2 = (_Bool)0; + } else { + p2_new = send2 != nomsg && p2_new == nomsg ? send2 : p2_new; + mode2 = (_Bool)1; + } + return; +} +} +void node3(void) +{ + msg_t m3 ; + + { + m3 = nomsg; + if (mode3) { + m3 = p2_old; + p2_old = nomsg; + if ((int )m3 != (int )nomsg) { + if ((int )m3 > (int )id3) { + send3 = m3; + } else + if ((int )m3 == (int )id3) { + st3 = (char)1; + } + } + mode3 = (_Bool)0; + } else { + p3_new = send3 != nomsg && p3_new == nomsg ? send3 : p3_new; + mode3 = (_Bool)1; + } + return; +} +} +int init(void) +{ + int tmp ; + + { + if ((int )r1 == 0) { + if ((int )id1 >= 0) { + if ((int )st1 == 0) { + if ((int )send1 == (int )id1) { + if ((int )mode1 == 0) { + if ((int )id2 >= 0) { + if ((int )st2 == 0) { + if ((int )send2 == (int )id2) { + if ((int )mode2 == 0) { + if ((int )id3 >= 0) { + if ((int )st3 == 0) { + if ((int )send3 == (int )id3) { + if ((int )mode3 == 0) { + if ((int )id1 != (int )id2) { + if ((int )id1 != (int )id3) { + if ((int )id2 != (int )id3) { + tmp = 1; + } else { + tmp = 0; + } + } else { + tmp = 0; + } + } else { + tmp = 0; + } + } else { + tmp = 0; + } + } else { + tmp = 0; + } + } else { + tmp = 0; + } + } else { + tmp = 0; + } + } else { + tmp = 0; + } + } else { + tmp = 0; + } + } else { + tmp = 0; + } + } else { + tmp = 0; + } + } else { + tmp = 0; + } + } else { + tmp = 0; + } + } else { + tmp = 0; + } + } else { + tmp = 0; + } + } else { + tmp = 0; + } + return (tmp); +} +} +int check(void) +{ + int tmp ; + + { + if (((int )st1 + (int )st2) + (int )st3 <= 1) { + if ((int )r1 >= 3) { + goto _L; + } else + if (((int )st1 + (int )st2) + (int )st3 == 0) { + _L: /* CIL Label */ + if ((int )r1 < 3) { + tmp = 1; + } else + if (((int )st1 + (int )st2) + (int )st3 == 1) { + tmp = 1; + } else { + tmp = 0; + } + } else { + tmp = 0; + } + } else { + tmp = 0; + } + return (tmp); +} +} +int main1(void) +{ + int c1 ; + int i2 ; + + { + c1 = 0; + r1 = __VERIFIER_nondet_uchar(); + id1 = __VERIFIER_nondet_char(); + st1 = __VERIFIER_nondet_char(); + send1 = __VERIFIER_nondet_char(); + mode1 = __VERIFIER_nondet_bool(); + id2 = __VERIFIER_nondet_char(); + st2 = __VERIFIER_nondet_char(); + send2 = __VERIFIER_nondet_char(); + mode2 = __VERIFIER_nondet_bool(); + id3 = __VERIFIER_nondet_char(); + st3 = __VERIFIER_nondet_char(); + send3 = __VERIFIER_nondet_char(); + mode3 = __VERIFIER_nondet_bool(); + i2 = init(); + assume_abort_if_not(i2); + p1_old = nomsg; + p1_new = nomsg; + p2_old = nomsg; + p2_new = nomsg; + p3_old = nomsg; + p3_new = nomsg; + i2 = 0; + while (1) { + { + node1(); + node2(); + node3(); + p1_old = p1_new; + p1_new = nomsg; + p2_old = p2_new; + p2_new = nomsg; + p3_old = p3_new; + p3_new = nomsg; + c1 = check(); + assert(c1); + } + } +} +return 0; +} +void assert(_Bool arg ) +{ + + + { + if (! arg) { + { + ERROR: {reach_error();abort();} + } + } +} +} + +int calculate_output(int); +int calculate_output2(int); +int calculate_output3(int); +int calculate_output4(int); +extern void abort(void); +extern void __assert_fail(const char *, const char *, unsigned int, const char *) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__noreturn__)); +extern int __VERIFIER_nondet_int(void); +extern void exit(int); + + // inputs + int inputC = 3; + int inputF = 6; + int inputA = 1; + int inputB = 2; + int inputD = 4; + int inputE = 5; + + + int a17 = -124; + int a5 = 4; + int a24 = 15; + int a2 = 170; + int a7 = 13; + + int calculate_output2(int input); + int calculate_output3(int input); + int calculate_output4(int input); + + int calculate_output(int input) { + if((((((a7==14) && a2 <= 189 ) && ((111 < a17) && (255 >= a17)) ) && (a24==13)) && (a5==3))){ + error_7: exit(0); + } + if((((((a7==12) && a2 <= 189 ) && a17 <= -108 ) && (a24==13)) && (a5==4))){ + error_35: exit(0); + } + if((((((a7==14) && a2 <= 189 ) && ((111 < a17) && (255 >= a17)) ) && (a24==14)) && (a5==4))){ + error_55: exit(0); + } + if((((((a7==14) && a2 <= 189 ) && ((-108 < a17) && (111 >= a17)) ) && (a24==13)) && (a5==4))){ + error_40: exit(0); + } + if((((((a7==13) && a2 <= 189 ) && a17 <= -108 ) && (a24==14)) && (a5==4))){ + error_48: exit(0); + } + if((((((a7==13) && a2 <= 189 ) && ((-108 < a17) && (111 >= a17)) ) && (a24==14)) && (a5==4))){ + error_51: exit(0); + } + if((((((a7==12) && a2 <= 189 ) && 255 < a17 ) && (a24==14)) && (a5==3))){ + error_20: exit(0); + } + if((((((a7==14) && a2 <= 189 ) && a17 <= -108 ) && (a24==13)) && (a5==4))){ + error_37: exit(0); + } + if((((((a7==14) && a2 <= 189 ) && ((111 < a17) && (255 >= a17)) ) && (a24==14)) && (a5==3))){ + error_19: exit(0); + } + if((((((a7==13) && a2 <= 189 ) && a17 <= -108 ) && (a24==13)) && (a5==3))){ + error_0: {reach_error();abort();} + } + if((((((a7==14) && a2 <= 189 ) && 255 < a17 ) && (a24==15)) && (a5==3))){ + error_34: exit(0); + } + if((((((a7==14) && a2 <= 189 ) && a17 <= -108 ) && (a24==15)) && (a5==3))){ + error_25: exit(0); + } + if((((((a7==12) && a2 <= 189 ) && ((-108 < a17) && (111 >= a17)) ) && (a24==14)) && (a5==4))){ + error_50: exit(0); + } + if((((((a7==13) && a2 <= 189 ) && ((-108 < a17) && (111 >= a17)) ) && (a24==13)) && (a5==3))){ + error_3: exit(0); + } + if((((((a7==14) && a2 <= 189 ) && ((-108 < a17) && (111 >= a17)) ) && (a24==15)) && (a5==3))){ + error_28: exit(0); + } + if((((((a7==13) && a2 <= 189 ) && ((-108 < a17) && (111 >= a17)) ) && (a24==13)) && (a5==4))){ + error_39: exit(0); + } + if((((((a7==13) && a2 <= 189 ) && 255 < a17 ) && (a24==14)) && (a5==3))){ + error_21: exit(0); + } + if((((((a7==13) && a2 <= 189 ) && ((111 < a17) && (255 >= a17)) ) && (a24==13)) && (a5==3))){ + error_6: exit(0); + } + if((((((a7==12) && a2 <= 189 ) && ((-108 < a17) && (111 >= a17)) ) && (a24==13)) && (a5==4))){ + error_38: exit(0); + } + if((((((a7==13) && a2 <= 189 ) && ((111 < a17) && (255 >= a17)) ) && (a24==15)) && (a5==3))){ + error_30: exit(0); + } + if((((((a7==13) && a2 <= 189 ) && ((111 < a17) && (255 >= a17)) ) && (a24==13)) && (a5==4))){ + error_42: exit(0); + } + if((((((a7==14) && a2 <= 189 ) && 255 < a17 ) && (a24==13)) && (a5==3))){ + error_10: exit(0); + } + if((((((a7==14) && a2 <= 189 ) && a17 <= -108 ) && (a24==14)) && (a5==3))){ + error_13: exit(0); + } + if((((((a7==12) && a2 <= 189 ) && 255 < a17 ) && (a24==13)) && (a5==3))){ + error_8: exit(0); + } + if((((((a7==14) && a2 <= 189 ) && ((-108 < a17) && (111 >= a17)) ) && (a24==14)) && (a5==4))){ + error_52: exit(0); + } + if((((((a7==13) && a2 <= 189 ) && ((-108 < a17) && (111 >= a17)) ) && (a24==15)) && (a5==3))){ + error_27: exit(0); + } + if((((((a7==12) && a2 <= 189 ) && ((111 < a17) && (255 >= a17)) ) && (a24==14)) && (a5==4))){ + error_53: exit(0); + } + if((((((a7==13) && a2 <= 189 ) && ((111 < a17) && (255 >= a17)) ) && (a24==14)) && (a5==4))){ + error_54: exit(0); + } + if((((((a7==14) && a2 <= 189 ) && 255 < a17 ) && (a24==14)) && (a5==4))){ + error_58: exit(0); + } + if((((((a7==12) && a2 <= 189 ) && a17 <= -108 ) && (a24==15)) && (a5==3))){ + error_23: exit(0); + } + if((((((a7==12) && a2 <= 189 ) && a17 <= -108 ) && (a24==13)) && (a5==3))){ + globalError: exit(0); + } + if((((((a7==13) && a2 <= 189 ) && 255 < a17 ) && (a24==14)) && (a5==4))){ + error_57: exit(0); + } + if((((((a7==12) && a2 <= 189 ) && a17 <= -108 ) && (a24==14)) && (a5==4))){ + error_47: exit(0); + } + if((((((a7==12) && a2 <= 189 ) && a17 <= -108 ) && (a24==14)) && (a5==3))){ + error_11: exit(0); + } + if((((((a7==12) && a2 <= 189 ) && ((111 < a17) && (255 >= a17)) ) && (a24==14)) && (a5==3))){ + error_17: exit(0); + } + if((((((a7==14) && a2 <= 189 ) && ((111 < a17) && (255 >= a17)) ) && (a24==13)) && (a5==4))){ + error_43: exit(0); + } + if((((((a7==14) && a2 <= 189 ) && a17 <= -108 ) && (a24==14)) && (a5==4))){ + error_49: exit(0); + } + if((((((a7==12) && a2 <= 189 ) && 255 < a17 ) && (a24==15)) && (a5==3))){ + error_32: exit(0); + } + if((((((a7==12) && a2 <= 189 ) && a17 <= -108 ) && (a24==15)) && (a5==4))){ + error_59: exit(0); + } + if((((((a7==12) && a2 <= 189 ) && ((-108 < a17) && (111 >= a17)) ) && (a24==15)) && (a5==3))){ + error_26: exit(0); + } + if((((((a7==13) && a2 <= 189 ) && a17 <= -108 ) && (a24==15)) && (a5==3))){ + error_24: exit(0); + } + if((((((a7==14) && a2 <= 189 ) && a17 <= -108 ) && (a24==13)) && (a5==3))){ + error_1: exit(0); + } + if((((((a7==12) && a2 <= 189 ) && ((-108 < a17) && (111 >= a17)) ) && (a24==14)) && (a5==3))){ + error_14: exit(0); + } + if((((((a7==13) && a2 <= 189 ) && 255 < a17 ) && (a24==15)) && (a5==3))){ + error_33: exit(0); + } + if((((((a7==12) && a2 <= 189 ) && 255 < a17 ) && (a24==13)) && (a5==4))){ + error_44: exit(0); + } + if((((((a7==13) && a2 <= 189 ) && 255 < a17 ) && (a24==13)) && (a5==4))){ + error_45: exit(0); + } + if((((((a7==12) && a2 <= 189 ) && ((111 < a17) && (255 >= a17)) ) && (a24==13)) && (a5==4))){ + error_41: exit(0); + } + if((((((a7==13) && a2 <= 189 ) && ((111 < a17) && (255 >= a17)) ) && (a24==14)) && (a5==3))){ + error_18: exit(0); + } + if((((((a7==13) && a2 <= 189 ) && ((-108 < a17) && (111 >= a17)) ) && (a24==14)) && (a5==3))){ + error_15: exit(0); + } + if((((((a7==12) && a2 <= 189 ) && ((111 < a17) && (255 >= a17)) ) && (a24==15)) && (a5==3))){ + error_29: exit(0); + } + if((((((a7==12) && a2 <= 189 ) && 255 < a17 ) && (a24==14)) && (a5==4))){ + error_56: exit(0); + } + if((((((a7==13) && a2 <= 189 ) && a17 <= -108 ) && (a24==13)) && (a5==4))){ + error_36: exit(0); + } + if((((((a7==13) && a2 <= 189 ) && a17 <= -108 ) && (a24==14)) && (a5==3))){ + error_12: exit(0); + } + if((((((a7==12) && a2 <= 189 ) && ((111 < a17) && (255 >= a17)) ) && (a24==13)) && (a5==3))){ + error_5: exit(0); + } + if((((((a7==14) && a2 <= 189 ) && ((-108 < a17) && (111 >= a17)) ) && (a24==13)) && (a5==3))){ + error_4: exit(0); + } + if((((((a7==14) && a2 <= 189 ) && 255 < a17 ) && (a24==13)) && (a5==4))){ + error_46: exit(0); + } + if((((((a7==12) && a2 <= 189 ) && ((-108 < a17) && (111 >= a17)) ) && (a24==13)) && (a5==3))){ + error_2: exit(0); + } + if((((((a7==14) && a2 <= 189 ) && ((111 < a17) && (255 >= a17)) ) && (a24==15)) && (a5==3))){ + error_31: exit(0); + } + if((((((a7==14) && a2 <= 189 ) && 255 < a17 ) && (a24==14)) && (a5==3))){ + error_22: exit(0); + } + if((((((a7==14) && a2 <= 189 ) && ((-108 < a17) && (111 >= a17)) ) && (a24==14)) && (a5==3))){ + error_16: exit(0); + } + if((((((a7==13) && a2 <= 189 ) && 255 < a17 ) && (a24==13)) && (a5==3))){ + error_9: exit(0); + } + + if(((( ((189 < a2) && (281 >= a2)) && ((input == 4) && (((a7==12) && 255 < a17 ) || (((a7==13) && ((111 < a17) && (255 >= a17)) ) || ( ((111 < a17) && (255 >= a17)) && (a7==14)))))) && (a5==4)) && (a24==14))){ + a17 = (((((a17 % 109)+ -11) - 547674) + -15873) - -563482); + a7 = 12; + + return -1; + } else if(((((a24==13) && (((input == 2) && ((a7==13) || (a7==14))) && (a5==3))) && a17 <= -108 ) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 * -5) - -478038) / -5); + a7 = 12; + + return -1; + } else if((((((((a7==12) && ((111 < a17) && (255 >= a17)) ) || (( ((-108 < a17) && (111 >= a17)) && (a7==13)) || ( ((-108 < a17) && (111 >= a17)) && (a7==14)))) && (input == 1)) && (a24==14)) && ((189 < a2) && (281 >= a2)) ) && (a5==5))){ + a2 = (((a2 - 384978) + -172247) * 1); + a17 = (((a17 * 5) + 542386) * 1); + a7 = 12; + a5 = 7; + + return -1; + } else if(((( ((189 < a2) && (281 >= a2)) && (((( a17 <= -108 && (a7==13)) || ( a17 <= -108 && (a7==14))) || ( ((-108 < a17) && (111 >= a17)) && (a7==12))) && (input == 4))) && (a5==3)) && (a24==14))){ + a2 = ((((a2 + -131864) * 10)/ 9) - 73578); + a17 = ((((a17 - 0) % 299946)+ -300053) * 1); + a7 = 13; + a5 = 4; + + return -1; + } else if(((a5==6) && (((a24==13) && ((input == 6) && ((((a7==13) && ((111 < a17) && (255 >= a17)) ) || ((a7==14) && ((111 < a17) && (255 >= a17)) )) || ( 255 < a17 && (a7==12))))) && a2 <= 189 ))){ + a2 = (((((a2 * 9)/ 10) % 45)+ 236) * 1); + a17 = ((((a17 + -100855) - 172157) / 5) + 357533); + a7 = 13; + a24 = 14; + a5 = 3; + + return 23; + } else if((((a24==13) && ( ((189 < a2) && (281 >= a2)) && (((((a7==13) && ((111 < a17) && (255 >= a17)) ) || ( ((111 < a17) && (255 >= a17)) && (a7==14))) || ( 255 < a17 && (a7==12))) && (input == 3)))) && (a5==6))){ + a17 = ((((a17 / 5) % 109)- -2) - 41); + a7 = 12; + + return -1; + } else if(((a5==4) && ( a2 <= 189 && ((((input == 1) && ((a7==13) || (a7==14))) && a17 <= -108 ) && (a24==15))))){ + + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a24==15) && ((( ((189 < a2) && (281 >= a2)) && ((input == 1) && (a5==4))) && (a7==13)) && 255 < a17 ))){ + a17 = ((((a17 % 71)+ 119) * 1) + -2); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a5==4) && ( ((189 < a2) && (281 >= a2)) && ((a24==14) && ((( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ((a7==12) && ((111 < a17) && (255 >= a17)) )) && (input == 4)))))){ + a2 = (((a2 + 448263) + -951842) * 1); + a17 = (((a17 * 5) / 5) + -274764); + a7 = 14; + a24 = 15; + a5 = 5; + + return -1; + } else if(((((a5==5) && ( a2 <= 189 && ((input == 1) && (a24==15)))) && 255 < a17 ) && (a7==14))){ + a2 = (((((a2 % 45)+ 236) * 5) % 45)- -199); + a7 = 13; + a24 = 14; + + return 26; + } else if((( a17 <= -108 && ( ((189 < a2) && (281 >= a2)) && ((((a7==14) || ((a7==12) || (a7==13))) && (input == 1)) && (a24==15)))) && (a5==5))){ + a17 = (((((a17 % 109)+ 16) * 5) % 109)- -2); + a7 = 14; + a24 = 13; + + return -1; + } else if((( a17 <= -108 && (( ((189 < a2) && (281 >= a2)) && (((a7==12) || (a7==13)) && (input == 5))) && (a24==13))) && (a5==6))){ + a17 = (((((a17 + 0) - -350799) - -197891) % 71)- -182); + a7 = 14; + a24 = 14; + a5 = 4; + + return -1; + } else if((((a24==13) && ( a17 <= -108 && (((a5==4) && (input == 2)) && ((189 < a2) && (281 >= a2)) ))) && (a7==12))){ + a17 = ((((((a17 - 0) * 9)/ 10) / 5) % 109)- -93); + a7 = 14; + a24 = 15; + a5 = 3; + + return -1; + } else if((((a5==3) && ( ((-108 < a17) && (111 >= a17)) && ((a24==13) && (((a7==12) || (a7==13)) && (input == 4))))) && ((189 < a2) && (281 >= a2)) )){ + + a7 = 12; + + return 26; + } else if(( ((111 < a17) && (255 >= a17)) && ((a5==4) && ( a2 <= 189 && ((a24==15) && (((a7==13) || (a7==14)) && (input == 5))))))){ + a17 = ((((a17 - 135275) * 10)/ 9) * 3); + a7 = 13; + a5 = 5; + + return 23; + } else if(( a2 <= 189 && ((((( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ( ((111 < a17) && (255 >= a17)) && (a7==12))) && (input == 6)) && (a5==7)) && (a24==13)))){ + a17 = ((((a17 % 109)+ 2) - 1) - -2); + a7 = 12; + a24 = 15; + a5 = 4; + + return -1; + } else if(((((((a24==13) && ( a17 <= -108 && (a7==13))) && (a5==5)) || (((a5==4) && ((a24==15) && ((a7==14) && 255 < a17 ))) || ((a5==5) && ((a24==13) && ((a7==12) && a17 <= -108 ))))) && (input == 1)) && ((189 < a2) && (281 >= a2)) )){ + a17 = (((((a17 - 0) % 109)- -2) + -577173) + 577173); + a7 = 14; + a24 = 13; + a5 = 3; + + return -1; + } else if(((((a24==13) && ((((a7==13) || (a7==14)) && (input == 5)) && ((189 < a2) && (281 >= a2)) )) && (a5==3)) && a17 <= -108 )){ + a2 = (((a2 + -532580) * 1) + -62227); + a7 = 14; + a24 = 14; + a5 = 5; + + return -1; + } else if((((a5==4) && ((((input == 5) && ((a7==12) || (a7==13))) && (a24==14)) && ((189 < a2) && (281 >= a2)) )) && a17 <= -108 )){ + a2 = (((a2 * 5) / -5) / 5); + a17 = (((((a17 % 109)+ 4) * 5) % 109)+ 1); + a7 = 13; + a5 = 7; + + return -1; + } else if(((a24==14) && ((a5==3) && (((( ((-108 < a17) && (111 >= a17)) && (a7==12)) || (( a17 <= -108 && (a7==13)) || ((a7==14) && a17 <= -108 ))) && (input == 2)) && ((189 < a2) && (281 >= a2)) )))){ + a2 = (((a2 - 260500) / 5) + -428690); + a17 = ((((a17 % 71)- -184) * 1) - -1); + a7 = 12; + a24 = 15; + a5 = 4; + + return 23; + } else if(((((a5==4) && (((input == 1) && (a24==15)) && ((-108 < a17) && (111 >= a17)) )) && a2 <= 189 ) && (a7==12))){ + + a24 = 13; + a5 = 5; + + return 23; + } else if(( a2 <= 189 && (((a5==4) && (((input == 2) && (a24==15)) && (a7==12))) && ((-108 < a17) && (111 >= a17)) ))){ + + a7 = 14; + a24 = 13; + a5 = 5; + + return 26; + } else if(((a24==13) && ( ((-108 < a17) && (111 >= a17)) && ((a5==5) && (((input == 2) && a2 <= 189 ) && (a7==14)))))){ + + a7 = 13; + a24 = 15; + a5 = 6; + + return 26; + } else if(( a2 <= 189 && ((((a5==5) && ((input == 3) && (a24==13))) && (a7==14)) && ((111 < a17) && (255 >= a17)) ))){ + a17 = (((a17 * 5) + -131690) - 406420); + a7 = 12; + a5 = 3; + + return -1; + } else if(((((((a5==5) && (input == 1)) && ((189 < a2) && (281 >= a2)) ) && (a24==13)) && (a7==13)) && ((-108 < a17) && (111 >= a17)) )){ + a2 = (((a2 / 5) - 248849) * 2); + a17 = ((((a17 / 5) * 5) / 5) - 458249); + a7 = 12; + a5 = 3; + + return -1; + } else if((( ((189 < a2) && (281 >= a2)) && (((input == 6) && ((( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ((a7==12) && ((111 < a17) && (255 >= a17)) )) || ((a7==13) && ((111 < a17) && (255 >= a17)) ))) && (a24==15))) && (a5==3))){ + a17 = ((((a17 - -260026) + 97662) * 10)/ 9); + a7 = 12; + a24 = 14; + + return -1; + } else if((((a5==7) && ((( ((-108 < a17) && (111 >= a17)) && (input == 1)) && (a7==13)) && a2 <= 189 )) && (a24==14))){ + a17 = ((((a17 % 71)+ 184) - -1) - 1); + a7 = 14; + a24 = 13; + a5 = 5; + + return 21; + } else if(( ((189 < a2) && (281 >= a2)) && ((a24==15) && ((a5==5) && ( ((111 < a17) && (255 >= a17)) && (((a7==14) || ((a7==12) || (a7==13))) && (input == 6))))))){ + a17 = (((a17 - 33426) - 518487) - 34791); + a7 = 13; + a5 = 4; + + return -1; + } else if((( a2 <= 189 && (( 255 < a17 && ((input == 3) && ((a7==13) || (a7==14)))) && (a5==7))) && (a24==15))){ + a17 = ((((a17 - 593212) - -274925) - -137841) + -419796); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((( ((189 < a2) && (281 >= a2)) && ((a24==13) && ( ((-108 < a17) && (111 >= a17)) && ((input == 4) && ((a7==12) || (a7==13)))))) && (a5==6))){ + a2 = (((a2 - 356828) + -57766) * 1); + a7 = 14; + + return 26; + } else if(( a17 <= -108 && (((((input == 5) && ((a7==12) || (a7==13))) && (a5==5)) && ((189 < a2) && (281 >= a2)) ) && (a24==14)))){ + a2 = (((a2 - 367280) / 5) + -340709); + a17 = (((((a17 % 299872)+ 300127) * 1) + -276171) + 347263); + a7 = 12; + a24 = 15; + a5 = 4; + + return -1; + } else if(( a2 <= 189 && ((a5==5) && ((input == 6) && (((a24==14) && ((a7==13) && a17 <= -108 )) || (((a24==13) && ( 255 < a17 && (a7==14))) || ((a24==14) && ((a7==12) && a17 <= -108 )))))))){ + a17 = (((((a17 - 0) % 299946)+ -300053) - -266634) + -266635); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((((a5==6) && ((a24==13) && (((((a7==13) && ((111 < a17) && (255 >= a17)) ) || ((a7==14) && ((111 < a17) && (255 >= a17)) )) || ((a7==12) && 255 < a17 )) && (input == 1)))) && a2 <= 189 )){ + a17 = ((((a17 + -600109) - 2) / 5) - 329060); + a7 = 12; + a5 = 3; + + return -1; + } else if((((a5==7) && ((((((a7==14) && a17 <= -108 ) || ((a7==12) && ((-108 < a17) && (111 >= a17)) )) || ( ((-108 < a17) && (111 >= a17)) && (a7==13))) && (input == 4)) && a2 <= 189 )) && (a24==13))){ + a2 = ((((a2 / 5) - 178027) % 45)- -249); + a17 = ((((a17 / 5) - 189029) * 10)/ 9); + a7 = 13; + a24 = 15; + a5 = 3; + + return 26; + } else if(( a2 <= 189 && ((a24==15) && ((((input == 6) && ((a7==13) || (a7==14))) && (a5==4)) && ((-108 < a17) && (111 >= a17)) )))){ + a17 = ((((a17 - -591336) + -371053) * -1)/ 10); + a7 = 14; + a24 = 14; + a5 = 5; + + return 21; + } else if((( ((189 < a2) && (281 >= a2)) && ((((( a17 <= -108 && (a7==13)) || ( a17 <= -108 && (a7==14))) || ( ((-108 < a17) && (111 >= a17)) && (a7==12))) && (input == 3)) && (a5==3))) && (a24==14))){ + a2 = (((a2 * -5) * 5) - 39358); + a17 = ((((a17 % 109)- -1) + -513301) + 513302); + a7 = 13; + a5 = 5; + + return 26; + } else if((((a24==13) && (((( ((111 < a17) && (255 >= a17)) && (a7==14)) || ( 255 < a17 && (a7==12))) && (input == 2)) && (a5==4))) && ((189 < a2) && (281 >= a2)) )){ + a2 = ((((a2 * -5) + -139298) * 10)/ 9); + a17 = (((a17 - 600110) - 0) * 1); + a7 = 12; + a5 = 3; + + return -1; + } else if(((( ((111 < a17) && (255 >= a17)) && (((a5==5) && (input == 4)) && a2 <= 189 )) && (a7==14)) && (a24==15))){ + a2 = ((((a2 / 5) + -370165) % 45)- -261); + a17 = (((a17 + 573666) * 1) + -329578); + a7 = 12; + a5 = 4; + + return 21; + } else if(((((((a7==12) && (input == 6)) && ((189 < a2) && (281 >= a2)) ) && (a5==4)) && (a24==13)) && a17 <= -108 )){ + + return 21; + } else if(((a24==15) && ((a5==6) && ((((a7==12) && (input == 6)) && a17 <= -108 ) && a2 <= 189 )))){ + a2 = ((((((a2 * 9)/ 10) + -20706) + -31885) % 45)- -245); + a17 = ((((a17 % 109)- -26) / 5) * 5); + a5 = 3; + + return 23; + } else if((( ((111 < a17) && (255 >= a17)) && ((a24==15) && ((a5==6) && ((a7==12) && (input == 6))))) && a2 <= 189 )){ + a2 = ((((a2 - 0) + 15546) % 45)+ 235); + a17 = (((a17 * 5) - -401693) - -144036); + a5 = 3; + + return 23; + } else if((((((a24==14) && ((input == 4) && ((a7==12) || (a7==13)))) && a17 <= -108 ) && ((189 < a2) && (281 >= a2)) ) && (a5==5))){ + a17 = ((((((a17 % 71)- -223) * 10)/ 9) * 9)/ 10); + a7 = 14; + a24 = 13; + a5 = 4; + + return -1; + } else if(((a24==13) && (( ((111 < a17) && (255 >= a17)) && (((input == 6) && ((a7==12) || (a7==13))) && (a5==4))) && ((189 < a2) && (281 >= a2)) ))){ + a2 = (((a2 - 188462) * 3) + -6); + a7 = 14; + a24 = 15; + a5 = 7; + + return -1; + } else if((((a24==15) && ( a2 <= 189 && ((((a7==12) || (a7==13)) && (input == 6)) && (a5==5)))) && 255 < a17 )){ + a17 = (((a17 + -66404) - -20679) + -554407); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((((a7==12) && ((a24==15) && ((a5==6) && ((input == 2) && a2 <= 189 )))) && a17 <= -108 )){ + a2 = (((((a2 % 45)+ 235) * 1) - -275959) + -275957); + a17 = (((((a17 % 71)+ 208) / 5) * 10)/ 2); + a7 = 13; + a24 = 13; + a5 = 3; + + return 23; + } else if(((a5==6) && ((((a7==12) && ((input == 3) && (a24==13))) && a2 <= 189 ) && a17 <= -108 ))){ + a2 = ((((a2 / 5) + 158559) % 45)+ 204); + a17 = (((((a17 % 109)+ 75) - 24) + 175099) - 175127); + a24 = 15; + a5 = 5; + + return 23; + } else if(( a2 <= 189 && ( ((111 < a17) && (255 >= a17)) && ((((a24==15) && (input == 6)) && (a5==4)) && (a7==12))))){ + a17 = (((a17 + -497569) + 497379) - -33); + a7 = 14; + a24 = 14; + a5 = 5; + + return 26; + } else if((((a5==6) && (((input == 2) && (( 255 < a17 && (a7==12)) || (( ((111 < a17) && (255 >= a17)) && (a7==13)) || ((a7==14) && ((111 < a17) && (255 >= a17)) )))) && (a24==13))) && ((189 < a2) && (281 >= a2)) )){ + a2 = ((((a2 / -5) * 10)/ 9) + -424739); + a17 = (((a17 + -600109) * 1) + -3); + a7 = 12; + a5 = 3; + + return -1; + } else if((((a24==15) && ((a5==4) && ((((a7==12) || (a7==13)) && (input == 6)) && a2 <= 189 ))) && 255 < a17 )){ + + a7 = 14; + a5 = 5; + + return 26; + } else if((((( ((189 < a2) && (281 >= a2)) && ((input == 6) && (a5==4))) && (a24==15)) && ((-108 < a17) && (111 >= a17)) ) && (a7==13))){ + a17 = (((a17 - 534822) - -388608) * 4); + a7 = 14; + a24 = 14; + + return -1; + } else if(( ((-108 < a17) && (111 >= a17)) && (((a24==13) && ((a5==4) && (((a7==13) || (a7==14)) && (input == 5)))) && ((189 < a2) && (281 >= a2)) ))){ + + a7 = 14; + a24 = 14; + a5 = 3; + + return -1; + } else if(( a17 <= -108 && ((a24==14) && (( a2 <= 189 && ((input == 3) && ((a7==13) || (a7==14)))) && (a5==6))))){ + a2 = ((((a2 / 5) * 4) % 45)+ 236); + a17 = ((((a17 - -556050) % 109)- -1) - 0); + a7 = 12; + a5 = 3; + + return 21; + } else if(( a2 <= 189 && (((a5==4) && ( 255 < a17 && (((a7==12) || (a7==13)) && (input == 1)))) && (a24==15)))){ + a17 = ((((a17 + -600240) / 5) * 10)/ 4); + a7 = 14; + a24 = 13; + a5 = 6; + + return 23; + } else if(((a5==7) && (((a24==14) && ((input == 2) && (( ((-108 < a17) && (111 >= a17)) && (a7==12)) || (( a17 <= -108 && (a7==13)) || ( a17 <= -108 && (a7==14)))))) && a2 <= 189 ))){ + a17 = ((((a17 % 299946)+ -300053) * 1) * 1); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a24==14) && (((a7==13) && ( ((189 < a2) && (281 >= a2)) && ((input == 2) && ((-108 < a17) && (111 >= a17)) ))) && (a5==4)))){ + a2 = (((a2 / 5) / -5) * 5); + a7 = 14; + a24 = 13; + + return -1; + } else if(((((a5==5) && (((((a7==14) && a17 <= -108 ) || ((a7==12) && ((-108 < a17) && (111 >= a17)) )) || ((a7==13) && ((-108 < a17) && (111 >= a17)) )) && (input == 6))) && (a24==13)) && a2 <= 189 )){ + a17 = (((((a17 / 5) + 383422) + -411251) % 71)- -233); + a7 = 14; + a24 = 14; + a5 = 6; + + return 21; + } else if(( ((-108 < a17) && (111 >= a17)) && ((a7==14) && ((a5==5) && (((a24==13) && (input == 6)) && a2 <= 189 ))))){ + a17 = (((a17 * 5) - 61428) + -534582); + a7 = 13; + a24 = 15; + a5 = 6; + + return 21; + } else if((( ((-108 < a17) && (111 >= a17)) && ((((input == 3) && ((a7==13) || (a7==14))) && (a5==6)) && (a24==15))) && a2 <= 189 )){ + a2 = (((((a2 + 39352) / 5) / 5) % 45)+ 234); + a7 = 12; + a24 = 14; + a5 = 3; + + return 21; + } else if(( ((189 < a2) && (281 >= a2)) && (((a24==14) && ((a7==13) && ((a5==3) && (input == 5)))) && ((111 < a17) && (255 >= a17)) ))){ + a2 = (((a2 - 43077) / 5) / 5); + a17 = (((a17 / 5) / 5) - -99709); + a7 = 12; + a24 = 13; + + return -1; + } else if(( a2 <= 189 && ((a24==14) && ( ((-108 < a17) && (111 >= a17)) && (((input == 2) && ((a7==14) || ((a7==12) || (a7==13)))) && (a5==6)))))){ + a2 = (((((a2 % 45)- -235) - -2) - 444254) - -444251); + a7 = 13; + a5 = 3; + + return 26; + } else if(((a5==5) && (((((((a7==12) || (a7==13)) || (a7==14)) && (input == 2)) && a17 <= -108 ) && ((189 < a2) && (281 >= a2)) ) && (a24==15)))){ + a2 = (((a2 + -159174) - 203606) + -130058); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(( a2 <= 189 && (( ((-108 < a17) && (111 >= a17)) && ((a24==14) && ((input == 3) && ((a7==14) || ((a7==12) || (a7==13)))))) && (a5==5)))){ + a17 = (((a17 + -547450) / 5) + -82633); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((((((input == 5) && ((( ((111 < a17) && (255 >= a17)) && (a7==13)) || ( ((111 < a17) && (255 >= a17)) && (a7==14))) || ( 255 < a17 && (a7==12)))) && (a24==14)) && (a5==5)) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 + -395244) - -867612) + -1020920); + a17 = (((((a17 % 299872)- -256) * 1) * 10)/ 9); + a7 = 12; + a24 = 15; + a5 = 7; + + return -1; + } else if(((a24==13) && ((((((a7==14) && ((111 < a17) && (255 >= a17)) ) || ((a7==12) && 255 < a17 )) && (input == 5)) && (a5==4)) && ((189 < a2) && (281 >= a2)) ))){ + a2 = ((((a2 - 325121) * 10)/ 9) * 1); + a17 = (((((a17 % 71)+ 160) / 5) + -586476) - -586646); + a7 = 14; + a24 = 15; + + return 21; + } else if((((((a24==14) && (((a7==13) || (a7==14)) && (input == 4))) && ((189 < a2) && (281 >= a2)) ) && (a5==4)) && 255 < a17 )){ + a2 = (((a2 - -513398) * 1) * -1); + a17 = (((a17 + -11058) * 1) + -589131); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a5==6) && (((a24==13) && ((input == 2) && (( ((111 < a17) && (255 >= a17)) && (a7==12)) || (( ((-108 < a17) && (111 >= a17)) && (a7==13)) || ( ((-108 < a17) && (111 >= a17)) && (a7==14)))))) && a2 <= 189 ))){ + a17 = (((a17 / 5) - -11377) - 448490); + a7 = 12; + a5 = 3; + + return -1; + } else if((((a5==5) && ( ((-108 < a17) && (111 >= a17)) && (((a7==14) && (input == 5)) && (a24==13)))) && ((189 < a2) && (281 >= a2)) )){ + a2 = ((((a2 / -5) * 10)/ 9) - 571457); + a17 = ((((a17 - -227661) + 18143) * 10)/ 9); + a7 = 12; + a24 = 15; + a5 = 7; + + return -1; + } else if(((a5==4) && ((((((a7==12) && 255 < a17 ) || (( ((111 < a17) && (255 >= a17)) && (a7==13)) || ((a7==14) && ((111 < a17) && (255 >= a17)) ))) && (input == 3)) && (a24==14)) && ((189 < a2) && (281 >= a2)) ))){ + a17 = (((((a17 % 109)+ 3) + -187035) + 26490) + 160528); + a7 = 13; + + return -1; + } else if(((a7==14) && ((a5==5) && ((( ((-108 < a17) && (111 >= a17)) && (input == 2)) && (a24==13)) && ((189 < a2) && (281 >= a2)) )))){ + a2 = (((a2 * -5) + -437978) + 281140); + a17 = ((((a17 * 5) / 5) / 5) - 83944); + a7 = 12; + a5 = 3; + + return -1; + } else if((( ((189 < a2) && (281 >= a2)) && ((((input == 1) && (a5==6)) && (a24==13)) && (a7==13))) && 255 < a17 )){ + a17 = (((a17 + -491213) - 108914) + -47); + a7 = 14; + a24 = 14; + a5 = 5; + + return -1; + } else if(((a5==6) && ( ((-108 < a17) && (111 >= a17)) && ( ((189 < a2) && (281 >= a2)) && ((((a7==12) || (a7==13)) && (input == 2)) && (a24==13)))))){ + a2 = (((a2 + 391304) * -1) / 5); + a17 = (((a17 - 532893) - 26035) + -34319); + a7 = 12; + a5 = 3; + + return -1; + } else if(((((a5==4) && ((((a7==13) || (a7==14)) && (input == 5)) && a2 <= 189 )) && ((-108 < a17) && (111 >= a17)) ) && (a24==15))){ + a17 = (((((a17 * 5) % 71)- -183) + -26829) + 26828); + a7 = 13; + a24 = 13; + a5 = 5; + + return 26; + } else if(( ((-108 < a17) && (111 >= a17)) && (((((a24==13) && (input == 4)) && (a5==5)) && (a7==14)) && ((189 < a2) && (281 >= a2)) ))){ + a2 = (((a2 * -5) * 5) - 149618); + a17 = (((a17 / 5) * 5) - 544978); + a7 = 13; + a24 = 14; + a5 = 7; + + return -1; + } else if((( a2 <= 189 && ((input == 4) && (((a24==13) && ( 255 < a17 && (a7==14))) || ((a24==14) && ( a17 <= -108 && (a7==12)))))) && (a5==7))){ + a17 = ((((a17 / 5) - -3819) - 117000) - 285915); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a5==5) && ((a24==13) && ( a2 <= 189 && ((a7==14) && ( ((-108 < a17) && (111 >= a17)) && (input == 5))))))){ + a17 = ((((a17 - 51813) - -610607) * -1)/ 10); + a24 = 15; + a5 = 6; + + return 23; + } else if(((((a24==14) && ((input == 2) && ((( ((111 < a17) && (255 >= a17)) && (a7==13)) || ((a7==14) && ((111 < a17) && (255 >= a17)) )) || ((a7==12) && 255 < a17 )))) && (a5==4)) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 * -5) + -132328) + -282019); + a17 = (((a17 + -600110) * 1) - 2); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((( a17 <= -108 && ((a5==4) && ( a2 <= 189 && ((input == 6) && ((a7==13) || (a7==14)))))) && (a24==15))){ + a17 = ((((((a17 % 109)- -74) * 5) * 5) % 109)- -2); + a7 = 14; + + return 21; + } else if((((a5==3) && ( ((189 < a2) && (281 >= a2)) && (((((a7==13) && ((111 < a17) && (255 >= a17)) ) || ( ((111 < a17) && (255 >= a17)) && (a7==14))) || ((a7==12) && 255 < a17 )) && (input == 2)))) && (a24==13))){ + a2 = ((((a2 / -5) + 8939) * 5) - 171471); + a17 = ((((a17 + -514608) + 103914) % 109)+ 2); + a7 = 14; + a5 = 7; + + return -1; + } else if(( 255 < a17 && ((a5==3) && ((((((a7==12) || (a7==13)) || (a7==14)) && (input == 6)) && ((189 < a2) && (281 >= a2)) ) && (a24==15))))){ + + a7 = 13; + a24 = 13; + + return -1; + } else if(((((((a24==13) && ((a7==13) && a17 <= -108 )) && (a5==5)) || (((( 255 < a17 && (a7==14)) && (a24==15)) && (a5==4)) || ((( a17 <= -108 && (a7==12)) && (a24==13)) && (a5==5)))) && (input == 2)) && a2 <= 189 )){ + a17 = (((((a17 + 0) - 0) / 5) % 71)- -184); + a7 = 13; + a24 = 13; + a5 = 6; + + return 26; + } else if(( a17 <= -108 && ((a24==15) && ( a2 <= 189 && ((((a7==13) || (a7==14)) && (input == 3)) && (a5==4)))))){ + a17 = ((((a17 % 299872)+ 300127) + 133154) / 5); + a7 = 12; + + return 21; + } else if(( a2 <= 189 && ((a24==14) && ((a5==6) && ( ((111 < a17) && (255 >= a17)) && ((((a7==12) || (a7==13)) || (a7==14)) && (input == 4))))))){ + a2 = (((((a2 % 45)- -234) * 1) + 447091) + -447090); + a7 = 13; + a5 = 3; + + return 23; + } else if((( 255 < a17 && (((a24==13) && (((a7==14) || ((a7==12) || (a7==13))) && (input == 3))) && (a5==5))) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 + -391458) - 38043) * 1); + a17 = ((((((a17 * 9)/ 10) - 302989) / 5) % 71)+ 184); + a7 = 14; + a24 = 14; + a5 = 7; + + return -1; + } else if((((a24==15) && ((((input == 4) && (a5==5)) && a17 <= -108 ) && (a7==14))) && a2 <= 189 )){ + a2 = (((((a2 % 45)- -234) * 5) % 45)+ 227); + a17 = ((((((a17 * 9)/ 10) * 1) + -14728) % 109)- -22); + a24 = 14; + a5 = 4; + + return 23; + } else if((((a5==3) && (((( 255 < a17 && (a7==14)) && (a24==14)) || ((a24==15) && ( a17 <= -108 && (a7==12)))) && (input == 6))) && ((189 < a2) && (281 >= a2)) )){ + a17 = ((((a17 - 0) % 109)- -1) - 0); + a7 = 12; + a24 = 14; + + return -1; + } else if((((a5==7) && ((a24==15) && (((input == 6) && 255 < a17 ) && (a7==12)))) && a2 <= 189 )){ + a17 = ((((a17 + -312975) + -287141) / 5) + -19782); + a24 = 14; + a5 = 5; + + return -1; + } else if(((a5==4) && ((a24==15) && ((((input == 5) && (((a7==12) || (a7==13)) || (a7==14))) && ((189 < a2) && (281 >= a2)) ) && a17 <= -108 )))){ + + a7 = 14; + + return -1; + } else if((( ((189 < a2) && (281 >= a2)) && ((((( ((111 < a17) && (255 >= a17)) && (a7==14)) || ((a7==12) && 255 < a17 )) || ((a7==13) && 255 < a17 )) && (input == 3)) && (a5==3))) && (a24==14))){ + a2 = (((a2 * 5) * 5) / -5); + a17 = (((a17 + 0) - 600109) - 1); + a7 = 12; + a24 = 13; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && (((input == 5) && ((( a17 <= -108 && (a7==12)) && (a24==14)) || ((((a7==13) && 255 < a17 ) && (a24==13)) || ((a24==13) && ( 255 < a17 && (a7==14)))))) && (a5==3)))){ + a2 = ((((a2 - 68838) - -367491) + 74473) * -1); + a17 = (((((a17 + 0) / 5) / 5) % 71)- -184); + a7 = 12; + a24 = 15; + a5 = 4; + + return 23; + } else if(((( a2 <= 189 && (((( a17 <= -108 && (a7==13)) || ((a7==14) && a17 <= -108 )) || ((a7==12) && ((-108 < a17) && (111 >= a17)) )) && (input == 5))) && (a24==14)) && (a5==7))){ + a17 = ((((a17 % 299946)- 300053) * 1) - 1); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((( ((111 < a17) && (255 >= a17)) && (((a7==13) && ((input == 2) && (a5==3))) && (a24==14))) && ((189 < a2) && (281 >= a2)) )){ + + a7 = 14; + a24 = 13; + + return -1; + } else if((((a24==13) && (((((a7==13) || (a7==14)) && (input == 5)) && ((189 < a2) && (281 >= a2)) ) && (a5==4))) && 255 < a17 )){ + a2 = (((a2 - 410733) / 5) / 5); + a17 = ((((a17 % 71)+ 113) * 1) + 14); + a7 = 13; + a24 = 15; + + return -1; + } else if(((a5==3) && (((((input == 2) && (a7==12)) && ((189 < a2) && (281 >= a2)) ) && (a24==13)) && a17 <= -108 ))){ + a2 = ((((a2 - 291109) - 296476) + 724390) + -687165); + return -1; + } else if(( a17 <= -108 && ((((a24==15) && ((a7==12) && (input == 1))) && a2 <= 189 ) && (a5==6)))){ + a2 = (((((a2 * 9)/ 10) - -368757) % 45)- -235); + a17 = ((((((a17 % 299872)- -300127) * 10)/ 9) * 10)/ 9); + a7 = 13; + a24 = 14; + a5 = 3; + + return 23; + } else if(((a24==13) && ((a5==6) && ((((((a7==13) && a17 <= -108 ) || ( a17 <= -108 && (a7==14))) || ( ((-108 < a17) && (111 >= a17)) && (a7==12))) && (input == 6)) && a2 <= 189 )))){ + a2 = ((((((a2 - 0) % 45)+ 235) / 5) * 51)/ 10); + a17 = ((((a17 / 5) / 5) / 5) - 297755); + a7 = 12; + + return 23; + } else if(( ((189 < a2) && (281 >= a2)) && (((a24==14) && (((((a7==14) && ((111 < a17) && (255 >= a17)) ) || ((a7==12) && 255 < a17 )) || ( 255 < a17 && (a7==13))) && (input == 5))) && (a5==3)))){ + a17 = (((((a17 - 157643) / 5) * 5) % 71)- -182); + a7 = 14; + + return 21; + } else if(((a5==3) && ((((input == 3) && ((((a7==13) && a17 <= -108 ) || ( a17 <= -108 && (a7==14))) || ((a7==12) && ((-108 < a17) && (111 >= a17)) ))) && (a24==15)) && ((189 < a2) && (281 >= a2)) ))){ + a2 = (((a2 * -5) * 5) * 5); + a17 = ((((a17 % 299946)+ -300053) * 1) - 1); + a7 = 12; + a24 = 13; + + return -1; + } else if(((a24==15) && (( a2 <= 189 && (((a5==6) && (input == 4)) && a17 <= -108 )) && (a7==12)))){ + a2 = ((((a2 % 45)+ 235) - 1) - 0); + a17 = ((((((a17 * 9)/ 10) % 109)- -104) + 237666) - 237686); + a5 = 3; + + return 21; + } else if((((((( a17 <= -108 && (a7==13)) && (a24==14)) || ((((a7==14) && 255 < a17 ) && (a24==13)) || (( a17 <= -108 && (a7==12)) && (a24==14)))) && (input == 3)) && (a5==5)) && a2 <= 189 )){ + a17 = ((((a17 % 299872)- -300127) - 0) + 1); + a7 = 12; + a24 = 15; + a5 = 7; + + return 23; + } else if(((( a2 <= 189 && (((a24==13) && (input == 2)) && (a5==5))) && (a7==14)) && ((111 < a17) && (255 >= a17)) )){ + a17 = ((((a17 + -462656) * 10)/ 9) + 160772); + a7 = 12; + a5 = 3; + + return -1; + } else if(((((((input == 4) && ((a7==12) || (a7==13))) && a17 <= -108 ) && ((189 < a2) && (281 >= a2)) ) && (a24==13)) && (a5==6))){ + + a7 = 12; + a24 = 15; + a5 = 5; + + return -1; + } else if(( a2 <= 189 && (((a24==15) && ((a5==7) && (((a7==14) || ((a7==12) || (a7==13))) && (input == 6)))) && ((111 < a17) && (255 >= a17)) ))){ + a17 = ((((a17 * 5) - 15195) % 109)+ 56); + a7 = 14; + a24 = 14; + + return -1; + } else if((((((input == 4) && ((( ((111 < a17) && (255 >= a17)) && (a7==13)) || ( ((111 < a17) && (255 >= a17)) && (a7==14))) || ( 255 < a17 && (a7==12)))) && (a24==13)) && (a5==6)) && ((189 < a2) && (281 >= a2)) )){ + a17 = (((((a17 * 9)/ 10) + -528924) % 109)+ 1); + a7 = 14; + a5 = 3; + + return -1; + } else if((((a5==7) && ((input == 2) && ((((a7==14) && 255 < a17 ) && (a24==13)) || (((a7==12) && a17 <= -108 ) && (a24==14))))) && a2 <= 189 )){ + a17 = (((((a17 % 299946)+ -300053) + 96027) - 5279) - 90748); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((( ((189 < a2) && (281 >= a2)) && ((((input == 1) && ((a7==12) || (a7==13))) && (a5==5)) && (a24==14))) && a17 <= -108 )){ + a2 = ((((a2 - 167702) / 5) - -475488) * -1); + a17 = (((((a17 % 109)+ 25) - -194163) + 403579) - 597709); + a7 = 13; + a5 = 7; + + return -1; + } else if(((a7==12) && (((a5==6) && (( a2 <= 189 && (input == 4)) && a17 <= -108 )) && (a24==13)))){ + a2 = (((((a2 - 0) * 9)/ 10) % 45)- -234); + a24 = 15; + a5 = 5; + + return 23; + } else if(( ((189 < a2) && (281 >= a2)) && ((((((a7==14) && a17 <= -108 ) || ( ((-108 < a17) && (111 >= a17)) && (a7==12))) && (input == 1)) && (a24==14)) && (a5==5)))){ + a2 = (((a2 * 5) * 5) - 477470); + a17 = ((((a17 % 299946)+ -300053) + 309977) - 309978); + a7 = 12; + a5 = 7; + + return -1; + } else if(((a5==6) && ((a24==13) && ( ((189 < a2) && (281 >= a2)) && ((( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ((a7==12) && ((111 < a17) && (255 >= a17)) )) && (input == 5)))))){ + a2 = (((a2 / -5) - 543395) - 31512); + a17 = (((a17 - 374709) - 89040) - 22731); + a7 = 12; + a5 = 3; + + return -1; + } else if((( a2 <= 189 && (((( a17 <= -108 && (a7==12)) && (a24==14)) || (((a24==13) && ( 255 < a17 && (a7==13))) || ((a24==13) && ( 255 < a17 && (a7==14))))) && (input == 6))) && (a5==6))){ + a2 = ((((a2 % 45)- -236) - 2) * 1); + a17 = ((((((a17 * 9)/ 10) % 299872)+ 300127) - 202607) - -202608); + a7 = 13; + a24 = 15; + a5 = 3; + + return 23; + } else if(( 255 < a17 && ((((a24==13) && (((a7==13) || (a7==14)) && (input == 4))) && (a5==4)) && ((189 < a2) && (281 >= a2)) ))){ + + a7 = 13; + + return -1; + } else if(((a24==13) && ((( ((189 < a2) && (281 >= a2)) && ((input == 3) && ((a7==14) || ((a7==12) || (a7==13))))) && ((111 < a17) && (255 >= a17)) ) && (a5==5)))){ + a2 = (((a2 * -5) + -99498) * 5); + a17 = (((a17 + 560485) + 34614) * 1); + a7 = 13; + a5 = 7; + + return -1; + } else if(((a24==14) && (((((((a7==14) && ((111 < a17) && (255 >= a17)) ) || ( 255 < a17 && (a7==12))) || ((a7==13) && 255 < a17 )) && (input == 4)) && (a5==3)) && ((189 < a2) && (281 >= a2)) ))){ + a2 = (((a2 / -5) + -562394) - 36545); + a17 = ((((a17 - 600109) - 2) + 90959) + -90958); + a7 = 12; + a24 = 13; + + return -1; + } else if(( a2 <= 189 && (((((((a7==12) || (a7==13)) || (a7==14)) && (input == 4)) && (a24==15)) && ((111 < a17) && (255 >= a17)) ) && (a5==7)))){ + + a7 = 14; + a24 = 13; + + return -1; + } else if(( a2 <= 189 && ((((a5==5) && ((((a7==12) || (a7==13)) || (a7==14)) && (input == 5))) && ((-108 < a17) && (111 >= a17)) ) && (a24==14)))){ + a2 = ((((a2 - -285304) + -146058) % 45)- -236); + a17 = ((((a17 / 5) - 378389) - 189972) + 981500); + a7 = 12; + a24 = 13; + a5 = 3; + + return 23; + } else if((((((input == 3) && ((((a7==13) && ((-108 < a17) && (111 >= a17)) ) || ((a7==14) && ((-108 < a17) && (111 >= a17)) )) || ( ((111 < a17) && (255 >= a17)) && (a7==12)))) && a2 <= 189 ) && (a5==6)) && (a24==13))){ + a2 = ((((a2 + 0) % 45)+ 235) + 1); + a17 = (((a17 * 5) - -515114) - 13294); + a7 = 13; + + return 26; + } else if(( a2 <= 189 && (( a17 <= -108 && ((a24==15) && ((input == 2) && ((a7==12) || (a7==13))))) && (a5==5)))){ + + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a7==12) && ((a24==15) && ((a5==4) && ( ((111 < a17) && (255 >= a17)) && ( a2 <= 189 && (input == 5))))))){ + a17 = ((((a17 * 10)/ -9) + -170917) * 3); + a24 = 13; + a5 = 3; + + return -1; + } else if(((((a24==15) && ( 255 < a17 && ((input == 4) && a2 <= 189 ))) && (a7==12)) && (a5==7))){ + a17 = ((((a17 % 71)+ 179) - 53) - -56); + a7 = 13; + a24 = 13; + + return -1; + } else if(((a24==15) && ( ((-108 < a17) && (111 >= a17)) && ((a5==5) && (((input == 1) && ((a7==13) || (a7==14))) && ((189 < a2) && (281 >= a2)) ))))){ + a2 = ((((a2 + -164688) * 10)/ 9) + -309761); + a17 = (((a17 * 5) + -186431) * 3); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a5==5) && ( ((189 < a2) && (281 >= a2)) && (((( ((111 < a17) && (255 >= a17)) && (a7==12)) || (( ((-108 < a17) && (111 >= a17)) && (a7==13)) || ((a7==14) && ((-108 < a17) && (111 >= a17)) ))) && (input == 6)) && (a24==14))))){ + a17 = ((((a17 - -337472) * 10)/ 9) + 150308); + a7 = 12; + a5 = 4; + + return -1; + } else if(((( ((189 < a2) && (281 >= a2)) && (((( a17 <= -108 && (a7==13)) || ( a17 <= -108 && (a7==14))) || ((a7==12) && ((-108 < a17) && (111 >= a17)) )) && (input == 5))) && (a24==14)) && (a5==3))){ + a17 = (((((a17 / 5) + 139884) - -176184) * -1)/ 10); + a7 = 13; + + return 23; + } else if((((a5==6) && (( 255 < a17 && ((input == 2) && ((a7==12) || (a7==13)))) && (a24==15))) && a2 <= 189 )){ + a17 = (((((a17 % 109)+ 1) + 493840) - 420141) + -73780); + a7 = 12; + a24 = 14; + a5 = 4; + + return -1; + } else if(((((((input == 6) && ((189 < a2) && (281 >= a2)) ) && 255 < a17 ) && (a24==15)) && (a5==4)) && (a7==13))){ + a2 = (((a2 * -5) + 126647) * -4); + a24 = 13; + a5 = 7; + + return -1; + } else if(((((((input == 1) && ((a7==12) || (a7==13))) && (a24==15)) && (a5==5)) && a2 <= 189 ) && 255 < a17 )){ + a2 = (((((a2 % 45)- -235) - 1) / 5) - -212); + a17 = ((((((a17 % 71)+ 132) - 10) * 5) % 71)+ 135); + a7 = 14; + a24 = 13; + + return 23; + } else if(((a7==13) && ( ((-108 < a17) && (111 >= a17)) && ((((a24==14) && (input == 2)) && a2 <= 189 ) && (a5==7))))){ + a17 = ((((a17 - 453039) * 10)/ 9) * 1); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a5==3) && ( ((-108 < a17) && (111 >= a17)) && ((((a24==15) && (input == 5)) && (a7==13)) && ((189 < a2) && (281 >= a2)) )))){ + a2 = (((a2 * 5) / 5) / -5); + a17 = (((a17 - 279125) - 101385) * 1); + a7 = 12; + a24 = 13; + + return -1; + } else if((((a5==6) && (((input == 5) && (((a7==12) && ((111 < a17) && (255 >= a17)) ) || (( ((-108 < a17) && (111 >= a17)) && (a7==13)) || ( ((-108 < a17) && (111 >= a17)) && (a7==14))))) && (a24==13))) && a2 <= 189 )){ + a2 = (((((a2 - 0) + 194300) * 1) % 45)+ 235); + a17 = ((((a17 - 508865) * 10)/ 9) + -4999); + a7 = 14; + + return 23; + } else if(((( a2 <= 189 && ((((a7==14) && ((111 < a17) && (255 >= a17)) ) || ( 255 < a17 && (a7==12))) && (input == 6))) && (a24==14)) && (a5==7))){ + a17 = ((((a17 * 9)/ 10) + 13957) - -35746); + a7 = 12; + + return -1; + } else if((((( ((189 < a2) && (281 >= a2)) && (((a7==14) || ((a7==12) || (a7==13))) && (input == 5))) && (a24==13)) && (a5==5)) && ((111 < a17) && (255 >= a17)) )){ + a17 = ((((a17 - 216) - 479578) - 45364) + 524988); + a7 = 12; + a24 = 15; + a5 = 4; + + return -1; + } else if(((( a2 <= 189 && (((input == 6) && ((a7==12) || (a7==13))) && (a5==5))) && (a24==15)) && a17 <= -108 )){ + a2 = (((((a2 % 45)- -235) + -1) - 553229) - -553229); + a17 = (((a17 / 5) - -167109) / 5); + a7 = 12; + a24 = 13; + a5 = 4; + + return 26; + } else if(( a2 <= 189 && ((input == 1) && ((((a5==4) && (( 255 < a17 && (a7==14)) && (a24==15))) || ((a5==5) && (((a7==12) && a17 <= -108 ) && (a24==13)))) || ((a5==5) && (( a17 <= -108 && (a7==13)) && (a24==13))))))){ + a17 = ((((a17 - 0) % 299946)- 300053) + -1); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((((((a24==15) && ((input == 5) && (a5==4))) && ((189 < a2) && (281 >= a2)) ) && 255 < a17 ) && (a7==13))){ + a2 = (((a2 / 5) / 5) - 136738); + a24 = 14; + a5 = 7; + + return -1; + } else if((( ((-108 < a17) && (111 >= a17)) && ( ((189 < a2) && (281 >= a2)) && (((input == 6) && ((a7==13) || (a7==14))) && (a24==15)))) && (a5==5))){ + a17 = (((a17 / 5) + 572999) + 22824); + a7 = 13; + a24 = 14; + + return -1; + } else if((((a5==5) && ((a24==14) && ((input == 4) && ((( ((111 < a17) && (255 >= a17)) && (a7==13)) || ( ((111 < a17) && (255 >= a17)) && (a7==14))) || ((a7==12) && 255 < a17 ))))) && ((189 < a2) && (281 >= a2)) )){ + a17 = ((((a17 % 109)+ 2) / 5) + -88); + a7 = 13; + a24 = 15; + a5 = 4; + + return -1; + } else if(( a2 <= 189 && (((((input == 6) && ((a7==13) || (a7==14))) && (a5==7)) && 255 < a17 ) && (a24==15)))){ + a17 = ((((a17 % 109)- 61) / 5) / 5); + a7 = 13; + a5 = 4; + + return -1; + } else if(((a24==13) && ((a5==7) && (((( ((-108 < a17) && (111 >= a17)) && (a7==13)) || (((a7==14) && a17 <= -108 ) || ((a7==12) && ((-108 < a17) && (111 >= a17)) ))) && (input == 5)) && a2 <= 189 )))){ + a2 = ((((((a2 % 45)+ 234) * 1) / 5) * 51)/ 10); + a17 = ((((a17 / 5) * 4) % 109)- -2); + a7 = 12; + a24 = 14; + a5 = 3; + + return 23; + } else if(((( a2 <= 189 && ((input == 3) && ((( a17 <= -108 && (a7==14)) || ((a7==12) && ((-108 < a17) && (111 >= a17)) )) || ((a7==13) && ((-108 < a17) && (111 >= a17)) )))) && (a5==7)) && (a24==13))){ + a17 = ((((a17 % 299946)+ -300053) * 1) - 1); + a7 = 12; + a5 = 3; + + return -1; + } else if((((a5==6) && ( a2 <= 189 && ((input == 1) && (( ((-108 < a17) && (111 >= a17)) && (a7==12)) || (( a17 <= -108 && (a7==13)) || ( a17 <= -108 && (a7==14))))))) && (a24==13))){ + a2 = (((((a2 + 0) % 45)+ 234) - 472412) + 472412); + a17 = ((((a17 + 0) % 71)- -182) + 3); + a7 = 12; + a24 = 15; + a5 = 5; + + return 23; + } else if(((((a24==15) && (((input == 2) && ((a7==12) || (a7==13))) && (a5==5))) && ((-108 < a17) && (111 >= a17)) ) && a2 <= 189 )){ + a17 = (((((a17 / 5) + -238456) - -765474) * -1)/ 10); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((((a24==15) && ((((input == 4) && (((a7==12) || (a7==13)) || (a7==14))) && ((189 < a2) && (281 >= a2)) ) && (a5==5))) && ((111 < a17) && (255 >= a17)) )){ + a2 = (((a2 * 5) * 5) + -325620); + a17 = (((a17 + 366270) + 10197) + 134633); + a7 = 14; + a24 = 13; + a5 = 7; + + return -1; + } else if(((a24==13) && ((a5==4) && (((((a7==13) || (a7==14)) && (input == 1)) && ((189 < a2) && (281 >= a2)) ) && ((-108 < a17) && (111 >= a17)) )))){ + + a7 = 14; + a24 = 15; + a5 = 3; + + return -1; + } else if((((a5==6) && ((a24==13) && ( ((189 < a2) && (281 >= a2)) && ((a7==14) && (input == 1))))) && a17 <= -108 )){ + a17 = ((((((a17 % 71)- -247) + 5) / 5) * 32)/ 10); + a7 = 13; + a24 = 15; + a5 = 5; + + return -1; + } else if(((((a5==5) && ((input == 4) && ((((a7==13) && ((-108 < a17) && (111 >= a17)) ) || ( ((-108 < a17) && (111 >= a17)) && (a7==14))) || ((a7==12) && ((111 < a17) && (255 >= a17)) )))) && ((189 < a2) && (281 >= a2)) ) && (a24==14))){ + a2 = (((a2 * 5) - 562071) * 1); + a17 = (((((a17 - -128476) + 315707) + -905468) * -1)/ 10); + a7 = 13; + a24 = 15; + a5 = 4; + + return -1; + } else if(( ((-108 < a17) && (111 >= a17)) && ((((((a7==13) || (a7==14)) && (input == 5)) && a2 <= 189 ) && (a5==7)) && (a24==15)))){ + a17 = (((((a17 - 271153) + 418092) / 5) * -1)/ 10); + a7 = 14; + + return -1; + } else if(((a24==13) && ((((((a7==12) || (a7==13)) && (input == 4)) && 255 < a17 ) && a2 <= 189 ) && (a5==5)))){ + a17 = (((((a17 % 109)+ 3) * 5) % 109)- -2); + a7 = 14; + a24 = 15; + a5 = 7; + + return 23; + } else if((((a5==4) && ((a24==14) && ((input == 3) && (( a17 <= -108 && (a7==14)) || ((a7==12) && ((-108 < a17) && (111 >= a17)) ))))) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 * 5) - 516770) - 71238); + a17 = ((((a17 - 0) % 299872)+ 300127) + 1); + a7 = 12; + a5 = 7; + + return -1; + } else if((( 255 < a17 && (((a24==15) && ((input == 2) && (((a7==12) || (a7==13)) || (a7==14)))) && (a5==3))) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 - 507108) + -40186) * 1); + a17 = ((((a17 % 71)- -168) + 373224) + -373250); + a7 = 14; + a24 = 14; + + return -1; + } else if(((((a7==14) && (((input == 3) && (a24==15)) && a2 <= 189 )) && 255 < a17 ) && (a5==5))){ + a2 = (((((a2 % 45)- -236) / 5) / 5) + 268); + a7 = 12; + a24 = 14; + + return 21; + } else if(((a5==5) && ( a2 <= 189 && ((((((a7==14) && ((-108 < a17) && (111 >= a17)) ) || ((a7==12) && ((111 < a17) && (255 >= a17)) )) || ( ((111 < a17) && (255 >= a17)) && (a7==13))) && (input == 1)) && (a24==15))))){ + a17 = ((((a17 - 99808) / 5) * 10)/ 9); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a5==3) && (((((((a7==14) && ((-108 < a17) && (111 >= a17)) ) || ((a7==12) && ((111 < a17) && (255 >= a17)) )) || ((a7==13) && ((111 < a17) && (255 >= a17)) )) && (input == 1)) && ((189 < a2) && (281 >= a2)) ) && (a24==15)))){ + a2 = (((a2 - -222045) / 5) + -435548); + a17 = (((((a17 * 5) % 71)- -183) + 531003) + -531001); + a7 = 14; + a24 = 14; + a5 = 5; + + return -1; + } else if(((a24==14) && ( ((189 < a2) && (281 >= a2)) && (((input == 3) && (( a17 <= -108 && (a7==14)) || ((a7==12) && ((-108 < a17) && (111 >= a17)) ))) && (a5==5))))){ + a2 = (((a2 - 537051) + -19713) - 17151); + a17 = (((((a17 % 299872)+ 300127) + -161234) - 361454) + 522690); + a7 = 13; + a24 = 15; + a5 = 7; + + return -1; + } else if((( ((111 < a17) && (255 >= a17)) && ( a2 <= 189 && ((((a7==13) || (a7==14)) && (input == 4)) && (a5==6)))) && (a24==15))){ + a17 = (((a17 - 438310) / 5) + -185271); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((((a24==13) && ((a5==4) && ((((a7==14) && ((111 < a17) && (255 >= a17)) ) || ((a7==12) && 255 < a17 )) && (input == 6)))) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 - 252975) * 2) - -454453); + a17 = (((((((a17 * 9)/ 10) % 71)+ 176) / 5) * 39)/ 10); + a7 = 13; + a24 = 15; + + return 21; + } else if(( 255 < a17 && ((( ((189 < a2) && (281 >= a2)) && ((a7==13) && (input == 5))) && (a24==13)) && (a5==6)))){ + + a7 = 14; + a24 = 15; + a5 = 4; + + return -1; + } else if((( ((189 < a2) && (281 >= a2)) && ((a24==14) && (((input == 3) && ((a7==12) || (a7==13))) && a17 <= -108 ))) && (a5==5))){ + a17 = ((((((a17 * 9)/ 10) * 1) * 1) % 109)- -107); + a7 = 14; + a5 = 4; + + return -1; + } else if(((a5==5) && ( a2 <= 189 && ((a24==13) && ((input == 4) && ((((a7==14) && a17 <= -108 ) || ((a7==12) && ((-108 < a17) && (111 >= a17)) )) || ((a7==13) && ((-108 < a17) && (111 >= a17)) ))))))){ + a17 = ((((a17 + 0) % 299946)- 300053) + -1); + a7 = 12; + a5 = 3; + + return -1; + } else if(( a2 <= 189 && ((a24==14) && ( ((111 < a17) && (255 >= a17)) && ((a5==6) && ((input == 6) && ((a7==14) || ((a7==12) || (a7==13))))))))){ + a17 = ((((a17 - -144076) * 10)/ -9) / 5); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && (( a17 <= -108 && ((((a7==13) || (a7==14)) && (input == 6)) && (a24==13))) && (a5==3)))){ + a2 = (((a2 - 324660) + 36683) * 2); + a7 = 14; + a24 = 15; + a5 = 7; + + return -1; + } else if(( a17 <= -108 && ( ((189 < a2) && (281 >= a2)) && (((a7==14) && ((a24==13) && (input == 2))) && (a5==6))))){ + a2 = (((a2 - -379518) + 60031) + -652869); + a7 = 12; + a5 = 3; + + return -1; + } else if((((a5==4) && (((( ((111 < a17) && (255 >= a17)) && (a7==14)) || ((a7==12) && 255 < a17 )) && (input == 3)) && ((189 < a2) && (281 >= a2)) )) && (a24==15))){ + a17 = (((a17 - 0) + -600109) - 1); + a7 = 14; + a24 = 14; + + return -1; + } else if((((((a24==15) && (((a7==12) || (a7==13)) && (input == 4))) && 255 < a17 ) && a2 <= 189 ) && (a5==5))){ + a2 = (((((a2 % 45)- -235) - -264986) / 5) - 52838); + a17 = (((((a17 % 109)+ 3) + -92) - -39346) - 39285); + a7 = 14; + a24 = 13; + + return 23; + } else if(( ((189 < a2) && (281 >= a2)) && ( ((-108 < a17) && (111 >= a17)) && (((a5==4) && ((input == 2) && ((a7==13) || (a7==14)))) && (a24==13))))){ + a17 = ((((a17 - 8964) * 10)/ 9) / 5); + a7 = 13; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && ((a5==5) && ((a24==15) && (((input == 1) && ((a7==14) || ((a7==12) || (a7==13)))) && 255 < a17 ))))){ + a17 = (((((a17 + -204208) + -294222) / 5) % 109)- -2); + a7 = 14; + a5 = 4; + + return -1; + } else if(((a24==15) && (( a2 <= 189 && ((input == 1) && ((((a7==13) && a17 <= -108 ) || ( a17 <= -108 && (a7==14))) || ( ((-108 < a17) && (111 >= a17)) && (a7==12))))) && (a5==7)))){ + a17 = ((((a17 + 445460) + -108723) % 109)+ 2); + a7 = 14; + a5 = 4; + + return -1; + } else if(((a5==6) && ( a17 <= -108 && ( ((189 < a2) && (281 >= a2)) && ((a24==13) && ((a7==14) && (input == 6))))))){ + a17 = ((((((a17 * 9)/ 10) + -8929) / 5) % 109)- -99); + a5 = 5; + + return -1; + } else if(( ((111 < a17) && (255 >= a17)) && (((((((a7==12) || (a7==13)) || (a7==14)) && (input == 6)) && ((189 < a2) && (281 >= a2)) ) && (a5==5)) && (a24==13)))){ + + a7 = 12; + + return -1; + } else if(((a24==13) && ((a5==3) && (((((a7==14) && ((-108 < a17) && (111 >= a17)) ) || ((a7==12) && ((111 < a17) && (255 >= a17)) )) && (input == 6)) && ((189 < a2) && (281 >= a2)) )))){ + a2 = ((((a2 * 5) - -456899) * 1) * -1); + a17 = ((((a17 % 109)+ 2) - -1) + -2); + a7 = 14; + a24 = 15; + a5 = 7; + + return -1; + } else if(((a5==5) && ( a2 <= 189 && ( ((-108 < a17) && (111 >= a17)) && ((((a7==12) || (a7==13)) && (input == 6)) && (a24==15)))))){ + a17 = (((((a17 - 533399) + 268098) + 539288) * -1)/ 10); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a5==5) && ((( ((189 < a2) && (281 >= a2)) && ((a24==13) && (input == 3))) && ((-108 < a17) && (111 >= a17)) ) && (a7==13)))){ + a2 = ((((a2 + 15012) - -575888) * 1) * -1); + a17 = ((((a17 - -31776) - -471905) / 5) - 154264); + a7 = 14; + a24 = 14; + a5 = 7; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && (((a5==4) && ((( ((111 < a17) && (255 >= a17)) && (a7==14)) || ( 255 < a17 && (a7==12))) && (input == 6))) && (a24==15)))){ + a17 = ((((a17 - 600111) + 328854) * 1) + -328853); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((((a5==7) && (((input == 4) && (((a7==14) && ((111 < a17) && (255 >= a17)) ) || ( 255 < a17 && (a7==12)))) && a2 <= 189 )) && (a24==14))){ + a17 = ((((a17 % 71)- -117) + 189902) - 189835); + a7 = 13; + + return -1; + } else if(((a24==13) && ( ((189 < a2) && (281 >= a2)) && (((a5==5) && ((input == 6) && ((a7==14) || ((a7==12) || (a7==13))))) && 255 < a17 )))){ + a2 = ((((a2 - 330313) * 10)/ 9) - 15295); + a17 = (((((a17 / 5) - 422861) + 205502) % 109)- -66); + a7 = 13; + a24 = 15; + a5 = 7; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && ((a24==13) && (( ((-108 < a17) && (111 >= a17)) && ((input == 4) && ((a7==13) || (a7==14)))) && (a5==4))))){ + a17 = (((a17 + -505795) * 1) * 1); + a7 = 14; + a24 = 15; + a5 = 3; + + return -1; + } else if((( a2 <= 189 && (( 255 < a17 && (((a7==14) || ((a7==12) || (a7==13))) && (input == 2))) && (a5==6))) && (a24==14))){ + a17 = (((a17 - 600255) + -1) - 0); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((((a24==14) && (((input == 4) && (a7==13)) && ((-108 < a17) && (111 >= a17)) )) && (a5==4)) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 - 574876) / 5) - 126841); + a17 = ((((a17 % 71)- -182) - 0) - 0); + a24 = 13; + a5 = 7; + + return -1; + } else if(((a5==3) && ( ((189 < a2) && (281 >= a2)) && ((((( ((-108 < a17) && (111 >= a17)) && (a7==13)) || ((a7==14) && ((-108 < a17) && (111 >= a17)) )) || ((a7==12) && ((111 < a17) && (255 >= a17)) )) && (input == 1)) && (a24==14))))){ + a2 = (((a2 / -5) - -106688) - 700155); + a17 = ((((a17 - -444995) * 1) % 71)- -142); + a7 = 12; + a24 = 15; + a5 = 4; + + return 23; + } else if((( a2 <= 189 && ( 255 < a17 && ((a24==15) && ((input == 3) && (a7==12))))) && (a5==7))){ + a17 = ((((a17 + -443894) / 5) / 5) + -460355); + a24 = 13; + a5 = 3; + + return -1; + } else if((((a5==5) && ( ((111 < a17) && (255 >= a17)) && (((input == 5) && (a24==13)) && (a7==12)))) && a2 <= 189 )){ + a17 = ((((a17 + -406871) - 29414) + 509500) - 209883); + a7 = 13; + a5 = 7; + + return 23; + } else if(((a5==5) && ( ((111 < a17) && (255 >= a17)) && ((((((a7==12) || (a7==13)) || (a7==14)) && (input == 1)) && (a24==13)) && ((189 < a2) && (281 >= a2)) )))){ + a17 = ((((a17 + -386404) - -386194) - -24721) - 24655); + a7 = 13; + a24 = 15; + a5 = 4; + + return -1; + } else if(( a2 <= 189 && ((((a5==4) && (((a7==13) || (a7==14)) && (input == 4))) && ((-108 < a17) && (111 >= a17)) ) && (a24==15)))){ + a17 = ((((a17 % 71)+ 184) - -1) - 1); + a7 = 14; + a24 = 13; + a5 = 5; + + return 21; + } else if(( ((189 < a2) && (281 >= a2)) && ((((a5==5) && ((a24==13) && ( a17 <= -108 && (a7==13)))) || (((( 255 < a17 && (a7==14)) && (a24==15)) && (a5==4)) || ((a5==5) && (((a7==12) && a17 <= -108 ) && (a24==13))))) && (input == 3)))){ + a2 = (((a2 * 5) + -496396) - -43586); + a17 = ((((a17 + 0) % 71)- -183) - -1); + a7 = 14; + a24 = 15; + a5 = 4; + + return -1; + } else if((((((( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ((a7==12) && ((111 < a17) && (255 >= a17)) )) && (input == 1)) && ((189 < a2) && (281 >= a2)) ) && (a5==6)) && (a24==13))){ + a17 = (((((a17 % 71)- -184) - 1) + -591569) + 591570); + a7 = 14; + a5 = 4; + + return -1; + } else if((((((input == 1) && ((((a7==14) && ((-108 < a17) && (111 >= a17)) ) || ((a7==12) && ((111 < a17) && (255 >= a17)) )) || ( ((111 < a17) && (255 >= a17)) && (a7==13)))) && (a24==14)) && (a5==7)) && a2 <= 189 )){ + a17 = ((((a17 / 5) - -456210) - 346519) + -109681); + a7 = 13; + + return -1; + } else if(((a7==13) && ((a24==15) && (((a5==6) && ((input == 2) && a17 <= -108 )) && a2 <= 189 )))){ + a17 = (((((a17 % 71)- -191) + 37) + 557078) + -557055); + a7 = 12; + a24 = 13; + a5 = 7; + + return 26; + } else if(((a5==7) && (((a24==14) && ((input == 5) && (((a7==14) && ((111 < a17) && (255 >= a17)) ) || ( 255 < a17 && (a7==12))))) && a2 <= 189 ))){ + a17 = (((((a17 + -437926) * 1) / 5) % 71)+ 182); + a7 = 14; + + return 26; + } else if(((a7==13) && ((a24==13) && ((((input == 3) && ((111 < a17) && (255 >= a17)) ) && a2 <= 189 ) && (a5==5))))){ + a17 = ((((a17 * 23)/ 10) - -95194) + 367978); + a5 = 7; + + return 23; + } else if(((a24==13) && ((a7==13) && ( ((-108 < a17) && (111 >= a17)) && (((input == 2) && (a5==5)) && ((189 < a2) && (281 >= a2)) ))))){ + a2 = (((a2 * 5) + -75316) * 5); + a17 = ((((a17 / 5) * 5) * 5) - 551159); + a7 = 12; + a5 = 3; + + return -1; + } else if(((a24==14) && ((a5==7) && ((((((a7==14) && ((-108 < a17) && (111 >= a17)) ) || ( ((111 < a17) && (255 >= a17)) && (a7==12))) || ((a7==13) && ((111 < a17) && (255 >= a17)) )) && (input == 6)) && a2 <= 189 )))){ + a17 = (((a17 + 497335) - 362468) / 5); + a7 = 13; + a24 = 13; + + return -1; + } else if(((a7==14) && ((a5==3) && ( ((111 < a17) && (255 >= a17)) && (((input == 4) && (a24==15)) && ((189 < a2) && (281 >= a2)) ))))){ + + a7 = 12; + a24 = 14; + + return -1; + } else if(( a2 <= 189 && ((a5==7) && ((a24==13) && (((( a17 <= -108 && (a7==14)) || ( ((-108 < a17) && (111 >= a17)) && (a7==12))) || ((a7==13) && ((-108 < a17) && (111 >= a17)) )) && (input == 2)))))){ + a2 = ((((a2 % 45)+ 235) - -164895) - 164893); + a17 = (((((a17 * 9)/ 10) % 109)- -2) / 5); + a7 = 12; + a24 = 14; + a5 = 3; + + return 23; + } else if(( ((-108 < a17) && (111 >= a17)) && ( a2 <= 189 && ((a24==14) && (((input == 2) && (((a7==12) || (a7==13)) || (a7==14))) && (a5==5)))))){ + a2 = ((((a2 / 5) / 5) % 45)- -235); + a17 = (((a17 * 5) - -230268) / 5); + a7 = 14; + a24 = 13; + a5 = 3; + + return 21; + } else if(( ((189 < a2) && (281 >= a2)) && (((a5==4) && ((input == 5) && (((a7==14) && ((111 < a17) && (255 >= a17)) ) || ((a7==12) && 255 < a17 )))) && (a24==15)))){ + a17 = (((((a17 % 71)+ 146) - -107220) - 259531) + 152347); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(( ((111 < a17) && (255 >= a17)) && ((a24==14) && (( a2 <= 189 && ((input == 4) && (a5==5))) && (a7==14))))){ + a17 = ((((a17 * 10)/ -9) * 5) / 5); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((( ((111 < a17) && (255 >= a17)) && (((a5==6) && (input == 5)) && (a24==15))) && (a7==12)) && a2 <= 189 )){ + a2 = ((((a2 % 45)+ 234) * 1) + 1); + a7 = 13; + a24 = 13; + a5 = 3; + + return 23; + } else if(((a5==5) && ((( a2 <= 189 && ( ((111 < a17) && (255 >= a17)) && (input == 3))) && (a7==12)) && (a24==13)))){ + a17 = ((((a17 * 10)/ -9) * 5) + -240506); + a5 = 3; + + return -1; + } else if(((((((( ((111 < a17) && (255 >= a17)) && (a7==13)) || ( ((111 < a17) && (255 >= a17)) && (a7==14))) || ((a7==12) && 255 < a17 )) && (input == 2)) && (a24==14)) && ((189 < a2) && (281 >= a2)) ) && (a5==5))){ + a2 = ((((a2 / -5) + -417573) * 10)/ 9); + a17 = ((((a17 - 128270) + -400314) + 6367) + -77894); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(( 255 < a17 && ( ((189 < a2) && (281 >= a2)) && ((((a5==4) && (input == 4)) && (a7==13)) && (a24==15))))){ + a2 = ((((a2 + -199858) * 10)/ 9) + -50269); + a17 = (((((a17 + -143986) * 1) / 5) % 71)- -183); + a7 = 14; + a24 = 13; + a5 = 7; + + return -1; + } else if(((a5==3) && ( ((189 < a2) && (281 >= a2)) && ((a24==14) && ((input == 6) && ((( ((111 < a17) && (255 >= a17)) && (a7==14)) || ((a7==12) && 255 < a17 )) || ((a7==13) && 255 < a17 ))))))){ + a2 = (((a2 * 5) / 5) - 103911); + a17 = (((a17 - 600110) * 1) - 2); + a7 = 12; + a24 = 13; + + return -1; + } else if(((( a2 <= 189 && ((input == 6) && ((( a17 <= -108 && (a7==14)) || ( ((-108 < a17) && (111 >= a17)) && (a7==12))) || ( ((-108 < a17) && (111 >= a17)) && (a7==13))))) && (a5==7)) && (a24==13))){ + a17 = ((((a17 % 299946)+ -300053) - 2) - 0); + a7 = 12; + a5 = 3; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && ((input == 2) && (((((a24==15) && ((a7==14) && 255 < a17 )) && (a5==4)) || ((((a7==12) && a17 <= -108 ) && (a24==13)) && (a5==5))) || (((a24==13) && ( a17 <= -108 && (a7==13))) && (a5==5)))))){ + a2 = (((a2 / -5) / 5) - 528849); + a17 = ((((a17 - 0) / 5) - 300593) + 687900); + a7 = 14; + a24 = 13; + a5 = 3; + + return -1; + } else if((( ((189 < a2) && (281 >= a2)) && ((a5==3) && ((input == 4) && (((a7==12) && ((-108 < a17) && (111 >= a17)) ) || (((a7==13) && a17 <= -108 ) || ((a7==14) && a17 <= -108 )))))) && (a24==15))){ + a2 = (((a2 + -76921) + -80615) - 172398); + a17 = (((((a17 - 0) % 299946)+ -300053) - -542550) - 542551); + a7 = 12; + a24 = 13; + + return -1; + } else if((( ((-108 < a17) && (111 >= a17)) && ( ((189 < a2) && (281 >= a2)) && (((a24==13) && (input == 5)) && (a7==13)))) && (a5==5))){ + a2 = (((a2 / 5) - 555637) + -17770); + a17 = (((((a17 - -266183) * 10)/ 9) * 10)/ 9); + a7 = 14; + a5 = 7; + + return -1; + } else if(( ((-108 < a17) && (111 >= a17)) && ((a5==3) && ((a24==15) && (((input == 1) && (a7==13)) && ((189 < a2) && (281 >= a2)) ))))){ + a17 = ((((a17 / 5) + 156) + 305089) + -305059); + a7 = 14; + a24 = 13; + + return -1; + } else if(( 255 < a17 && ((a24==14) && (( a2 <= 189 && ((input == 1) && (((a7==12) || (a7==13)) || (a7==14)))) && (a5==5))))){ + a2 = ((((((a2 % 45)- -235) * 1) * 5) % 45)+ 226); + a17 = (((a17 - 600142) + 457437) + -457541); + a7 = 12; + a24 = 13; + a5 = 4; + + return 21; + } else if((((a7==12) && (((a5==4) && ((input == 3) && ((111 < a17) && (255 >= a17)) )) && a2 <= 189 )) && (a24==15))){ + + a24 = 14; + a5 = 5; + + return 23; + } else if(( a2 <= 189 && ((input == 4) && (((((a24==15) && ((a7==14) && 255 < a17 )) && (a5==6)) || ((a5==7) && ((a24==13) && ( a17 <= -108 && (a7==12))))) || ((( a17 <= -108 && (a7==13)) && (a24==13)) && (a5==7)))))){ + a2 = ((((a2 % 45)+ 234) * 1) * 1); + a17 = ((((a17 % 109)- -2) - -1) / 5); + a7 = 14; + a24 = 15; + a5 = 3; + + return 26; + } else if(((a5==4) && ((a24==14) && ( ((189 < a2) && (281 >= a2)) && ( 255 < a17 && (((a7==13) || (a7==14)) && (input == 5))))))){ + a2 = (((a2 * -5) + 490210) + -622035); + a17 = (((((a17 / 5) + -253338) - -303884) * -1)/ 10); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a5==4) && ((a24==15) && ((((( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ((a7==12) && ((111 < a17) && (255 >= a17)) )) || ( ((111 < a17) && (255 >= a17)) && (a7==13))) && (input == 5)) && ((189 < a2) && (281 >= a2)) )))){ + a17 = (((((a17 / 5) * 5) - 517057) % 71)- -222); + a7 = 13; + + return 26; + } else if((( ((189 < a2) && (281 >= a2)) && ( a17 <= -108 && ((a5==5) && ((input == 5) && ((a7==14) || ((a7==12) || (a7==13))))))) && (a24==15))){ + a2 = (((a2 - 51957) - 201016) + -229661); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((((((input == 4) && ((a7==14) || ((a7==12) || (a7==13)))) && (a5==5)) && a2 <= 189 ) && ((-108 < a17) && (111 >= a17)) ) && (a24==14))){ + a17 = ((((a17 + -583681) / 5) * 10)/ 9); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((((( ((189 < a2) && (281 >= a2)) && ((input == 2) && ((a7==12) || (a7==13)))) && a17 <= -108 ) && (a5==4)) && (a24==14))){ + a2 = ((((a2 * -5) / 5) - -461012) * -1); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((( a2 <= 189 && ((((((a7==13) && 255 < a17 ) && (a24==14)) || (((a7==14) && 255 < a17 ) && (a24==14))) || ((a24==15) && ((a7==12) && a17 <= -108 ))) && (input == 2))) && (a5==7))){ + a17 = ((((a17 % 299946)- 300053) * 1) * 1); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((((((((a7==13) && ((111 < a17) && (255 >= a17)) ) || ( ((111 < a17) && (255 >= a17)) && (a7==14))) || ( 255 < a17 && (a7==12))) && (input == 1)) && ((189 < a2) && (281 >= a2)) ) && (a24==14)) && (a5==4))){ + a2 = (((a2 + -56097) + -204457) / 5); + a17 = ((((a17 - 0) - 600111) / 5) + -466402); + a7 = 14; + a5 = 7; + + return -1; + } else if(((a24==15) && (((((input == 1) && (a5==3)) && ((189 < a2) && (281 >= a2)) ) && ((111 < a17) && (255 >= a17)) ) && (a7==14)))){ + a2 = (((a2 + -198382) * 3) - 2631); + a17 = ((((a17 / 5) * 10)/ -2) + -174727); + a7 = 12; + a24 = 13; + + return -1; + } else if(((a24==14) && ((a5==7) && (((input == 5) && ((( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ((a7==12) && ((111 < a17) && (255 >= a17)) )) || ((a7==13) && ((111 < a17) && (255 >= a17)) ))) && a2 <= 189 )))){ + a17 = ((((a17 - 587947) / 5) / 5) + 23535); + a7 = 13; + a24 = 15; + a5 = 4; + + return -1; + } else if((((a24==15) && ( ((189 < a2) && (281 >= a2)) && ((a7==13) && ((a5==4) && (input == 4))))) && ((-108 < a17) && (111 >= a17)) )){ + a2 = (((a2 * 5) / 5) + -257179); + a17 = (((((a17 % 71)- -184) + 43333) / 5) + -8544); + a7 = 12; + a5 = 5; + + return -1; + } else if((((((a24==14) && (((a7==12) || (a7==13)) && (input == 2))) && a2 <= 189 ) && ((111 < a17) && (255 >= a17)) ) && (a5==5))){ + a2 = (((((a2 % 45)+ 234) * 5) % 45)+ 193); + a17 = ((((a17 - -121418) * 10)/ -9) + -75458); + a7 = 12; + a24 = 15; + a5 = 3; + + return 23; + } else if(( a17 <= -108 && ( ((189 < a2) && (281 >= a2)) && ((a5==3) && ((a24==13) && (((a7==13) || (a7==14)) && (input == 1))))))){ + a2 = (((a2 + -566056) + -17565) - 7708); + a17 = ((((((a17 - -545152) % 109)- -2) * 5) % 109)- -2); + a7 = 13; + a24 = 15; + a5 = 4; + + return 21; + } else if(((a7==12) && (((( a2 <= 189 && (input == 2)) && ((111 < a17) && (255 >= a17)) ) && (a5==4)) && (a24==15)))){ + a17 = ((((((a17 - -393608) * 10)/ 9) - 738081) * -1)/ 10); + a7 = 13; + a24 = 14; + a5 = 5; + + return 23; + } else if((( ((-108 < a17) && (111 >= a17)) && ((((input == 1) && ((a7==13) || (a7==14))) && a2 <= 189 ) && (a5==4))) && (a24==15))){ + a17 = (((a17 - -93652) / 5) * 5); + a7 = 14; + a24 = 13; + a5 = 5; + + return 23; + } + return calculate_output2(input); + } + + int calculate_output2(int input) { + + + if(((a5==7) && (((((((a7==13) && ((111 < a17) && (255 >= a17)) ) || ((a7==14) && ((111 < a17) && (255 >= a17)) )) || ((a7==12) && 255 < a17 )) && (input == 4)) && a2 <= 189 ) && (a24==13)))){ + a17 = (((a17 + -223220) - 376890) - 0); + a7 = 12; + a5 = 3; + + return -1; + } else if((((a24==13) && (((a5==3) && (((a7==13) || (a7==14)) && (input == 3))) && ((189 < a2) && (281 >= a2)) )) && a17 <= -108 )){ + a2 = (((a2 * 5) - 572766) - 10840); + a17 = (((((a17 + 0) % 299872)+ 300127) * 10)/ 9); + a7 = 12; + a5 = 7; + + return -1; + } else if((((a5==5) && ( a17 <= -108 && (((input == 5) && ((a7==12) || (a7==13))) && a2 <= 189 ))) && (a24==15))){ + a2 = ((((a2 % 45)- -234) * 1) + 0); + a17 = (((((a17 % 299872)- -300127) - -85883) - 234462) - -340820); + a7 = 13; + a24 = 13; + a5 = 4; + + return 23; + } else if(((a5==7) && ((( ((111 < a17) && (255 >= a17)) && ((input == 3) && ((a7==14) || ((a7==12) || (a7==13))))) && (a24==15)) && a2 <= 189 ))){ + a17 = (((a17 - 554057) - 32150) * 1); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((( a2 <= 189 && ((input == 4) && (((a24==14) && ((a7==12) && a17 <= -108 )) || ((( 255 < a17 && (a7==13)) && (a24==13)) || (((a7==14) && 255 < a17 ) && (a24==13)))))) && (a5==6))){ + a17 = (((a17 / 5) - 146392) - 201110); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((( ((189 < a2) && (281 >= a2)) && ((((a7==14) && ((-108 < a17) && (111 >= a17)) ) || ((a7==12) && ((111 < a17) && (255 >= a17)) )) && (input == 2))) && (a5==4)) && (a24==14))){ + a2 = ((((a2 + -438465) * 10)/ 9) + -61750); + a17 = (((a17 - -547585) - -40543) + -650123); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a5==5) && (((a24==14) && ((( a17 <= -108 && (a7==14)) || ( ((-108 < a17) && (111 >= a17)) && (a7==12))) && (input == 2))) && ((189 < a2) && (281 >= a2)) ))){ + a2 = (((a2 * 5) - 588386) - 700); + a17 = ((((a17 % 299946)- 300053) / 5) - 223475); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a24==15) && ( ((-108 < a17) && (111 >= a17)) && ( ((189 < a2) && (281 >= a2)) && (((input == 1) && (a5==5)) && (a7==12)))))){ + a17 = (((a17 - -556781) - -32123) - -2336); + a7 = 13; + a5 = 4; + + return -1; + } else if(((a5==4) && ( ((189 < a2) && (281 >= a2)) && ((((a7==12) && (input == 1)) && (a24==13)) && a17 <= -108 )))){ + + a7 = 14; + a24 = 14; + a5 = 3; + + return -1; + } else if(((a24==13) && ((a5==3) && (((( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ((a7==12) && ((111 < a17) && (255 >= a17)) )) && (input == 5)) && ((189 < a2) && (281 >= a2)) )))){ + a2 = (((a2 + -105771) / 5) * 5); + a17 = ((((a17 / 5) + 192183) * -1)/ 10); + a7 = 12; + + return -1; + } else if(((((((a24==13) && (input == 6)) && (a7==14)) && ((189 < a2) && (281 >= a2)) ) && (a5==5)) && ((-108 < a17) && (111 >= a17)) )){ + a2 = (((a2 - 160975) / 5) * 5); + a17 = (((a17 + -217141) + 302270) - 56859); + a7 = 13; + a24 = 15; + a5 = 4; + + return -1; + } else if(((a24==13) && ((((input == 3) && (((a7==14) && ((-108 < a17) && (111 >= a17)) ) || ((a7==12) && ((111 < a17) && (255 >= a17)) ))) && (a5==7)) && a2 <= 189 ))){ + a17 = (((((a17 * 5) - 221071) / 5) % 71)- -220); + a7 = 12; + a5 = 5; + + return 21; + } else if((((( a2 <= 189 && ((input == 4) && (a24==13))) && ((111 < a17) && (255 >= a17)) ) && (a7==12)) && (a5==5))){ + a17 = (((a17 + -543666) - 48044) - 4253); + a5 = 3; + + return -1; + } else if(((a5==6) && ( ((189 < a2) && (281 >= a2)) && (((((a7==12) || (a7==13)) && (input == 3)) && (a24==13)) && ((-108 < a17) && (111 >= a17)) )))){ + a17 = (((a17 + -479754) * 1) - 60677); + a7 = 12; + a24 = 14; + a5 = 5; + + return -1; + } else if(( ((-108 < a17) && (111 >= a17)) && ((a5==4) && ( ((189 < a2) && (281 >= a2)) && (((a24==15) && (input == 5)) && (a7==13)))))){ + a17 = ((((a17 - 89845) % 71)- -187) * 1); + a24 = 13; + + return -1; + } else if(((( ((111 < a17) && (255 >= a17)) && (((((a7==12) || (a7==13)) || (a7==14)) && (input == 2)) && (a24==13))) && ((189 < a2) && (281 >= a2)) ) && (a5==5))){ + a2 = (((a2 / 5) * 5) + -133618); + a17 = ((((a17 - 64840) - 296199) * 10)/ 9); + a7 = 12; + a5 = 3; + + return -1; + } else if(((( ((189 < a2) && (281 >= a2)) && (((a7==12) && (input == 6)) && ((-108 < a17) && (111 >= a17)) )) && (a24==15)) && (a5==5))){ + a2 = (((a2 + -519111) - -90859) / 5); + a17 = (((a17 / 5) + -553032) + 553176); + a7 = 13; + a24 = 14; + a5 = 7; + + return -1; + } else if(((a5==4) && ((a24==15) && ( ((-108 < a17) && (111 >= a17)) && (((input == 3) && a2 <= 189 ) && (a7==12)))))){ + a17 = (((((a17 / 5) + 521700) - 934556) * -1)/ 10); + a7 = 14; + + return 23; + } else if(( ((189 < a2) && (281 >= a2)) && ((a5==3) && ((a24==14) && ((input == 6) && ((((a7==13) && ((-108 < a17) && (111 >= a17)) ) || ( ((-108 < a17) && (111 >= a17)) && (a7==14))) || ( ((111 < a17) && (255 >= a17)) && (a7==12)))))))){ + a2 = (((a2 / 5) * -5) * 5); + a17 = ((((a17 * 5) % 71)+ 182) + 1); + a7 = 12; + a24 = 15; + a5 = 4; + + return -1; + } else if((((((((a7==13) || (a7==14)) && (input == 4)) && a17 <= -108 ) && (a24==15)) && (a5==4)) && a2 <= 189 )){ + a17 = ((((((a17 + 343527) % 71)+ 183) * 5) % 71)- -165); + a7 = 13; + + return 21; + } else if((( a17 <= -108 && ((a5==6) && ( a2 <= 189 && ((a24==15) && (input == 3))))) && (a7==13))){ + + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && ((((input == 3) && (( 255 < a17 && (a7==12)) || (( ((111 < a17) && (255 >= a17)) && (a7==13)) || ((a7==14) && ((111 < a17) && (255 >= a17)) )))) && (a5==5)) && (a24==14)))){ + a2 = (((a2 + -81628) * 5) - 151837); + a17 = (((a17 + -600110) - 0) + -2); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(( 255 < a17 && (((a5==5) && ( ((189 < a2) && (281 >= a2)) && ((input == 6) && ((a7==14) || ((a7==12) || (a7==13)))))) && (a24==15)))){ + a17 = (((((a17 - 0) + -206889) + 16806) % 109)- -2); + a7 = 13; + a5 = 4; + + return -1; + } else if((((((a24==14) && (((a7==12) || (a7==13)) && (input == 3))) && (a5==4)) && a17 <= -108 ) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 - 217302) + -351806) / 5); + a17 = ((((((a17 % 71)- -205) * 9)/ 10) * 10)/ 9); + a7 = 14; + a5 = 7; + + return -1; + } else if(( a2 <= 189 && ((input == 6) && (((( a17 <= -108 && (a7==13)) && (a24==13)) && (a5==5)) || ((((a24==15) && ( 255 < a17 && (a7==14))) && (a5==4)) || (((a24==13) && ( a17 <= -108 && (a7==12))) && (a5==5))))))){ + a17 = ((((a17 + 0) % 299946)+ -300053) - 2); + a7 = 14; + a24 = 14; + a5 = 6; + + return 26; + } else if(((((input == 6) && ((( 255 < a17 && (a7==14)) && (a24==13)) || (((a7==12) && a17 <= -108 ) && (a24==14)))) && (a5==7)) && a2 <= 189 )){ + a17 = (((((a17 + 0) - 0) + 0) % 299946)+ -300053); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a24==15) && ( a2 <= 189 && ((((input == 2) && ((a7==13) || (a7==14))) && (a5==4)) && ((111 < a17) && (255 >= a17)) )))){ + a17 = (((a17 - 112842) + -369240) / 5); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((( ((189 < a2) && (281 >= a2)) && ((((a24==15) && (input == 3)) && (a5==5)) && ((-108 < a17) && (111 >= a17)) )) && (a7==12))){ + a17 = (((a17 + 316175) * 1) + 233255); + a24 = 14; + a5 = 4; + + return -1; + } else if((((a5==7) && ((a24==13) && (((( ((111 < a17) && (255 >= a17)) && (a7==13)) || ( ((111 < a17) && (255 >= a17)) && (a7==14))) || ((a7==12) && 255 < a17 )) && (input == 6)))) && a2 <= 189 )){ + a17 = (((a17 + -600109) + -1) + -2); + a7 = 12; + a5 = 3; + + return -1; + } else if((((( a17 <= -108 && ((input == 6) && (a5==5))) && (a7==14)) && (a24==15)) && a2 <= 189 )){ + + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(( ((111 < a17) && (255 >= a17)) && ( ((189 < a2) && (281 >= a2)) && (((a5==4) && ((input == 1) && ((a7==12) || (a7==13)))) && (a24==13))))){ + + a7 = 12; + + return 23; + } else if((((((input == 4) && (( ((111 < a17) && (255 >= a17)) && (a7==14)) || ( 255 < a17 && (a7==12)))) && (a24==13)) && (a5==4)) && ((189 < a2) && (281 >= a2)) )){ + a17 = (((((a17 + -427791) / 5) / 5) % 71)+ 182); + a7 = 13; + + return -1; + } else if((( ((189 < a2) && (281 >= a2)) && ((((( ((-108 < a17) && (111 >= a17)) && (a7==13)) || ( ((-108 < a17) && (111 >= a17)) && (a7==14))) || ( ((111 < a17) && (255 >= a17)) && (a7==12))) && (input == 3)) && (a5==3))) && (a24==14))){ + a2 = (((a2 + -120881) * 4) * 1); + a17 = (((((a17 % 109)- -2) + -127431) - 362706) + 490136); + a7 = 12; + a5 = 5; + + return 26; + } else if((( ((189 < a2) && (281 >= a2)) && (((input == 2) && ((( a17 <= -108 && (a7==13)) || ( a17 <= -108 && (a7==14))) || ((a7==12) && ((-108 < a17) && (111 >= a17)) ))) && (a5==3))) && (a24==15))){ + a2 = (((a2 * 5) * -5) - 245970); + a17 = (((((a17 % 299946)+ -300053) + -1) + 161315) - 161314); + a7 = 12; + a24 = 13; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && (((a24==14) && ((input == 6) && (( a17 <= -108 && (a7==14)) || ((a7==12) && ((-108 < a17) && (111 >= a17)) )))) && (a5==4)))){ + a17 = ((((a17 % 299946)- 300053) * 1) * 1); + a7 = 13; + a24 = 13; + a5 = 3; + + return -1; + } else if((((( ((189 < a2) && (281 >= a2)) && ((input == 3) && (a7==12))) && (a24==13)) && a17 <= -108 ) && (a5==3))){ + a2 = (((a2 + 430380) * 1) / -5); + a17 = (((((a17 * 9)/ 10) % 109)+ 42) - 25); + a7 = 14; + a24 = 15; + a5 = 7; + + return -1; + } else if(((a5==3) && ( ((189 < a2) && (281 >= a2)) && ((((((a7==13) && 255 < a17 ) && (a24==13)) || (((a7==14) && 255 < a17 ) && (a24==13))) || ((a24==14) && ((a7==12) && a17 <= -108 ))) && (input == 3))))){ + a2 = (((a2 - -54478) + -529752) + -118732); + a17 = (((a17 / 5) / 5) + -531417); + a7 = 12; + a24 = 13; + + return -1; + } else if(((a24==13) && ((a5==7) && ((a7==13) && ( a2 <= 189 && ( 255 < a17 && (input == 2))))))){ + a17 = (((a17 - 0) + -600254) - 1); + a7 = 12; + a5 = 3; + + return -1; + } else if((((((((a7==12) || (a7==13)) && (input == 5)) && (a24==15)) && 255 < a17 ) && a2 <= 189 ) && (a5==5))){ + a2 = (((((a2 - -169038) + -8583) + -45242) % 45)+ 234); + a7 = 13; + a24 = 13; + + return 23; + } else if(((a24==15) && ((a5==6) && ( a2 <= 189 && ((((a7==14) && a17 <= -108 ) || ((a7==12) && ((-108 < a17) && (111 >= a17)) )) && (input == 3)))))){ + a17 = ((((a17 % 299946)+ -300053) * 1) - 2); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((((a7==12) && (((input == 2) && ((111 < a17) && (255 >= a17)) ) && (a5==6))) && a2 <= 189 ) && (a24==15))){ + a2 = (((((a2 % 45)- -236) / 5) - -550201) + -549992); + a7 = 14; + a5 = 3; + + return 26; + } else if(( a2 <= 189 && (((a5==4) && (((input == 3) && ((a7==13) || (a7==14))) && ((111 < a17) && (255 >= a17)) )) && (a24==15)))){ + + a7 = 14; + a5 = 5; + + return 23; + } else if(((a7==14) && (((( a2 <= 189 && (input == 2)) && (a24==14)) && (a5==5)) && ((111 < a17) && (255 >= a17)) ))){ + a2 = (((((a2 % 45)- -235) - -1) + 81498) - 81497); + a17 = (((((a17 * 10)/ 4) / 5) * 10)/ 2); + a7 = 12; + a24 = 15; + a5 = 3; + + return 21; + } else if(((a24==13) && ( 255 < a17 && (((a5==5) && (((a7==12) || (a7==13)) && (input == 5))) && a2 <= 189 )))){ + a17 = ((((a17 % 109)+ -14) + -65) - 16); + a7 = 12; + a24 = 15; + a5 = 7; + + return 26; + } else if(( a2 <= 189 && (( ((-108 < a17) && (111 >= a17)) && (((a5==5) && (input == 4)) && (a24==13))) && (a7==14)))){ + a17 = (((((a17 - 567803) % 71)+ 187) - 424769) - -424798); + a24 = 15; + a5 = 6; + + return 23; + } else if(( a2 <= 189 && (((((input == 3) && (((a7==12) || (a7==13)) || (a7==14))) && ((111 < a17) && (255 >= a17)) ) && (a24==14)) && (a5==6)))){ + a2 = (((((a2 - -148382) + 15537) - 69273) % 45)+ 235); + a17 = (((a17 - 250975) * 2) - -374533); + a7 = 13; + a24 = 15; + a5 = 3; + + return 26; + } else if(( ((111 < a17) && (255 >= a17)) && (((a24==14) && (((input == 1) && (((a7==12) || (a7==13)) || (a7==14))) && a2 <= 189 )) && (a5==6)))){ + a2 = (((((((a2 * 9)/ 10) % 45)- -234) / 5) * 51)/ 10); + a7 = 13; + a5 = 3; + + return 23; + } else if(( 255 < a17 && (((a5==5) && (((input == 1) && ((a7==12) || (a7==13))) && a2 <= 189 )) && (a24==13)))){ + a17 = ((((a17 / 5) * 10)/ -4) - 18616); + a7 = 12; + a5 = 3; + + return -1; + } else if(((a5==6) && (((((a24==14) && ((a7==12) && a17 <= -108 )) || ((((a7==13) && 255 < a17 ) && (a24==13)) || ((a24==13) && ( 255 < a17 && (a7==14))))) && (input == 3)) && a2 <= 189 ))){ + a2 = (((((a2 * 9)/ 10) % 45)+ 234) + 0); + a17 = (((((a17 * 9)/ 10) % 299946)+ -300053) - 0); + a7 = 13; + a24 = 13; + a5 = 4; + + return 26; + } else if(( ((189 < a2) && (281 >= a2)) && (((a5==4) && ( a17 <= -108 && ((input == 1) && ((a7==14) || ((a7==12) || (a7==13)))))) && (a24==15)))){ + a17 = (((((a17 * 9)/ 10) - -39396) % 109)- -1); + a7 = 12; + a24 = 14; + + return -1; + } else if(((((((a7==12) && (input == 4)) && ((-108 < a17) && (111 >= a17)) ) && (a5==4)) && a2 <= 189 ) && (a24==15))){ + a17 = (((a17 * 5) / 5) - 8323); + a24 = 13; + a5 = 3; + + return -1; + } else if(((( a2 <= 189 && ((a5==6) && ((input == 5) && a17 <= -108 ))) && (a24==13)) && (a7==12))){ + + a5 = 3; + + return -1; + } else if(((((a5==5) && ((((a7==14) && a17 <= -108 ) || ((a7==12) && ((-108 < a17) && (111 >= a17)) )) && (input == 5))) && (a24==13)) && ((189 < a2) && (281 >= a2)) )){ + a17 = ((((((a17 % 71)+ 183) * 5) * 5) % 71)- -147); + a7 = 13; + a5 = 4; + + return -1; + } else if(((a5==3) && ( ((189 < a2) && (281 >= a2)) && (((((a7==12) && a17 <= -108 ) && (a24==14)) || ((( 255 < a17 && (a7==13)) && (a24==13)) || ((a24==13) && ( 255 < a17 && (a7==14))))) && (input == 1))))){ + a2 = ((((a2 * -5) + 512688) / 5) + -671267); + a17 = (((((a17 % 299946)+ -300053) + -2) - -209672) - 209671); + a7 = 12; + a24 = 13; + + return -1; + } else if((((a5==3) && ( ((189 < a2) && (281 >= a2)) && ((( ((-108 < a17) && (111 >= a17)) && (a7==12)) || (( a17 <= -108 && (a7==13)) || ( a17 <= -108 && (a7==14)))) && (input == 1)))) && (a24==15))){ + a17 = ((((((a17 * 9)/ 10) % 71)- -182) - -14398) + -14397); + a7 = 13; + a24 = 14; + + return -1; + } else if((((a5==3) && ((((((a7==14) && ((-108 < a17) && (111 >= a17)) ) || ((a7==12) && ((111 < a17) && (255 >= a17)) )) || ((a7==13) && ((111 < a17) && (255 >= a17)) )) && (input == 4)) && (a24==15))) && ((189 < a2) && (281 >= a2)) )){ + a2 = ((((a2 - 440571) * 10)/ 9) * 1); + a17 = (((a17 / 5) + 199) + -13); + a7 = 12; + a24 = 13; + a5 = 7; + + return -1; + } else if(((a24==14) && (((a5==6) && ( a2 <= 189 && (((a7==14) || ((a7==12) || (a7==13))) && (input == 5)))) && 255 < a17 ))){ + + a7 = 12; + + return 21; + } else if(( ((-108 < a17) && (111 >= a17)) && ((a5==5) && ((a24==15) && ((((a7==12) || (a7==13)) && (input == 1)) && a2 <= 189 ))))){ + a17 = ((((a17 - 548709) + 66483) * 10)/ 9); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((((((input == 4) && (((a7==14) && ((-108 < a17) && (111 >= a17)) ) || ((a7==12) && ((111 < a17) && (255 >= a17)) ))) && (a5==6)) && ((189 < a2) && (281 >= a2)) ) && (a24==13))){ + a17 = ((((a17 * 5) - 44693) % 109)+ 15); + a7 = 14; + a5 = 5; + + return -1; + } else if((((a24==13) && (( ((189 < a2) && (281 >= a2)) && ( a17 <= -108 && (input == 5))) && (a7==12))) && (a5==3))){ + a2 = (((a2 + -572725) + 175794) * 1); + a17 = ((((a17 / 5) % 109)- -105) / 5); + a7 = 13; + a24 = 15; + a5 = 4; + + return -1; + } else if(((((( a17 <= -108 && (input == 1)) && (a7==14)) && a2 <= 189 ) && (a24==14)) && (a5==5))){ + a2 = ((((a2 / 5) % 45)+ 235) - 1); + a17 = (((((a17 % 109)- -95) - 397967) + 16520) + 381429); + a24 = 13; + a5 = 3; + + return 26; + } else if(( ((111 < a17) && (255 >= a17)) && ((a7==12) && ((a5==6) && (( a2 <= 189 && (input == 4)) && (a24==15)))))){ + a17 = ((((a17 - -175358) * 10)/ -9) * 3); + a24 = 13; + a5 = 3; + + return -1; + } else if(((((((input == 5) && a2 <= 189 ) && (a5==5)) && (a24==15)) && (a7==14)) && a17 <= -108 )){ + a2 = (((((a2 + 0) - -533443) / 5) % 45)- -235); + a17 = ((((a17 % 109)+ 56) + 32) - 64); + a7 = 13; + a24 = 14; + a5 = 4; + + return 23; + } else if(((a5==6) && ((a24==14) && ((((input == 4) && (((a7==12) || (a7==13)) || (a7==14))) && a2 <= 189 ) && ((-108 < a17) && (111 >= a17)) )))){ + a2 = ((((a2 % 45)+ 236) * 1) - 2); + a17 = ((((a17 - -285478) - -176297) % 71)+ 120); + a7 = 14; + a5 = 3; + + return 23; + } else if((((a5==3) && ((((((a7==14) && ((-108 < a17) && (111 >= a17)) ) || ( ((111 < a17) && (255 >= a17)) && (a7==12))) || ( ((111 < a17) && (255 >= a17)) && (a7==13))) && (input == 3)) && (a24==15))) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 / -5) * 5) * 5); + a17 = (((a17 / 5) + 443474) - -14231); + a7 = 13; + a24 = 14; + + return -1; + } else if(((a5==4) && ((a7==12) && ( ((-108 < a17) && (111 >= a17)) && ((a24==15) && ((input == 2) && ((189 < a2) && (281 >= a2)) )))))){ + a2 = ((((a2 - -382813) + -765612) - -535577) * -3); + a17 = ((((a17 - 191016) * 10)/ 9) * 2); + a24 = 13; + a5 = 3; + + return -1; + } else if(((((((( 255 < a17 && (a7==14)) && (a24==15)) && (a5==6)) || ((a5==7) && (( a17 <= -108 && (a7==12)) && (a24==13)))) || ((a5==7) && (((a7==13) && a17 <= -108 ) && (a24==13)))) && (input == 2)) && a2 <= 189 )){ + a17 = ((((a17 % 299946)- 300053) * 1) + -1); + a7 = 14; + a24 = 13; + a5 = 4; + + return -1; + } else if((((a5==3) && ((( ((111 < a17) && (255 >= a17)) && (input == 5)) && ((189 < a2) && (281 >= a2)) ) && (a7==14))) && (a24==15))){ + a2 = ((((a2 - 503628) * 10)/ 9) * 1); + a17 = (((a17 - 141047) * 4) - 9786); + a7 = 12; + a24 = 13; + + return -1; + } else if((((a24==14) && ( a2 <= 189 && ((input == 6) && ((((a7==13) && a17 <= -108 ) || ((a7==14) && a17 <= -108 )) || ((a7==12) && ((-108 < a17) && (111 >= a17)) ))))) && (a5==7))){ + a17 = (((((a17 % 109)+ 1) * 5) % 109)- -1); + a7 = 13; + a24 = 15; + a5 = 4; + + return -1; + } else if(((a5==7) && (((a24==15) && (((input == 5) && ((a7==13) || (a7==14))) && a2 <= 189 )) && 255 < a17 ))){ + a17 = (((((a17 % 71)+ 138) + 39) - 439359) + 439313); + a7 = 13; + a24 = 14; + + return -1; + } else if(((a5==4) && ((a24==13) && ((((input == 2) && ((a7==12) || (a7==13))) && ((189 < a2) && (281 >= a2)) ) && ((111 < a17) && (255 >= a17)) )))){ + a2 = (((a2 * 5) - -555151) * -1); + a17 = (((((a17 / 5) - 449993) + 603017) * -1)/ 10); + a7 = 12; + a5 = 3; + + return -1; + } else if((((a5==6) && ( ((-108 < a17) && (111 >= a17)) && ( a2 <= 189 && (((a7==13) || (a7==14)) && (input == 2))))) && (a24==15))){ + a2 = ((((((a2 % 45)+ 235) + 1) * 5) % 45)+ 219); + a17 = ((((a17 % 71)+ 184) + 1) + -1); + a7 = 14; + a24 = 13; + a5 = 3; + + return 21; + } else if((( a2 <= 189 && ( ((111 < a17) && (255 >= a17)) && ((a7==12) && ((input == 2) && (a5==5))))) && (a24==13))){ + a17 = (((a17 - 199) + -6) + -5); + a7 = 14; + a5 = 7; + + return 21; + } else if(((a7==13) && (((((input == 4) && (a5==7)) && (a24==14)) && a2 <= 189 ) && ((-108 < a17) && (111 >= a17)) ))){ + a17 = (((a17 - 357382) + -119715) * 1); + a7 = 14; + + return -1; + } else if(((a24==14) && ((a5==5) && ( ((189 < a2) && (281 >= a2)) && ((input == 2) && (( ((111 < a17) && (255 >= a17)) && (a7==12)) || (((a7==13) && ((-108 < a17) && (111 >= a17)) ) || ((a7==14) && ((-108 < a17) && (111 >= a17)) )))))))){ + a2 = (((a2 - -271816) / 5) * -5); + a17 = ((((a17 - -250279) + 97462) * -1)/ 10); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((((((input == 3) && (((a7==12) && ((-108 < a17) && (111 >= a17)) ) || (( a17 <= -108 && (a7==13)) || ((a7==14) && a17 <= -108 )))) && a2 <= 189 ) && (a5==6)) && (a24==13))){ + a17 = (((((a17 % 299946)- 300053) / 5) / 5) + -264660); + a7 = 12; + a5 = 3; + + return -1; + } else if(((a7==12) && ((a5==5) && ((((input == 1) && (a24==13)) && a2 <= 189 ) && ((111 < a17) && (255 >= a17)) )))){ + a17 = (((((a17 * -1)/ 10) + 161751) + -250598) + 88873); + a5 = 7; + + return 23; + } else if((((a24==13) && ((((input == 1) && (a5==5)) && ((-108 < a17) && (111 >= a17)) ) && (a7==14))) && a2 <= 189 )){ + a17 = ((((((a17 % 71)- -182) - 0) * 5) % 71)- -178); + a7 = 12; + a24 = 15; + a5 = 6; + + return 26; + } else if((((a5==3) && ( a17 <= -108 && (((a24==13) && (input == 4)) && ((189 < a2) && (281 >= a2)) ))) && (a7==12))){ + a2 = (((a2 * -5) * 5) / 5); + a24 = 14; + a5 = 5; + + return 23; + } else if((((a5==3) && ( ((189 < a2) && (281 >= a2)) && ((( ((111 < a17) && (255 >= a17)) && (a7==12)) || (( ((-108 < a17) && (111 >= a17)) && (a7==13)) || ((a7==14) && ((-108 < a17) && (111 >= a17)) ))) && (input == 4)))) && (a24==14))){ + a17 = (((((a17 % 109)+ 2) - 348657) + -227996) - -576653); + a7 = 14; + + return -1; + } else if(((a24==14) && ((a5==4) && (( ((-108 < a17) && (111 >= a17)) && ((input == 3) && (a7==13))) && ((189 < a2) && (281 >= a2)) )))){ + a2 = (((a2 / -5) - -389340) * -1); + a17 = (((((a17 + 69965) + -188133) + -248443) * -1)/ 10); + a7 = 14; + a24 = 15; + a5 = 7; + + return -1; + } else if(((a7==13) && ((a24==15) && ( ((189 < a2) && (281 >= a2)) && ( ((-108 < a17) && (111 >= a17)) && ((a5==4) && (input == 3))))))){ + a2 = (((a2 * -5) - 523034) * 1); + a17 = ((((((a17 % 71)+ 184) + 138561) * 4) % 71)+ 151); + a24 = 13; + a5 = 7; + + return -1; + } else if(( ((111 < a17) && (255 >= a17)) && ( a2 <= 189 && (((((a7==13) || (a7==14)) && (input == 2)) && (a5==6)) && (a24==15))))){ + a2 = ((((((a2 - 0) % 45)+ 236) * 5) % 45)+ 213); + a17 = (((a17 - -31328) * 5) * 3); + a7 = 12; + a24 = 13; + a5 = 3; + + return 23; + } else if(((a5==7) && ( a2 <= 189 && ((a24==13) && ((input == 3) && ((((a7==13) && ((111 < a17) && (255 >= a17)) ) || ( ((111 < a17) && (255 >= a17)) && (a7==14))) || ( 255 < a17 && (a7==12)))))))){ + a17 = ((((((a17 % 109)- 13) * 5) + -231249) % 109)- -55); + a7 = 14; + a24 = 15; + a5 = 4; + + return -1; + } else if(((a5==6) && ( a2 <= 189 && ((a24==14) && ( ((-108 < a17) && (111 >= a17)) && ((((a7==12) || (a7==13)) || (a7==14)) && (input == 5))))))){ + a17 = (((((a17 % 71)+ 184) * 1) / 5) + 111); + a7 = 12; + a24 = 13; + a5 = 7; + + return 23; + } else if(((a5==5) && ( ((-108 < a17) && (111 >= a17)) && ((((input == 6) && ((a7==14) || ((a7==12) || (a7==13)))) && (a24==14)) && a2 <= 189 )))){ + a2 = (((((a2 % 45)- -234) * 1) + -304708) - -304710); + a7 = 13; + a5 = 3; + + return 26; + } else if(( ((-108 < a17) && (111 >= a17)) && ((a24==14) && ((((input == 6) && ((a7==14) || ((a7==12) || (a7==13)))) && (a5==6)) && a2 <= 189 )))){ + a2 = (((((a2 % 45)- -236) - -1) / 5) + 208); + a17 = (((((a17 + -583311) / 5) * 5) % 71)- -225); + a7 = 14; + a24 = 15; + a5 = 3; + + return 23; + } else if(((a24==14) && ((a5==4) && (((((a7==12) && 255 < a17 ) || (( ((111 < a17) && (255 >= a17)) && (a7==13)) || ((a7==14) && ((111 < a17) && (255 >= a17)) ))) && (input == 5)) && ((189 < a2) && (281 >= a2)) )))){ + a2 = (((a2 * 5) * 5) - 372070); + a17 = ((((a17 % 71)+ 123) - -13742) + -13696); + a7 = 14; + a24 = 15; + + return 21; + } else if((((a5==4) && ( ((189 < a2) && (281 >= a2)) && ((input == 1) && ((((a7==14) && ((-108 < a17) && (111 >= a17)) ) || ((a7==12) && ((111 < a17) && (255 >= a17)) )) || ((a7==13) && ((111 < a17) && (255 >= a17)) ))))) && (a24==15))){ + a2 = ((((a2 - 67499) * 5) * 10)/ 9); + a17 = ((((((a17 % 71)+ 183) * 5) * 5) % 71)- -126); + a7 = 12; + a5 = 5; + + return 21; + } else if(((((a24==13) && ((input == 1) && (((a7==14) && a17 <= -108 ) || ((a7==12) && ((-108 < a17) && (111 >= a17)) )))) && (a5==5)) && ((189 < a2) && (281 >= a2)) )){ + a17 = ((((a17 - 0) % 109)+ 2) + 1); + a7 = 13; + a5 = 3; + + return -1; + } else if(((a5==6) && (((a24==13) && ((input == 6) && (( ((111 < a17) && (255 >= a17)) && (a7==12)) || (((a7==13) && ((-108 < a17) && (111 >= a17)) ) || ((a7==14) && ((-108 < a17) && (111 >= a17)) ))))) && a2 <= 189 ))){ + a2 = ((((a2 / 5) - -545601) % 45)+ 203); + a17 = ((((a17 % 109)- -2) + 1) + -2); + a7 = 13; + + return 23; + } else if(((a5==4) && ((((input == 1) && (( ((-108 < a17) && (111 >= a17)) && (a7==12)) || (((a7==13) && a17 <= -108 ) || ( a17 <= -108 && (a7==14))))) && ((189 < a2) && (281 >= a2)) ) && (a24==13)))){ + a17 = (((((a17 % 71)- -182) - -29808) + -229764) + 199957); + a7 = 14; + a24 = 15; + a5 = 3; + + return -1; + } else if((((a5==5) && ((( ((189 < a2) && (281 >= a2)) && (input == 6)) && (a24==13)) && ((-108 < a17) && (111 >= a17)) )) && (a7==13))){ + a2 = ((((a2 - -93069) / 5) * 5) - 656223); + a17 = (((a17 + -400644) - 189700) - 2801); + a7 = 12; + a5 = 3; + + return -1; + } else if(((((a7==14) && (((input == 1) && a2 <= 189 ) && (a5==5))) && (a24==15)) && a17 <= -108 )){ + + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((((a5==3) && ( ((189 < a2) && (281 >= a2)) && (((input == 4) && ((-108 < a17) && (111 >= a17)) ) && (a24==15)))) && (a7==13))){ + + return 26; + } else if(((((((input == 5) && (((a7==12) || (a7==13)) || (a7==14))) && ((189 < a2) && (281 >= a2)) ) && (a24==15)) && (a5==5)) && 255 < a17 )){ + a2 = (((a2 + -1933) * 5) + -538505); + a7 = 13; + a5 = 7; + + return -1; + } else if(( 255 < a17 && ((((a5==3) && (((a7==14) || ((a7==12) || (a7==13))) && (input == 5))) && (a24==15)) && ((189 < a2) && (281 >= a2)) ))){ + a17 = ((((a17 % 71)+ 182) + -10) + 11); + a7 = 13; + a24 = 13; + + return -1; + } else if(((a5==6) && (((((input == 5) && (a7==12)) && (a24==15)) && a2 <= 189 ) && a17 <= -108 ))){ + a2 = ((((a2 % 45)- -235) + 1) + -2); + a7 = 13; + a24 = 14; + a5 = 3; + + return 26; + } else if(( a2 <= 189 && (((input == 5) && (((a24==13) && ( 255 < a17 && (a7==14))) || (( a17 <= -108 && (a7==12)) && (a24==14)))) && (a5==7)))){ + a17 = (((((a17 % 109)- -2) + 1) - -372693) - 372693); + a7 = 13; + a24 = 15; + a5 = 4; + + return -1; + } else if(((((a24==14) && ((((a7==14) && ((-108 < a17) && (111 >= a17)) ) || ( ((111 < a17) && (255 >= a17)) && (a7==12))) && (input == 3))) && ((189 < a2) && (281 >= a2)) ) && (a5==4))){ + a2 = (((a2 * 5) + -72167) * 5); + a17 = ((((a17 + -186071) + -206980) * 10)/ 9); + a7 = 12; + a24 = 15; + a5 = 7; + + return -1; + } else if((((((a24==13) && ((input == 6) && ((a7==12) || (a7==13)))) && 255 < a17 ) && (a5==5)) && a2 <= 189 )){ + a17 = (((a17 + -600164) * 1) + -53); + a7 = 12; + a5 = 3; + + return -1; + } else if(((a24==13) && ( 255 < a17 && (((a7==13) && ((input == 4) && (a5==7))) && a2 <= 189 )))){ + a17 = (((((a17 - 0) - 0) + 0) % 71)- -150); + a5 = 5; + + return -1; + } else if(( a2 <= 189 && ((((a24==15) && (((a7==13) || (a7==14)) && (input == 2))) && ((-108 < a17) && (111 >= a17)) ) && (a5==4)))){ + a17 = (((a17 - 164414) - 174884) + -159208); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((( ((189 < a2) && (281 >= a2)) && (((a24==14) && (((a7==12) || (a7==13)) && (input == 1))) && a17 <= -108 )) && (a5==4))){ + a2 = (((a2 / 5) * 5) / -5); + a7 = 12; + a24 = 15; + a5 = 5; + + return -1; + } else if((((a24==15) && ( 255 < a17 && ((a5==7) && (((a7==13) || (a7==14)) && (input == 2))))) && a2 <= 189 )){ + a17 = (((a17 - 600173) / 5) * 5); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a5==4) && (( 255 < a17 && ( a2 <= 189 && ((input == 3) && ((a7==12) || (a7==13))))) && (a24==15)))){ + + a7 = 13; + a5 = 5; + + return 23; + } else if((( a17 <= -108 && ((a24==15) && ( a2 <= 189 && ((a5==6) && (input == 3))))) && (a7==12))){ + a17 = ((((a17 % 109)- -35) - 26) / 5); + a5 = 4; + + return 21; + } else if(((a24==15) && ((a5==4) && ( ((189 < a2) && (281 >= a2)) && ((((a7==14) && ((111 < a17) && (255 >= a17)) ) || ((a7==12) && 255 < a17 )) && (input == 4)))))){ + a17 = ((((a17 - 384201) % 109)+ 1) + 2); + a7 = 13; + a24 = 13; + a5 = 3; + + return -1; + } else if((( a17 <= -108 && ((a5==6) && ((a24==13) && ((input == 6) && (a7==12))))) && a2 <= 189 )){ + a2 = ((((((a2 * 9)/ 10) * 1) - -556567) % 45)+ 231); + a17 = ((((a17 % 109)+ 37) + 6) - 19); + a7 = 13; + a24 = 15; + a5 = 5; + + return 23; + } else if(((a5==3) && (((((((a7==12) || (a7==13)) || (a7==14)) && (input == 3)) && 255 < a17 ) && ((189 < a2) && (281 >= a2)) ) && (a24==15)))){ + a17 = (((((a17 % 109)+ 3) + -50) - -516936) + -516973); + a7 = 12; + a24 = 14; + + return -1; + } else if((( ((189 < a2) && (281 >= a2)) && (( ((-108 < a17) && (111 >= a17)) && (((a7==12) || (a7==13)) && (input == 6))) && (a5==3))) && (a24==13))){ + a2 = (((a2 + -109630) - 123244) - 219626); + a17 = ((((a17 + -100817) * 5) * 10)/ 9); + a7 = 14; + a24 = 15; + a5 = 7; + + return -1; + } else if(((a24==13) && ((a5==5) && ( ((-108 < a17) && (111 >= a17)) && (((input == 1) && (a7==14)) && ((189 < a2) && (281 >= a2)) ))))){ + a17 = (((a17 + 526530) + 65040) + 5305); + a7 = 13; + a24 = 15; + a5 = 4; + + return -1; + } else if(((a5==5) && ( ((189 < a2) && (281 >= a2)) && ((a24==14) && ((input == 6) && (( 255 < a17 && (a7==12)) || (((a7==13) && ((111 < a17) && (255 >= a17)) ) || ((a7==14) && ((111 < a17) && (255 >= a17)) )))))))){ + a2 = (((a2 * 5) / 5) / -5); + a17 = (((a17 - 0) - 600110) + -2); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((( a2 <= 189 && (( a17 <= -108 && ((input == 2) && (a7==12))) && (a5==6))) && (a24==13))){ + + a5 = 3; + + return -1; + } else if(((((a24==15) && ( a2 <= 189 && ((input == 2) && ((a7==12) || (a7==13))))) && 255 < a17 ) && (a5==5))){ + a17 = ((((a17 + 0) / 5) * 4) + -576078); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a5==7) && ((((input == 2) && (((a7==12) && 255 < a17 ) || (((a7==13) && ((111 < a17) && (255 >= a17)) ) || ( ((111 < a17) && (255 >= a17)) && (a7==14))))) && a2 <= 189 ) && (a24==13)))){ + a17 = (((((a17 + -600111) + -1) * 9)/ 10) + -11291); + a7 = 12; + a5 = 3; + + return -1; + } else if(((a5==7) && ( a2 <= 189 && ((input == 4) && (((((a7==13) && 255 < a17 ) && (a24==14)) || (( 255 < a17 && (a7==14)) && (a24==14))) || ((a24==15) && ((a7==12) && a17 <= -108 ))))))){ + a17 = (((((a17 * 9)/ 10) % 71)- -184) - 2); + a7 = 14; + a24 = 13; + a5 = 5; + + return 21; + } else if((((a24==14) && ( a2 <= 189 && (((( a17 <= -108 && (a7==13)) || ((a7==14) && a17 <= -108 )) || ( ((-108 < a17) && (111 >= a17)) && (a7==12))) && (input == 3)))) && (a5==7))){ + a17 = ((((a17 % 109)+ 1) - -2) - 1); + a7 = 12; + + return -1; + } else if((((((( ((111 < a17) && (255 >= a17)) && (a7==14)) || ((a7==12) && 255 < a17 )) && (input == 2)) && a2 <= 189 ) && (a24==14)) && (a5==7))){ + a17 = (((a17 - 600111) - 1) - 0); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a24==14) && ((a5==5) && (( a2 <= 189 && ((input == 3) && (a7==14))) && a17 <= -108 )))){ + a2 = ((((a2 % 45)+ 236) - -1) * 1); + a24 = 13; + a5 = 3; + + return 26; + } else if(( a2 <= 189 && ((a5==7) && ((a24==13) && (((((a7==13) && ((111 < a17) && (255 >= a17)) ) || ( ((111 < a17) && (255 >= a17)) && (a7==14))) || ((a7==12) && 255 < a17 )) && (input == 5)))))){ + a17 = ((((((a17 % 71)+ 166) * 9)/ 10) * 9)/ 10); + a7 = 13; + + return -1; + } else if((( a2 <= 189 && ( ((111 < a17) && (255 >= a17)) && (((input == 1) && (a7==13)) && (a24==13)))) && (a5==5))){ + + a5 = 7; + + return 26; + } else if((((a24==13) && ((a5==5) && (((((a7==12) || (a7==13)) || (a7==14)) && (input == 5)) && ((189 < a2) && (281 >= a2)) ))) && 255 < a17 )){ + + a7 = 13; + + return 23; + } else if(( a2 <= 189 && ((a24==13) && ((a5==5) && ((( ((-108 < a17) && (111 >= a17)) && (a7==13)) || (((a7==14) && a17 <= -108 ) || ( ((-108 < a17) && (111 >= a17)) && (a7==12)))) && (input == 5)))))){ + a17 = ((((a17 * 9)/ 10) - 5211) + 549653); + a7 = 13; + a24 = 14; + a5 = 6; + + return 26; + } else if((( ((111 < a17) && (255 >= a17)) && ((a5==5) && ((a7==14) && ((input == 6) && (a24==13))))) && a2 <= 189 )){ + a17 = ((((a17 + 372015) + -372184) + 315921) + -315903); + a24 = 14; + a5 = 7; + + return 23; + } else if(( ((189 < a2) && (281 >= a2)) && ((a24==13) && ((a5==4) && ((input == 3) && ((((a7==13) && a17 <= -108 ) || ((a7==14) && a17 <= -108 )) || ( ((-108 < a17) && (111 >= a17)) && (a7==12)))))))){ + a2 = (((a2 * 5) - 399704) * 1); + a17 = (((((a17 % 299946)- 300053) + -1) - -345280) - 345280); + a7 = 12; + a5 = 3; + + return -1; + } else if((((a24==15) && ( ((-108 < a17) && (111 >= a17)) && ((((a7==13) || (a7==14)) && (input == 5)) && ((189 < a2) && (281 >= a2)) ))) && (a5==5))){ + a2 = ((((a2 * -5) * 5) - -579500) * -1); + a17 = (((a17 / 5) - 391832) / 5); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a24==15) && ( ((189 < a2) && (281 >= a2)) && (((((a7==13) && ((111 < a17) && (255 >= a17)) ) || (( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ((a7==12) && ((111 < a17) && (255 >= a17)) ))) && (input == 2)) && (a5==3))))){ + a2 = (((a2 + -106788) * 5) * 1); + a17 = ((((a17 + 74148) + 98517) % 109)- 1); + a7 = 13; + a24 = 13; + a5 = 4; + + return -1; + } else if((((a5==5) && ((((input == 3) && ((-108 < a17) && (111 >= a17)) ) && (a7==14)) && (a24==13))) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 / -5) - 597366) + -852); + a17 = (((a17 - 484669) + -100380) - 5769); + a7 = 12; + a24 = 15; + a5 = 7; + + return -1; + } else if((((a5==7) && (((input == 1) && (( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ( ((111 < a17) && (255 >= a17)) && (a7==12)))) && (a24==13))) && a2 <= 189 )){ + a17 = ((((a17 % 109)- -2) / 5) / 5); + a7 = 14; + a24 = 15; + a5 = 3; + + return -1; + } else if(((a5==6) && ((a24==14) && ((((((a7==12) || (a7==13)) || (a7==14)) && (input == 6)) && 255 < a17 ) && a2 <= 189 )))){ + a2 = ((((a2 - -292946) + -155034) % 45)+ 234); + a17 = (((((a17 % 109)+ -95) - -473885) * 1) - 473817); + a7 = 13; + a24 = 13; + a5 = 4; + + return 26; + } else if(((a24==14) && (((a5==5) && ( 255 < a17 && (((a7==13) || (a7==14)) && (input == 3)))) && ((189 < a2) && (281 >= a2)) ))){ + a17 = (((((a17 + -251055) % 71)+ 183) + 492006) + -492005); + a7 = 12; + + return -1; + } else if((( 255 < a17 && ((((input == 2) && (a7==14)) && a2 <= 189 ) && (a5==5))) && (a24==15))){ + a17 = ((((a17 / 5) * 4) * -6)/ 10); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a5==4) && (((a7==13) && ( 255 < a17 && ((a24==15) && (input == 3)))) && ((189 < a2) && (281 >= a2)) ))){ + a17 = ((((a17 % 109)- 46) - 573448) + 573425); + a24 = 14; + + return -1; + } else if((( ((189 < a2) && (281 >= a2)) && (((a5==3) && ((input == 3) && (a24==15))) && (a7==14))) && ((111 < a17) && (255 >= a17)) )){ + a2 = (((a2 - 230215) / 5) + -123947); + a17 = ((((a17 / 5) * 10)/ -2) * 5); + a7 = 12; + a24 = 13; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && ((( ((111 < a17) && (255 >= a17)) && ((input == 4) && ((a7==12) || (a7==13)))) && (a5==4)) && (a24==13)))){ + a2 = ((((a2 * -5) * 10)/ 9) * 5); + a17 = (((a17 * 5) * 5) / 5); + a7 = 12; + a24 = 14; + a5 = 7; + + return -1; + } else if(((( 255 < a17 && ( a2 <= 189 && ((input == 4) && ((a7==12) || (a7==13))))) && (a5==4)) && (a24==15))){ + a17 = ((((((a17 % 71)+ 177) * 9)/ 10) + -198267) + 198271); + a7 = 12; + a24 = 13; + a5 = 6; + + return 26; + } else if(( a2 <= 189 && ((input == 3) && (((a5==7) && ((a24==13) && ((a7==13) && a17 <= -108 ))) || (((( 255 < a17 && (a7==14)) && (a24==15)) && (a5==6)) || ((a5==7) && ((a24==13) && ( a17 <= -108 && (a7==12))))))))){ + a2 = (((((a2 % 45)+ 235) - -2) - 281898) - -281896); + a17 = (((((a17 * 9)/ 10) % 299946)- 300053) - 2); + a7 = 13; + a24 = 15; + a5 = 3; + + return 26; + } else if(((((a5==6) && ((((a7==13) || (a7==14)) && (input == 1)) && ((111 < a17) && (255 >= a17)) )) && a2 <= 189 ) && (a24==15))){ + a2 = ((((a2 + 0) % 45)- -235) + -1); + a7 = 13; + a24 = 13; + a5 = 3; + + return 23; + } else if((((a5==6) && (((a24==14) && ((((a7==12) || (a7==13)) || (a7==14)) && (input == 4))) && 255 < a17 )) && a2 <= 189 )){ + a2 = (((((a2 - 0) % 45)+ 236) + 67568) - 67569); + a7 = 12; + a24 = 13; + a5 = 3; + + return 23; + } else if((((((a24==15) && ((input == 3) && ((111 < a17) && (255 >= a17)) )) && a2 <= 189 ) && (a5==6)) && (a7==12))){ + + return 23; + } else if((( ((189 < a2) && (281 >= a2)) && ((a24==14) && ( 255 < a17 && (((a7==13) || (a7==14)) && (input == 2))))) && (a5==4))){ + a2 = (((a2 - 517350) / 5) + -227328); + a17 = ((((a17 * 9)/ 10) + -544188) / 5); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((((((a5==5) && (((a7==12) || (a7==13)) && (input == 1))) && (a24==14)) && a2 <= 189 ) && ((111 < a17) && (255 >= a17)) )){ + a2 = (((((a2 % 45)- -236) * 5) % 45)- -234); + a7 = 13; + a5 = 3; + + return 26; + } else if(((a24==14) && (( ((189 < a2) && (281 >= a2)) && ((((a7==13) || (a7==14)) && (input == 1)) && (a5==4))) && 255 < a17 ))){ + a17 = ((((((a17 % 71)+ 148) * 9)/ 10) * 9)/ 10); + a7 = 14; + a24 = 13; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && ((((input == 2) && (( ((-108 < a17) && (111 >= a17)) && (a7==12)) || (( a17 <= -108 && (a7==13)) || ((a7==14) && a17 <= -108 )))) && (a5==4)) && (a24==13)))){ + a2 = (((a2 - 478599) * 1) * 1); + a17 = ((((a17 / 5) / 5) / 5) + -495670); + a7 = 12; + a5 = 3; + + return -1; + } else if((( ((-108 < a17) && (111 >= a17)) && ((((input == 3) && ((a7==12) || (a7==13))) && (a24==13)) && (a5==3))) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 * -5) + -578339) + -2272); + a17 = ((((a17 % 71)+ 183) + 2) - 1); + a7 = 14; + a5 = 7; + + return -1; + } else if(((a5==7) && (((input == 5) && ((((a24==14) && ( 255 < a17 && (a7==13))) || ((a24==14) && ((a7==14) && 255 < a17 ))) || (( a17 <= -108 && (a7==12)) && (a24==15)))) && a2 <= 189 ))){ + a17 = (((((a17 * 9)/ 10) % 109)- -2) + -1); + a7 = 14; + a24 = 14; + + return -1; + } else if(((a5==4) && ( a17 <= -108 && ((((input == 3) && (a24==13)) && (a7==12)) && ((189 < a2) && (281 >= a2)) )))){ + a2 = ((((a2 + -508787) / 5) * 10)/ 9); + a17 = (((((a17 + 0) % 71)+ 254) * 9)/ 10); + a24 = 15; + + return -1; + } else if((( a17 <= -108 && (((a5==6) && ((input == 5) && ((a7==13) || (a7==14)))) && (a24==14))) && a2 <= 189 )){ + a2 = ((((((a2 % 45)+ 236) - 1) / 5) * 51)/ 10); + a17 = ((((a17 % 109)- -32) + -26) - -40); + a7 = 14; + a5 = 3; + + return 23; + } else if((((a24==13) && (((input == 3) && (( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ( ((111 < a17) && (255 >= a17)) && (a7==12)))) && ((189 < a2) && (281 >= a2)) )) && (a5==3))){ + a17 = (((((a17 % 109)+ 1) + 536699) + 4168) - 540865); + a7 = 13; + + return -1; + } else if((((a24==13) && ((((( ((111 < a17) && (255 >= a17)) && (a7==13)) || ((a7==14) && ((111 < a17) && (255 >= a17)) )) || ( 255 < a17 && (a7==12))) && (input == 1)) && ((189 < a2) && (281 >= a2)) )) && (a5==3))){ + a2 = (((a2 * 5) / -5) - 131726); + a17 = (((((a17 / 5) / 5) - 197914) % 109)+ 43); + a7 = 13; + a24 = 14; + a5 = 5; + + return -1; + } else if(((a24==13) && ( a17 <= -108 && (((a5==6) && (((a7==12) || (a7==13)) && (input == 2))) && ((189 < a2) && (281 >= a2)) )))){ + a2 = (((a2 + 123909) - 483346) - 41719); + a7 = 12; + a5 = 3; + + return -1; + } else if((((a5==3) && ((a24==14) && ((input == 5) && (( ((111 < a17) && (255 >= a17)) && (a7==12)) || (((a7==13) && ((-108 < a17) && (111 >= a17)) ) || ((a7==14) && ((-108 < a17) && (111 >= a17)) )))))) && ((189 < a2) && (281 >= a2)) )){ + a2 = ((((a2 - -143250) / -5) * 10)/ 9); + a17 = ((((a17 % 71)+ 183) / 5) + 104); + a7 = 12; + a24 = 15; + a5 = 4; + + return -1; + } else if(( ((-108 < a17) && (111 >= a17)) && (((a7==12) && ( ((189 < a2) && (281 >= a2)) && ((a24==15) && (input == 2)))) && (a5==5)))){ + a2 = (((a2 + -139817) - 311967) / 5); + a17 = (((a17 - 584030) / 5) / 5); + a24 = 13; + a5 = 3; + + return -1; + } else if(((a24==13) && ((a5==6) && (((( ((111 < a17) && (255 >= a17)) && (a7==12)) || (((a7==13) && ((-108 < a17) && (111 >= a17)) ) || ((a7==14) && ((-108 < a17) && (111 >= a17)) ))) && (input == 4)) && a2 <= 189 )))){ + a2 = (((((a2 * 9)/ 10) % 45)- -236) + -2); + a17 = ((((a17 % 71)+ 183) + 2) + -3); + a7 = 14; + + return 21; + } else if(( ((-108 < a17) && (111 >= a17)) && ((a24==15) && ((a5==4) && ((((a7==13) || (a7==14)) && (input == 3)) && a2 <= 189 ))))){ + a17 = ((((a17 + -240122) * 10)/ -9) / 5); + a7 = 12; + a24 = 13; + a5 = 5; + + return 26; + } else if(( a2 <= 189 && ((a5==6) && ( a17 <= -108 && ((a24==14) && (((a7==13) || (a7==14)) && (input == 6))))))){ + a2 = (((((a2 % 45)- -236) - -1) - -152243) - 152245); + a7 = 12; + a5 = 3; + + return 26; + } else if(((a5==6) && (((a24==13) && (((( ((111 < a17) && (255 >= a17)) && (a7==13)) || ( ((111 < a17) && (255 >= a17)) && (a7==14))) || ((a7==12) && 255 < a17 )) && (input == 4))) && a2 <= 189 ))){ + a2 = (((((a2 % 45)+ 236) - -249333) - 625277) - -375944); + a17 = ((((((a17 % 109)- -1) - 100) * 5) % 109)+ 2); + a7 = 13; + a5 = 4; + + return 26; + } else if((((((( 255 < a17 && (a7==12)) || (( ((111 < a17) && (255 >= a17)) && (a7==13)) || ((a7==14) && ((111 < a17) && (255 >= a17)) ))) && (input == 2)) && (a5==6)) && a2 <= 189 ) && (a24==13))){ + a2 = (((((a2 % 45)- -234) + -442292) - -617405) - 175110); + a17 = ((((((a17 * 9)/ 10) % 71)- -115) / 5) - -197); + a7 = 13; + a24 = 14; + a5 = 3; + + return 21; + } else if((( a2 <= 189 && ((((a7==14) && (input == 4)) && (a5==5)) && (a24==14))) && a17 <= -108 )){ + a2 = ((((a2 % 45)+ 235) - 1) + 2); + a17 = ((((a17 % 109)+ 8) - 7) - -91); + a7 = 13; + a24 = 13; + a5 = 3; + + return 26; + } else if((( a2 <= 189 && ((a24==14) && ((input == 4) && (((a7==13) && ((111 < a17) && (255 >= a17)) ) || (( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ((a7==12) && ((111 < a17) && (255 >= a17)) )))))) && (a5==7))){ + a17 = ((((a17 - 363253) / 5) + -406812) + 479520); + a7 = 13; + + return -1; + } else if((( a2 <= 189 && ((((((a7==12) || (a7==13)) || (a7==14)) && (input == 6)) && (a24==14)) && (a5==5))) && 255 < a17 )){ + a17 = (((((a17 * 9)/ 10) / 5) * 10)/ -4); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((((((a5==7) && (((a7==14) || ((a7==12) || (a7==13))) && (input == 5))) && a2 <= 189 ) && (a24==15)) && ((111 < a17) && (255 >= a17)) )){ + a17 = ((((a17 / 5) + -515705) * 10)/ 9); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((( a17 <= -108 && ((a5==5) && ((input == 2) && (a24==14)))) && (a7==14)) && a2 <= 189 )){ + + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(( a2 <= 189 && ( ((-108 < a17) && (111 >= a17)) && ((a5==6) && ((((a7==14) || ((a7==12) || (a7==13))) && (input == 3)) && (a24==14)))))){ + a2 = (((((a2 + 0) / 5) * 4) % 45)+ 234); + a7 = 12; + a5 = 3; + + return 26; + } else if((((a24==15) && ((((input == 2) && a2 <= 189 ) && (a7==12)) && (a5==7))) && 255 < a17 )){ + a17 = ((((a17 - 570713) - 29535) / 5) - 458064); + a24 = 13; + a5 = 3; + + return -1; + } else if((((a5==5) && (((input == 3) && ((( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ((a7==12) && ((111 < a17) && (255 >= a17)) )) || ( ((111 < a17) && (255 >= a17)) && (a7==13)))) && a2 <= 189 )) && (a24==15))){ + a2 = ((((((a2 * 9)/ 10) * 1) - 13827) % 45)+ 249); + a17 = ((((a17 % 109)+ 1) - -2) + -2); + a7 = 14; + a5 = 4; + + return 26; + } else if((((a24==15) && ( a2 <= 189 && ((input == 4) && ((( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ((a7==12) && ((111 < a17) && (255 >= a17)) )) || ( ((111 < a17) && (255 >= a17)) && (a7==13)))))) && (a5==5))){ + a2 = (((((a2 % 45)- -235) - 195114) - 258356) - -453470); + a17 = (((((a17 + 155793) % 109)- 63) + 567392) - 567346); + a7 = 13; + a5 = 4; + + return 23; + } else if((((a24==14) && ((a5==4) && ((((a7==14) && ((-108 < a17) && (111 >= a17)) ) || ((a7==12) && ((111 < a17) && (255 >= a17)) )) && (input == 6)))) && ((189 < a2) && (281 >= a2)) )){ + a17 = ((((a17 - -528091) - 699874) + 649609) + -972756); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((( 255 < a17 && ((a24==15) && (((((a7==12) || (a7==13)) || (a7==14)) && (input == 1)) && ((189 < a2) && (281 >= a2)) ))) && (a5==3))){ + a2 = (((a2 / -5) - 163348) + 56585); + a7 = 14; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && ((a5==3) && ((a24==15) && ((input == 5) && (((a7==12) && ((-108 < a17) && (111 >= a17)) ) || (((a7==13) && a17 <= -108 ) || ( a17 <= -108 && (a7==14))))))))){ + a2 = (((a2 / -5) + -568912) + -5609); + a17 = (((((a17 % 71)+ 184) + -1) / 5) - -182); + a7 = 12; + a5 = 4; + + return 23; + } else if(((a24==13) && ((((input == 1) && (((a7==14) && ((111 < a17) && (255 >= a17)) ) || ( 255 < a17 && (a7==12)))) && (a5==4)) && ((189 < a2) && (281 >= a2)) ))){ + a2 = ((((a2 - 161488) * 3) + 590787) + -671028); + a17 = ((((a17 - 600109) + 22162) + -18521) - 3641); + a7 = 12; + a24 = 14; + a5 = 7; + + return -1; + } else if(((a5==6) && (((a24==14) && (((input == 3) && (((a7==12) || (a7==13)) || (a7==14))) && a2 <= 189 )) && 255 < a17 ))){ + + a7 = 14; + + return 26; + } else if((((((input == 6) && (( 255 < a17 && (a7==12)) || (( ((111 < a17) && (255 >= a17)) && (a7==13)) || ( ((111 < a17) && (255 >= a17)) && (a7==14))))) && (a24==14)) && ((189 < a2) && (281 >= a2)) ) && (a5==4))){ + a2 = (((a2 - 579407) - 8118) * 1); + a17 = (((((a17 % 109)+ 3) + -458073) + 848155) + -390111); + a7 = 13; + a24 = 15; + a5 = 5; + + return -1; + } else if(((((((((a7==14) && 255 < a17 ) && (a24==15)) && (a5==4)) || ((((a7==12) && a17 <= -108 ) && (a24==13)) && (a5==5))) || ((( a17 <= -108 && (a7==13)) && (a24==13)) && (a5==5))) && (input == 5)) && ((189 < a2) && (281 >= a2)) )){ + a17 = ((((a17 % 299872)- -300127) - -1) + 0); + a7 = 14; + a24 = 13; + a5 = 4; + + return -1; + } else if(((a5==5) && ((( ((111 < a17) && (255 >= a17)) && ( a2 <= 189 && (input == 5))) && (a24==13)) && (a7==13)))){ + a17 = (((a17 + -452489) * 1) * 1); + a7 = 12; + a5 = 3; + + return -1; + } else if((( a2 <= 189 && ((a5==7) && ((( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ( ((111 < a17) && (255 >= a17)) && (a7==12))) && (input == 4)))) && (a24==13))){ + a17 = ((((a17 % 109)- -1) / 5) / 5); + a7 = 12; + a24 = 15; + a5 = 4; + + return 21; + } else if((((a24==13) && (((((a7==14) && a17 <= -108 ) || ( ((-108 < a17) && (111 >= a17)) && (a7==12))) && (input == 6)) && (a5==5))) && ((189 < a2) && (281 >= a2)) )){ + a2 = ((((a2 / 5) + -341809) * 10)/ 9); + a17 = (((((a17 % 299872)- -300127) - 515739) + 17318) - -498422); + a7 = 12; + a24 = 15; + a5 = 7; + + return -1; + } else if(((((a24==15) && ((((a7==13) || (a7==14)) && (input == 3)) && a2 <= 189 )) && (a5==7)) && ((-108 < a17) && (111 >= a17)) )){ + + a7 = 14; + a24 = 14; + + return -1; + } else if(((a7==12) && (( a2 <= 189 && (((input == 5) && (a5==4)) && (a24==15))) && ((-108 < a17) && (111 >= a17)) ))){ + a17 = (((a17 - 277016) * 2) + -6397); + a24 = 13; + a5 = 3; + + return -1; + } else if(((a5==7) && (((((a24==15) && ( a17 <= -108 && (a7==12))) || (((a24==14) && ((a7==13) && 255 < a17 )) || ((a24==14) && ( 255 < a17 && (a7==14))))) && (input == 1)) && a2 <= 189 ))){ + a17 = ((((a17 % 299872)- -300127) + 1) + 0); + a7 = 12; + a24 = 13; + + return -1; + } else if(( ((111 < a17) && (255 >= a17)) && (((a5==5) && ((a24==15) && ((input == 5) && ((a7==14) || ((a7==12) || (a7==13)))))) && ((189 < a2) && (281 >= a2)) ))){ + + a7 = 13; + a24 = 13; + a5 = 4; + + return -1; + } else if(((a5==5) && (((((a24==14) && ( a17 <= -108 && (a7==13))) || (((a24==13) && ((a7==14) && 255 < a17 )) || ((a24==14) && ((a7==12) && a17 <= -108 )))) && (input == 4)) && a2 <= 189 ))){ + a17 = ((((a17 + 0) - 0) / 5) + -383300); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((((((((a7==13) && ((111 < a17) && (255 >= a17)) ) || (((a7==14) && ((-108 < a17) && (111 >= a17)) ) || ((a7==12) && ((111 < a17) && (255 >= a17)) ))) && (input == 5)) && (a24==15)) && (a5==3)) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 - 219315) + -185024) / 5); + a17 = ((((a17 + -245709) % 71)- -191) * 1); + a7 = 13; + a24 = 13; + + return -1; + } else if((((a5==6) && ((a24==13) && ((( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ( ((111 < a17) && (255 >= a17)) && (a7==12))) && (input == 2)))) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 * -5) / 5) + -556465); + a17 = (((a17 / 5) + -548457) + -1247); + a7 = 12; + a5 = 3; + + return -1; + } else if(((a24==15) && (((((input == 5) && (a5==7)) && a2 <= 189 ) && 255 < a17 ) && (a7==12)))){ + a17 = ((((((a17 * 9)/ 10) * 1) - 509339) % 71)+ 183); + a7 = 13; + a24 = 14; + + return -1; + } else if((((a5==7) && (((input == 2) && (((a7==14) && ((-108 < a17) && (111 >= a17)) ) || ((a7==12) && ((111 < a17) && (255 >= a17)) ))) && a2 <= 189 )) && (a24==13))){ + a2 = ((((((a2 % 45)+ 236) * 5) - -150446) % 45)- -205); + a17 = ((((a17 + -490890) / 5) + -314798) + 884206); + a7 = 14; + a24 = 14; + a5 = 3; + + return 23; + } else if((( 255 < a17 && (( a2 <= 189 && ((a24==15) && (input == 6))) && (a5==5))) && (a7==14))){ + a2 = (((((a2 * 9)/ 10) % 45)- -234) + 2); + a17 = (((((a17 / 5) + 157023) - 304246) % 109)+ 90); + a7 = 13; + a24 = 14; + + return 23; + } else if(((((a5==6) && (((((a7==13) && a17 <= -108 ) || ( a17 <= -108 && (a7==14))) || ( ((-108 < a17) && (111 >= a17)) && (a7==12))) && (input == 2))) && a2 <= 189 ) && (a24==13))){ + a17 = ((((a17 % 299946)- 300053) * 1) - 1); + a7 = 12; + a5 = 3; + + return -1; + } else if(( ((111 < a17) && (255 >= a17)) && ((a5==6) && ((((input == 2) && ((a7==14) || ((a7==12) || (a7==13)))) && a2 <= 189 ) && (a24==14))))){ + a2 = (((((a2 + 0) * 9)/ 10) % 45)- -236); + a17 = ((((a17 + -217095) - -761433) * -1)/ 10); + a7 = 12; + a24 = 13; + a5 = 4; + + return 21; + } else if(( a2 <= 189 && (((a7==14) && (((input == 1) && ((111 < a17) && (255 >= a17)) ) && (a5==5))) && (a24==14)))){ + a2 = ((((a2 % 45)- -234) - 10732) - -10732); + a24 = 15; + a5 = 3; + + return 26; + } else if(( a17 <= -108 && ((( ((189 < a2) && (281 >= a2)) && ((a5==3) && (input == 1))) && (a7==12)) && (a24==13)))){ + a2 = (((a2 + -187375) * 3) - -239890); + a17 = ((((((a17 % 71)- -216) * 9)/ 10) * 10)/ 9); + a7 = 13; + a24 = 15; + a5 = 7; + + return -1; + } else if(((((((((a7==13) && ((111 < a17) && (255 >= a17)) ) || ((a7==14) && ((111 < a17) && (255 >= a17)) )) || ((a7==12) && 255 < a17 )) && (input == 1)) && (a5==5)) && (a24==14)) && ((189 < a2) && (281 >= a2)) )){ + a17 = ((((a17 - 309533) % 299872)- -300127) * 1); + a7 = 14; + a24 = 13; + a5 = 4; + + return -1; + } else if((( ((189 < a2) && (281 >= a2)) && (((((a7==14) && ((-108 < a17) && (111 >= a17)) ) || ( ((111 < a17) && (255 >= a17)) && (a7==12))) && (input == 4)) && (a24==13))) && (a5==3))){ + a2 = (((a2 / 5) / 5) + -113113); + a17 = ((((a17 + -152498) - 120570) * 10)/ 9); + a7 = 14; + a24 = 14; + a5 = 5; + + return 21; + } else if(( ((189 < a2) && (281 >= a2)) && ((a5==3) && ((((( 255 < a17 && (a7==13)) && (a24==13)) || (( 255 < a17 && (a7==14)) && (a24==13))) || (((a7==12) && a17 <= -108 ) && (a24==14))) && (input == 4))))){ + a2 = (((a2 + -277502) * 2) - 40398); + a17 = ((((a17 + 0) / 5) + 23146) - 484422); + a7 = 12; + a24 = 13; + + return -1; + } else if(((a24==13) && ((a5==3) && ( ((189 < a2) && (281 >= a2)) && ((input == 4) && ((( ((111 < a17) && (255 >= a17)) && (a7==13)) || ((a7==14) && ((111 < a17) && (255 >= a17)) )) || ((a7==12) && 255 < a17 ))))))){ + a2 = (((a2 / 5) / -5) - 183721); + a17 = ((((a17 % 109)+ -83) + -12) + 78); + a7 = 13; + a24 = 14; + a5 = 5; + + return 26; + } else if((((((input == 3) && (( 255 < a17 && (a7==12)) || (( ((111 < a17) && (255 >= a17)) && (a7==13)) || ((a7==14) && ((111 < a17) && (255 >= a17)) )))) && (a24==13)) && (a5==6)) && a2 <= 189 )){ + a2 = ((((a2 + 0) % 45)- -234) * 1); + a17 = (((((a17 * 9)/ 10) * 1) % 71)- -138); + a7 = 13; + a24 = 15; + a5 = 3; + + return 26; + } else if(((a24==13) && ( ((189 < a2) && (281 >= a2)) && ((a5==4) && (((input == 5) && ((a7==12) || (a7==13))) && ((111 < a17) && (255 >= a17)) ))))){ + + a7 = 13; + + return -1; + } else if(((a5==4) && (( ((189 < a2) && (281 >= a2)) && ((input == 4) && (( ((-108 < a17) && (111 >= a17)) && (a7==12)) || (((a7==13) && a17 <= -108 ) || ((a7==14) && a17 <= -108 ))))) && (a24==13)))){ + a2 = (((a2 * 5) * 5) + -590870); + a17 = ((((a17 + 439473) + -202777) % 299946)+ -300053); + a7 = 12; + a5 = 3; + + return -1; + } else if(((a24==15) && (( 255 < a17 && ((a5==5) && ((input == 3) && (((a7==12) || (a7==13)) || (a7==14))))) && ((189 < a2) && (281 >= a2)) ))){ + a2 = (((a2 - -345840) * 1) * -1); + a17 = ((((a17 % 109)- 50) - 15) / 5); + a7 = 13; + a5 = 7; + + return -1; + } else if(( a2 <= 189 && (( ((111 < a17) && (255 >= a17)) && (((input == 2) && (((a7==12) || (a7==13)) || (a7==14))) && (a5==7))) && (a24==15)))){ + a17 = ((((a17 / 5) + -289356) * 10)/ 9); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a5==4) && ((a24==13) && (((((a7==12) && ((-108 < a17) && (111 >= a17)) ) || (((a7==13) && a17 <= -108 ) || ( a17 <= -108 && (a7==14)))) && (input == 6)) && ((189 < a2) && (281 >= a2)) )))){ + a17 = (((((a17 % 299872)- -300127) / 5) / 5) - -212547); + a7 = 14; + a24 = 14; + a5 = 3; + + return -1; + } else if(( ((-108 < a17) && (111 >= a17)) && ( a2 <= 189 && ((a24==15) && ((((a7==13) || (a7==14)) && (input == 6)) && (a5==6)))))){ + a2 = ((((a2 % 45)+ 234) / 5) - -178); + a7 = 14; + a5 = 3; + + return 26; + } else if(( ((-108 < a17) && (111 >= a17)) && (((((a24==15) && (input == 2)) && ((189 < a2) && (281 >= a2)) ) && (a5==4)) && (a7==13)))){ + a2 = (((a2 + -185317) * 3) * 1); + a17 = (((a17 - -209383) / 5) + -402688); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((((a5==4) && ((a24==13) && ((input == 4) && a17 <= -108 ))) && (a7==12)) && ((189 < a2) && (281 >= a2)) )){ + a2 = ((((a2 + -340540) + -216382) - -1035898) * -1); + a17 = ((((a17 % 299872)- -300127) - 43079) + 207436); + a7 = 14; + a24 = 14; + a5 = 5; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && ((a5==3) && (((input == 1) && ((( a17 <= -108 && (a7==13)) || ((a7==14) && a17 <= -108 )) || ( ((-108 < a17) && (111 >= a17)) && (a7==12)))) && (a24==14))))){ + a2 = (((a2 * 5) * 5) - 195095); + a17 = ((((((a17 * 9)/ 10) * 1) * 1) % 109)+ 2); + a7 = 13; + a5 = 5; + + return 26; + } else if(((a5==4) && (( ((189 < a2) && (281 >= a2)) && ((((a7==12) || (a7==13)) && (input == 4)) && a17 <= -108 )) && (a24==14)))){ + + a7 = 12; + + return -1; + } else if(( a2 <= 189 && ( ((111 < a17) && (255 >= a17)) && ((a7==12) && ((a5==4) && ((a24==15) && (input == 4))))))){ + a17 = ((((a17 * 5) * 5) * 10)/ -9); + a24 = 13; + a5 = 3; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && (( ((-108 < a17) && (111 >= a17)) && ((a7==13) && ((input == 6) && (a5==3)))) && (a24==15)))){ + a2 = (((a2 + 505188) / 5) - 263894); + a17 = (((((a17 % 71)- -182) + 569253) * 1) + -569250); + a7 = 12; + a5 = 4; + + return -1; + } else if(( a2 <= 189 && ((input == 6) && ((((((a7==14) && 255 < a17 ) && (a24==15)) && (a5==6)) || ((((a7==12) && a17 <= -108 ) && (a24==13)) && (a5==7))) || (((a24==13) && ( a17 <= -108 && (a7==13))) && (a5==7)))))){ + a2 = (((((a2 % 45)- -236) + -2) / 5) - -177); + a17 = ((((a17 % 299872)- -300127) / 5) - -33046); + a7 = 12; + a24 = 13; + a5 = 3; + + return 23; + } else if(((( ((189 < a2) && (281 >= a2)) && (((input == 6) && ((a7==13) || (a7==14))) && (a24==14))) && 255 < a17 ) && (a5==4))){ + + a7 = 12; + a24 = 13; + + return -1; + } else if(((a5==6) && ((a24==15) && (((a7==13) && ((input == 6) && a17 <= -108 )) && a2 <= 189 )))){ + a2 = (((((a2 % 45)- -235) + 573332) * 1) + -573331); + a17 = ((((a17 % 109)- -40) - 575414) + 575451); + a7 = 14; + a24 = 13; + a5 = 4; + + return 23; + } else if(((a24==15) && ((a5==4) && ((((( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ( ((111 < a17) && (255 >= a17)) && (a7==12))) || ( ((111 < a17) && (255 >= a17)) && (a7==13))) && (input == 4)) && ((189 < a2) && (281 >= a2)) )))){ + a2 = (((a2 * 5) + -205527) + -261072); + a17 = ((((a17 * 5) + 376065) % 71)+ 172); + a7 = 12; + a5 = 5; + + return 21; + } else if((( a2 <= 189 && ((((( 255 < a17 && (a7==13)) && (a24==13)) || (((a7==14) && 255 < a17 ) && (a24==13))) || ((a24==14) && ( a17 <= -108 && (a7==12)))) && (input == 1))) && (a5==6))){ + a2 = ((((a2 % 45)- -235) / 5) * 5); + a17 = (((((a17 * 9)/ 10) % 299946)- 300053) - 1); + a7 = 12; + a24 = 15; + a5 = 3; + + return 26; + } else if(((a7==14) && ((a24==15) && ((((input == 6) && ((111 < a17) && (255 >= a17)) ) && ((189 < a2) && (281 >= a2)) ) && (a5==3))))){ + a17 = (((a17 + -508114) * 1) - 7160); + a7 = 13; + a24 = 14; + + return -1; + } else if((((a5==5) && (( a2 <= 189 && ((input == 5) && (a7==14))) && 255 < a17 )) && (a24==15))){ + a2 = ((((a2 - 0) / 5) % 45)- -236); + a17 = (((a17 - 600247) * 1) * 1); + a7 = 12; + a24 = 14; + + return 21; + } else if(((((a24==13) && ((input == 6) && (( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ((a7==12) && ((111 < a17) && (255 >= a17)) )))) && ((189 < a2) && (281 >= a2)) ) && (a5==6))){ + a17 = (((((a17 / 5) - -11) * 5) % 109)+ 1); + a7 = 12; + a5 = 3; + + return -1; + } else if((((a24==15) && ((a5==4) && ((input == 3) && (( ((111 < a17) && (255 >= a17)) && (a7==13)) || (( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ((a7==12) && ((111 < a17) && (255 >= a17)) )))))) && ((189 < a2) && (281 >= a2)) )){ + a2 = ((((a2 - 251250) * 10)/ 9) + -123956); + a17 = ((((a17 + -55926) + -49743) * 10)/ 9); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a7==13) && ((a5==6) && ((((input == 2) && 255 < a17 ) && ((189 < a2) && (281 >= a2)) ) && (a24==13))))){ + a2 = ((((a2 + -73789) * 10)/ 9) - 475570); + a17 = (((a17 + -600188) - 1) + -26); + a7 = 12; + a5 = 3; + + return -1; + } else if(( ((111 < a17) && (255 >= a17)) && ((((((a7==13) || (a7==14)) && (input == 4)) && a2 <= 189 ) && (a24==15)) && (a5==4)))){ + + a7 = 13; + a5 = 5; + + return 21; + } + return calculate_output3(input); + } + + int calculate_output3(int input) { + + + if(( a2 <= 189 && ((a24==15) && ((a7==14) && ((a5==5) && ( a17 <= -108 && (input == 2))))))){ + + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((((a24==15) && ( ((-108 < a17) && (111 >= a17)) && ( ((189 < a2) && (281 >= a2)) && ((input == 3) && ((a7==13) || (a7==14)))))) && (a5==5))){ + a2 = (((a2 / 5) * -5) / 5); + a17 = ((((a17 + 77227) + 218385) - 579561) - -466982); + a7 = 12; + a24 = 14; + a5 = 7; + + return -1; + } else if((((a5==5) && ( a2 <= 189 && ((a7==14) && ((a24==13) && (input == 4))))) && ((111 < a17) && (255 >= a17)) )){ + a17 = ((((a17 + -361852) * 1) / 5) - -72429); + a7 = 13; + a24 = 14; + a5 = 7; + + return 21; + } else if(( ((189 < a2) && (281 >= a2)) && ((((a7==13) && ((a5==3) && (input == 3))) && (a24==15)) && ((-108 < a17) && (111 >= a17)) ))){ + + a7 = 14; + a24 = 14; + + return -1; + } else if(((((((((a7==14) && a17 <= -108 ) || ( ((-108 < a17) && (111 >= a17)) && (a7==12))) || ( ((-108 < a17) && (111 >= a17)) && (a7==13))) && (input == 1)) && a2 <= 189 ) && (a5==7)) && (a24==13))){ + a2 = ((((a2 - -278577) * 1) % 45)- -234); + a17 = ((((a17 / 5) % 109)- -2) - 1); + a7 = 13; + a24 = 15; + a5 = 3; + + return 26; + } else if(( ((-108 < a17) && (111 >= a17)) && ((a24==13) && (((a5==3) && ((input == 2) && ((a7==12) || (a7==13)))) && ((189 < a2) && (281 >= a2)) )))){ + a2 = (((a2 + 542429) / -5) + -452431); + a17 = (((((a17 + -62715) % 71)- -200) * 9)/ 10); + a7 = 14; + + return -1; + } else if(((((a5==5) && ((((a7==12) || (a7==13)) && (input == 5)) && (a24==14))) && ((111 < a17) && (255 >= a17)) ) && a2 <= 189 )){ + a17 = ((((a17 * 5) / 5) * 10)/ -9); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a24==13) && ( 255 < a17 && ( ((189 < a2) && (281 >= a2)) && ((((a7==13) || (a7==14)) && (input == 1)) && (a5==4)))))){ + a2 = ((((a2 + -345206) - -753451) / 5) * -5); + a17 = ((((a17 % 109)- 98) - 8) + 96); + a7 = 12; + a24 = 15; + a5 = 7; + + return -1; + } else if(( 255 < a17 && (((a24==14) && ((a5==5) && ((input == 1) && ((a7==13) || (a7==14))))) && ((189 < a2) && (281 >= a2)) ))){ + a2 = (((a2 * 5) + 150678) + -312416); + a17 = (((((a17 + 0) + 0) / 5) % 71)+ 147); + a7 = 13; + a5 = 7; + + return -1; + } else if(((((((input == 2) && (((a7==12) || (a7==13)) || (a7==14))) && 255 < a17 ) && ((189 < a2) && (281 >= a2)) ) && (a24==13)) && (a5==5))){ + a2 = (((a2 + -439935) * 1) * 1); + a17 = (((a17 - 581561) + -18563) - 36); + a7 = 12; + a5 = 3; + + return -1; + } else if((( a2 <= 189 && (((input == 2) && ((((a7==14) && ((-108 < a17) && (111 >= a17)) ) || ( ((111 < a17) && (255 >= a17)) && (a7==12))) || ((a7==13) && ((111 < a17) && (255 >= a17)) ))) && (a5==7))) && (a24==14))){ + a17 = (((a17 - 547158) * 1) * 1); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a5==3) && ((a24==14) && ( ((189 < a2) && (281 >= a2)) && ((input == 2) && ((((a7==14) && ((111 < a17) && (255 >= a17)) ) || ((a7==12) && 255 < a17 )) || ( 255 < a17 && (a7==13)))))))){ + a2 = (((a2 * -5) * 5) - 267645); + a17 = ((((((a17 * 9)/ 10) % 71)+ 146) - 7467) - -7498); + a7 = 12; + a24 = 15; + a5 = 4; + + return 23; + } else if((((a5==5) && (( a2 <= 189 && (((a7==14) || ((a7==12) || (a7==13))) && (input == 5))) && (a24==14))) && 255 < a17 )){ + a17 = (((a17 + -600255) + -1) + 0); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((((a5==6) && (( ((189 < a2) && (281 >= a2)) && ((input == 5) && (a7==14))) && a17 <= -108 )) && (a24==13))){ + a17 = ((((((a17 % 109)- -39) * 5) - 208544) % 109)+ 56); + a5 = 3; + + return -1; + } else if(((a7==14) && ( ((189 < a2) && (281 >= a2)) && ((( a17 <= -108 && (input == 3)) && (a24==13)) && (a5==6))))){ + a2 = (((a2 + -369894) + -119659) - 59892); + a7 = 12; + a5 = 3; + + return -1; + } else if((((a7==14) && (((a5==5) && ((input == 1) && (a24==13))) && ((111 < a17) && (255 >= a17)) )) && a2 <= 189 )){ + a17 = (((((a17 * 10)/ -9) - -538584) * 1) - 852442); + a7 = 12; + a24 = 15; + a5 = 7; + + return 23; + } else if((( a2 <= 189 && ((((input == 3) && ((a7==12) || (a7==13))) && (a5==6)) && 255 < a17 )) && (a24==15))){ + a2 = ((((a2 - 0) % 45)+ 235) + 1); + a17 = ((((a17 - 0) % 109)- 13) - -1); + a7 = 13; + a24 = 13; + a5 = 4; + + return 26; + } else if((((a24==15) && ( ((189 < a2) && (281 >= a2)) && ((((a7==14) && ((111 < a17) && (255 >= a17)) ) || ( 255 < a17 && (a7==12))) && (input == 2)))) && (a5==4))){ + a2 = (((a2 * 5) / -5) * 5); + a17 = (((a17 + -600110) * 1) + -1); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && (((((a24==14) && ( 255 < a17 && (a7==14))) || ((a24==15) && ( a17 <= -108 && (a7==12)))) && (input == 5)) && (a5==3)))){ + a2 = (((a2 * -5) - 176348) - 175983); + a17 = ((((a17 % 71)- -182) + 3) - 3); + a7 = 12; + a24 = 13; + a5 = 7; + + return -1; + } else if(((((((input == 3) && (((a7==12) || (a7==13)) || (a7==14))) && 255 < a17 ) && a2 <= 189 ) && (a24==14)) && (a5==5))){ + a2 = (((((a2 + 252809) % 45)+ 234) - -188524) + -188523); + a17 = ((((((a17 / 5) % 109)+ 1) * 5) % 109)+ 3); + a7 = 14; + a24 = 13; + a5 = 4; + + return 21; + } else if(( a2 <= 189 && ((a24==14) && ( ((-108 < a17) && (111 >= a17)) && ((a7==13) && ((input == 3) && (a5==7))))))){ + a17 = (((a17 - 479950) * 1) / 5); + a7 = 12; + + return -1; + } else if((((((( ((-108 < a17) && (111 >= a17)) && (a7==13)) || (( a17 <= -108 && (a7==14)) || ((a7==12) && ((-108 < a17) && (111 >= a17)) ))) && (input == 1)) && a2 <= 189 ) && (a5==5)) && (a24==13))){ + a17 = ((((a17 - -331363) % 109)- -1) + 0); + a7 = 12; + a24 = 14; + a5 = 6; + + return 21; + } else if((( 255 < a17 && (( ((189 < a2) && (281 >= a2)) && ((input == 4) && (((a7==12) || (a7==13)) || (a7==14)))) && (a24==15))) && (a5==3))){ + a2 = ((((a2 * 5) / 5) - -456557) * -1); + a17 = (((a17 / 5) * 4) + -534343); + a7 = 13; + a24 = 13; + + return -1; + } else if((((a24==15) && (((input == 2) && (( a17 <= -108 && (a7==14)) || ( ((-108 < a17) && (111 >= a17)) && (a7==12)))) && a2 <= 189 )) && (a5==6))){ + a17 = ((((a17 % 299946)- 300053) / 5) + -177770); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(( a2 <= 189 && (((a24==15) && (((input == 4) && ((a7==13) || (a7==14))) && (a5==7))) && 255 < a17 ))){ + + a7 = 13; + a24 = 13; + + return -1; + } else if(((a5==3) && ( ((189 < a2) && (281 >= a2)) && ((input == 4) && ((( 255 < a17 && (a7==14)) && (a24==14)) || ((a24==15) && ( a17 <= -108 && (a7==12)))))))){ + a17 = (((((a17 % 299872)+ 300127) + 0) + -528429) + 528430); + a7 = 13; + a24 = 14; + + return -1; + } else if((((a24==14) && ((a5==4) && ((( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ( ((111 < a17) && (255 >= a17)) && (a7==12))) && (input == 1)))) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 + -412962) - 162289) + -93); + a17 = ((((a17 + 200708) / 5) - -224575) + -264525); + a7 = 13; + a24 = 15; + + return 21; + } else if(( 255 < a17 && ((a5==4) && ((((a7==13) && (input == 2)) && ((189 < a2) && (281 >= a2)) ) && (a24==15))))){ + a2 = ((((a2 + 17174) - -390384) * 1) * -1); + a17 = (((a17 + -200385) - 399757) + -108); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((((((a5==5) && ((input == 3) && ((a7==14) || ((a7==12) || (a7==13))))) && (a24==15)) && ((189 < a2) && (281 >= a2)) ) && ((111 < a17) && (255 >= a17)) )){ + a2 = (((a2 / 5) / 5) * 5); + a7 = 14; + a24 = 13; + a5 = 7; + + return -1; + } else if(((a24==15) && ( a2 <= 189 && ((a5==6) && (((input == 1) && ((a7==13) || (a7==14))) && ((-108 < a17) && (111 >= a17)) ))))){ + a2 = ((((a2 % 45)- -236) + 1) - 2); + a17 = ((((a17 * 5) % 71)- -183) + -1); + a7 = 14; + a24 = 14; + a5 = 3; + + return 21; + } else if((((a24==13) && (((input == 5) && ((((a7==13) && a17 <= -108 ) || ( a17 <= -108 && (a7==14))) || ((a7==12) && ((-108 < a17) && (111 >= a17)) ))) && a2 <= 189 )) && (a5==6))){ + a2 = ((((a2 % 45)+ 235) - 1) + 1); + a17 = ((((a17 - 0) % 299872)- -300127) * 1); + a7 = 13; + a24 = 15; + a5 = 5; + + return 26; + } else if((((((a24==14) && (((a7==14) || ((a7==12) || (a7==13))) && (input == 1))) && a2 <= 189 ) && (a5==5)) && ((-108 < a17) && (111 >= a17)) )){ + a2 = ((((a2 % 45)+ 234) + 293810) + -293808); + a7 = 12; + a5 = 3; + + return 23; + } else if(((((((a24==15) && (input == 1)) && (a5==4)) && (a7==12)) && ((111 < a17) && (255 >= a17)) ) && a2 <= 189 )){ + + a7 = 14; + a24 = 14; + a5 = 5; + + return 23; + } else if(((a5==5) && ( ((-108 < a17) && (111 >= a17)) && ((((input == 5) && ((a7==12) || (a7==13))) && a2 <= 189 ) && (a24==15))))){ + a2 = (((((a2 % 45)+ 236) - 49315) / 5) + 10068); + a17 = (((a17 + -103117) / 5) - 439137); + a7 = 13; + a5 = 4; + + return 21; + } else if(( ((189 < a2) && (281 >= a2)) && ((a24==13) && ((a5==4) && ( ((111 < a17) && (255 >= a17)) && ((input == 3) && ((a7==12) || (a7==13)))))))){ + a2 = ((((a2 * -5) - 314138) - -565933) + -292419); + a17 = (((a17 + -173172) + -177178) * 1); + a7 = 13; + a24 = 15; + a5 = 5; + + return -1; + } else if((((a5==3) && (((( a17 <= -108 && (a7==12)) && (a24==14)) || (((a24==13) && ( 255 < a17 && (a7==13))) || ((a24==13) && ( 255 < a17 && (a7==14))))) && (input == 2))) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 + -532738) + -47238) * 1); + a17 = (((((a17 + 0) * 9)/ 10) % 71)- -182); + a7 = 12; + a24 = 15; + a5 = 4; + + return 23; + } else if(((a5==6) && ((a24==13) && (((input == 4) && ((( a17 <= -108 && (a7==13)) || ((a7==14) && a17 <= -108 )) || ((a7==12) && ((-108 < a17) && (111 >= a17)) ))) && a2 <= 189 )))){ + a17 = ((((a17 - -565469) + -60299) / 5) - 520148); + a7 = 12; + a5 = 3; + + return -1; + } else if((((( 255 < a17 && ((input == 3) && (a7==13))) && (a24==13)) && (a5==6)) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 / -5) - 310362) - 118239); + a17 = ((((a17 + -527475) + -43049) / 5) + -159294); + a7 = 12; + a5 = 3; + + return -1; + } else if((((a24==14) && ((a5==4) && ((input == 1) && (( a17 <= -108 && (a7==14)) || ((a7==12) && ((-108 < a17) && (111 >= a17)) ))))) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((((a2 * -5) * 10)/ 9) - -320944) * -1); + a17 = (((((a17 * 9)/ 10) + 31872) % 71)+ 182); + a7 = 13; + a24 = 13; + + return -1; + } else if(( a2 <= 189 && ((a24==15) && ( a17 <= -108 && (((a7==13) && (input == 4)) && (a5==6)))))){ + + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((((((input == 5) && (( a17 <= -108 && (a7==14)) || ((a7==12) && ((-108 < a17) && (111 >= a17)) ))) && (a24==14)) && (a5==5)) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 * 5) - 436847) + -130272); + a17 = (((a17 / 5) - 469094) - -33679); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((((a5==4) && ( 255 < a17 && ( ((189 < a2) && (281 >= a2)) && ((input == 3) && ((a7==13) || (a7==14)))))) && (a24==14))){ + a17 = (((((a17 / 5) * 4) - -51204) % 71)+ 129); + a7 = 14; + + return -1; + } else if((((( a2 <= 189 && ((a7==12) && (input == 1))) && (a5==7)) && 255 < a17 ) && (a24==15))){ + a17 = ((((a17 - 204408) - -50146) % 109)- -2); + a7 = 14; + a5 = 4; + + return -1; + } else if(( a2 <= 189 && ((a24==15) && ((a5==5) && ( a17 <= -108 && ((a7==14) && (input == 3))))))){ + a2 = (((((a2 % 45)+ 236) * 5) % 45)+ 204); + a17 = (((((a17 + 0) * 9)/ 10) % 109)+ 90); + a7 = 12; + a24 = 14; + a5 = 4; + + return 26; + } else if(((((a5==6) && ((((a7==14) && a17 <= -108 ) || ( ((-108 < a17) && (111 >= a17)) && (a7==12))) && (input == 5))) && (a24==15)) && a2 <= 189 )){ + a17 = ((((a17 % 71)+ 184) - 1) - 1); + a7 = 12; + a24 = 13; + a5 = 7; + + return 26; + } else if((( ((189 < a2) && (281 >= a2)) && ((a24==14) && ((( 255 < a17 && (a7==13)) || (((a7==14) && ((111 < a17) && (255 >= a17)) ) || ( 255 < a17 && (a7==12)))) && (input == 1)))) && (a5==3))){ + a17 = (((((a17 * 9)/ 10) % 109)- -2) + 1); + a7 = 12; + + return -1; + } else if(((a24==15) && ( a2 <= 189 && ((a7==14) && (((input == 2) && ((111 < a17) && (255 >= a17)) ) && (a5==5)))))){ + a17 = ((((a17 - 501351) * 10)/ 9) * 1); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a7==13) && (((((input == 5) && (a5==7)) && (a24==14)) && ((-108 < a17) && (111 >= a17)) ) && a2 <= 189 ))){ + a17 = (((a17 + -506871) + -84379) / 5); + a7 = 12; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && ((((input == 2) && (( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ( ((111 < a17) && (255 >= a17)) && (a7==12)))) && (a5==3)) && (a24==13)))){ + a2 = (((a2 / 5) * 5) - 539865); + a17 = (((a17 + -583438) - 9976) - 606); + a7 = 12; + + return -1; + } else if((((( ((111 < a17) && (255 >= a17)) && ((input == 5) && a2 <= 189 )) && (a7==14)) && (a5==5)) && (a24==14))){ + a17 = ((((a17 / 5) + 148886) * 10)/ -9); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a5==7) && (((( 255 < a17 && (input == 1)) && (a24==13)) && a2 <= 189 ) && (a7==13)))){ + + return -1; + } else if(((( ((111 < a17) && (255 >= a17)) && (( ((189 < a2) && (281 >= a2)) && (input == 4)) && (a7==13))) && (a24==14)) && (a5==3))){ + a17 = ((((a17 / 5) - 84) * 10)/ 9); + a7 = 12; + + return -1; + } else if((((((a24==15) && ((input == 6) && ((111 < a17) && (255 >= a17)) )) && (a5==5)) && (a7==14)) && a2 <= 189 )){ + a2 = (((((a2 % 45)- -234) + 3) - 467950) - -467949); + a17 = ((((a17 * 23)/ 10) - -254710) + 246366); + a5 = 4; + + return 21; + } else if(((((((a5==4) && ((a24==15) && ((a7==14) && 255 < a17 ))) || ((( a17 <= -108 && (a7==12)) && (a24==13)) && (a5==5))) || ((a5==5) && (((a7==13) && a17 <= -108 ) && (a24==13)))) && (input == 4)) && a2 <= 189 )){ + a17 = ((((a17 + 0) + 0) % 299946)+ -300053); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((((( ((111 < a17) && (255 >= a17)) && (input == 6)) && (a7==13)) && a2 <= 189 ) && (a24==13)) && (a5==5))){ + a17 = (((a17 * 5) + 157598) / 5); + a7 = 14; + a5 = 7; + + return 21; + } else if(( a2 <= 189 && ((a5==7) && (((( 255 < a17 && (a7==14)) && (a24==13)) || ((a24==14) && ( a17 <= -108 && (a7==12)))) && (input == 3))))){ + a17 = ((((a17 + 0) + 0) % 299872)+ 300127); + a7 = 13; + a24 = 13; + + return -1; + } else if(( a2 <= 189 && ((a5==6) && (((((a7==12) && a17 <= -108 ) && (a24==14)) || (((a24==13) && ( 255 < a17 && (a7==13))) || (( 255 < a17 && (a7==14)) && (a24==13)))) && (input == 2))))){ + a2 = (((((a2 + 453687) % 45)- -236) - -350177) + -350178); + a17 = (((((a17 % 71)+ 182) + 0) - -438904) - 438902); + a7 = 12; + a24 = 14; + a5 = 3; + + return 23; + } else if(( ((111 < a17) && (255 >= a17)) && ((a7==13) && ((( ((189 < a2) && (281 >= a2)) && (input == 3)) && (a24==14)) && (a5==3))))){ + a2 = (((a2 / 5) / -5) * 5); + a17 = (((a17 * 5) - -273749) - 586768); + a7 = 14; + + return -1; + } else if(((a5==7) && (( a2 <= 189 && ((input == 3) && (( ((111 < a17) && (255 >= a17)) && (a7==13)) || (( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ( ((111 < a17) && (255 >= a17)) && (a7==12)))))) && (a24==14)))){ + a17 = (((((a17 - 515132) / 5) + 523785) * -1)/ 10); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((((a5==5) && ((((a7==14) && a17 <= -108 ) || ((a7==12) && ((-108 < a17) && (111 >= a17)) )) && (input == 2))) && ((189 < a2) && (281 >= a2)) ) && (a24==13))){ + a2 = (((a2 * 5) + 144469) + -189230); + a17 = (((((a17 + 0) % 299946)- 300053) / 5) + -445482); + a7 = 12; + a5 = 3; + + return -1; + } else if(((((a5==5) && (( ((189 < a2) && (281 >= a2)) && (input == 4)) && ((-108 < a17) && (111 >= a17)) )) && (a24==15)) && (a7==12))){ + a2 = (((a2 * 5) / -5) * 5); + a17 = ((((((a17 * 5) % 71)+ 184) * 5) % 71)- -152); + a24 = 14; + a5 = 7; + + return -1; + } else if((( ((-108 < a17) && (111 >= a17)) && ((a5==3) && ( ((189 < a2) && (281 >= a2)) && ((input == 2) && (a24==15))))) && (a7==13))){ + a17 = (((a17 - -116942) * 5) * 1); + a24 = 13; + + return -1; + } else if(((a5==5) && ((a24==13) && ( ((111 < a17) && (255 >= a17)) && ( a2 <= 189 && ((a7==13) && (input == 4))))))){ + a17 = (((a17 * 5) - 554850) + -19327); + a24 = 14; + a5 = 7; + + return 23; + } else if((( ((-108 < a17) && (111 >= a17)) && (((((a7==13) || (a7==14)) && (input == 4)) && (a24==15)) && a2 <= 189 )) && (a5==7))){ + a17 = (((a17 / 5) + -465987) + -123095); + a7 = 12; + + return -1; + } else if((((((a24==13) && (((a7==13) || (a7==14)) && (input == 3))) && ((-108 < a17) && (111 >= a17)) ) && (a5==4)) && ((189 < a2) && (281 >= a2)) )){ + a17 = ((((a17 % 71)+ 183) - 106273) - -106273); + a7 = 14; + a24 = 15; + a5 = 3; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && (((a24==13) && ( ((-108 < a17) && (111 >= a17)) && (((a7==12) || (a7==13)) && (input == 5)))) && (a5==3)))){ + a2 = ((((a2 * -5) * 5) + 590510) - 671065); + a7 = 14; + a24 = 15; + a5 = 4; + + return -1; + } else if((( ((111 < a17) && (255 >= a17)) && ((a5==5) && (((input == 6) && (a24==14)) && (a7==14)))) && a2 <= 189 )){ + a17 = ((((a17 * 5) * 10)/ -9) / 5); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((((((( a17 <= -108 && (a7==12)) && (a24==15)) || ((( 255 < a17 && (a7==13)) && (a24==14)) || ((a24==14) && ( 255 < a17 && (a7==14))))) && (input == 6)) && a2 <= 189 ) && (a5==7))){ + a17 = (((a17 / 5) - 232817) * 1); + a7 = 12; + a24 = 15; + + return -1; + } else if((( a2 <= 189 && (((input == 6) && (((a7==14) && a17 <= -108 ) || ((a7==12) && ((-108 < a17) && (111 >= a17)) ))) && (a5==6))) && (a24==15))){ + a17 = (((((a17 % 299946)+ -300053) + 0) / 5) + -24082); + a7 = 14; + + return 23; + } else if((((a24==14) && (((((a7==14) && ((111 < a17) && (255 >= a17)) ) || ( 255 < a17 && (a7==12))) && (input == 1)) && (a5==7))) && a2 <= 189 )){ + a17 = (((((a17 % 299872)- -256) * 1) / 5) - -44806); + a7 = 13; + a24 = 13; + + return -1; + } else if(((a24==14) && ((( a2 <= 189 && ((input == 1) && (((a7==12) || (a7==13)) || (a7==14)))) && (a5==6)) && 255 < a17 ))){ + a2 = ((((((a2 / 5) % 45)+ 235) / 5) * 51)/ 10); + a17 = ((((((a17 / 5) % 109)+ 2) * 5) % 109)+ -3); + a7 = 13; + a24 = 15; + a5 = 3; + + return 26; + } else if(((( a2 <= 189 && ((a5==6) && (((a7==13) || (a7==14)) && (input == 4)))) && ((-108 < a17) && (111 >= a17)) ) && (a24==15))){ + a2 = ((((a2 + 216043) % 45)+ 236) - -1); + a17 = (((((a17 - 429059) + 308928) * 4) % 71)- -208); + a7 = 14; + a5 = 3; + + return 21; + } else if((((((((a7==13) || (a7==14)) && (input == 5)) && a2 <= 189 ) && ((111 < a17) && (255 >= a17)) ) && (a24==15)) && (a5==6))){ + a17 = (((a17 + -54487) - 92979) - 379120); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(( ((-108 < a17) && (111 >= a17)) && (( ((189 < a2) && (281 >= a2)) && ((a5==6) && (((a7==12) || (a7==13)) && (input == 1)))) && (a24==13)))){ + a2 = (((a2 - 455132) - 98197) + -25953); + a17 = (((a17 + 255777) * 2) + -670603); + a7 = 12; + a5 = 3; + + return -1; + } else if((((a24==14) && ((a5==3) && (((( a17 <= -108 && (a7==13)) || ((a7==14) && a17 <= -108 )) || ( ((-108 < a17) && (111 >= a17)) && (a7==12))) && (input == 6)))) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 + -585771) + -2935) * 1); + a17 = (((((a17 * 9)/ 10) / 5) % 109)- -1); + a7 = 13; + a5 = 4; + + return -1; + } else if(((a5==5) && (((a24==15) && ( a2 <= 189 && (((a7==12) || (a7==13)) && (input == 4)))) && ((-108 < a17) && (111 >= a17)) ))){ + a2 = ((((((a2 - 0) + 0) * 9)/ 10) % 45)- -234); + a17 = ((((a17 % 71)- -184) - 1) + 1); + a7 = 14; + a24 = 14; + a5 = 4; + + return 21; + } else if((((a5==5) && (((input == 6) && (((a7==14) && a17 <= -108 ) || ((a7==12) && ((-108 < a17) && (111 >= a17)) ))) && (a24==14))) && ((189 < a2) && (281 >= a2)) )){ + a17 = ((((((a17 * 9)/ 10) / 5) - 287459) % 109)- -2); + a7 = 12; + a5 = 4; + + return -1; + } else if((( ((111 < a17) && (255 >= a17)) && ((a24==15) && ( ((189 < a2) && (281 >= a2)) && ((a7==14) && (input == 2))))) && (a5==3))){ + + return 26; + } else if(((( a2 <= 189 && ((a24==13) && ((input == 3) && ((-108 < a17) && (111 >= a17)) ))) && (a5==5)) && (a7==14))){ + a17 = ((((a17 / 5) * 5) / 5) - -181132); + a7 = 13; + a24 = 15; + a5 = 6; + + return 23; + } else if(( a2 <= 189 && ((((((a7==13) || (a7==14)) && (input == 2)) && ((-108 < a17) && (111 >= a17)) ) && (a24==15)) && (a5==7)))){ + a17 = (((a17 - 261314) + 71142) / 5); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((( 255 < a17 && (((a24==13) && ((input == 2) && ((a7==13) || (a7==14)))) && (a5==4))) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 * 5) + -450773) - 107216); + a17 = ((((((a17 % 71)+ 158) - 39) / 5) * 49)/ 10); + a7 = 14; + a24 = 14; + + return -1; + } else if(((( a2 <= 189 && (((((a7==13) && a17 <= -108 ) || ((a7==14) && a17 <= -108 )) || ((a7==12) && ((-108 < a17) && (111 >= a17)) )) && (input == 4))) && (a5==7)) && (a24==14))){ + a17 = (((((a17 * 9)/ 10) % 109)- -1) + 0); + a7 = 14; + a24 = 15; + a5 = 4; + + return 21; + } else if(((((a5==4) && ( ((189 < a2) && (281 >= a2)) && (((a7==14) || ((a7==12) || (a7==13))) && (input == 4)))) && (a24==15)) && a17 <= -108 )){ + a17 = (((((a17 % 71)- -182) + 0) / 5) - -96); + a7 = 13; + a24 = 14; + + return -1; + } else if(( a2 <= 189 && ((a5==6) && (((((a7==12) || (a7==13)) && (input == 5)) && (a24==15)) && 255 < a17 )))){ + a2 = ((((a2 % 45)- -236) + 127994) - 127995); + a17 = (((((a17 - 156755) * 1) * 1) % 109)- -2); + a7 = 13; + a5 = 3; + + return 21; + } else if(((a24==13) && (((a5==6) && ((input == 3) && (((a7==14) && ((-108 < a17) && (111 >= a17)) ) || ( ((111 < a17) && (255 >= a17)) && (a7==12))))) && ((189 < a2) && (281 >= a2)) ))){ + a17 = (((((a17 / 5) * 5) + -36231) * -1)/ 10); + a7 = 14; + a5 = 4; + + return -1; + } else if(((((((( a17 <= -108 && (a7==13)) || ((a7==14) && a17 <= -108 )) || ( ((-108 < a17) && (111 >= a17)) && (a7==12))) && (input == 6)) && (a24==15)) && a2 <= 189 ) && (a5==7))){ + a17 = (((((a17 + 0) / 5) + 400868) % 109)+ -80); + a7 = 13; + a24 = 14; + + return -1; + } else if((((a24==15) && ((((input == 3) && ((a7==12) || (a7==13))) && 255 < a17 ) && (a5==5))) && a2 <= 189 )){ + a17 = (((a17 - 600131) - 103) + -13); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a24==14) && ((a5==5) && (((input == 5) && (((a7==12) && ((111 < a17) && (255 >= a17)) ) || (((a7==13) && ((-108 < a17) && (111 >= a17)) ) || ((a7==14) && ((-108 < a17) && (111 >= a17)) )))) && ((189 < a2) && (281 >= a2)) )))){ + a2 = ((((a2 + 363060) - 21984) + -307797) * -5); + a17 = ((((a17 / 5) / 5) - -385642) - 385582); + a7 = 13; + a5 = 7; + + return -1; + } else if(((a5==7) && ( a2 <= 189 && ((a24==15) && ((input == 4) && ((( a17 <= -108 && (a7==13)) || ((a7==14) && a17 <= -108 )) || ( ((-108 < a17) && (111 >= a17)) && (a7==12)))))))){ + a17 = ((((a17 - 0) % 299872)- -300127) + 1); + a7 = 13; + a24 = 14; + + return -1; + } else if((((((a5==5) && ((a24==13) && ((a7==13) && a17 <= -108 ))) || (((a5==4) && (( 255 < a17 && (a7==14)) && (a24==15))) || ((((a7==12) && a17 <= -108 ) && (a24==13)) && (a5==5)))) && (input == 3)) && a2 <= 189 )){ + a17 = (((a17 / 5) - -222886) * 1); + a7 = 14; + a24 = 13; + a5 = 6; + + return 26; + } else if((((a5==6) && ((((input == 1) && ((a7==13) || (a7==14))) && a2 <= 189 ) && (a24==14))) && a17 <= -108 )){ + a2 = ((((((a2 % 45)+ 235) + -1) * 5) % 45)- -223); + a17 = ((((a17 % 109)+ 16) + -191467) - -191547); + a7 = 12; + a24 = 13; + a5 = 4; + + return 26; + } else if((( ((189 < a2) && (281 >= a2)) && ( ((-108 < a17) && (111 >= a17)) && (((input == 1) && (a24==14)) && (a7==13)))) && (a5==4))){ + a2 = (((a2 * 5) * 5) - 342077); + a17 = ((((a17 * 5) / 5) % 71)+ 184); + a24 = 15; + + return 21; + } else if(((a5==5) && ( a2 <= 189 && (( ((111 < a17) && (255 >= a17)) && (((a7==12) || (a7==13)) && (input == 4))) && (a24==14))))){ + a2 = ((((a2 + 110417) % 45)- -236) * 1); + a17 = ((((a17 * 5) * 10)/ -9) - 228824); + a7 = 13; + a24 = 15; + a5 = 3; + + return 21; + } else if((((a24==13) && ( a2 <= 189 && ((input == 1) && ((( ((-108 < a17) && (111 >= a17)) && (a7==13)) || ((a7==14) && ((-108 < a17) && (111 >= a17)) )) || ((a7==12) && ((111 < a17) && (255 >= a17)) ))))) && (a5==6))){ + a2 = (((((a2 % 45)+ 234) / 5) - -431906) + -431702); + a17 = (((((a17 + -434179) % 109)+ 30) + 138172) + -138140); + a7 = 14; + + return 26; + } else if(( ((111 < a17) && (255 >= a17)) && (( a2 <= 189 && (((a24==13) && (input == 5)) && (a5==5))) && (a7==14)))){ + a17 = (((a17 + 592041) * 1) - -2226); + a7 = 12; + a24 = 14; + a5 = 7; + + return 26; + } else if(((((a24==13) && ((( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ((a7==12) && ((111 < a17) && (255 >= a17)) )) && (input == 5))) && (a5==7)) && a2 <= 189 )){ + a17 = (((((a17 % 71)+ 182) / 5) * 51)/ 10); + a7 = 12; + a5 = 5; + + return 21; + } else if((((a24==15) && (((a5==4) && ( ((-108 < a17) && (111 >= a17)) && (input == 5))) && (a7==12))) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 / 5) / -5) * 5); + a17 = (((a17 - -517716) / 5) * 5); + a7 = 13; + a24 = 13; + a5 = 7; + + return -1; + } else if(((a5==5) && ((a24==13) && ( a2 <= 189 && ((input == 3) && (((a7==13) && ((-108 < a17) && (111 >= a17)) ) || (((a7==14) && a17 <= -108 ) || ((a7==12) && ((-108 < a17) && (111 >= a17)) )))))))){ + a17 = ((((a17 % 299946)+ -300053) - 1) - 1); + a7 = 12; + a24 = 15; + a5 = 6; + + return 26; + } else if(( a2 <= 189 && ((((a5==7) && (((a7==13) && a17 <= -108 ) && (a24==13))) || (((a5==6) && ((a24==15) && ( 255 < a17 && (a7==14)))) || ((a5==7) && ((a24==13) && ((a7==12) && a17 <= -108 ))))) && (input == 5)))){ + a2 = ((((a2 - -71451) % 45)- -236) + -1); + a17 = (((((a17 * 9)/ 10) % 109)- -2) + -1); + a7 = 13; + a24 = 15; + a5 = 3; + + return 21; + } else if(( ((189 < a2) && (281 >= a2)) && ((((( 255 < a17 && (a7==14)) && (a24==14)) || (( a17 <= -108 && (a7==12)) && (a24==15))) && (input == 2)) && (a5==3)))){ + a2 = (((a2 * 5) - 448501) * 1); + a17 = (((((a17 % 71)- -182) / 5) / 5) + 165); + a7 = 12; + a24 = 13; + a5 = 7; + + return -1; + } else if((((((( ((111 < a17) && (255 >= a17)) && (a7==14)) || ( 255 < a17 && (a7==12))) && (input == 3)) && a2 <= 189 ) && (a5==7)) && (a24==14))){ + a17 = ((((a17 % 299872)+ 256) - -48274) + 28236); + a7 = 12; + a24 = 13; + + return -1; + } else if((((( 255 < a17 && ((input == 4) && ((a7==14) || ((a7==12) || (a7==13))))) && (a5==5)) && (a24==13)) && ((189 < a2) && (281 >= a2)) )){ + a17 = (((a17 - 0) - 595306) - 4802); + a7 = 14; + a24 = 15; + a5 = 4; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && (((((input == 5) && (a24==13)) && (a5==4)) && (a7==12)) && a17 <= -108 ))){ + a2 = (((a2 / -5) / 5) - 315470); + a5 = 3; + + return -1; + } else if(((a24==15) && ((((input == 4) && (( a17 <= -108 && (a7==14)) || ((a7==12) && ((-108 < a17) && (111 >= a17)) ))) && (a5==6)) && a2 <= 189 ))){ + a17 = ((((a17 - -17630) - 6795) % 109)- -1); + a7 = 12; + + return 26; + } else if((((((((a7==12) || (a7==13)) && (input == 2)) && (a24==15)) && 255 < a17 ) && a2 <= 189 ) && (a5==4))){ + a17 = (((a17 + 0) - 600231) * 1); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(( 255 < a17 && ((a5==5) && ((a24==14) && ((((a7==13) || (a7==14)) && (input == 5)) && ((189 < a2) && (281 >= a2)) ))))){ + a17 = ((((a17 + 0) % 71)- -167) + 11); + a7 = 13; + a5 = 4; + + return -1; + } else if(((a5==4) && (( ((189 < a2) && (281 >= a2)) && ((a24==14) && ((input == 6) && (a7==13)))) && ((-108 < a17) && (111 >= a17)) ))){ + + return 23; + } else if((( a17 <= -108 && ((((input == 6) && ((a7==12) || (a7==13))) && (a5==5)) && ((189 < a2) && (281 >= a2)) )) && (a24==14))){ + a17 = ((((a17 / 5) % 109)- -109) / 5); + a7 = 13; + a5 = 4; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && ((((( a17 <= -108 && (a7==14)) || ((a7==12) && ((-108 < a17) && (111 >= a17)) )) && (input == 3)) && (a24==13)) && (a5==5)))){ + a2 = (((a2 / -5) * 5) - 263640); + a17 = ((((a17 * 9)/ 10) + -31880) - 20940); + a7 = 14; + a24 = 15; + a5 = 7; + + return -1; + } else if((((a24==15) && ( a2 <= 189 && (((( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ((a7==12) && ((111 < a17) && (255 >= a17)) )) || ( ((111 < a17) && (255 >= a17)) && (a7==13))) && (input == 2)))) && (a5==5))){ + a17 = (((a17 + 26382) - 539571) - 38393); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(( a17 <= -108 && ((a5==6) && ((((a7==12) && (input == 1)) && (a24==13)) && a2 <= 189 )))){ + + a5 = 3; + + return -1; + } else if(((a5==3) && (((((((a7==13) && a17 <= -108 ) || ( a17 <= -108 && (a7==14))) || ((a7==12) && ((-108 < a17) && (111 >= a17)) )) && (input == 6)) && (a24==15)) && ((189 < a2) && (281 >= a2)) ))){ + a17 = ((((a17 - 0) % 109)- -2) - -1); + a7 = 12; + + return -1; + } else if((( ((189 < a2) && (281 >= a2)) && ((a24==14) && ((input == 2) && (((a7==14) && a17 <= -108 ) || ((a7==12) && ((-108 < a17) && (111 >= a17)) ))))) && (a5==4))){ + a2 = ((((a2 / -5) + 523985) * 1) + -866052); + a17 = (((((a17 % 109)+ 2) + -1) - -574310) + -574309); + a7 = 12; + a24 = 13; + + return -1; + } else if((((a24==15) && (((a7==12) && ((a5==6) && (input == 1))) && ((111 < a17) && (255 >= a17)) )) && a2 <= 189 )){ + a2 = ((((a2 + 0) + 6154) % 45)- -236); + a17 = (((a17 / 5) / 5) + -109); + a7 = 13; + a24 = 13; + a5 = 4; + + return 26; + } else if((((( a17 <= -108 && (((a7==12) || (a7==13)) && (input == 3))) && ((189 < a2) && (281 >= a2)) ) && (a5==6)) && (a24==13))){ + a17 = ((((a17 * 9)/ 10) * 1) - -571423); + a7 = 14; + a24 = 14; + a5 = 5; + + return -1; + } else if((((a24==15) && ((a7==14) && (((input == 4) && 255 < a17 ) && (a5==5)))) && a2 <= 189 )){ + a2 = (((((a2 % 45)- -235) * 1) / 5) - -166); + a17 = ((((a17 * 9)/ 10) / 5) + -557397); + a24 = 14; + + return 23; + } else if((((((((a7==14) && a17 <= -108 ) || ( ((-108 < a17) && (111 >= a17)) && (a7==12))) && (input == 4)) && ((189 < a2) && (281 >= a2)) ) && (a24==14)) && (a5==4))){ + a2 = ((((a2 - -6843) - 234103) - -260659) + -346865); + a17 = (((((a17 % 71)+ 182) - -2) - -415451) - 415452); + a7 = 13; + a24 = 15; + a5 = 3; + + return -1; + } else if(( a2 <= 189 && ((a5==5) && ((a24==15) && ((( ((111 < a17) && (255 >= a17)) && (a7==13)) || (( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ( ((111 < a17) && (255 >= a17)) && (a7==12)))) && (input == 5)))))){ + a2 = ((((((a2 % 45)- -235) - -220353) * 2) % 45)- -192); + a17 = (((((a17 % 109)- -1) - 487372) / 5) + 97389); + a7 = 12; + a5 = 4; + + return 26; + } else if((((a7==13) && ((((input == 4) && ((189 < a2) && (281 >= a2)) ) && (a5==5)) && ((-108 < a17) && (111 >= a17)) )) && (a24==13))){ + + a24 = 14; + a5 = 4; + + return -1; + } else if((((a7==13) && ((((input == 3) && a2 <= 189 ) && (a24==13)) && 255 < a17 )) && (a5==7))){ + a17 = (((((a17 % 71)- -147) * 5) % 71)- -157); + a5 = 5; + + return 26; + } else if(((( 255 < a17 && ((a5==5) && ((input == 4) && ((a7==14) || ((a7==12) || (a7==13)))))) && (a24==15)) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 + -324872) - 111167) - 140231); + a7 = 12; + a24 = 14; + a5 = 7; + + return -1; + } else if(((a5==7) && (((input == 3) && ((((a7==12) && a17 <= -108 ) && (a24==15)) || ((((a7==13) && 255 < a17 ) && (a24==14)) || (((a7==14) && 255 < a17 ) && (a24==14))))) && a2 <= 189 ))){ + a17 = ((((a17 % 299872)+ 300127) + 0) - -1); + a7 = 14; + a24 = 14; + + return 23; + } else if(( a2 <= 189 && (((((( 255 < a17 && (a7==14)) && (a24==13)) || ((a24==14) && ( a17 <= -108 && (a7==12)))) || ((a24==14) && ((a7==13) && a17 <= -108 ))) && (input == 1)) && (a5==5)))){ + a17 = ((((a17 % 299872)+ 300127) - 0) - 0); + a7 = 13; + a24 = 15; + a5 = 7; + + return 23; + } else if(((((a5==7) && ((((a7==13) || (a7==14)) && (input == 1)) && a2 <= 189 )) && (a24==15)) && 255 < a17 )){ + + a7 = 13; + a24 = 14; + + return -1; + } else if((((((((a7==14) && ((111 < a17) && (255 >= a17)) ) || ((a7==12) && 255 < a17 )) && (input == 3)) && (a24==13)) && ((189 < a2) && (281 >= a2)) ) && (a5==4))){ + a2 = (((a2 - 228436) / 5) * 5); + a17 = ((((a17 * 9)/ 10) - -37438) - 617865); + a7 = 14; + a24 = 14; + a5 = 7; + + return -1; + } else if((((((((a7==14) && a17 <= -108 ) || ((a7==12) && ((-108 < a17) && (111 >= a17)) )) && (input == 4)) && ((189 < a2) && (281 >= a2)) ) && (a24==13)) && (a5==5))){ + a2 = (((a2 * -5) + -362469) + 206807); + a17 = (((((a17 / 5) / 5) / 5) % 71)+ 183); + a7 = 12; + a24 = 15; + a5 = 7; + + return -1; + } else if(((a24==14) && (((a5==5) && ( 255 < a17 && ((input == 4) && ((a7==13) || (a7==14))))) && ((189 < a2) && (281 >= a2)) ))){ + + a7 = 13; + + return 26; + } else if((( a2 <= 189 && ((((a24==14) && ( a17 <= -108 && (a7==13))) || (((a24==13) && ( 255 < a17 && (a7==14))) || ((a24==14) && ((a7==12) && a17 <= -108 )))) && (input == 5))) && (a5==5))){ + a2 = ((((a2 / 5) % 45)- -235) + 1); + a17 = (((a17 / 5) - 256291) * 1); + a7 = 12; + a24 = 13; + a5 = 3; + + return 26; + } else if(((a24==15) && (( a17 <= -108 && ((a5==6) && ((a7==13) && (input == 1)))) && a2 <= 189 ))){ + a2 = (((((a2 / 5) * 4) / 5) % 45)- -234); + a17 = ((((a17 - -120776) / 5) % 109)- -2); + a24 = 13; + a5 = 4; + + return 21; + } else if((((a5==4) && (( a2 <= 189 && ((input == 6) && ((a7==13) || (a7==14)))) && (a24==15))) && ((111 < a17) && (255 >= a17)) )){ + a17 = (((((a17 * -1)/ 10) * 10)/ 9) + -47); + a7 = 13; + a5 = 5; + + return 21; + } else if(((a5==6) && ((a24==13) && ((( ((189 < a2) && (281 >= a2)) && (input == 4)) && 255 < a17 ) && (a7==13))))){ + a2 = (((a2 / -5) * 5) + -60399); + a17 = ((((a17 / 5) % 109)+ -92) / 5); + a7 = 12; + a24 = 14; + a5 = 7; + + return -1; + } else if((((((a5==5) && ((input == 3) && ((a7==12) || (a7==13)))) && a2 <= 189 ) && (a24==14)) && ((111 < a17) && (255 >= a17)) )){ + a2 = (((((a2 + 399174) % 45)+ 234) - 119189) + 119189); + a17 = (((a17 + -440715) / 5) + 88187); + a7 = 13; + a24 = 15; + a5 = 3; + + return 26; + } else if(((a24==13) && ( a17 <= -108 && (((a5==6) && (((a7==12) || (a7==13)) && (input == 1))) && ((189 < a2) && (281 >= a2)) )))){ + a17 = ((((a17 + 0) + 354212) % 109)+ 1); + a7 = 12; + a5 = 3; + + return -1; + } else if((((a24==15) && (((a5==4) && (((a7==13) || (a7==14)) && (input == 1))) && a2 <= 189 )) && ((111 < a17) && (255 >= a17)) )){ + a17 = (((a17 * 5) - 379915) - -55808); + a7 = 14; + a5 = 5; + + return 23; + } else if(((a5==4) && ( a2 <= 189 && (((((a7==13) || (a7==14)) && (input == 5)) && a17 <= -108 ) && (a24==15))))){ + a17 = ((((((a17 % 71)- -187) * 5) * 5) % 71)- -127); + a7 = 12; + + return 23; + } else if((((a5==4) && (( 255 < a17 && ((input == 6) && ((a7==13) || (a7==14)))) && ((189 < a2) && (281 >= a2)) )) && (a24==13))){ + a17 = ((((a17 / 5) + -588303) % 71)+ 218); + a7 = 12; + + return -1; + } else if(( a2 <= 189 && ((input == 1) && (((a5==7) && ((a24==13) && ((a7==13) && a17 <= -108 ))) || (((((a7==14) && 255 < a17 ) && (a24==15)) && (a5==6)) || ((a5==7) && ((a24==13) && ((a7==12) && a17 <= -108 )))))))){ + a17 = ((((((a17 * 9)/ 10) * 1) * 1) % 299946)- 300053); + a7 = 12; + a24 = 13; + a5 = 7; + + return 21; + } else if(((a5==3) && ( ((189 < a2) && (281 >= a2)) && ((((a24==14) && ((a7==14) && 255 < a17 )) || (( a17 <= -108 && (a7==12)) && (a24==15))) && (input == 3))))){ + a2 = (((a2 + -143123) + -98171) * 2); + a17 = (((((a17 % 71)- -184) * 5) % 71)+ 132); + a7 = 12; + a24 = 14; + a5 = 5; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && ( ((-108 < a17) && (111 >= a17)) && ((a5==4) && (((a7==12) && (input == 3)) && (a24==15)))))){ + a2 = (((a2 * -5) * 5) - 163900); + a17 = (((a17 - 263174) * 2) / 5); + a24 = 13; + a5 = 3; + + return -1; + } else if(((a5==5) && ( ((189 < a2) && (281 >= a2)) && (((((a7==14) && a17 <= -108 ) || ( ((-108 < a17) && (111 >= a17)) && (a7==12))) && (input == 4)) && (a24==14))))){ + a2 = (((a2 / -5) / 5) + -193140); + a17 = ((((a17 % 299946)- 300053) - 2) + 0); + a7 = 12; + a5 = 7; + + return -1; + } else if((((input == 6) && ((((a5==4) && ((a24==15) && ( 255 < a17 && (a7==14)))) || (((a24==13) && ((a7==12) && a17 <= -108 )) && (a5==5))) || (((a24==13) && ((a7==13) && a17 <= -108 )) && (a5==5)))) && ((189 < a2) && (281 >= a2)) )){ + a2 = ((((a2 / -5) * 5) * 10)/ 9); + a17 = (((((a17 % 299872)+ 300127) + 0) - 193833) - -193835); + a7 = 13; + a24 = 15; + a5 = 7; + + return -1; + } else if((( ((189 < a2) && (281 >= a2)) && ((a24==14) && ( 255 < a17 && (((a7==13) || (a7==14)) && (input == 2))))) && (a5==5))){ + a2 = (((a2 / 5) * -5) - 445381); + a17 = (((a17 - 533326) - 24751) + -42172); + a7 = 12; + a24 = 13; + a5 = 4; + + return -1; + } else if(((( a2 <= 189 && ((((a7==12) || (a7==13)) && (input == 2)) && 255 < a17 )) && (a24==13)) && (a5==5))){ + a17 = ((((a17 * 9)/ 10) - 571338) / 5); + a7 = 12; + a5 = 3; + + return -1; + } else if(( a2 <= 189 && ((((input == 6) && (((a7==13) && ((111 < a17) && (255 >= a17)) ) || (( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ( ((111 < a17) && (255 >= a17)) && (a7==12))))) && (a24==15)) && (a5==5)))){ + a17 = (((a17 * 5) + -240915) + -308966); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((( ((189 < a2) && (281 >= a2)) && (((input == 5) && (((a7==14) && a17 <= -108 ) || ( ((-108 < a17) && (111 >= a17)) && (a7==12)))) && (a24==14))) && (a5==4))){ + a2 = (((a2 - 446402) + -60965) * 1); + a17 = ((((a17 % 299946)- 300053) * 1) * 1); + a7 = 14; + a24 = 15; + a5 = 7; + + return -1; + } else if((((a24==14) && ((((( ((-108 < a17) && (111 >= a17)) && (a7==13)) || ( ((-108 < a17) && (111 >= a17)) && (a7==14))) || ( ((111 < a17) && (255 >= a17)) && (a7==12))) && (input == 3)) && ((189 < a2) && (281 >= a2)) )) && (a5==5))){ + a2 = (((a2 - 299989) - 282684) + -11091); + a17 = ((((a17 + -13195) * 10)/ 9) / 5); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((((((a24==15) && (input == 1)) && (a5==5)) && ((111 < a17) && (255 >= a17)) ) && a2 <= 189 ) && (a7==14))){ + a2 = (((((a2 % 45)+ 234) + 93283) + 429518) + -522800); + a17 = ((((a17 - 192) - 1) + 44565) - 44563); + a7 = 13; + a24 = 13; + + return 23; + } else if(( ((111 < a17) && (255 >= a17)) && ((((a5==5) && (((a7==14) || ((a7==12) || (a7==13))) && (input == 4))) && ((189 < a2) && (281 >= a2)) ) && (a24==13)))){ + a2 = (((a2 * 5) - 529848) + -4150); + a17 = (((a17 / 5) / 5) - 39); + a7 = 13; + a24 = 14; + a5 = 7; + + return -1; + } else if(((( a17 <= -108 && ((a24==14) && ((input == 4) && ((a7==13) || (a7==14))))) && a2 <= 189 ) && (a5==6))){ + + a7 = 13; + a24 = 13; + a5 = 5; + + return 26; + } else if((( a2 <= 189 && ((a5==5) && ( ((111 < a17) && (255 >= a17)) && (((a7==12) || (a7==13)) && (input == 6))))) && (a24==14))){ + a2 = ((((a2 % 45)+ 234) * 5) / 5); + a7 = 14; + a5 = 3; + + return 21; + } else if(((a24==15) && ( a2 <= 189 && (((((a7==12) && ((-108 < a17) && (111 >= a17)) ) || (((a7==13) && a17 <= -108 ) || ( a17 <= -108 && (a7==14)))) && (input == 2)) && (a5==7))))){ + a17 = ((((a17 % 299946)+ -300053) + -2) + 0); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && ((input == 4) && ((((( 255 < a17 && (a7==14)) && (a24==15)) && (a5==4)) || (((a24==13) && ((a7==12) && a17 <= -108 )) && (a5==5))) || ((((a7==13) && a17 <= -108 ) && (a24==13)) && (a5==5)))))){ + a2 = (((a2 - -563886) * -1) + 466041); + a17 = ((((a17 % 109)- -2) + 1) - 1); + a7 = 13; + a24 = 14; + a5 = 7; + + return -1; + } else if((( ((111 < a17) && (255 >= a17)) && (((((a7==14) || ((a7==12) || (a7==13))) && (input == 2)) && ((189 < a2) && (281 >= a2)) ) && (a24==15))) && (a5==5))){ + a2 = (((a2 / -5) - 416146) / 5); + a17 = (((a17 - 462537) + -101249) + 137036); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a24==15) && ( ((189 < a2) && (281 >= a2)) && ( ((-108 < a17) && (111 >= a17)) && ((a5==5) && ((input == 4) && ((a7==13) || (a7==14)))))))){ + a17 = ((((a17 + 115929) / 5) + -404240) + 381192); + a7 = 14; + a24 = 13; + + return -1; + } else if((((a24==15) && ((a5==6) && ( 255 < a17 && (((a7==12) || (a7==13)) && (input == 4))))) && a2 <= 189 )){ + a17 = (((((a17 + -82645) / 5) / 5) % 109)+ 1); + a7 = 14; + a24 = 13; + a5 = 5; + + return 21; + } else if(((a24==13) && (( a17 <= -108 && (((input == 4) && ((a7==13) || (a7==14))) && ((189 < a2) && (281 >= a2)) )) && (a5==3)))){ + a2 = (((a2 * -5) + -23430) * 5); + a7 = 14; + a24 = 14; + a5 = 5; + + return 21; + } else if(( ((-108 < a17) && (111 >= a17)) && ( ((189 < a2) && (281 >= a2)) && ((a7==12) && ((a24==15) && ((input == 1) && (a5==4))))))){ + a2 = ((((a2 - 86020) + -319001) - -534468) - 217545); + a17 = (((a17 - -503276) + 60279) / 5); + a7 = 13; + a5 = 7; + + return -1; + } else if(((((a5==5) && ( a2 <= 189 && ((input == 4) && ((a7==12) || (a7==13))))) && (a24==15)) && a17 <= -108 )){ + a2 = ((((a2 % 45)- -236) - 1) * 1); + a7 = 13; + a24 = 14; + a5 = 4; + + return 26; + } else if(((((a5==3) && ((input == 6) && (((a7==12) && 255 < a17 ) || (( ((111 < a17) && (255 >= a17)) && (a7==13)) || ( ((111 < a17) && (255 >= a17)) && (a7==14)))))) && (a24==13)) && ((189 < a2) && (281 >= a2)) )){ + a17 = (((((a17 + -429873) % 299872)+ 300127) - 39771) - -39773); + a7 = 12; + + return 23; + } else if((((((((a7==12) || (a7==13)) && (input == 1)) && ((-108 < a17) && (111 >= a17)) ) && (a24==13)) && ((189 < a2) && (281 >= a2)) ) && (a5==3))){ + + a7 = 13; + + return 26; + } else if(( ((189 < a2) && (281 >= a2)) && ((a24==15) && (((input == 6) && ((( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ((a7==12) && ((111 < a17) && (255 >= a17)) )) || ( ((111 < a17) && (255 >= a17)) && (a7==13)))) && (a5==4))))){ + a2 = (((a2 * 5) * 5) - 126327); + a17 = (((a17 + -140957) * 4) - -269430); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && ((( ((-108 < a17) && (111 >= a17)) && ((a24==15) && (input == 4))) && (a7==12)) && (a5==4)))){ + a2 = (((a2 - 514328) - 2041) - -399856); + a7 = 14; + a5 = 7; + + return -1; + } else if((((a5==3) && ((a24==13) && ((input == 3) && ((((a7==13) && ((111 < a17) && (255 >= a17)) ) || ((a7==14) && ((111 < a17) && (255 >= a17)) )) || ((a7==12) && 255 < a17 ))))) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 - 307516) - 193341) * 1); + a17 = (((((a17 % 71)+ 181) - -293974) / 5) + -58626); + a7 = 12; + a24 = 15; + a5 = 4; + + return -1; + } else if(((a5==7) && ( a2 <= 189 && ((((a24==13) && ( 255 < a17 && (a7==14))) || ((a24==14) && ((a7==12) && a17 <= -108 ))) && (input == 1))))){ + a17 = (((((a17 % 71)+ 183) - 1) - -531843) - 531841); + a7 = 13; + a24 = 13; + a5 = 5; + + return -1; + } else if((((((a24==13) && ((((a7==12) || (a7==13)) || (a7==14)) && (input == 1))) && ((189 < a2) && (281 >= a2)) ) && (a5==5)) && 255 < a17 )){ + a2 = ((((a2 + -443081) * 10)/ 9) * 1); + a17 = ((((((a17 % 71)- -174) * 5) * 5) % 71)- -133); + a7 = 13; + a5 = 7; + + return -1; + } else if((((((input == 1) && (((a7==14) && ((111 < a17) && (255 >= a17)) ) || ((a7==12) && 255 < a17 ))) && (a24==15)) && ((189 < a2) && (281 >= a2)) ) && (a5==4))){ + a2 = ((((a2 + -122718) * 10)/ 9) - -74204); + a17 = ((((a17 % 109)- -2) + -34) + 9); + a7 = 14; + a5 = 7; + + return -1; + } else if(((a5==4) && ((((a24==15) && ((input == 2) && (((a7==12) || (a7==13)) || (a7==14)))) && a17 <= -108 ) && ((189 < a2) && (281 >= a2)) ))){ + a2 = ((((a2 - -117222) - 186157) - -508770) - 673504); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((((a5==7) && ((((a7==13) || (a7==14)) && (input == 1)) && (a24==15))) && a2 <= 189 ) && ((-108 < a17) && (111 >= a17)) )){ + a17 = ((((((a17 % 71)- -183) * 1) * 5) % 71)- -154); + a7 = 12; + a24 = 14; + + return -1; + } else if(((((((( 255 < a17 && (a7==13)) && (a24==13)) || (( 255 < a17 && (a7==14)) && (a24==13))) || (((a7==12) && a17 <= -108 ) && (a24==14))) && (input == 6)) && (a5==3)) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 - 596397) + -1500) + -536); + a17 = (((((a17 * 9)/ 10) % 109)+ 2) + -1); + a7 = 13; + a24 = 14; + a5 = 5; + + return 26; + } else if(((a24==13) && (( ((-108 < a17) && (111 >= a17)) && ((a5==6) && ((input == 5) && ((a7==12) || (a7==13))))) && ((189 < a2) && (281 >= a2)) ))){ + a2 = (((a2 + -92113) - 295718) + -53625); + a17 = (((a17 / 5) / 5) - 76916); + a7 = 12; + a5 = 3; + + return -1; + } else if(((((a24==15) && ( ((-108 < a17) && (111 >= a17)) && ((input == 5) && ((a7==13) || (a7==14))))) && a2 <= 189 ) && (a5==6))){ + a2 = ((((a2 % 45)- -236) - -1) + -3); + a17 = ((((a17 + -62237) % 71)+ 199) + -15); + a7 = 13; + a5 = 3; + + return 26; + } else if(( a17 <= -108 && (((a24==13) && ( ((189 < a2) && (281 >= a2)) && (((a7==12) || (a7==13)) && (input == 6)))) && (a5==6)))){ + a17 = (((((a17 % 71)- -223) * 5) % 71)- -154); + a7 = 13; + a24 = 14; + a5 = 5; + + return -1; + } else if(((((((input == 2) && ((a7==12) || (a7==13))) && ((189 < a2) && (281 >= a2)) ) && (a5==5)) && (a24==14)) && a17 <= -108 )){ + a2 = ((((a2 - 55102) - -372533) - 62328) * -2); + a17 = (((((a17 * 9)/ 10) * 1) / 5) + 203115); + a7 = 12; + a5 = 3; + + return -1; + } else if((( a17 <= -108 && (((a5==3) && ((a7==12) && (input == 6))) && ((189 < a2) && (281 >= a2)) )) && (a24==13))){ + a2 = (((a2 / -5) / 5) * 5); + a17 = ((((((a17 % 71)- -247) + 8) * 5) % 71)+ 139); + a7 = 14; + a24 = 14; + a5 = 7; + + return -1; + } else if(( a2 <= 189 && (( 255 < a17 && ((((a7==12) || (a7==13)) && (input == 5)) && (a5==4))) && (a24==15)))){ + a17 = (((a17 + -600167) * 1) + -74); + a7 = 12; + a24 = 13; + a5 = 6; + + return 21; + } else if(( ((111 < a17) && (255 >= a17)) && ((a5==3) && ((a24==14) && (((input == 1) && ((189 < a2) && (281 >= a2)) ) && (a7==13)))))){ + a2 = (((a2 + 97520) - -476171) + -703390); + a17 = (((a17 - 192516) + 192347) + 14); + a7 = 14; + a5 = 4; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && (((a24==15) && ( a17 <= -108 && ((input == 6) && (((a7==12) || (a7==13)) || (a7==14))))) && (a5==4)))){ + a2 = (((a2 / 5) - -274462) - 512632); + a17 = (((((a17 % 71)- -206) - -20) - 351411) + 351407); + a7 = 13; + a24 = 14; + a5 = 7; + + return -1; + } else if((((a5==5) && ( a2 <= 189 && ( 255 < a17 && (((a7==12) || (a7==13)) && (input == 3))))) && (a24==13))){ + a17 = (((((a17 % 71)+ 123) - 11) + 84970) + -84956); + a7 = 14; + a24 = 15; + a5 = 7; + + return 21; + } else if(( ((189 < a2) && (281 >= a2)) && ((a24==15) && (( ((111 < a17) && (255 >= a17)) && ((input == 1) && (((a7==12) || (a7==13)) || (a7==14)))) && (a5==5))))){ + a17 = ((((a17 * 5) % 109)- 71) - -9); + a7 = 13; + a24 = 14; + + return -1; + } else if((((((((a7==13) || (a7==14)) && (input == 6)) && (a5==5)) && 255 < a17 ) && (a24==14)) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 - -501110) / -5) + -432351); + a17 = (((((a17 % 71)+ 148) + -248919) + -89135) - -338038); + a7 = 14; + a24 = 13; + a5 = 7; + + return -1; + } else if(((( 255 < a17 && ((a7==13) && ((a24==13) && (input == 5)))) && (a5==7)) && a2 <= 189 )){ + + return -1; + } else if(((((a5==5) && (((((a7==12) || (a7==13)) || (a7==14)) && (input == 4)) && a2 <= 189 )) && (a24==14)) && 255 < a17 )){ + a17 = (((a17 + -600231) * 1) * 1); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((( ((-108 < a17) && (111 >= a17)) && (((input == 6) && (a7==13)) && a2 <= 189 )) && (a24==14)) && (a5==7))){ + + return 21; + } else if(( 255 < a17 && ((a5==6) && ( a2 <= 189 && ((a24==15) && (((a7==12) || (a7==13)) && (input == 1))))))){ + a17 = ((((a17 % 109)- 52) - 44) + -3); + a7 = 13; + a24 = 13; + a5 = 3; + + return -1; + } else if(( ((-108 < a17) && (111 >= a17)) && ((((((a7==14) || ((a7==12) || (a7==13))) && (input == 1)) && (a5==6)) && (a24==14)) && a2 <= 189 ))){ + a17 = ((((a17 / 5) + 148) * 9)/ 10); + a7 = 12; + a24 = 13; + a5 = 7; + + return 23; + } else if(( ((189 < a2) && (281 >= a2)) && ((a5==6) && ((a24==13) && ((input == 1) && ((((a7==13) && ((111 < a17) && (255 >= a17)) ) || ( ((111 < a17) && (255 >= a17)) && (a7==14))) || ( 255 < a17 && (a7==12)))))))){ + a17 = ((((((a17 + 0) % 109)- 20) * 5) % 109)+ 1); + a7 = 14; + a24 = 15; + a5 = 4; + + return -1; + } else if((( ((-108 < a17) && (111 >= a17)) && ( ((189 < a2) && (281 >= a2)) && ((((a7==13) || (a7==14)) && (input == 6)) && (a24==13)))) && (a5==4))){ + a17 = (((((a17 - 297061) - -413246) * 5) % 71)- -126); + a7 = 14; + a24 = 15; + a5 = 3; + + return -1; + } else if((((a24==15) && ((a5==4) && ((input == 2) && (( ((111 < a17) && (255 >= a17)) && (a7==13)) || (((a7==14) && ((-108 < a17) && (111 >= a17)) ) || ((a7==12) && ((111 < a17) && (255 >= a17)) )))))) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 - -381050) + -586556) - 318711); + a17 = (((a17 * 5) * 5) - 315241); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a5==5) && ((((((a7==13) && a17 <= -108 ) && (a24==14)) || ((( 255 < a17 && (a7==14)) && (a24==13)) || (((a7==12) && a17 <= -108 ) && (a24==14)))) && (input == 2)) && a2 <= 189 ))){ + a17 = ((((a17 % 299946)+ -300053) * 1) * 1); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((((( ((111 < a17) && (255 >= a17)) && ((input == 3) && (a7==14))) && (a24==14)) && a2 <= 189 ) && (a5==5))){ + a2 = ((((a2 % 45)- -235) + -1) - 0); + a17 = (((((a17 / 5) * 10)/ 9) * 10)/ 9); + a24 = 15; + a5 = 3; + + return 23; + } else if(( a2 <= 189 && ((a24==14) && (((((a7==12) && ((-108 < a17) && (111 >= a17)) ) || (((a7==13) && a17 <= -108 ) || ((a7==14) && a17 <= -108 ))) && (input == 1)) && (a5==7))))){ + a17 = ((((a17 / 5) * 4) % 109)+ 2); + a7 = 13; + a24 = 15; + a5 = 4; + + return 21; + } else if((( a17 <= -108 && (((((a7==12) || (a7==13)) && (input == 3)) && a2 <= 189 ) && (a5==5))) && (a24==15))){ + + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((((((a24==15) && (input == 3)) && (a5==5)) && (a7==14)) && ((111 < a17) && (255 >= a17)) ) && a2 <= 189 )){ + a2 = ((((a2 % 45)- -236) * 1) - 1); + a17 = ((((a17 - 477741) * 10)/ 9) + -8957); + a24 = 13; + + return 23; + } else if(((((((input == 6) && ((a7==13) || (a7==14))) && a2 <= 189 ) && ((111 < a17) && (255 >= a17)) ) && (a24==15)) && (a5==6))){ + + a7 = 12; + a24 = 13; + a5 = 7; + + return 21; + } else if(((( ((189 < a2) && (281 >= a2)) && ((( 255 < a17 && (a7==12)) || (((a7==13) && ((111 < a17) && (255 >= a17)) ) || ( ((111 < a17) && (255 >= a17)) && (a7==14)))) && (input == 6))) && (a5==6)) && (a24==13))){ + a2 = (((a2 / 5) - 67976) + -37056); + a17 = ((((a17 % 109)+ -50) + 36) / 5); + a7 = 14; + a24 = 15; + a5 = 7; + + return -1; + } else if(( 255 < a17 && ((a24==13) && ( ((189 < a2) && (281 >= a2)) && ((a5==4) && ((input == 3) && ((a7==13) || (a7==14)))))))){ + a2 = (((a2 + -368535) + -129446) * 1); + a17 = (((((a17 * 9)/ 10) * 1) / 5) - 289303); + a7 = 14; + a24 = 14; + a5 = 7; + + return -1; + } else if((((a24==14) && ((a5==4) && ( ((189 < a2) && (281 >= a2)) && (((a7==12) || (a7==13)) && (input == 6))))) && a17 <= -108 )){ + a2 = (((a2 / 5) + -164157) * 3); + a7 = 13; + a5 = 7; + + return -1; + } else if(( a2 <= 189 && ((a24==15) && ((a5==7) && (((( a17 <= -108 && (a7==13)) || ((a7==14) && a17 <= -108 )) || ((a7==12) && ((-108 < a17) && (111 >= a17)) )) && (input == 3)))))){ + a17 = (((((a17 % 109)- -2) + -1) + 462727) + -462726); + a7 = 14; + a24 = 14; + + return -1; + } else if(((((a5==3) && ((input == 2) && ((( ((-108 < a17) && (111 >= a17)) && (a7==13)) || ( ((-108 < a17) && (111 >= a17)) && (a7==14))) || ( ((111 < a17) && (255 >= a17)) && (a7==12))))) && ((189 < a2) && (281 >= a2)) ) && (a24==14))){ + a17 = ((((a17 % 109)- -2) + -1) - -2); + a7 = 14; + + return -1; + } else if(((a5==3) && ( ((189 < a2) && (281 >= a2)) && (((((a7==14) && 255 < a17 ) && (a24==14)) || ((a24==15) && ((a7==12) && a17 <= -108 ))) && (input == 1))))){ + a17 = (((((a17 / 5) % 71)- -184) / 5) + 143); + a7 = 13; + a24 = 14; + + return -1; + } else if(((( a2 <= 189 && (( ((111 < a17) && (255 >= a17)) && (input == 5)) && (a24==15))) && (a5==5)) && (a7==14))){ + a2 = ((((((a2 - 0) * 9)/ 10) - 15643) % 45)+ 276); + a17 = (((a17 / 5) / 5) - -310668); + a7 = 13; + a5 = 4; + + return 23; + } else if((( ((189 < a2) && (281 >= a2)) && ((a24==15) && (((input == 6) && ((a7==14) || ((a7==12) || (a7==13)))) && (a5==5)))) && a17 <= -108 )){ + a2 = ((((a2 + 140796) / 5) / 5) * -5); + a7 = 12; + a24 = 14; + a5 = 7; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && ((((input == 5) && (((a7==12) && ((-108 < a17) && (111 >= a17)) ) || (( a17 <= -108 && (a7==13)) || ( a17 <= -108 && (a7==14))))) && (a24==13)) && (a5==4)))){ + a17 = (((a17 / 5) / 5) + -194917); + a7 = 14; + a24 = 14; + a5 = 3; + + return -1; + } else if((( a2 <= 189 && ((a5==4) && ( a17 <= -108 && ((input == 2) && ((a7==13) || (a7==14)))))) && (a24==15))){ + a17 = ((((a17 % 109)- -85) + -84) - 0); + a7 = 12; + + return 21; + } else if(((a5==6) && (( 255 < a17 && ((((a7==12) || (a7==13)) && (input == 6)) && a2 <= 189 )) && (a24==15)))){ + a2 = (((((a2 % 45)- -235) / 5) / 5) + 244); + a7 = 13; + a5 = 3; + + return 26; + } else if(((a5==3) && (((a24==13) && ((( 255 < a17 && (a7==12)) || (( ((111 < a17) && (255 >= a17)) && (a7==13)) || ((a7==14) && ((111 < a17) && (255 >= a17)) ))) && (input == 5))) && ((189 < a2) && (281 >= a2)) ))){ + a2 = (((a2 - -580869) + -652808) * 5); + a17 = ((((a17 % 109)- -3) + -41) + 9); + a7 = 12; + a24 = 14; + a5 = 5; + + return -1; + } else if(((((a24==15) && ((((a7==12) || (a7==13)) && (input == 1)) && a17 <= -108 )) && (a5==5)) && a2 <= 189 )){ + a2 = (((((a2 * 9)/ 10) + -16953) % 45)+ 272); + a17 = ((((((a17 % 71)+ 236) * 5) + 502892) % 71)+ 132); + a7 = 13; + a24 = 13; + a5 = 4; + + return 23; + } else if(((((a24==13) && ((input == 1) && (( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ( ((111 < a17) && (255 >= a17)) && (a7==12))))) && (a5==3)) && ((189 < a2) && (281 >= a2)) )){ + a2 = (((a2 * -5) + 409580) + -457191); + a17 = (((a17 - -196150) + 128540) - -116144); + a7 = 12; + a24 = 15; + a5 = 7; + + return -1; + } else if(((a24==15) && ((a5==4) && ((( ((-108 < a17) && (111 >= a17)) && (input == 1)) && ((189 < a2) && (281 >= a2)) ) && (a7==13))))){ + + return -1; + } else if((((((((a7==12) || (a7==13)) && (input == 3)) && (a5==5)) && ((-108 < a17) && (111 >= a17)) ) && a2 <= 189 ) && (a24==15))){ + a2 = ((((a2 % 45)+ 234) - -448340) + -448339); + a17 = (((a17 * 5) / 5) - -211113); + a7 = 13; + a24 = 14; + a5 = 4; + + return 26; + } else if((((a24==13) && (((((a7==12) && 255 < a17 ) || (((a7==13) && ((111 < a17) && (255 >= a17)) ) || ( ((111 < a17) && (255 >= a17)) && (a7==14)))) && (input == 5)) && ((189 < a2) && (281 >= a2)) )) && (a5==6))){ + a2 = (((a2 / 5) / 5) * -5); + a17 = (((((a17 % 299872)+ 256) + 239410) * 10)/ 9); + a7 = 12; + a24 = 15; + a5 = 7; + + return -1; + } else if(((a5==5) && ((a24==14) && ( a2 <= 189 && (((((a7==12) || (a7==13)) || (a7==14)) && (input == 2)) && 255 < a17 ))))){ + a2 = (((((a2 % 45)+ 236) * 5) % 45)- -195); + a17 = (((a17 - 600134) * 1) - 48); + a7 = 13; + a24 = 13; + a5 = 4; + + return 23; + } else if(( a2 <= 189 && ((a24==15) && (((((a7==14) && a17 <= -108 ) || ( ((-108 < a17) && (111 >= a17)) && (a7==12))) && (input == 1)) && (a5==6))))){ + a17 = (((((a17 * 9)/ 10) * 1) / 5) - 216856); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((a24==13) && ((a5==6) && (((input == 5) && (( 255 < a17 && (a7==12)) || (((a7==13) && ((111 < a17) && (255 >= a17)) ) || ((a7==14) && ((111 < a17) && (255 >= a17)) )))) && a2 <= 189 )))){ + a17 = ((((a17 % 109)- -1) - 83) - -75); + a7 = 12; + a24 = 15; + a5 = 4; + + return 26; + } else if((((a5==7) && (((input == 1) && (( 255 < a17 && (a7==12)) || (( ((111 < a17) && (255 >= a17)) && (a7==13)) || ( ((111 < a17) && (255 >= a17)) && (a7==14))))) && a2 <= 189 )) && (a24==13))){ + a17 = (((((a17 - 274936) + 211306) * 1) % 71)+ 182); + a7 = 13; + a5 = 5; + + return -1; + } else if(((a5==6) && ((a24==13) && (((((a7==12) || (a7==13)) && (input == 6)) && ((-108 < a17) && (111 >= a17)) ) && ((189 < a2) && (281 >= a2)) )))){ + a2 = (((a2 + -87407) - -312987) - 526695); + a17 = (((a17 + 556571) * 1) * 1); + a7 = 12; + a24 = 15; + a5 = 7; + + return -1; + } else if((( a2 <= 189 && ((a5==6) && ((((a7==13) || (a7==14)) && (input == 2)) && (a24==14)))) && a17 <= -108 )){ + + a7 = 14; + a24 = 15; + a5 = 3; + + return -1; + } else if(((a24==15) && (((a7==12) && (((input == 6) && a2 <= 189 ) && ((-108 < a17) && (111 >= a17)) )) && (a5==4)))){ + a17 = (((((a17 % 71)+ 182) + 0) + -506914) - -506916); + a24 = 13; + a5 = 5; + + return 21; + } else if(((( a17 <= -108 && (((a5==5) && (input == 5)) && a2 <= 189 )) && (a7==14)) && (a24==14))){ + + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if((( a2 <= 189 && (((( a17 <= -108 && (a7==12)) && (a24==14)) || ((((a7==13) && 255 < a17 ) && (a24==13)) || ((a24==13) && ((a7==14) && 255 < a17 )))) && (input == 5))) && (a5==6))){ + a2 = (((((a2 % 45)+ 234) / 5) / 5) + 253); + a17 = ((((a17 % 299872)+ 300127) + 0) + 0); + a7 = 13; + a24 = 14; + a5 = 3; + + return 26; + } + return calculate_output4(input); + } + + int calculate_output4(int input) { + + + if((( ((-108 < a17) && (111 >= a17)) && ((((input == 6) && ((a7==13) || (a7==14))) && (a24==15)) && a2 <= 189 )) && (a5==7))){ + + a7 = 13; + + return -1; + } else if(((((((input == 6) && a2 <= 189 ) && (a24==13)) && (a7==12)) && (a5==5)) && ((111 < a17) && (255 >= a17)) )){ + a17 = ((((a17 - -162890) - -143056) * 10)/ -9); + a5 = 3; + + return -1; + } else if((( ((189 < a2) && (281 >= a2)) && ((a24==15) && (((input == 3) && (((a7==12) || (a7==13)) || (a7==14))) && (a5==5)))) && a17 <= -108 )){ + a17 = (((((a17 + 326777) + 251227) - 58119) % 109)+ 1); + a7 = 12; + a24 = 13; + + return -1; + } else if(((a24==14) && ((a7==13) && ((( ((189 < a2) && (281 >= a2)) && (input == 5)) && ((-108 < a17) && (111 >= a17)) ) && (a5==4))))){ + + return 23; + } else if(( a2 <= 189 && ((((((a7==13) || (a7==14)) && (input == 3)) && (a24==15)) && (a5==6)) && ((111 < a17) && (255 >= a17)) ))){ + + a7 = 14; + + return 21; + } else if(((a7==13) && ( a17 <= -108 && ( a2 <= 189 && (((input == 5) && (a24==15)) && (a5==6)))))){ + + return 23; + } else if(((a24==14) && (((a5==5) && (( a2 <= 189 && (input == 6)) && a17 <= -108 )) && (a7==14)))){ + + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && ((a24==15) && ((a5==5) && ( a17 <= -108 && ((input == 4) && (((a7==12) || (a7==13)) || (a7==14)))))))){ + + a7 = 14; + a24 = 14; + + return -1; + } else if(((((((((a7==12) || (a7==13)) || (a7==14)) && (input == 1)) && (a5==7)) && a2 <= 189 ) && ((111 < a17) && (255 >= a17)) ) && (a24==15))){ + + a7 = 12; + a24 = 14; + + return -1; + } else if(( a2 <= 189 && ((((((a24==15) && ( 255 < a17 && (a7==14))) && (a5==4)) || ((a5==5) && (( a17 <= -108 && (a7==12)) && (a24==13)))) || ((a5==5) && (((a7==13) && a17 <= -108 ) && (a24==13)))) && (input == 5)))){ + a17 = ((((a17 % 299946)- 300053) + -1) + 0); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(( 255 < a17 && (((a5==6) && (((input == 6) && (a24==13)) && ((189 < a2) && (281 >= a2)) )) && (a7==13)))){ + a2 = (((a2 + -559930) - -930633) - 537732); + a17 = (((a17 - 600136) * 1) - 66); + a7 = 12; + a5 = 3; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && ( ((-108 < a17) && (111 >= a17)) && (((a24==15) && ((input == 2) && ((a7==13) || (a7==14)))) && (a5==5))))){ + a2 = ((((a2 * -5) * 10)/ 9) * 5); + a17 = (((a17 - 416379) / 5) * 5); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((( ((189 < a2) && (281 >= a2)) && ((a24==15) && ((input == 3) && (((a7==12) || (a7==13)) || (a7==14))))) && a17 <= -108 ) && (a5==4))){ + a2 = (((a2 / 5) + -106387) + -147146); + a17 = ((((a17 % 299872)- -300127) - -270865) + 27768); + a7 = 12; + a5 = 7; + + return -1; + } else if(((( ((189 < a2) && (281 >= a2)) && ((a5==5) && ((a24==15) && (input == 5)))) && (a7==12)) && ((-108 < a17) && (111 >= a17)) )){ + a17 = (((a17 - -533048) + 40396) * 1); + a7 = 13; + a24 = 13; + + return -1; + } else if((( ((189 < a2) && (281 >= a2)) && ((((input == 6) && (a24==15)) && (a5==4)) && (a7==12))) && ((-108 < a17) && (111 >= a17)) )){ + a2 = (((a2 * -5) * 5) * 5); + a17 = (((a17 - 418037) * 1) - -234835); + a24 = 13; + a5 = 3; + + return -1; + } else if(((((((input == 4) && (a24==13)) && (a5==6)) && a17 <= -108 ) && (a7==14)) && ((189 < a2) && (281 >= a2)) )){ + + a7 = 12; + a5 = 3; + + return -1; + } else if(((a24==13) && ((a5==5) && ( a2 <= 189 && ((((a7==13) && ((-108 < a17) && (111 >= a17)) ) || (((a7==14) && a17 <= -108 ) || ( ((-108 < a17) && (111 >= a17)) && (a7==12)))) && (input == 2)))))){ + a17 = ((((a17 - -453354) % 299946)+ -300053) * 1); + a7 = 12; + a5 = 3; + + return -1; + } else if(((a24==15) && ( a2 <= 189 && (((((a7==12) && ((-108 < a17) && (111 >= a17)) ) || (((a7==13) && a17 <= -108 ) || ((a7==14) && a17 <= -108 ))) && (input == 5)) && (a5==7))))){ + a17 = ((((a17 - 0) % 299872)+ 300127) * 1); + a7 = 13; + a24 = 13; + a5 = 5; + + return -1; + } else if(( ((189 < a2) && (281 >= a2)) && ((a24==14) && ((a7==13) && (((input == 6) && (a5==3)) && ((111 < a17) && (255 >= a17)) ))))){ + + return 26; + } else if(( 255 < a17 && ((a24==13) && (((a7==13) && ((input == 6) && a2 <= 189 )) && (a5==7))))){ + a17 = (((((a17 % 109)+ 3) - 249216) * 2) - -498320); + a7 = 14; + a24 = 15; + a5 = 4; + + return -1; + } else if(((a24==14) && ( ((111 < a17) && (255 >= a17)) && (((a5==6) && ((input == 5) && ((a7==14) || ((a7==12) || (a7==13))))) && a2 <= 189 )))){ + a2 = (((((a2 % 45)+ 234) * 5) % 45)- -233); + a17 = ((((((a17 * 10)/ -9) + 137075) * 4) * -1)/ 10); + a7 = 12; + a24 = 13; + a5 = 4; + + return 26; + } else if(( ((189 < a2) && (281 >= a2)) && ((a5==4) && ((a24==14) && ((input == 5) && (( ((-108 < a17) && (111 >= a17)) && (a7==14)) || ( ((111 < a17) && (255 >= a17)) && (a7==12)))))))){ + a2 = (((a2 / -5) + -474783) / 5); + a17 = (((a17 - 32453) * 5) / 5); + a7 = 14; + a24 = 15; + a5 = 5; + + return 23; + } else if(( 255 < a17 && ((a24==15) && ((a5==5) && ( ((189 < a2) && (281 >= a2)) && (((a7==14) || ((a7==12) || (a7==13))) && (input == 2))))))){ + a2 = (((a2 + -107856) - 174986) / 5); + a17 = (((a17 - 83582) + -516569) * 1); + a7 = 12; + a24 = 13; + a5 = 3; + + return -1; + } else if(((((a5==5) && (((a24==13) && (input == 2)) && a2 <= 189 )) && (a7==13)) && ((111 < a17) && (255 >= a17)) )){ + a17 = (((a17 - 3949) * 5) * 5); + a7 = 12; + a5 = 3; + + return -1; + } + return -2; + } + +int main2() +{ + // default output + int output = -1; + + // main i/o-loop + while(1) + { + // read input + int input; + input = __VERIFIER_nondet_int(); + if ((input != 1) && (input != 2) && (input != 3) && (input != 4) && (input != 5) && (input != 6)) return -2; + + // operate eca engine + output = calculate_output(input); + } +}int main() +{ + if(__VERIFIER_nondet_int()) + main1(); + else + main2(); +} From ca88a990006e875e8ffcf2b02e8a6c461c5c8a66 Mon Sep 17 00:00:00 2001 From: Sergey Morozov Date: Thu, 12 Oct 2023 18:10:19 +0400 Subject: [PATCH 040/103] [fix] Fixed inner types for unnamed structs. --- lib/Core/TypeManager.cpp | 20 ++++- test/regression/2023-10-12-inner-types-fix.c | 89 ++++++++++++++++++++ 2 files changed, 105 insertions(+), 4 deletions(-) create mode 100644 test/regression/2023-10-12-inner-types-fix.c diff --git a/lib/Core/TypeManager.cpp b/lib/Core/TypeManager.cpp index 0ba8f8ffb1..c053d449fa 100644 --- a/lib/Core/TypeManager.cpp +++ b/lib/Core/TypeManager.cpp @@ -37,6 +37,12 @@ KType *TypeManager::getWrappedType(llvm::Type *type) { if (typesMap.count(type) == 0) { types.emplace_back(new KType(type, this)); typesMap.emplace(type, types.back().get()); + if (type && type->isPointerTy()) { + getWrappedType(type->getPointerElementType()); + } + if (type && type->isArrayTy()) { + getWrappedType(type->getArrayElementType()); + } } return typesMap[type]; } @@ -61,15 +67,21 @@ void TypeManager::initTypesFromStructs() { * and pull types to top. */ - std::vector collectedStructTypes = - parent->module->getIdentifiedStructTypes(); - for (auto &structType : collectedStructTypes) { + for (auto &structType : parent->module->getIdentifiedStructTypes()) { getWrappedType(structType); } + std::unordered_set collectedStructTypes; + for (const auto &it : typesMap) { + if (llvm::StructType *itStruct = + llvm::dyn_cast(it.first)) { + collectedStructTypes.insert(itStruct); + } + } + for (auto &typesToOffsets : typesMap) { if (llvm::isa(typesToOffsets.first)) { - collectedStructTypes.emplace_back( + collectedStructTypes.insert( llvm::cast(typesToOffsets.first)); } } diff --git a/test/regression/2023-10-12-inner-types-fix.c b/test/regression/2023-10-12-inner-types-fix.c new file mode 100644 index 0000000000..2484dc6a1f --- /dev/null +++ b/test/regression/2023-10-12-inner-types-fix.c @@ -0,0 +1,89 @@ +// RUN: %clang -Wno-everything %s -emit-llvm %O0opt -g -c -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --entry-point=klee_entry --skip-not-lazy-initialized --min-number-elements-li=1 %t1.bc 2>&1 +// RUN: %ktest-tool %t.klee-out/test000003.ktest | FileCheck %s + +#include "klee/klee.h" + +struct StructWithPointer { + int x; + int *y; +}; + +struct StructWithDoublePointer { + int x; + int **y; +}; + +struct StructWithArrayOfPointer { + int x; + int *y[2]; +}; + +struct StructWithStructWithPointer { + struct StructWithPointer swp; + struct StructWithDoublePointer *swdp; +}; + +struct StructManyPointers { + int a; + int *b; + int **c; + int ***d; +}; + +struct StructComplex { + int x; + int *y; + int **z; + struct StructWithPointer *swp; + struct StructWithDoublePointer **swdp; + struct StructManyPointers smp; +}; + +int sumStructWithPointer(struct StructWithPointer par) { + return par.x + *par.y; +} + +int sumStructWithPointerAsPointer(struct StructWithPointer *par) { + return par->x + *par->y; +} + +int sumStructWithDoublePointer(struct StructWithDoublePointer par) { + return par.x + **par.y; +} + +int sumStructWithArrayOfPointer(struct StructWithArrayOfPointer par) { + return par.x + *(par.y[0]) + *(par.y[1]); +} + +int sumStructWithStructWithPointer(struct StructWithStructWithPointer par) { + int sswp = sumStructWithPointer(par.swp); + int sswdp = sumStructWithDoublePointer(*par.swdp); + return sswp + sswdp; +} + +int sumStructManyPointers(struct StructManyPointers par) { + return par.a + *par.b + **par.c + ***par.d; +} + +int sumStructComplex(struct StructComplex par) { + int sswp = sumStructWithPointer(*par.swp); + int sswdp = sumStructWithDoublePointer(**par.swdp); + int ssmp = sumStructManyPointers(par.smp); + return par.x + *par.y + **par.z + sswp + sswdp + ssmp; +} + +// CHECK: object 2: pointers: [(8, 3, 0)] +int klee_entry(int utbot_argc, char **utbot_argv, char **utbot_envp) { + struct StructComplex par; + klee_make_symbolic(&par, sizeof(par), "par"); + klee_prefer_cex(&par, par.x >= -10 & par.x <= 10); + klee_prefer_cex(&par, par.smp.a >= -10 & par.smp.a <= 10); + //////////////////////////////////////////// + int utbot_result; + klee_make_symbolic(&utbot_result, sizeof(utbot_result), "utbot_result"); + int utbot_tmp = sumStructComplex(par); + klee_assume(utbot_tmp == utbot_result); + return 0; +} \ No newline at end of file From 2171ce36df95918d0f01a1ee4f86d05c5e43aa45 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Sat, 23 Sep 2023 00:18:27 +0400 Subject: [PATCH 041/103] [feat] Separate branch and block coverage --- include/klee/Module/CodeGraphInfo.h | 8 + lib/Core/Executor.cpp | 7 + lib/Core/TargetCalculator.cpp | 239 +-- lib/Core/TargetCalculator.h | 27 +- lib/Module/CodeGraphInfo.cpp | 34 + test/Industry/ll_create_rec-alloca-2.c | 57 + ...r.3.ufo.UNBOUNDED.pals+Problem12_label00.c | 2 +- test/regression/2023-10-16-CostasArray-17.c | 1741 +++++++++++++++++ 8 files changed, 1956 insertions(+), 159 deletions(-) create mode 100644 test/Industry/ll_create_rec-alloca-2.c create mode 100644 test/regression/2023-10-16-CostasArray-17.c diff --git a/include/klee/Module/CodeGraphInfo.h b/include/klee/Module/CodeGraphInfo.h index c13a7a0337..f1576336b1 100644 --- a/include/klee/Module/CodeGraphInfo.h +++ b/include/klee/Module/CodeGraphInfo.h @@ -45,6 +45,8 @@ class CodeGraphInfo { functionDistanceList functionSortedBackwardDistance; functionBranchesSet functionBranches; + functionBranchesSet functionConditionalBranches; + functionBranchesSet functionBlocks; private: void calculateDistance(KBlock *bb); @@ -54,6 +56,8 @@ class CodeGraphInfo { void calculateBackwardDistance(KFunction *kf); void calculateFunctionBranches(KFunction *kf); + void calculateFunctionConditionalBranches(KFunction *kf); + void calculateFunctionBlocks(KFunction *kf); public: const std::unordered_map &getDistance(KBlock *kb); @@ -78,6 +82,10 @@ class CodeGraphInfo { const std::map> & getFunctionBranches(KFunction *kf); + const std::map> & + getFunctionConditionalBranches(KFunction *kf); + const std::map> & + getFunctionBlocks(KFunction *kf); }; } // namespace klee diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index 0705439d90..96f55a2b3a 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -445,6 +445,7 @@ bool allLeafsAreConstant(const ref &expr) { extern llvm::cl::opt MaxConstantAllocationSize; extern llvm::cl::opt MaxSymbolicAllocationSize; extern llvm::cl::opt UseSymbolicSizeAllocation; +extern llvm::cl::opt TrackCoverage; // XXX hack extern "C" unsigned dumpStates, dumpPForest; @@ -4373,6 +4374,7 @@ static std::string terminationTypeFileExtension(StateTerminationType type) { }; void Executor::executeStep(ExecutionState &state) { + KFunction *initKF = state.initPC->parent->parent; if (CoverOnTheFly && guidanceKind != GuidanceKind::ErrorGuidance && stats::instructions > DelayCoverOnTheFly && shouldWriteTest(state)) { state.clearCoveredNew(); @@ -4407,6 +4409,11 @@ void Executor::executeStep(ExecutionState &state) { // pressure updateStates(nullptr); } + + if (targetCalculator && TrackCoverage != TrackCoverageBy::None && + targetCalculator->isCovered(initKF)) { + haltExecution = HaltExecution::CovCheck; + } } void Executor::targetedRun(ExecutionState &initialState, KBlock *target, diff --git a/lib/Core/TargetCalculator.cpp b/lib/Core/TargetCalculator.cpp index e6a8f8834c..94953d51b8 100644 --- a/lib/Core/TargetCalculator.cpp +++ b/lib/Core/TargetCalculator.cpp @@ -22,52 +22,49 @@ using namespace llvm; using namespace klee; -namespace klee { -llvm::cl::opt TargetCalculatorMode( - "target-calculator-kind", cl::desc("Specifiy the target calculator mode."), - cl::values( - clEnumValN(TargetCalculateBy::Default, "default", - "Looks for the closest uncovered block."), - clEnumValN( - TargetCalculateBy::Blocks, "blocks", - "Looks for the closest uncovered block by state blocks history."), - clEnumValN(TargetCalculateBy::Transitions, "transitions", - "Looks for the closest uncovered block by state transitions " - "history.")), - cl::init(TargetCalculateBy::Default), cl::cat(ExecCat)); -} // namespace klee +llvm::cl::opt TrackCoverage( + "track-coverage", cl::desc("Specifiy the track coverage mode."), + cl::values(clEnumValN(TrackCoverageBy::None, "none", "Not track coverage."), + clEnumValN(TrackCoverageBy::Blocks, "blocks", + "Track only covered block."), + clEnumValN(TrackCoverageBy::Branches, "branches", + "Track only covered conditional branches."), + clEnumValN(TrackCoverageBy::All, "all", "Track all.")), + cl::init(TrackCoverageBy::None), cl::cat(ExecCat)); void TargetCalculator::update(const ExecutionState &state) { Function *initialFunction = state.getInitPCBlock()->getParent(); - if (state.prevPC == state.prevPC->parent->getLastInstruction()) { - coveredBlocks[state.getPrevPCBlock()->getParent()].insert( - state.prevPC->parent); - } if (state.prevPC == state.prevPC->parent->getLastInstruction() && !fullyCoveredFunctions.count(state.prevPC->parent->parent)) { + auto &fBranches = getCoverageTargets(state.prevPC->parent->parent); if (!coveredFunctionsInBranches.count(state.prevPC->parent->parent)) { - unsigned index = 0; - if (!coveredBranches[state.prevPC->parent->parent].count( - state.prevPC->parent)) { - state.coverNew(); - coveredBranches[state.prevPC->parent->parent][state.prevPC->parent]; - } - for (auto succ : successors(state.getPrevPCBlock())) { - if (succ == state.getPCBlock()) { - if (!coveredBranches[state.prevPC->parent->parent] - [state.prevPC->parent] - .count(index)) { - state.coverNew(); - coveredBranches[state.prevPC->parent->parent][state.prevPC->parent] - .insert(index); + if (fBranches.count(state.prevPC->parent) != 0) { + if (!coveredBranches[state.prevPC->parent->parent].count( + state.prevPC->parent)) { + state.coverNew(); + coveredBranches[state.prevPC->parent->parent][state.prevPC->parent]; + } + if (!fBranches.at(state.prevPC->parent).empty()) { + unsigned index = 0; + for (auto succ : successors(state.getPrevPCBlock())) { + if (succ == state.getPCBlock()) { + if (!coveredBranches[state.prevPC->parent->parent] + [state.prevPC->parent] + .count(index)) { + state.coverNew(); + coveredBranches[state.prevPC->parent->parent] + [state.prevPC->parent] + .insert(index); + } + break; + } + ++index; } - break; } - ++index; } - if (codeGraphInfo.getFunctionBranches(state.prevPC->parent->parent) == + if (getCoverageTargets(state.prevPC->parent->parent) == coveredBranches[state.prevPC->parent->parent]) { coveredFunctionsInBranches.insert(state.prevPC->parent->parent); } @@ -88,12 +85,15 @@ void TargetCalculator::update(const ExecutionState &state) { KFunction *calledKFunction = state.prevPC->parent->parent->parent ->functionMap[calledFunction]; if (calledKFunction->numInstructions != 0 && - coveredFunctionsInBranches.count(calledKFunction) == 0) { + coveredFunctionsInBranches.count(calledKFunction) == 0 && + !getCoverageTargets(calledKFunction).empty()) { covered = false; break; } if (!fnsTaken.count(calledKFunction) && - fullyCoveredFunctions.count(calledKFunction) == 0) { + fullyCoveredFunctions.count(calledKFunction) == 0 && + calledKFunction->numInstructions != 0 && + !getCoverageTargets(calledKFunction).empty()) { fns.push_back(calledKFunction); } } @@ -106,25 +106,6 @@ void TargetCalculator::update(const ExecutionState &state) { } } } - - switch (TargetCalculatorMode) { - case TargetCalculateBy::Default: - blocksHistory[initialFunction][state.getPrevPCBlock()].insert( - state.initPC->parent); - break; - - case TargetCalculateBy::Blocks: - blocksHistory[initialFunction][state.getPrevPCBlock()].insert( - state.level.begin(), state.level.end()); - break; - - case TargetCalculateBy::Transitions: - blocksHistory[initialFunction][state.getPrevPCBlock()].insert( - state.level.begin(), state.level.end()); - transitionsHistory[initialFunction][state.getPrevPCBlock()].insert( - state.transitionLevel.begin(), state.transitionLevel.end()); - break; - } } void TargetCalculator::update( @@ -151,73 +132,48 @@ void TargetCalculator::update( localStates.clear(); } -bool TargetCalculator::differenceIsEmpty( - const ExecutionState &state, - const std::unordered_map &history, - KBlock *target) { - std::vector diff; - std::set left(state.level.begin(), state.level.end()); - std::set right(history.at(target->basicBlock).begin(), - history.at(target->basicBlock).end()); - std::set_difference(left.begin(), left.end(), right.begin(), right.end(), - std::inserter(diff, diff.begin())); - return diff.empty(); -} +const std::map> & +TargetCalculator::getCoverageTargets(KFunction *kf) { + switch (TrackCoverage) { + case TrackCoverageBy::Blocks: + return codeGraphInfo.getFunctionBlocks(kf); + case TrackCoverageBy::Branches: + return codeGraphInfo.getFunctionConditionalBranches(kf); + case TrackCoverageBy::None: + case TrackCoverageBy::All: + return codeGraphInfo.getFunctionBranches(kf); -bool TargetCalculator::differenceIsEmpty( - const ExecutionState &state, - const std::unordered_map &history, - KBlock *target) { - std::vector diff; - std::set left(state.transitionLevel.begin(), - state.transitionLevel.end()); - std::set right(history.at(target->basicBlock).begin(), - history.at(target->basicBlock).end()); - std::set_difference(left.begin(), left.end(), right.begin(), right.end(), - std::inserter(diff, diff.begin())); - return diff.empty(); + default: + assert(0 && "not implemented"); + } } bool TargetCalculator::uncoveredBlockPredicate(ExecutionState *state, KBlock *kblock) { Function *initialFunction = state->getInitPCBlock()->getParent(); - std::unordered_map &history = - blocksHistory[initialFunction]; - std::unordered_map - &transitionHistory = transitionsHistory[initialFunction]; bool result = false; - if (coveredBranches[kblock->parent].count(kblock) == 0) { - result = true; - } else { - auto &cb = coveredBranches[kblock->parent][kblock]; - if (isa(kblock) && - cast(kblock)->calledFunctions.size() == 1) { - auto calledFunction = *cast(kblock)->calledFunctions.begin(); - KFunction *calledKFunction = - kblock->parent->parent->functionMap[calledFunction]; - result = fullyCoveredFunctions.count(calledKFunction) == 0 && - calledKFunction->numInstructions; - } - result |= - kblock->basicBlock->getTerminator()->getNumSuccessors() > cb.size(); - } - switch (TargetCalculatorMode) { - case TargetCalculateBy::Default: { - break; - } - case TargetCalculateBy::Blocks: { - if (history[kblock->basicBlock].size() != 0) { - result |= !differenceIsEmpty(*state, history, kblock); - } - break; - } - case TargetCalculateBy::Transitions: { - if (history[kblock->basicBlock].size() != 0) { - result |= !differenceIsEmpty(*state, transitionHistory, kblock); + auto &fBranches = getCoverageTargets(kblock->parent); + + if (fBranches.count(kblock) != 0 || isa(kblock)) { + if (coveredBranches[kblock->parent].count(kblock) == 0) { + result = true; + } else { + auto &cb = coveredBranches[kblock->parent][kblock]; + if (isa(kblock) && + cast(kblock)->calledFunctions.size() == 1) { + auto calledFunction = + *cast(kblock)->calledFunctions.begin(); + KFunction *calledKFunction = + kblock->parent->parent->functionMap[calledFunction]; + result = fullyCoveredFunctions.count(calledKFunction) == 0 && + calledKFunction->numInstructions; + } + if (fBranches.at(kblock) != cb) { + result |= + kblock->basicBlock->getTerminator()->getNumSuccessors() > cb.size(); + } } - break; - } } return result; @@ -246,29 +202,36 @@ TargetHashSet TargetCalculator::calculate(ExecutionState &state) { if (!blocks.empty()) { TargetHashSet targets; for (auto block : blocks) { - if (coveredBranches[block->parent].count(block) == 0) { - targets.insert(ReachBlockTarget::create(block, false)); - } else { - auto &cb = coveredBranches[block->parent][block]; - bool notCoveredFunction = false; - if (isa(block) && - cast(block)->calledFunctions.size() == 1) { - auto calledFunction = - *cast(block)->calledFunctions.begin(); - KFunction *calledKFunction = - block->parent->parent->functionMap[calledFunction]; - notCoveredFunction = - fullyCoveredFunctions.count(calledKFunction) == 0 && - calledKFunction->numInstructions; - } - if (notCoveredFunction) { - targets.insert(ReachBlockTarget::create(block, true)); + auto &fBranches = getCoverageTargets(block->parent); + + if (fBranches.count(block) != 0 || isa(block)) { + if (coveredBranches[block->parent].count(block) == 0) { + targets.insert(ReachBlockTarget::create(block, false)); } else { - for (unsigned index = 0; - index < block->basicBlock->getTerminator()->getNumSuccessors(); - ++index) { - if (!cb.count(index)) - targets.insert(CoverBranchTarget::create(block, index)); + auto &cb = coveredBranches[block->parent][block]; + bool notCoveredFunction = false; + if (isa(block) && + cast(block)->calledFunctions.size() == 1) { + auto calledFunction = + *cast(block)->calledFunctions.begin(); + KFunction *calledKFunction = + block->parent->parent->functionMap[calledFunction]; + notCoveredFunction = + fullyCoveredFunctions.count(calledKFunction) == 0 && + calledKFunction->numInstructions; + } + if (notCoveredFunction) { + targets.insert(ReachBlockTarget::create(block, true)); + } else { + if (fBranches.at(block) != cb) { + for (unsigned index = 0; + index < + block->basicBlock->getTerminator()->getNumSuccessors(); + ++index) { + if (!cb.count(index)) + targets.insert(CoverBranchTarget::create(block, index)); + } + } } } } @@ -289,3 +252,7 @@ TargetHashSet TargetCalculator::calculate(ExecutionState &state) { return {}; } + +bool TargetCalculator::isCovered(KFunction *kf) const { + return fullyCoveredFunctions.count(kf) != 0; +} diff --git a/lib/Core/TargetCalculator.h b/lib/Core/TargetCalculator.h index 75bd8413d8..cd96306524 100644 --- a/lib/Core/TargetCalculator.h +++ b/lib/Core/TargetCalculator.h @@ -36,9 +36,8 @@ class CodeGraphInfo; class ExecutionState; struct TransitionHash; -enum TargetCalculateBy { Default, Blocks, Transitions }; +enum class TrackCoverageBy { None, Blocks, Branches, All }; -typedef std::pair Transition; typedef std::pair Branch; class TargetCalculator { @@ -50,21 +49,12 @@ class TargetCalculator { enum HistoryKind { Blocks, Transitions }; - typedef std::unordered_map< - llvm::Function *, std::unordered_map> - BlocksHistory; - typedef std::unordered_map< - llvm::Function *, - std::unordered_map> - TransitionsHistory; - typedef std::unordered_map>> CoveredBranches; typedef std::unordered_set CoveredFunctionsBranches; - typedef std::unordered_map CoveredBlocks; void update(const ExecutionState &state); public: @@ -77,24 +67,17 @@ class TargetCalculator { TargetHashSet calculate(ExecutionState &state); + bool isCovered(KFunction *kf) const; + private: CodeGraphInfo &codeGraphInfo; - BlocksHistory blocksHistory; - TransitionsHistory transitionsHistory; CoveredBranches coveredBranches; CoveredFunctionsBranches coveredFunctionsInBranches; CoveredFunctionsBranches fullyCoveredFunctions; - CoveredBlocks coveredBlocks; StatesSet localStates; - bool differenceIsEmpty( - const ExecutionState &state, - const std::unordered_map &history, - KBlock *target); - bool differenceIsEmpty( - const ExecutionState &state, - const std::unordered_map &history, - KBlock *target); + const std::map> & + getCoverageTargets(KFunction *kf); bool uncoveredBlockPredicate(ExecutionState *state, KBlock *kblock); }; diff --git a/lib/Module/CodeGraphInfo.cpp b/lib/Module/CodeGraphInfo.cpp index 045c379932..a0df05e8c1 100644 --- a/lib/Module/CodeGraphInfo.cpp +++ b/lib/Module/CodeGraphInfo.cpp @@ -130,6 +130,26 @@ void CodeGraphInfo::calculateFunctionBranches(KFunction *kf) { } } } +void CodeGraphInfo::calculateFunctionConditionalBranches(KFunction *kf) { + std::map> &fbranches = + functionConditionalBranches[kf]; + for (auto &kb : kf->blocks) { + if (kb->basicBlock->getTerminator()->getNumSuccessors() > 1) { + fbranches[kb.get()]; + for (unsigned branch = 0; + branch < kb->basicBlock->getTerminator()->getNumSuccessors(); + ++branch) { + fbranches[kb.get()].insert(branch); + } + } + } +} +void CodeGraphInfo::calculateFunctionBlocks(KFunction *kf) { + std::map> &fbranches = functionBlocks[kf]; + for (auto &kb : kf->blocks) { + fbranches[kb.get()]; + } +} const std::unordered_map & CodeGraphInfo::getDistance(KBlock *kb) { @@ -219,3 +239,17 @@ CodeGraphInfo::getFunctionBranches(KFunction *kf) { calculateFunctionBranches(kf); return functionBranches.at(kf); } + +const std::map> & +CodeGraphInfo::getFunctionConditionalBranches(KFunction *kf) { + if (functionConditionalBranches.count(kf) == 0) + calculateFunctionConditionalBranches(kf); + return functionConditionalBranches.at(kf); +} + +const std::map> & +CodeGraphInfo::getFunctionBlocks(KFunction *kf) { + if (functionBlocks.count(kf) == 0) + calculateFunctionBlocks(kf); + return functionBlocks.at(kf); +} diff --git a/test/Industry/ll_create_rec-alloca-2.c b/test/Industry/ll_create_rec-alloca-2.c new file mode 100644 index 0000000000..127a38df5f --- /dev/null +++ b/test/Industry/ll_create_rec-alloca-2.c @@ -0,0 +1,57 @@ +// RUN: %clang -Wno-everything %s -emit-llvm %O0opt -g -c -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --track-coverage=branches --delete-dead-loops=false --cex-cache-validity-cores --optimize=true --emit-all-errors --only-output-states-covering-new=true --dump-states-on-halt=true --search=dfs --search=random-path %t1.bc +// RUN: %klee-stats --print-columns 'ICov(%),BCov(%)' --table-format=csv %t.klee-out > %t.stats +// RUN: FileCheck -check-prefix=CHECK-BRANCH -input-file=%t.stats %s + +// Branch coverage 100%, and instruction coverage is very small: +// CHECK-BRANCH: ICov(%),BCov(%) +// CHECK-BRANCH-NEXT: {{([1-9][0-9]\.[0-9][0-9])}},100.00 + +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --track-coverage=blocks --delete-dead-loops=false --cex-cache-validity-cores --optimize=true --emit-all-errors --only-output-states-covering-new=true --dump-states-on-halt=true --search=dfs --search=random-path %t1.bc +// RUN: %klee-stats --print-columns 'ICov(%),BCov(%)' --table-format=csv %t.klee-out > %t.stats +// RUN: FileCheck -check-prefix=CHECK-BLOCK -input-file=%t.stats %s + +// Branch coverage 100%, and instruction coverage is very small: +// CHECK-BLOCK: ICov(%),BCov(%) +// CHECK-BLOCK-NEXT: 100.00,100.00 + + +#include "klee-test-comp.c" + +/* + * Date: 30/09/2015 + * Created by: + * Ton Chanh Le (chanhle@comp.nus.edu.sg) and + * Duc Muoi Tran (muoitranduc@gmail.com) + */ + +extern int __VERIFIER_nondet_int(); + +typedef struct node { + int val; + struct node* next; +} node_t; + +// Create a new linked list with length n when n >= 0 +// or non-terminating when n < 0 +node_t* new_ll(int n) +{ + if (n == 0) + return 0; + node_t* head = malloc(sizeof(node_t)); + head->val = n; + head->next = new_ll(n-1); + return head; +} + +int main () +{ + int n = __VERIFIER_nondet_int(); + if (n < 0) { + return 0; + } + node_t* head = new_ll(n); + return 0; +} diff --git a/test/Industry/pals_lcr.3.ufo.UNBOUNDED.pals+Problem12_label00.c b/test/Industry/pals_lcr.3.ufo.UNBOUNDED.pals+Problem12_label00.c index 36a3bb4ab7..7b90ea5b2d 100644 --- a/test/Industry/pals_lcr.3.ufo.UNBOUNDED.pals+Problem12_label00.c +++ b/test/Industry/pals_lcr.3.ufo.UNBOUNDED.pals+Problem12_label00.c @@ -1,7 +1,7 @@ // REQUIRES: geq-llvm-14.0 // RUN: %clang %s -emit-llvm %O0opt -g -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --delete-dead-loops=false --emit-all-errors --mock-all-externals --use-forked-solver=false --optimize --skip-not-lazy-initialized --output-source=false --output-stats=true --output-istats=true -istats-write-interval=3s --use-sym-size-alloc=true --cex-cache-validity-cores --symbolic-allocation-threshold=8192 --cover-on-the-fly=false --delay-cover-on-the-fly=400000 --only-output-states-covering-new --dump-states-on-halt=true --search=dfs --search=random-state --use-iterative-deepening-search=max-cycles --max-cycles=4 %t1.bc +// RUN: %klee --output-dir=%t.klee-out --track-coverage=branches --delete-dead-loops=false --emit-all-errors --mock-all-externals --use-forked-solver=false --optimize --skip-not-lazy-initialized --output-source=false --output-stats=true --output-istats=true -istats-write-interval=3s --use-sym-size-alloc=true --cex-cache-validity-cores --symbolic-allocation-threshold=8192 --cover-on-the-fly=false --delay-cover-on-the-fly=400000 --only-output-states-covering-new --dump-states-on-halt=true --search=dfs --search=random-state --use-iterative-deepening-search=max-cycles --max-cycles=4 %t1.bc // RUN: %klee-stats --print-columns 'BCov(%)' --table-format=csv %t.klee-out > %t.stats // RUN: FileCheck -input-file=%t.stats %s diff --git a/test/regression/2023-10-16-CostasArray-17.c b/test/regression/2023-10-16-CostasArray-17.c new file mode 100644 index 0000000000..0321c71828 --- /dev/null +++ b/test/regression/2023-10-16-CostasArray-17.c @@ -0,0 +1,1741 @@ +// RUN: %clang -Wno-everything %s -emit-llvm %O0opt -g -c -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --track-coverage=branches --optimize=true --emit-all-errors --only-output-states-covering-new=true --dump-states-on-halt=true --search=dfs %t1.bc +// RUN: %klee-stats --print-columns 'ICov(%),BCov(%)' --table-format=csv %t.klee-out > %t.stats +// RUN: FileCheck -input-file=%t.stats %s + +// Branch coverage 100%, and instruction coverage is very small: +// CHECK: ICov(%),BCov(%) +// CHECK-NEXT: {{(0\.[0-9][0-9])}},100.00 + +#include "klee-test-comp.c" + +// This file is part of the SV-Benchmarks collection of verification tasks: +// https://github.com/sosy-lab/sv-benchmarks +// +// SPDX-FileCopyrightText: 2016 Gilles Audemard +// SPDX-FileCopyrightText: 2020 Dirk Beyer +// SPDX-FileCopyrightText: 2020 The SV-Benchmarks Community +// +// SPDX-License-Identifier: MIT + +extern void abort(void) __attribute__((__nothrow__, __leaf__)) +__attribute__((__noreturn__)); +extern void __assert_fail(const char *, const char *, unsigned int, + const char *) __attribute__((__nothrow__, __leaf__)) +__attribute__((__noreturn__)); +int __VERIFIER_nondet_int(); +void reach_error() { __assert_fail("0", "CostasArray-17.c", 5, "reach_error"); } +void assume(int cond) { + if (!cond) + abort(); +} +int main() { + int cond0; + int dummy = 0; + int N; + int var0; + var0 = __VERIFIER_nondet_int(); + assume(var0 >= 1); + assume(var0 <= 17); + int var1; + var1 = __VERIFIER_nondet_int(); + assume(var1 >= 1); + assume(var1 <= 17); + int var2; + var2 = __VERIFIER_nondet_int(); + assume(var2 >= 1); + assume(var2 <= 17); + int var3; + var3 = __VERIFIER_nondet_int(); + assume(var3 >= 1); + assume(var3 <= 17); + int var4; + var4 = __VERIFIER_nondet_int(); + assume(var4 >= 1); + assume(var4 <= 17); + int var5; + var5 = __VERIFIER_nondet_int(); + assume(var5 >= 1); + assume(var5 <= 17); + int var6; + var6 = __VERIFIER_nondet_int(); + assume(var6 >= 1); + assume(var6 <= 17); + int var7; + var7 = __VERIFIER_nondet_int(); + assume(var7 >= 1); + assume(var7 <= 17); + int var8; + var8 = __VERIFIER_nondet_int(); + assume(var8 >= 1); + assume(var8 <= 17); + int var9; + var9 = __VERIFIER_nondet_int(); + assume(var9 >= 1); + assume(var9 <= 17); + int var10; + var10 = __VERIFIER_nondet_int(); + assume(var10 >= 1); + assume(var10 <= 17); + int var11; + var11 = __VERIFIER_nondet_int(); + assume(var11 >= 1); + assume(var11 <= 17); + int var12; + var12 = __VERIFIER_nondet_int(); + assume(var12 >= 1); + assume(var12 <= 17); + int var13; + var13 = __VERIFIER_nondet_int(); + assume(var13 >= 1); + assume(var13 <= 17); + int var14; + var14 = __VERIFIER_nondet_int(); + assume(var14 >= 1); + assume(var14 <= 17); + int var15; + var15 = __VERIFIER_nondet_int(); + assume(var15 >= 1); + assume(var15 <= 17); + int var16; + var16 = __VERIFIER_nondet_int(); + assume(var16 >= 1); + assume(var16 <= 17); + int var17; + var17 = __VERIFIER_nondet_int(); + assume(var17 >= -16); + assume(var17 <= 16); + assume(var17 != 0); + int var18; + var18 = __VERIFIER_nondet_int(); + assume(var18 >= -16); + assume(var18 <= 16); + assume(var18 != 0); + int var19; + var19 = __VERIFIER_nondet_int(); + assume(var19 >= -16); + assume(var19 <= 16); + assume(var19 != 0); + int var20; + var20 = __VERIFIER_nondet_int(); + assume(var20 >= -16); + assume(var20 <= 16); + assume(var20 != 0); + int var21; + var21 = __VERIFIER_nondet_int(); + assume(var21 >= -16); + assume(var21 <= 16); + assume(var21 != 0); + int var22; + var22 = __VERIFIER_nondet_int(); + assume(var22 >= -16); + assume(var22 <= 16); + assume(var22 != 0); + int var23; + var23 = __VERIFIER_nondet_int(); + assume(var23 >= -16); + assume(var23 <= 16); + assume(var23 != 0); + int var24; + var24 = __VERIFIER_nondet_int(); + assume(var24 >= -16); + assume(var24 <= 16); + assume(var24 != 0); + int var25; + var25 = __VERIFIER_nondet_int(); + assume(var25 >= -16); + assume(var25 <= 16); + assume(var25 != 0); + int var26; + var26 = __VERIFIER_nondet_int(); + assume(var26 >= -16); + assume(var26 <= 16); + assume(var26 != 0); + int var27; + var27 = __VERIFIER_nondet_int(); + assume(var27 >= -16); + assume(var27 <= 16); + assume(var27 != 0); + int var28; + var28 = __VERIFIER_nondet_int(); + assume(var28 >= -16); + assume(var28 <= 16); + assume(var28 != 0); + int var29; + var29 = __VERIFIER_nondet_int(); + assume(var29 >= -16); + assume(var29 <= 16); + assume(var29 != 0); + int var30; + var30 = __VERIFIER_nondet_int(); + assume(var30 >= -16); + assume(var30 <= 16); + assume(var30 != 0); + int var31; + var31 = __VERIFIER_nondet_int(); + assume(var31 >= -16); + assume(var31 <= 16); + assume(var31 != 0); + int var32; + var32 = __VERIFIER_nondet_int(); + assume(var32 >= -16); + assume(var32 <= 16); + assume(var32 != 0); + int var33; + var33 = __VERIFIER_nondet_int(); + assume(var33 >= -16); + assume(var33 <= 16); + assume(var33 != 0); + int var34; + var34 = __VERIFIER_nondet_int(); + assume(var34 >= -16); + assume(var34 <= 16); + assume(var34 != 0); + int var35; + var35 = __VERIFIER_nondet_int(); + assume(var35 >= -16); + assume(var35 <= 16); + assume(var35 != 0); + int var36; + var36 = __VERIFIER_nondet_int(); + assume(var36 >= -16); + assume(var36 <= 16); + assume(var36 != 0); + int var37; + var37 = __VERIFIER_nondet_int(); + assume(var37 >= -16); + assume(var37 <= 16); + assume(var37 != 0); + int var38; + var38 = __VERIFIER_nondet_int(); + assume(var38 >= -16); + assume(var38 <= 16); + assume(var38 != 0); + int var39; + var39 = __VERIFIER_nondet_int(); + assume(var39 >= -16); + assume(var39 <= 16); + assume(var39 != 0); + int var40; + var40 = __VERIFIER_nondet_int(); + assume(var40 >= -16); + assume(var40 <= 16); + assume(var40 != 0); + int var41; + var41 = __VERIFIER_nondet_int(); + assume(var41 >= -16); + assume(var41 <= 16); + assume(var41 != 0); + int var42; + var42 = __VERIFIER_nondet_int(); + assume(var42 >= -16); + assume(var42 <= 16); + assume(var42 != 0); + int var43; + var43 = __VERIFIER_nondet_int(); + assume(var43 >= -16); + assume(var43 <= 16); + assume(var43 != 0); + int var44; + var44 = __VERIFIER_nondet_int(); + assume(var44 >= -16); + assume(var44 <= 16); + assume(var44 != 0); + int var45; + var45 = __VERIFIER_nondet_int(); + assume(var45 >= -16); + assume(var45 <= 16); + assume(var45 != 0); + int var46; + var46 = __VERIFIER_nondet_int(); + assume(var46 >= -16); + assume(var46 <= 16); + assume(var46 != 0); + int var47; + var47 = __VERIFIER_nondet_int(); + assume(var47 >= -16); + assume(var47 <= 16); + assume(var47 != 0); + int var48; + var48 = __VERIFIER_nondet_int(); + assume(var48 >= -16); + assume(var48 <= 16); + assume(var48 != 0); + int var49; + var49 = __VERIFIER_nondet_int(); + assume(var49 >= -16); + assume(var49 <= 16); + assume(var49 != 0); + int var50; + var50 = __VERIFIER_nondet_int(); + assume(var50 >= -16); + assume(var50 <= 16); + assume(var50 != 0); + int var51; + var51 = __VERIFIER_nondet_int(); + assume(var51 >= -16); + assume(var51 <= 16); + assume(var51 != 0); + int var52; + var52 = __VERIFIER_nondet_int(); + assume(var52 >= -16); + assume(var52 <= 16); + assume(var52 != 0); + int var53; + var53 = __VERIFIER_nondet_int(); + assume(var53 >= -16); + assume(var53 <= 16); + assume(var53 != 0); + int var54; + var54 = __VERIFIER_nondet_int(); + assume(var54 >= -16); + assume(var54 <= 16); + assume(var54 != 0); + int var55; + var55 = __VERIFIER_nondet_int(); + assume(var55 >= -16); + assume(var55 <= 16); + assume(var55 != 0); + int var56; + var56 = __VERIFIER_nondet_int(); + assume(var56 >= -16); + assume(var56 <= 16); + assume(var56 != 0); + int var57; + var57 = __VERIFIER_nondet_int(); + assume(var57 >= -16); + assume(var57 <= 16); + assume(var57 != 0); + int var58; + var58 = __VERIFIER_nondet_int(); + assume(var58 >= -16); + assume(var58 <= 16); + assume(var58 != 0); + int var59; + var59 = __VERIFIER_nondet_int(); + assume(var59 >= -16); + assume(var59 <= 16); + assume(var59 != 0); + int var60; + var60 = __VERIFIER_nondet_int(); + assume(var60 >= -16); + assume(var60 <= 16); + assume(var60 != 0); + int var61; + var61 = __VERIFIER_nondet_int(); + assume(var61 >= -16); + assume(var61 <= 16); + assume(var61 != 0); + int var62; + var62 = __VERIFIER_nondet_int(); + assume(var62 >= -16); + assume(var62 <= 16); + assume(var62 != 0); + int var63; + var63 = __VERIFIER_nondet_int(); + assume(var63 >= -16); + assume(var63 <= 16); + assume(var63 != 0); + int var64; + var64 = __VERIFIER_nondet_int(); + assume(var64 >= -16); + assume(var64 <= 16); + assume(var64 != 0); + int var65; + var65 = __VERIFIER_nondet_int(); + assume(var65 >= -16); + assume(var65 <= 16); + assume(var65 != 0); + int var66; + var66 = __VERIFIER_nondet_int(); + assume(var66 >= -16); + assume(var66 <= 16); + assume(var66 != 0); + int var67; + var67 = __VERIFIER_nondet_int(); + assume(var67 >= -16); + assume(var67 <= 16); + assume(var67 != 0); + int var68; + var68 = __VERIFIER_nondet_int(); + assume(var68 >= -16); + assume(var68 <= 16); + assume(var68 != 0); + int var69; + var69 = __VERIFIER_nondet_int(); + assume(var69 >= -16); + assume(var69 <= 16); + assume(var69 != 0); + int var70; + var70 = __VERIFIER_nondet_int(); + assume(var70 >= -16); + assume(var70 <= 16); + assume(var70 != 0); + int var71; + var71 = __VERIFIER_nondet_int(); + assume(var71 >= -16); + assume(var71 <= 16); + assume(var71 != 0); + int var72; + var72 = __VERIFIER_nondet_int(); + assume(var72 >= -16); + assume(var72 <= 16); + assume(var72 != 0); + int var73; + var73 = __VERIFIER_nondet_int(); + assume(var73 >= -16); + assume(var73 <= 16); + assume(var73 != 0); + int var74; + var74 = __VERIFIER_nondet_int(); + assume(var74 >= -16); + assume(var74 <= 16); + assume(var74 != 0); + int var75; + var75 = __VERIFIER_nondet_int(); + assume(var75 >= -16); + assume(var75 <= 16); + assume(var75 != 0); + int var76; + var76 = __VERIFIER_nondet_int(); + assume(var76 >= -16); + assume(var76 <= 16); + assume(var76 != 0); + int var77; + var77 = __VERIFIER_nondet_int(); + assume(var77 >= -16); + assume(var77 <= 16); + assume(var77 != 0); + int var78; + var78 = __VERIFIER_nondet_int(); + assume(var78 >= -16); + assume(var78 <= 16); + assume(var78 != 0); + int var79; + var79 = __VERIFIER_nondet_int(); + assume(var79 >= -16); + assume(var79 <= 16); + assume(var79 != 0); + int var80; + var80 = __VERIFIER_nondet_int(); + assume(var80 >= -16); + assume(var80 <= 16); + assume(var80 != 0); + int var81; + var81 = __VERIFIER_nondet_int(); + assume(var81 >= -16); + assume(var81 <= 16); + assume(var81 != 0); + int var82; + var82 = __VERIFIER_nondet_int(); + assume(var82 >= -16); + assume(var82 <= 16); + assume(var82 != 0); + int var83; + var83 = __VERIFIER_nondet_int(); + assume(var83 >= -16); + assume(var83 <= 16); + assume(var83 != 0); + int var84; + var84 = __VERIFIER_nondet_int(); + assume(var84 >= -16); + assume(var84 <= 16); + assume(var84 != 0); + int var85; + var85 = __VERIFIER_nondet_int(); + assume(var85 >= -16); + assume(var85 <= 16); + assume(var85 != 0); + int var86; + var86 = __VERIFIER_nondet_int(); + assume(var86 >= -16); + assume(var86 <= 16); + assume(var86 != 0); + int var87; + var87 = __VERIFIER_nondet_int(); + assume(var87 >= -16); + assume(var87 <= 16); + assume(var87 != 0); + int var88; + var88 = __VERIFIER_nondet_int(); + assume(var88 >= -16); + assume(var88 <= 16); + assume(var88 != 0); + int var89; + var89 = __VERIFIER_nondet_int(); + assume(var89 >= -16); + assume(var89 <= 16); + assume(var89 != 0); + int var90; + var90 = __VERIFIER_nondet_int(); + assume(var90 >= -16); + assume(var90 <= 16); + assume(var90 != 0); + int var91; + var91 = __VERIFIER_nondet_int(); + assume(var91 >= -16); + assume(var91 <= 16); + assume(var91 != 0); + int var92; + var92 = __VERIFIER_nondet_int(); + assume(var92 >= -16); + assume(var92 <= 16); + assume(var92 != 0); + int var93; + var93 = __VERIFIER_nondet_int(); + assume(var93 >= -16); + assume(var93 <= 16); + assume(var93 != 0); + int var94; + var94 = __VERIFIER_nondet_int(); + assume(var94 >= -16); + assume(var94 <= 16); + assume(var94 != 0); + int var95; + var95 = __VERIFIER_nondet_int(); + assume(var95 >= -16); + assume(var95 <= 16); + assume(var95 != 0); + int var96; + var96 = __VERIFIER_nondet_int(); + assume(var96 >= -16); + assume(var96 <= 16); + assume(var96 != 0); + int var97; + var97 = __VERIFIER_nondet_int(); + assume(var97 >= -16); + assume(var97 <= 16); + assume(var97 != 0); + int var98; + var98 = __VERIFIER_nondet_int(); + assume(var98 >= -16); + assume(var98 <= 16); + assume(var98 != 0); + int var99; + var99 = __VERIFIER_nondet_int(); + assume(var99 >= -16); + assume(var99 <= 16); + assume(var99 != 0); + int var100; + var100 = __VERIFIER_nondet_int(); + assume(var100 >= -16); + assume(var100 <= 16); + assume(var100 != 0); + int var101; + var101 = __VERIFIER_nondet_int(); + assume(var101 >= -16); + assume(var101 <= 16); + assume(var101 != 0); + int var102; + var102 = __VERIFIER_nondet_int(); + assume(var102 >= -16); + assume(var102 <= 16); + assume(var102 != 0); + int var103; + var103 = __VERIFIER_nondet_int(); + assume(var103 >= -16); + assume(var103 <= 16); + assume(var103 != 0); + int var104; + var104 = __VERIFIER_nondet_int(); + assume(var104 >= -16); + assume(var104 <= 16); + assume(var104 != 0); + int var105; + var105 = __VERIFIER_nondet_int(); + assume(var105 >= -16); + assume(var105 <= 16); + assume(var105 != 0); + int var106; + var106 = __VERIFIER_nondet_int(); + assume(var106 >= -16); + assume(var106 <= 16); + assume(var106 != 0); + int var107; + var107 = __VERIFIER_nondet_int(); + assume(var107 >= -16); + assume(var107 <= 16); + assume(var107 != 0); + int var108; + var108 = __VERIFIER_nondet_int(); + assume(var108 >= -16); + assume(var108 <= 16); + assume(var108 != 0); + int var109; + var109 = __VERIFIER_nondet_int(); + assume(var109 >= -16); + assume(var109 <= 16); + assume(var109 != 0); + int var110; + var110 = __VERIFIER_nondet_int(); + assume(var110 >= -16); + assume(var110 <= 16); + assume(var110 != 0); + int var111; + var111 = __VERIFIER_nondet_int(); + assume(var111 >= -16); + assume(var111 <= 16); + assume(var111 != 0); + int var112; + var112 = __VERIFIER_nondet_int(); + assume(var112 >= -16); + assume(var112 <= 16); + assume(var112 != 0); + int var113; + var113 = __VERIFIER_nondet_int(); + assume(var113 >= -16); + assume(var113 <= 16); + assume(var113 != 0); + int var114; + var114 = __VERIFIER_nondet_int(); + assume(var114 >= -16); + assume(var114 <= 16); + assume(var114 != 0); + int var115; + var115 = __VERIFIER_nondet_int(); + assume(var115 >= -16); + assume(var115 <= 16); + assume(var115 != 0); + int var116; + var116 = __VERIFIER_nondet_int(); + assume(var116 >= -16); + assume(var116 <= 16); + assume(var116 != 0); + int var117; + var117 = __VERIFIER_nondet_int(); + assume(var117 >= -16); + assume(var117 <= 16); + assume(var117 != 0); + int var118; + var118 = __VERIFIER_nondet_int(); + assume(var118 >= -16); + assume(var118 <= 16); + assume(var118 != 0); + int var119; + var119 = __VERIFIER_nondet_int(); + assume(var119 >= -16); + assume(var119 <= 16); + assume(var119 != 0); + int var120; + var120 = __VERIFIER_nondet_int(); + assume(var120 >= -16); + assume(var120 <= 16); + assume(var120 != 0); + int var121; + var121 = __VERIFIER_nondet_int(); + assume(var121 >= -16); + assume(var121 <= 16); + assume(var121 != 0); + int var122; + var122 = __VERIFIER_nondet_int(); + assume(var122 >= -16); + assume(var122 <= 16); + assume(var122 != 0); + int var123; + var123 = __VERIFIER_nondet_int(); + assume(var123 >= -16); + assume(var123 <= 16); + assume(var123 != 0); + int var124; + var124 = __VERIFIER_nondet_int(); + assume(var124 >= -16); + assume(var124 <= 16); + assume(var124 != 0); + int var125; + var125 = __VERIFIER_nondet_int(); + assume(var125 >= -16); + assume(var125 <= 16); + assume(var125 != 0); + int var126; + var126 = __VERIFIER_nondet_int(); + assume(var126 >= -16); + assume(var126 <= 16); + assume(var126 != 0); + int var127; + var127 = __VERIFIER_nondet_int(); + assume(var127 >= -16); + assume(var127 <= 16); + assume(var127 != 0); + int var128; + var128 = __VERIFIER_nondet_int(); + assume(var128 >= -16); + assume(var128 <= 16); + assume(var128 != 0); + int var129; + var129 = __VERIFIER_nondet_int(); + assume(var129 >= -16); + assume(var129 <= 16); + assume(var129 != 0); + int var130; + var130 = __VERIFIER_nondet_int(); + assume(var130 >= -16); + assume(var130 <= 16); + assume(var130 != 0); + int var131; + var131 = __VERIFIER_nondet_int(); + assume(var131 >= -16); + assume(var131 <= 16); + assume(var131 != 0); + int var132; + var132 = __VERIFIER_nondet_int(); + assume(var132 >= -16); + assume(var132 <= 16); + assume(var132 != 0); + int var133; + var133 = __VERIFIER_nondet_int(); + assume(var133 >= -16); + assume(var133 <= 16); + assume(var133 != 0); + int var134; + var134 = __VERIFIER_nondet_int(); + assume(var134 >= -16); + assume(var134 <= 16); + assume(var134 != 0); + int var135; + var135 = __VERIFIER_nondet_int(); + assume(var135 >= -16); + assume(var135 <= 16); + assume(var135 != 0); + int var136; + var136 = __VERIFIER_nondet_int(); + assume(var136 >= -16); + assume(var136 <= 16); + assume(var136 != 0); + int var137; + var137 = __VERIFIER_nondet_int(); + assume(var137 >= -16); + assume(var137 <= 16); + assume(var137 != 0); + int var138; + var138 = __VERIFIER_nondet_int(); + assume(var138 >= -16); + assume(var138 <= 16); + assume(var138 != 0); + int var139; + var139 = __VERIFIER_nondet_int(); + assume(var139 >= -16); + assume(var139 <= 16); + assume(var139 != 0); + int var140; + var140 = __VERIFIER_nondet_int(); + assume(var140 >= -16); + assume(var140 <= 16); + assume(var140 != 0); + int var141; + var141 = __VERIFIER_nondet_int(); + assume(var141 >= -16); + assume(var141 <= 16); + assume(var141 != 0); + int var142; + var142 = __VERIFIER_nondet_int(); + assume(var142 >= -16); + assume(var142 <= 16); + assume(var142 != 0); + int var143; + var143 = __VERIFIER_nondet_int(); + assume(var143 >= -16); + assume(var143 <= 16); + assume(var143 != 0); + int var144; + var144 = __VERIFIER_nondet_int(); + assume(var144 >= -16); + assume(var144 <= 16); + assume(var144 != 0); + int var145; + var145 = __VERIFIER_nondet_int(); + assume(var145 >= -16); + assume(var145 <= 16); + assume(var145 != 0); + int var146; + var146 = __VERIFIER_nondet_int(); + assume(var146 >= -16); + assume(var146 <= 16); + assume(var146 != 0); + int var147; + var147 = __VERIFIER_nondet_int(); + assume(var147 >= -16); + assume(var147 <= 16); + assume(var147 != 0); + int var148; + var148 = __VERIFIER_nondet_int(); + assume(var148 >= -16); + assume(var148 <= 16); + assume(var148 != 0); + int var149; + var149 = __VERIFIER_nondet_int(); + assume(var149 >= -16); + assume(var149 <= 16); + assume(var149 != 0); + int myvar0 = 1; + assume(var0 != var1); + assume(var0 != var2); + assume(var0 != var3); + assume(var0 != var4); + assume(var0 != var5); + assume(var0 != var6); + assume(var0 != var7); + assume(var0 != var8); + assume(var0 != var9); + assume(var0 != var10); + assume(var0 != var11); + assume(var0 != var12); + assume(var0 != var13); + assume(var0 != var14); + assume(var0 != var15); + assume(var0 != var16); + assume(var1 != var2); + assume(var1 != var3); + assume(var1 != var4); + assume(var1 != var5); + assume(var1 != var6); + assume(var1 != var7); + assume(var1 != var8); + assume(var1 != var9); + assume(var1 != var10); + assume(var1 != var11); + assume(var1 != var12); + assume(var1 != var13); + assume(var1 != var14); + assume(var1 != var15); + assume(var1 != var16); + assume(var2 != var3); + assume(var2 != var4); + assume(var2 != var5); + assume(var2 != var6); + assume(var2 != var7); + assume(var2 != var8); + assume(var2 != var9); + assume(var2 != var10); + assume(var2 != var11); + assume(var2 != var12); + assume(var2 != var13); + assume(var2 != var14); + assume(var2 != var15); + assume(var2 != var16); + assume(var3 != var4); + assume(var3 != var5); + assume(var3 != var6); + assume(var3 != var7); + assume(var3 != var8); + assume(var3 != var9); + assume(var3 != var10); + assume(var3 != var11); + assume(var3 != var12); + assume(var3 != var13); + assume(var3 != var14); + assume(var3 != var15); + assume(var3 != var16); + assume(var4 != var5); + assume(var4 != var6); + assume(var4 != var7); + assume(var4 != var8); + assume(var4 != var9); + assume(var4 != var10); + assume(var4 != var11); + assume(var4 != var12); + assume(var4 != var13); + assume(var4 != var14); + assume(var4 != var15); + assume(var4 != var16); + assume(var5 != var6); + assume(var5 != var7); + assume(var5 != var8); + assume(var5 != var9); + assume(var5 != var10); + assume(var5 != var11); + assume(var5 != var12); + assume(var5 != var13); + assume(var5 != var14); + assume(var5 != var15); + assume(var5 != var16); + assume(var6 != var7); + assume(var6 != var8); + assume(var6 != var9); + assume(var6 != var10); + assume(var6 != var11); + assume(var6 != var12); + assume(var6 != var13); + assume(var6 != var14); + assume(var6 != var15); + assume(var6 != var16); + assume(var7 != var8); + assume(var7 != var9); + assume(var7 != var10); + assume(var7 != var11); + assume(var7 != var12); + assume(var7 != var13); + assume(var7 != var14); + assume(var7 != var15); + assume(var7 != var16); + assume(var8 != var9); + assume(var8 != var10); + assume(var8 != var11); + assume(var8 != var12); + assume(var8 != var13); + assume(var8 != var14); + assume(var8 != var15); + assume(var8 != var16); + assume(var9 != var10); + assume(var9 != var11); + assume(var9 != var12); + assume(var9 != var13); + assume(var9 != var14); + assume(var9 != var15); + assume(var9 != var16); + assume(var10 != var11); + assume(var10 != var12); + assume(var10 != var13); + assume(var10 != var14); + assume(var10 != var15); + assume(var10 != var16); + assume(var11 != var12); + assume(var11 != var13); + assume(var11 != var14); + assume(var11 != var15); + assume(var11 != var16); + assume(var12 != var13); + assume(var12 != var14); + assume(var12 != var15); + assume(var12 != var16); + assume(var13 != var14); + assume(var13 != var15); + assume(var13 != var16); + assume(var14 != var15); + assume(var14 != var16); + assume(var15 != var16); + assume(var17 != var18); + assume(var17 != var19); + assume(var17 != var20); + assume(var17 != var21); + assume(var17 != var22); + assume(var17 != var23); + assume(var17 != var24); + assume(var17 != var25); + assume(var17 != var26); + assume(var17 != var27); + assume(var17 != var28); + assume(var17 != var29); + assume(var17 != var30); + assume(var17 != var31); + assume(var17 != var32); + assume(var18 != var19); + assume(var18 != var20); + assume(var18 != var21); + assume(var18 != var22); + assume(var18 != var23); + assume(var18 != var24); + assume(var18 != var25); + assume(var18 != var26); + assume(var18 != var27); + assume(var18 != var28); + assume(var18 != var29); + assume(var18 != var30); + assume(var18 != var31); + assume(var18 != var32); + assume(var19 != var20); + assume(var19 != var21); + assume(var19 != var22); + assume(var19 != var23); + assume(var19 != var24); + assume(var19 != var25); + assume(var19 != var26); + assume(var19 != var27); + assume(var19 != var28); + assume(var19 != var29); + assume(var19 != var30); + assume(var19 != var31); + assume(var19 != var32); + assume(var20 != var21); + assume(var20 != var22); + assume(var20 != var23); + assume(var20 != var24); + assume(var20 != var25); + assume(var20 != var26); + assume(var20 != var27); + assume(var20 != var28); + assume(var20 != var29); + assume(var20 != var30); + assume(var20 != var31); + assume(var20 != var32); + assume(var21 != var22); + assume(var21 != var23); + assume(var21 != var24); + assume(var21 != var25); + assume(var21 != var26); + assume(var21 != var27); + assume(var21 != var28); + assume(var21 != var29); + assume(var21 != var30); + assume(var21 != var31); + assume(var21 != var32); + assume(var22 != var23); + assume(var22 != var24); + assume(var22 != var25); + assume(var22 != var26); + assume(var22 != var27); + assume(var22 != var28); + assume(var22 != var29); + assume(var22 != var30); + assume(var22 != var31); + assume(var22 != var32); + assume(var23 != var24); + assume(var23 != var25); + assume(var23 != var26); + assume(var23 != var27); + assume(var23 != var28); + assume(var23 != var29); + assume(var23 != var30); + assume(var23 != var31); + assume(var23 != var32); + assume(var24 != var25); + assume(var24 != var26); + assume(var24 != var27); + assume(var24 != var28); + assume(var24 != var29); + assume(var24 != var30); + assume(var24 != var31); + assume(var24 != var32); + assume(var25 != var26); + assume(var25 != var27); + assume(var25 != var28); + assume(var25 != var29); + assume(var25 != var30); + assume(var25 != var31); + assume(var25 != var32); + assume(var26 != var27); + assume(var26 != var28); + assume(var26 != var29); + assume(var26 != var30); + assume(var26 != var31); + assume(var26 != var32); + assume(var27 != var28); + assume(var27 != var29); + assume(var27 != var30); + assume(var27 != var31); + assume(var27 != var32); + assume(var28 != var29); + assume(var28 != var30); + assume(var28 != var31); + assume(var28 != var32); + assume(var29 != var30); + assume(var29 != var31); + assume(var29 != var32); + assume(var30 != var31); + assume(var30 != var32); + assume(var31 != var32); + assume(var33 != var34); + assume(var33 != var35); + assume(var33 != var36); + assume(var33 != var37); + assume(var33 != var38); + assume(var33 != var39); + assume(var33 != var40); + assume(var33 != var41); + assume(var33 != var42); + assume(var33 != var43); + assume(var33 != var44); + assume(var33 != var45); + assume(var33 != var46); + assume(var33 != var47); + assume(var34 != var35); + assume(var34 != var36); + assume(var34 != var37); + assume(var34 != var38); + assume(var34 != var39); + assume(var34 != var40); + assume(var34 != var41); + assume(var34 != var42); + assume(var34 != var43); + assume(var34 != var44); + assume(var34 != var45); + assume(var34 != var46); + assume(var34 != var47); + assume(var35 != var36); + assume(var35 != var37); + assume(var35 != var38); + assume(var35 != var39); + assume(var35 != var40); + assume(var35 != var41); + assume(var35 != var42); + assume(var35 != var43); + assume(var35 != var44); + assume(var35 != var45); + assume(var35 != var46); + assume(var35 != var47); + assume(var36 != var37); + assume(var36 != var38); + assume(var36 != var39); + assume(var36 != var40); + assume(var36 != var41); + assume(var36 != var42); + assume(var36 != var43); + assume(var36 != var44); + assume(var36 != var45); + assume(var36 != var46); + assume(var36 != var47); + assume(var37 != var38); + assume(var37 != var39); + assume(var37 != var40); + assume(var37 != var41); + assume(var37 != var42); + assume(var37 != var43); + assume(var37 != var44); + assume(var37 != var45); + assume(var37 != var46); + assume(var37 != var47); + assume(var38 != var39); + assume(var38 != var40); + assume(var38 != var41); + assume(var38 != var42); + assume(var38 != var43); + assume(var38 != var44); + assume(var38 != var45); + assume(var38 != var46); + assume(var38 != var47); + assume(var39 != var40); + assume(var39 != var41); + assume(var39 != var42); + assume(var39 != var43); + assume(var39 != var44); + assume(var39 != var45); + assume(var39 != var46); + assume(var39 != var47); + assume(var40 != var41); + assume(var40 != var42); + assume(var40 != var43); + assume(var40 != var44); + assume(var40 != var45); + assume(var40 != var46); + assume(var40 != var47); + assume(var41 != var42); + assume(var41 != var43); + assume(var41 != var44); + assume(var41 != var45); + assume(var41 != var46); + assume(var41 != var47); + assume(var42 != var43); + assume(var42 != var44); + assume(var42 != var45); + assume(var42 != var46); + assume(var42 != var47); + assume(var43 != var44); + assume(var43 != var45); + assume(var43 != var46); + assume(var43 != var47); + assume(var44 != var45); + assume(var44 != var46); + assume(var44 != var47); + assume(var45 != var46); + assume(var45 != var47); + assume(var46 != var47); + assume(var48 != var49); + assume(var48 != var50); + assume(var48 != var51); + assume(var48 != var52); + assume(var48 != var53); + assume(var48 != var54); + assume(var48 != var55); + assume(var48 != var56); + assume(var48 != var57); + assume(var48 != var58); + assume(var48 != var59); + assume(var48 != var60); + assume(var48 != var61); + assume(var49 != var50); + assume(var49 != var51); + assume(var49 != var52); + assume(var49 != var53); + assume(var49 != var54); + assume(var49 != var55); + assume(var49 != var56); + assume(var49 != var57); + assume(var49 != var58); + assume(var49 != var59); + assume(var49 != var60); + assume(var49 != var61); + assume(var50 != var51); + assume(var50 != var52); + assume(var50 != var53); + assume(var50 != var54); + assume(var50 != var55); + assume(var50 != var56); + assume(var50 != var57); + assume(var50 != var58); + assume(var50 != var59); + assume(var50 != var60); + assume(var50 != var61); + assume(var51 != var52); + assume(var51 != var53); + assume(var51 != var54); + assume(var51 != var55); + assume(var51 != var56); + assume(var51 != var57); + assume(var51 != var58); + assume(var51 != var59); + assume(var51 != var60); + assume(var51 != var61); + assume(var52 != var53); + assume(var52 != var54); + assume(var52 != var55); + assume(var52 != var56); + assume(var52 != var57); + assume(var52 != var58); + assume(var52 != var59); + assume(var52 != var60); + assume(var52 != var61); + assume(var53 != var54); + assume(var53 != var55); + assume(var53 != var56); + assume(var53 != var57); + assume(var53 != var58); + assume(var53 != var59); + assume(var53 != var60); + assume(var53 != var61); + assume(var54 != var55); + assume(var54 != var56); + assume(var54 != var57); + assume(var54 != var58); + assume(var54 != var59); + assume(var54 != var60); + assume(var54 != var61); + assume(var55 != var56); + assume(var55 != var57); + assume(var55 != var58); + assume(var55 != var59); + assume(var55 != var60); + assume(var55 != var61); + assume(var56 != var57); + assume(var56 != var58); + assume(var56 != var59); + assume(var56 != var60); + assume(var56 != var61); + assume(var57 != var58); + assume(var57 != var59); + assume(var57 != var60); + assume(var57 != var61); + assume(var58 != var59); + assume(var58 != var60); + assume(var58 != var61); + assume(var59 != var60); + assume(var59 != var61); + assume(var60 != var61); + assume(var62 != var63); + assume(var62 != var64); + assume(var62 != var65); + assume(var62 != var66); + assume(var62 != var67); + assume(var62 != var68); + assume(var62 != var69); + assume(var62 != var70); + assume(var62 != var71); + assume(var62 != var72); + assume(var62 != var73); + assume(var62 != var74); + assume(var63 != var64); + assume(var63 != var65); + assume(var63 != var66); + assume(var63 != var67); + assume(var63 != var68); + assume(var63 != var69); + assume(var63 != var70); + assume(var63 != var71); + assume(var63 != var72); + assume(var63 != var73); + assume(var63 != var74); + assume(var64 != var65); + assume(var64 != var66); + assume(var64 != var67); + assume(var64 != var68); + assume(var64 != var69); + assume(var64 != var70); + assume(var64 != var71); + assume(var64 != var72); + assume(var64 != var73); + assume(var64 != var74); + assume(var65 != var66); + assume(var65 != var67); + assume(var65 != var68); + assume(var65 != var69); + assume(var65 != var70); + assume(var65 != var71); + assume(var65 != var72); + assume(var65 != var73); + assume(var65 != var74); + assume(var66 != var67); + assume(var66 != var68); + assume(var66 != var69); + assume(var66 != var70); + assume(var66 != var71); + assume(var66 != var72); + assume(var66 != var73); + assume(var66 != var74); + assume(var67 != var68); + assume(var67 != var69); + assume(var67 != var70); + assume(var67 != var71); + assume(var67 != var72); + assume(var67 != var73); + assume(var67 != var74); + assume(var68 != var69); + assume(var68 != var70); + assume(var68 != var71); + assume(var68 != var72); + assume(var68 != var73); + assume(var68 != var74); + assume(var69 != var70); + assume(var69 != var71); + assume(var69 != var72); + assume(var69 != var73); + assume(var69 != var74); + assume(var70 != var71); + assume(var70 != var72); + assume(var70 != var73); + assume(var70 != var74); + assume(var71 != var72); + assume(var71 != var73); + assume(var71 != var74); + assume(var72 != var73); + assume(var72 != var74); + assume(var73 != var74); + assume(var75 != var76); + assume(var75 != var77); + assume(var75 != var78); + assume(var75 != var79); + assume(var75 != var80); + assume(var75 != var81); + assume(var75 != var82); + assume(var75 != var83); + assume(var75 != var84); + assume(var75 != var85); + assume(var75 != var86); + assume(var76 != var77); + assume(var76 != var78); + assume(var76 != var79); + assume(var76 != var80); + assume(var76 != var81); + assume(var76 != var82); + assume(var76 != var83); + assume(var76 != var84); + assume(var76 != var85); + assume(var76 != var86); + assume(var77 != var78); + assume(var77 != var79); + assume(var77 != var80); + assume(var77 != var81); + assume(var77 != var82); + assume(var77 != var83); + assume(var77 != var84); + assume(var77 != var85); + assume(var77 != var86); + assume(var78 != var79); + assume(var78 != var80); + assume(var78 != var81); + assume(var78 != var82); + assume(var78 != var83); + assume(var78 != var84); + assume(var78 != var85); + assume(var78 != var86); + assume(var79 != var80); + assume(var79 != var81); + assume(var79 != var82); + assume(var79 != var83); + assume(var79 != var84); + assume(var79 != var85); + assume(var79 != var86); + assume(var80 != var81); + assume(var80 != var82); + assume(var80 != var83); + assume(var80 != var84); + assume(var80 != var85); + assume(var80 != var86); + assume(var81 != var82); + assume(var81 != var83); + assume(var81 != var84); + assume(var81 != var85); + assume(var81 != var86); + assume(var82 != var83); + assume(var82 != var84); + assume(var82 != var85); + assume(var82 != var86); + assume(var83 != var84); + assume(var83 != var85); + assume(var83 != var86); + assume(var84 != var85); + assume(var84 != var86); + assume(var85 != var86); + assume(var87 != var88); + assume(var87 != var89); + assume(var87 != var90); + assume(var87 != var91); + assume(var87 != var92); + assume(var87 != var93); + assume(var87 != var94); + assume(var87 != var95); + assume(var87 != var96); + assume(var87 != var97); + assume(var88 != var89); + assume(var88 != var90); + assume(var88 != var91); + assume(var88 != var92); + assume(var88 != var93); + assume(var88 != var94); + assume(var88 != var95); + assume(var88 != var96); + assume(var88 != var97); + assume(var89 != var90); + assume(var89 != var91); + assume(var89 != var92); + assume(var89 != var93); + assume(var89 != var94); + assume(var89 != var95); + assume(var89 != var96); + assume(var89 != var97); + assume(var90 != var91); + assume(var90 != var92); + assume(var90 != var93); + assume(var90 != var94); + assume(var90 != var95); + assume(var90 != var96); + assume(var90 != var97); + assume(var91 != var92); + assume(var91 != var93); + assume(var91 != var94); + assume(var91 != var95); + assume(var91 != var96); + assume(var91 != var97); + assume(var92 != var93); + assume(var92 != var94); + assume(var92 != var95); + assume(var92 != var96); + assume(var92 != var97); + assume(var93 != var94); + assume(var93 != var95); + assume(var93 != var96); + assume(var93 != var97); + assume(var94 != var95); + assume(var94 != var96); + assume(var94 != var97); + assume(var95 != var96); + assume(var95 != var97); + assume(var96 != var97); + assume(var98 != var99); + assume(var98 != var100); + assume(var98 != var101); + assume(var98 != var102); + assume(var98 != var103); + assume(var98 != var104); + assume(var98 != var105); + assume(var98 != var106); + assume(var98 != var107); + assume(var99 != var100); + assume(var99 != var101); + assume(var99 != var102); + assume(var99 != var103); + assume(var99 != var104); + assume(var99 != var105); + assume(var99 != var106); + assume(var99 != var107); + assume(var100 != var101); + assume(var100 != var102); + assume(var100 != var103); + assume(var100 != var104); + assume(var100 != var105); + assume(var100 != var106); + assume(var100 != var107); + assume(var101 != var102); + assume(var101 != var103); + assume(var101 != var104); + assume(var101 != var105); + assume(var101 != var106); + assume(var101 != var107); + assume(var102 != var103); + assume(var102 != var104); + assume(var102 != var105); + assume(var102 != var106); + assume(var102 != var107); + assume(var103 != var104); + assume(var103 != var105); + assume(var103 != var106); + assume(var103 != var107); + assume(var104 != var105); + assume(var104 != var106); + assume(var104 != var107); + assume(var105 != var106); + assume(var105 != var107); + assume(var106 != var107); + assume(var108 != var109); + assume(var108 != var110); + assume(var108 != var111); + assume(var108 != var112); + assume(var108 != var113); + assume(var108 != var114); + assume(var108 != var115); + assume(var108 != var116); + assume(var109 != var110); + assume(var109 != var111); + assume(var109 != var112); + assume(var109 != var113); + assume(var109 != var114); + assume(var109 != var115); + assume(var109 != var116); + assume(var110 != var111); + assume(var110 != var112); + assume(var110 != var113); + assume(var110 != var114); + assume(var110 != var115); + assume(var110 != var116); + assume(var111 != var112); + assume(var111 != var113); + assume(var111 != var114); + assume(var111 != var115); + assume(var111 != var116); + assume(var112 != var113); + assume(var112 != var114); + assume(var112 != var115); + assume(var112 != var116); + assume(var113 != var114); + assume(var113 != var115); + assume(var113 != var116); + assume(var114 != var115); + assume(var114 != var116); + assume(var115 != var116); + assume(var117 != var118); + assume(var117 != var119); + assume(var117 != var120); + assume(var117 != var121); + assume(var117 != var122); + assume(var117 != var123); + assume(var117 != var124); + assume(var118 != var119); + assume(var118 != var120); + assume(var118 != var121); + assume(var118 != var122); + assume(var118 != var123); + assume(var118 != var124); + assume(var119 != var120); + assume(var119 != var121); + assume(var119 != var122); + assume(var119 != var123); + assume(var119 != var124); + assume(var120 != var121); + assume(var120 != var122); + assume(var120 != var123); + assume(var120 != var124); + assume(var121 != var122); + assume(var121 != var123); + assume(var121 != var124); + assume(var122 != var123); + assume(var122 != var124); + assume(var123 != var124); + assume(var125 != var126); + assume(var125 != var127); + assume(var125 != var128); + assume(var125 != var129); + assume(var125 != var130); + assume(var125 != var131); + assume(var126 != var127); + assume(var126 != var128); + assume(var126 != var129); + assume(var126 != var130); + assume(var126 != var131); + assume(var127 != var128); + assume(var127 != var129); + assume(var127 != var130); + assume(var127 != var131); + assume(var128 != var129); + assume(var128 != var130); + assume(var128 != var131); + assume(var129 != var130); + assume(var129 != var131); + assume(var130 != var131); + assume(var132 != var133); + assume(var132 != var134); + assume(var132 != var135); + assume(var132 != var136); + assume(var132 != var137); + assume(var133 != var134); + assume(var133 != var135); + assume(var133 != var136); + assume(var133 != var137); + assume(var134 != var135); + assume(var134 != var136); + assume(var134 != var137); + assume(var135 != var136); + assume(var135 != var137); + assume(var136 != var137); + assume(var138 != var139); + assume(var138 != var140); + assume(var138 != var141); + assume(var138 != var142); + assume(var139 != var140); + assume(var139 != var141); + assume(var139 != var142); + assume(var140 != var141); + assume(var140 != var142); + assume(var141 != var142); + assume(var143 != var144); + assume(var143 != var145); + assume(var143 != var146); + assume(var144 != var145); + assume(var144 != var146); + assume(var145 != var146); + assume(var147 != var148); + assume(var147 != var149); + assume(var148 != var149); + assume(var0 - var1 == var17); + assume(var1 - var2 == var18); + assume(var2 - var3 == var19); + assume(var3 - var4 == var20); + assume(var4 - var5 == var21); + assume(var5 - var6 == var22); + assume(var6 - var7 == var23); + assume(var7 - var8 == var24); + assume(var8 - var9 == var25); + assume(var9 - var10 == var26); + assume(var10 - var11 == var27); + assume(var11 - var12 == var28); + assume(var12 - var13 == var29); + assume(var13 - var14 == var30); + assume(var14 - var15 == var31); + assume(var15 - var16 == var32); + assume(var0 - var2 == var33); + assume(var1 - var3 == var34); + assume(var2 - var4 == var35); + assume(var3 - var5 == var36); + assume(var4 - var6 == var37); + assume(var5 - var7 == var38); + assume(var6 - var8 == var39); + assume(var7 - var9 == var40); + assume(var8 - var10 == var41); + assume(var9 - var11 == var42); + assume(var10 - var12 == var43); + assume(var11 - var13 == var44); + assume(var12 - var14 == var45); + assume(var13 - var15 == var46); + assume(var14 - var16 == var47); + assume(var0 - var3 == var48); + assume(var1 - var4 == var49); + assume(var2 - var5 == var50); + assume(var3 - var6 == var51); + assume(var4 - var7 == var52); + assume(var5 - var8 == var53); + assume(var6 - var9 == var54); + assume(var7 - var10 == var55); + assume(var8 - var11 == var56); + assume(var9 - var12 == var57); + assume(var10 - var13 == var58); + assume(var11 - var14 == var59); + assume(var12 - var15 == var60); + assume(var13 - var16 == var61); + assume(var0 - var4 == var62); + assume(var1 - var5 == var63); + assume(var2 - var6 == var64); + assume(var3 - var7 == var65); + assume(var4 - var8 == var66); + assume(var5 - var9 == var67); + assume(var6 - var10 == var68); + assume(var7 - var11 == var69); + assume(var8 - var12 == var70); + assume(var9 - var13 == var71); + assume(var10 - var14 == var72); + assume(var11 - var15 == var73); + assume(var12 - var16 == var74); + assume(var0 - var5 == var75); + assume(var1 - var6 == var76); + assume(var2 - var7 == var77); + assume(var3 - var8 == var78); + assume(var4 - var9 == var79); + assume(var5 - var10 == var80); + assume(var6 - var11 == var81); + assume(var7 - var12 == var82); + assume(var8 - var13 == var83); + assume(var9 - var14 == var84); + assume(var10 - var15 == var85); + assume(var11 - var16 == var86); + assume(var0 - var6 == var87); + assume(var1 - var7 == var88); + assume(var2 - var8 == var89); + assume(var3 - var9 == var90); + assume(var4 - var10 == var91); + assume(var5 - var11 == var92); + assume(var6 - var12 == var93); + assume(var7 - var13 == var94); + assume(var8 - var14 == var95); + assume(var9 - var15 == var96); + assume(var10 - var16 == var97); + assume(var0 - var7 == var98); + assume(var1 - var8 == var99); + assume(var2 - var9 == var100); + assume(var3 - var10 == var101); + assume(var4 - var11 == var102); + assume(var5 - var12 == var103); + assume(var6 - var13 == var104); + assume(var7 - var14 == var105); + assume(var8 - var15 == var106); + assume(var9 - var16 == var107); + assume(var0 - var8 == var108); + assume(var1 - var9 == var109); + assume(var2 - var10 == var110); + assume(var3 - var11 == var111); + assume(var4 - var12 == var112); + assume(var5 - var13 == var113); + assume(var6 - var14 == var114); + assume(var7 - var15 == var115); + assume(var8 - var16 == var116); + assume(var0 - var9 == var117); + assume(var1 - var10 == var118); + assume(var2 - var11 == var119); + assume(var3 - var12 == var120); + assume(var4 - var13 == var121); + assume(var5 - var14 == var122); + assume(var6 - var15 == var123); + assume(var7 - var16 == var124); + assume(var0 - var10 == var125); + assume(var1 - var11 == var126); + assume(var2 - var12 == var127); + assume(var3 - var13 == var128); + assume(var4 - var14 == var129); + assume(var5 - var15 == var130); + assume(var6 - var16 == var131); + assume(var0 - var11 == var132); + assume(var1 - var12 == var133); + assume(var2 - var13 == var134); + assume(var3 - var14 == var135); + assume(var4 - var15 == var136); + assume(var5 - var16 == var137); + assume(var0 - var12 == var138); + assume(var1 - var13 == var139); + assume(var2 - var14 == var140); + assume(var3 - var15 == var141); + assume(var4 - var16 == var142); + assume(var0 - var13 == var143); + assume(var1 - var14 == var144); + assume(var2 - var15 == var145); + assume(var3 - var16 == var146); + assume(var0 - var14 == var147); + assume(var1 - var15 == var148); + assume(var2 - var16 == var149); + assume((var0 - var15) != (var1 - var16)); + reach_error(); + return 0; /* 0 x[0]1 x[1]2 x[2]3 x[3]4 x[4]5 x[5]6 x[6]7 x[7]8 x[8]9 x[9]10 + x[10]11 x[11]12 x[12]13 x[13]14 x[14]15 x[15]16 x[16]17 y[0]18 + y[1]19 y[2]20 y[3]21 y[4]22 y[5]23 y[6]24 y[7]25 y[8]26 y[9]27 + y[10]28 y[11]29 y[12]30 y[13]31 y[14]32 y[15]33 y[16]34 y[17]35 + y[18]36 y[19]37 y[20]38 y[21]39 y[22]40 y[23]41 y[24]42 y[25]43 + y[26]44 y[27]45 y[28]46 y[29]47 y[30]48 y[31]49 y[32]50 y[33]51 + y[34]52 y[35]53 y[36]54 y[37]55 y[38]56 y[39]57 y[40]58 y[41]59 + y[42]60 y[43]61 y[44]62 y[45]63 y[46]64 y[47]65 y[48]66 y[49]67 + y[50]68 y[51]69 y[52]70 y[53]71 y[54]72 y[55]73 y[56]74 y[57]75 + y[58]76 y[59]77 y[60]78 y[61]79 y[62]80 y[63]81 y[64]82 y[65]83 + y[66]84 y[67]85 y[68]86 y[69]87 y[70]88 y[71]89 y[72]90 y[73]91 + y[74]92 y[75]93 y[76]94 y[77]95 y[78]96 y[79]97 y[80]98 y[81]99 + y[82]100 y[83]101 y[84]102 y[85]103 y[86]104 y[87]105 y[88]106 + y[89]107 y[90]108 y[91]109 y[92]110 y[93]111 y[94]112 y[95]113 + y[96]114 y[97]115 y[98]116 y[99]117 y[100]118 y[101]119 y[102]120 + y[103]121 y[104]122 y[105]123 y[106]124 y[107]125 y[108]126 + y[109]127 y[110]128 y[111]129 y[112]130 y[113]131 y[114]132 + y[115]133 y[116]134 y[117]135 y[118]136 y[119]137 y[120]138 + y[121]139 y[122]140 y[123]141 y[124]142 y[125]143 y[126]144 + y[127]145 y[128]146 y[129]147 y[130]148 y[131]149 y[132] */ +} \ No newline at end of file From d0e280bccee54d9cbb969e69975ad62897fc7384 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Mon, 16 Oct 2023 12:49:15 +0400 Subject: [PATCH 042/103] [chore] Update build.sh --- build.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.sh b/build.sh index 7d575dad08..cc41037dcb 100755 --- a/build.sh +++ b/build.sh @@ -29,9 +29,9 @@ SQLITE_VERSION="3400100" ## LLVM Required options LLVM_VERSION=14 ENABLE_OPTIMIZED=1 -ENABLE_DEBUG=1 +ENABLE_DEBUG=0 DISABLE_ASSERTIONS=1 -REQUIRES_RTTI=1 +REQUIRES_RTTI=0 ## Solvers Required options # SOLVERS=STP From cdc1f7ff8c2ff13d13177eace57f502130f09c07 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Tue, 17 Oct 2023 00:08:54 +0400 Subject: [PATCH 043/103] [feat] Prefer a smaller integer vaule in a model --- include/klee-test-comp.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/klee-test-comp.c b/include/klee-test-comp.c index bad3b783d0..90774aa2b2 100644 --- a/include/klee-test-comp.c +++ b/include/klee-test-comp.c @@ -24,12 +24,14 @@ void __assert_fail(const char *assertion, const char *file, unsigned int line, int __VERIFIER_nondet_int(void) { int x; klee_make_symbolic(&x, sizeof(x), "int"); + klee_prefer_cex(&x, x < 1024); return x; } unsigned int __VERIFIER_nondet_uint(void) { unsigned int x; klee_make_symbolic(&x, sizeof(x), "unsigned int"); + klee_prefer_cex(&x, x < 1024); return x; } From bfaabefa90ab5ed078efb7381a5d9927c307073b Mon Sep 17 00:00:00 2001 From: Yurii Kostyukov Date: Fri, 20 Oct 2023 14:09:50 +0300 Subject: [PATCH 044/103] [chore] Optimized IterativeDeepeningSearcher --- lib/Core/Searcher.cpp | 99 ++++++++++++++------------------ lib/Core/Searcher.h | 58 ++++++++----------- lib/Core/TargetManager.h | 118 ++++++++++++++++++++++++++++++++++++++- 3 files changed, 178 insertions(+), 97 deletions(-) diff --git a/lib/Core/Searcher.cpp b/lib/Core/Searcher.cpp index d9762e752d..ad73527320 100644 --- a/lib/Core/Searcher.cpp +++ b/lib/Core/Searcher.cpp @@ -47,8 +47,8 @@ using namespace llvm; ExecutionState &DFSSearcher::selectState() { return *states.back(); } void DFSSearcher::update(ExecutionState *current, - const std::vector &addedStates, - const std::vector &removedStates) { + const StateIterable &addedStates, + const StateIterable &removedStates) { // insert states states.insert(states.end(), addedStates.begin(), addedStates.end()); @@ -73,8 +73,8 @@ void DFSSearcher::printName(llvm::raw_ostream &os) { os << "DFSSearcher\n"; } ExecutionState &BFSSearcher::selectState() { return *states.front(); } void BFSSearcher::update(ExecutionState *current, - const std::vector &addedStates, - const std::vector &removedStates) { + const StateIterable &addedStates, + const StateIterable &removedStates) { // update current state // Assumption: If new states were added KLEE forked, therefore states evolved. // constraints were added to the current state, it evolved. @@ -114,9 +114,9 @@ ExecutionState &RandomSearcher::selectState() { return *states[theRNG.getInt32() % states.size()]; } -void RandomSearcher::update( - ExecutionState *current, const std::vector &addedStates, - const std::vector &removedStates) { +void RandomSearcher::update(ExecutionState *current, + const StateIterable &addedStates, + const StateIterable &removedStates) { // insert states states.insert(states.end(), addedStates.begin(), addedStates.end()); @@ -167,9 +167,9 @@ TargetedSearcher::TargetedSearcher(ref target, ExecutionState &TargetedSearcher::selectState() { return *states->choose(0); } -void TargetedSearcher::update( - ExecutionState *current, const std::vector &addedStates, - const std::vector &removedStates) { +void TargetedSearcher::update(ExecutionState *current, + const StateIterable &addedStates, + const StateIterable &removedStates) { // update current if (current && std::find(removedStates.begin(), removedStates.end(), @@ -224,9 +224,9 @@ ExecutionState &GuidedSearcher::selectState() { return *state; } -void GuidedSearcher::update( - ExecutionState *current, const std::vector &addedStates, - const std::vector &removedStates) { +void GuidedSearcher::update(ExecutionState *current, + const StateIterable &addedStates, + const StateIterable &removedStates) { if (current) { ref history = current->history(); @@ -421,9 +421,9 @@ double WeightedRandomSearcher::getWeight(ExecutionState *es) { } } -void WeightedRandomSearcher::update( - ExecutionState *current, const std::vector &addedStates, - const std::vector &removedStates) { +void WeightedRandomSearcher::update(ExecutionState *current, + const StateIterable &addedStates, + const StateIterable &removedStates) { // update current if (current && updateWeights && @@ -514,11 +514,11 @@ ExecutionState &RandomPathSearcher::selectState() { return *n->state; } -void RandomPathSearcher::update( - ExecutionState *current, const std::vector &addedStates, - const std::vector &removedStates) { +void RandomPathSearcher::update(ExecutionState *current, + const StateIterable &addedStates, + const StateIterable &removedStates) { // insert states - for (auto &es : addedStates) { + for (auto es : addedStates) { PTreeNode *pnode = es->ptreeNode, *parent = pnode->parent; PTreeNodePtr &root = processForest.getPTrees().at(pnode->getTreeID())->root; PTreeNodePtr *childPtr; @@ -618,9 +618,9 @@ ExecutionState &BatchingSearcher::selectState() { return *lastState; } -void BatchingSearcher::update( - ExecutionState *current, const std::vector &addedStates, - const std::vector &removedStates) { +void BatchingSearcher::update(ExecutionState *current, + const StateIterable &addedStates, + const StateIterable &removedStates) { // drop memoized state if it is marked for deletion if (std::find(removedStates.begin(), removedStates.end(), lastState) != removedStates.end()) @@ -697,46 +697,30 @@ ExecutionState &IterativeDeepeningSearcher::selectState() { return res; } -void IterativeDeepeningSearcher::filter(const StatesVector &states, - StatesVector &result) const { - StatesVector states1(states); - std::sort(states1.begin(), states1.end()); - std::set_difference(states1.begin(), states1.end(), pausedStates.begin(), - pausedStates.end(), std::back_inserter(result)); -} - void IterativeDeepeningSearcher::update( const TargetHistoryTargetPairToStatesMap &added, const TargetHistoryTargetPairToStatesMap &removed) { if (!tms) return; - TargetHistoryTargetPairToStatesMap removedRefined(removed.size()); - for (const auto &pair : removed) { - StatesVector refined; - IterativeDeepeningSearcher::filter(pair.second, refined); - removedRefined.emplace(pair.first, std::move(refined)); - } - tms->update(added, removedRefined); + added.setWithout(&pausedStates); + removed.setWithout(&pausedStates); + tms->update(added, removed); + added.clearWithout(); + removed.clearWithout(); } void IterativeDeepeningSearcher::update(ExecutionState *current, - const StatesVector &addedStates, - const StatesVector &removedStates) { - - // update underlying searcher (filter paused states unknown to underlying - // searcher) - if (!removedStates.empty()) { - StatesVector alt; - IterativeDeepeningSearcher::filter(removedStates, alt); - baseSearcher->update(current, addedStates, alt); - } else { - baseSearcher->update(current, addedStates, removedStates); - } + const StateIterable &added, + const StateIterable &removed) { + removed.setWithout(&pausedStates); + baseSearcher->update(current, added, removed); + removed.clearWithout(); + + for (auto state : removed) + pausedStates.erase(state); - // update current: pause if time exceeded if (current && - std::find(removedStates.begin(), removedStates.end(), current) == - removedStates.end() && + std::find(removed.begin(), removed.end(), current) == removed.end() && metric->exceeds(*current)) { pausedStates.insert(current); baseSearcher->update(nullptr, {}, {current}); @@ -745,8 +729,7 @@ void IterativeDeepeningSearcher::update(ExecutionState *current, // no states left in underlying searcher: fill with paused states if (baseSearcher->empty()) { metric->increaseLimit(); - StatesVector ps(pausedStates.begin(), pausedStates.end()); - baseSearcher->update(nullptr, ps, {}); + baseSearcher->update(nullptr, pausedStates, {}); pausedStates.clear(); } } @@ -775,9 +758,9 @@ ExecutionState &InterleavedSearcher::selectState() { return s->selectState(); } -void InterleavedSearcher::update( - ExecutionState *current, const std::vector &addedStates, - const std::vector &removedStates) { +void InterleavedSearcher::update(ExecutionState *current, + const StateIterable &addedStates, + const StateIterable &removedStates) { // update underlying searchers for (auto &searcher : searchers) diff --git a/lib/Core/Searcher.h b/lib/Core/Searcher.h index 957ca3d18f..8b8224f85c 100644 --- a/lib/Core/Searcher.h +++ b/lib/Core/Searcher.h @@ -63,9 +63,8 @@ class Searcher { /// \param current The currently selected state for exploration. /// \param addedStates The newly branched states with `current` as common /// ancestor. \param removedStates The states that will be terminated. - virtual void update(ExecutionState *current, - const std::vector &addedStates, - const std::vector &removedStates) = 0; + virtual void update(ExecutionState *current, const StateIterable &addedStates, + const StateIterable &removedStates) = 0; /// \return True if no state left for exploration, False otherwise virtual bool empty() = 0; @@ -96,9 +95,8 @@ class DFSSearcher final : public Searcher { public: ExecutionState &selectState() override; - void update(ExecutionState *current, - const std::vector &addedStates, - const std::vector &removedStates) override; + void update(ExecutionState *current, const StateIterable &addedStates, + const StateIterable &removedStates) override; bool empty() override; void printName(llvm::raw_ostream &os) override; }; @@ -112,9 +110,8 @@ class BFSSearcher final : public Searcher { public: ExecutionState &selectState() override; - void update(ExecutionState *current, - const std::vector &addedStates, - const std::vector &removedStates) override; + void update(ExecutionState *current, const StateIterable &addedStates, + const StateIterable &removedStates) override; bool empty() override; void printName(llvm::raw_ostream &os) override; }; @@ -127,9 +124,8 @@ class RandomSearcher final : public Searcher { public: explicit RandomSearcher(RNG &rng); ExecutionState &selectState() override; - void update(ExecutionState *current, - const std::vector &addedStates, - const std::vector &removedStates) override; + void update(ExecutionState *current, const StateIterable &addedStates, + const StateIterable &removedStates) override; bool empty() override; void printName(llvm::raw_ostream &os) override; }; @@ -148,9 +144,8 @@ class TargetedSearcher final : public Searcher { ~TargetedSearcher() override; ExecutionState &selectState() override; - void update(ExecutionState *current, - const std::vector &addedStates, - const std::vector &removedStates) override; + void update(ExecutionState *current, const StateIterable &addedStates, + const StateIterable &removedStates) override; bool empty() override; void printName(llvm::raw_ostream &os) override; }; @@ -197,9 +192,8 @@ class GuidedSearcher final : public Searcher, public TargetManagerSubscriber { theRNG(rng) {} ~GuidedSearcher() override = default; ExecutionState &selectState() override; - void update(ExecutionState *current, - const std::vector &addedStates, - const std::vector &removedStates) override; + void update(ExecutionState *current, const StateIterable &addedStates, + const StateIterable &removedStates) override; void update(const TargetHistoryTargetPairToStatesMap &added, const TargetHistoryTargetPairToStatesMap &removed) override; void updateTargets(ExecutionState *current); @@ -238,9 +232,8 @@ class WeightedRandomSearcher final : public Searcher { ~WeightedRandomSearcher() override = default; ExecutionState &selectState() override; - void update(ExecutionState *current, - const std::vector &addedStates, - const std::vector &removedStates) override; + void update(ExecutionState *current, const StateIterable &addedStates, + const StateIterable &removedStates) override; bool empty() override; void printName(llvm::raw_ostream &os) override; }; @@ -275,9 +268,8 @@ class RandomPathSearcher final : public Searcher { ~RandomPathSearcher() override = default; ExecutionState &selectState() override; - void update(ExecutionState *current, - const std::vector &addedStates, - const std::vector &removedStates) override; + void update(ExecutionState *current, const StateIterable &addedStates, + const StateIterable &removedStates) override; bool empty() override; void printName(llvm::raw_ostream &os) override; }; @@ -309,9 +301,8 @@ class BatchingSearcher final : public Searcher { ~BatchingSearcher() override = default; ExecutionState &selectState() override; - void update(ExecutionState *current, - const std::vector &addedStates, - const std::vector &removedStates) override; + void update(ExecutionState *current, const StateIterable &addedStates, + const StateIterable &removedStates) override; bool empty() override; void printName(llvm::raw_ostream &os) override; }; @@ -337,9 +328,6 @@ class IterativeDeepeningSearcher final : public Searcher, std::unique_ptr metric; std::set pausedStates; - void filter(const std::vector &states, - std::vector &result) const; - public: /// \param baseSearcher The underlying searcher (takes ownership). explicit IterativeDeepeningSearcher(Searcher *baseSearcher, @@ -348,9 +336,8 @@ class IterativeDeepeningSearcher final : public Searcher, ~IterativeDeepeningSearcher() override = default; ExecutionState &selectState() override; - void update(ExecutionState *current, - const std::vector &addedStates, - const std::vector &removedStates) override; + void update(ExecutionState *current, const StateIterable &addedStates, + const StateIterable &removedStates) override; void update(const TargetHistoryTargetPairToStatesMap &added, const TargetHistoryTargetPairToStatesMap &removed) override; bool empty() override; @@ -370,9 +357,8 @@ class InterleavedSearcher final : public Searcher { ~InterleavedSearcher() override = default; ExecutionState &selectState() override; - void update(ExecutionState *current, - const std::vector &addedStates, - const std::vector &removedStates) override; + void update(ExecutionState *current, const StateIterable &addedStates, + const StateIterable &removedStates) override; bool empty() override; void printName(llvm::raw_ostream &os) override; }; diff --git a/lib/Core/TargetManager.h b/lib/Core/TargetManager.h index 5e65834140..c135f354dd 100644 --- a/lib/Core/TargetManager.h +++ b/lib/Core/TargetManager.h @@ -28,9 +28,121 @@ class TargetCalculator; using TargetHistoryTargetPair = std::pair, ref>; using StatesVector = std::vector; -using TargetHistoryTargetPairToStatesMap = - std::unordered_map; +using StateSet = std::set; + +class StateIterable final { +private: + using v = ExecutionState *; + const StatesVector *self; + mutable const StateSet *without = nullptr; + using vec_it = StatesVector::const_iterator; + bool shouldDestruct; + + class it : public std::iterator { + vec_it self; + const vec_it ie; + const StateSet *without = nullptr; + void goUntilRealNode() { + if (!without) + return; + for (; self != ie; self++) { + if (!without->count(*self)) + return; + } + } + + public: + it(vec_it i, vec_it ie, const StateSet *without) + : self(i), ie(ie), without(without) { + goUntilRealNode(); + } + bool operator==(const it &other) const noexcept { + return self == other.self; + }; + bool operator!=(const it &other) const noexcept { + return self != other.self; + }; + it &operator++() noexcept { + if (self != ie) { + self++; + goUntilRealNode(); + } + return *this; + } + v operator*() const noexcept { return *self; } + }; + +public: + StateIterable() : self(new StatesVector()), shouldDestruct(true) {} + StateIterable(v s) : self(new StatesVector({s})), shouldDestruct(true) {} + StateIterable(const StatesVector &v, const StateSet *without) + : self(&v), without(without), shouldDestruct(false) {} + StateIterable(const StatesVector &v) : StateIterable(v, nullptr) {} + StateIterable(const StateSet &s) + : self(new StatesVector(s.begin(), s.end())), shouldDestruct(true) {} + ~StateIterable() { + if (shouldDestruct) + delete self; + } + bool empty() const noexcept { + return without ? begin() == end() : self->empty(); + } + it begin() const noexcept { return it(self->begin(), self->end(), without); } + it end() const noexcept { return it(self->end(), self->end(), without); } + + void setWithout(const StateSet *w) const { without = w; } + void clearWithout() const { without = nullptr; } +}; + +class TargetHistoryTargetPairToStatesMap final { +private: + using k = TargetHistoryTargetPair; + using cv = StateIterable; + using p = std::pair; + using v = StatesVector; + using t = + std::unordered_map; + using map_it = t::iterator; + using map_cit = t::const_iterator; + t self; + mutable const StateSet *without = nullptr; + + class it : public std::iterator { + protected: + map_cit self; + const StateSet *without = nullptr; + + public: + it(map_cit i, const StateSet *without) : self(i), without(without) {} + bool operator==(const it &other) const noexcept { + return self == other.self; + }; + bool operator!=(const it &other) const noexcept { + return self != other.self; + }; + it &operator++() noexcept { + self++; + return *this; + } + p operator*() const noexcept { + return std::make_pair(self->first, StateIterable(self->second, without)); + } + }; + +public: + inline v &operator[](const k &__k) { return self[__k]; } + inline v &operator[](k &&__k) { return self[std::move(__k)]; } + inline v &at(const k &__k) { return self.at(__k); } + inline map_it begin() noexcept { return self.begin(); } + inline map_it end() noexcept { return self.end(); } + + inline const cv at(const k &__k) const { return self.at(__k); } + inline it begin() const noexcept { return it(self.begin(), without); }; + inline it end() const noexcept { return it(self.end(), without); }; + + void setWithout(const StateSet *w) const { without = w; } + void clearWithout() const { without = nullptr; } +}; class TargetManagerSubscriber { public: From febf79db0e7c9d46bd266ebf2a1bf635166de93f Mon Sep 17 00:00:00 2001 From: Yurii Kostyukov Date: Fri, 20 Oct 2023 14:09:26 +0300 Subject: [PATCH 045/103] [chore] Optimized getDistance --- include/klee/Module/CodeGraphInfo.h | 61 ++++----- lib/Core/DistanceCalculator.cpp | 130 +++++++----------- lib/Core/DistanceCalculator.h | 19 +-- lib/Core/TargetedExecutionManager.cpp | 10 +- lib/Module/CodeGraphInfo.cpp | 185 ++++++++++++-------------- lib/Module/KModule.cpp | 8 +- 6 files changed, 174 insertions(+), 239 deletions(-) diff --git a/include/klee/Module/CodeGraphInfo.h b/include/klee/Module/CodeGraphInfo.h index f1576336b1..549964287a 100644 --- a/include/klee/Module/CodeGraphInfo.h +++ b/include/klee/Module/CodeGraphInfo.h @@ -16,31 +16,35 @@ namespace klee { +using Block = llvm::BasicBlock; +using BlockDistanceMap = std::unordered_map; +using FunctionDistanceMap = std::unordered_map; +using SortedBlockDistances = std::vector>; +using SortedFunctionDistances = + std::vector>; + class CodeGraphInfo { - using blockDistanceMap = - std::unordered_map>; - using blockDistanceList = - std::unordered_map>>; + using blockToDistanceMap = std::unordered_map; + using blockDistanceList = std::unordered_map; - using functionDistanceMap = - std::unordered_map>; + using functionToDistanceMap = + std::unordered_map; using functionDistanceList = - std::unordered_map>>; + std::unordered_map; using functionBranchesSet = std::unordered_map>>; private: - blockDistanceMap blockDistance; - blockDistanceMap blockBackwardDistance; + blockToDistanceMap blockDistance; + blockToDistanceMap blockBackwardDistance; + std::set blockCycles; blockDistanceList blockSortedDistance; blockDistanceList blockSortedBackwardDistance; - functionDistanceMap functionDistance; - functionDistanceMap functionBackwardDistance; + functionToDistanceMap functionDistance; + functionToDistanceMap functionBackwardDistance; functionDistanceList functionSortedDistance; functionDistanceList functionSortedBackwardDistance; @@ -49,33 +53,24 @@ class CodeGraphInfo { functionBranchesSet functionBlocks; private: - void calculateDistance(KBlock *bb); - void calculateBackwardDistance(KBlock *bb); + void calculateDistance(Block *bb); + void calculateBackwardDistance(Block *bb); - void calculateDistance(KFunction *kf); - void calculateBackwardDistance(KFunction *kf); + void calculateDistance(KFunction *f); + void calculateBackwardDistance(KFunction *f); void calculateFunctionBranches(KFunction *kf); void calculateFunctionConditionalBranches(KFunction *kf); void calculateFunctionBlocks(KFunction *kf); public: - const std::unordered_map &getDistance(KBlock *kb); - const std::unordered_map & - getBackwardDistance(KBlock *kb); - const std::vector> & - getSortedDistance(KBlock *kb); - const std::vector> & - getSortedBackwardDistance(KBlock *kb); - - const std::unordered_map & - getDistance(KFunction *kf); - const std::unordered_map & - getBackwardDistance(KFunction *kf); - const std::vector> & - getSortedDistance(KFunction *kf); - const std::vector> & - getSortedBackwardDistance(KFunction *kf); + const BlockDistanceMap &getDistance(Block *b); + const BlockDistanceMap &getDistance(KBlock *kb); + const BlockDistanceMap &getBackwardDistance(KBlock *kb); + bool hasCycle(KBlock *kb); + + const FunctionDistanceMap &getDistance(KFunction *kf); + const FunctionDistanceMap &getBackwardDistance(KFunction *kf); void getNearestPredicateSatisfying(KBlock *from, KBlockPredicate predicate, std::set &result); diff --git a/lib/Core/DistanceCalculator.cpp b/lib/Core/DistanceCalculator.cpp index 24d1d47898..26aa37350a 100644 --- a/lib/Core/DistanceCalculator.cpp +++ b/lib/Core/DistanceCalculator.cpp @@ -56,18 +56,23 @@ DistanceResult DistanceCalculator::getDistance(const ExecutionState &state, DistanceResult DistanceCalculator::getDistance(KBlock *kb, TargetKind kind, KBlock *target) { SpeculativeState specState(kb, kind); - if (distanceResultCache.count(target) == 0 || - distanceResultCache.at(target).count(specState) == 0) { + auto it1 = distanceResultCache.find(target); + if (it1 == distanceResultCache.end()) { + SpeculativeStateToDistanceResultMap m; + it1 = distanceResultCache.emplace(target, std::move(m)).first; + } + auto &m = it1->second; + auto it2 = m.find(specState); + if (it2 == m.end()) { auto result = computeDistance(kb, kind, target); - distanceResultCache[target][specState] = result; + m.emplace(specState, result); + return result; } - return distanceResultCache.at(target).at(specState); + return it2->second; } DistanceResult DistanceCalculator::computeDistance(KBlock *kb, TargetKind kind, KBlock *target) const { - const auto &distanceToTargetFunction = - codeGraphInfo.getBackwardDistance(target->parent); weight_type weight = 0; WeightResult res = Miss; bool isInsideFunction = true; @@ -77,7 +82,7 @@ DistanceResult DistanceCalculator::computeDistance(KBlock *kb, TargetKind kind, break; case PreTarget: - res = tryGetPreTargetWeight(kb, weight, distanceToTargetFunction, target); + res = tryGetPreTargetWeight(kb, weight, target); isInsideFunction = false; break; @@ -102,26 +107,21 @@ DistanceResult DistanceCalculator::getDistance( auto sfi = frames.rbegin(), sfe = frames.rend(); bool strictlyAfterKB = sfi != sfe && sfi->kf->parent->inMainModule(*sfi->kf->function); - for (; sfi != sfe; sfi++) { + for (; sfi != sfe; sfi++, sfNum++) { unsigned callWeight; if (distanceInCallGraph(sfi->kf, kb, callWeight, distanceToTargetFunction, target, strictlyAfterKB && sfNum != 0)) { - callWeight *= 2; - callWeight += sfNum; + callWeight = 2 * callWeight + sfNum; if (callWeight < UINT_MAX) { minCallWeight = callWeight; minSfNum = sfNum; + break; } } - if (sfi->caller) { + if (sfi->caller) kb = sfi->caller->parent; - } - sfNum++; - - if (minCallWeight < UINT_MAX) - break; } TargetKind kind = NoneTarget; @@ -138,71 +138,38 @@ DistanceResult DistanceCalculator::getDistance( bool DistanceCalculator::distanceInCallGraph( KFunction *kf, KBlock *origKB, unsigned int &distance, - const std::unordered_map - &distanceToTargetFunction, - KBlock *target, bool strictlyAfterKB) const { - distance = UINT_MAX; - const std::unordered_map &dist = - codeGraphInfo.getDistance(origKB); - KBlock *targetBB = target; - KFunction *targetF = targetBB->parent; - - if (kf == targetF && dist.count(targetBB) != 0) { + const FunctionDistanceMap &distanceToTargetFunction, KBlock *targetKB, + bool strictlyAfterKB) const { + auto &dist = codeGraphInfo.getDistance(origKB->basicBlock); + if (kf == targetKB->parent && dist.count(targetKB->basicBlock)) { distance = 0; return true; } - if (!strictlyAfterKB) - return distanceInCallGraph(kf, origKB, distance, distanceToTargetFunction, - target); - auto min_distance = UINT_MAX; distance = UINT_MAX; - for (auto bb : successors(origKB->basicBlock)) { - auto kb = kf->blockMap[bb]; - distanceInCallGraph(kf, kb, distance, distanceToTargetFunction, target); - if (distance < min_distance) - min_distance = distance; - } - distance = min_distance; - return distance != UINT_MAX; -} - -bool DistanceCalculator::distanceInCallGraph( - KFunction *kf, KBlock *kb, unsigned int &distance, - const std::unordered_map - &distanceToTargetFunction, - KBlock *target) const { - distance = UINT_MAX; - const std::unordered_map &dist = - codeGraphInfo.getDistance(kb); - - for (auto &kCallBlock : kf->kCallBlocks) { - if (dist.count(kCallBlock) == 0) + bool cannotReachItself = strictlyAfterKB && !codeGraphInfo.hasCycle(origKB); + for (auto kCallBlock : kf->kCallBlocks) { + if (!dist.count(kCallBlock->basicBlock) || + (cannotReachItself && origKB == kCallBlock)) continue; - for (auto &calledFunction : kCallBlock->calledFunctions) { - KFunction *calledKFunction = kf->parent->functionMap[calledFunction]; - if (distanceToTargetFunction.count(calledKFunction) != 0 && - distance > distanceToTargetFunction.at(calledKFunction) + 1) { - distance = distanceToTargetFunction.at(calledKFunction) + 1; - } + for (auto calledFunction : kCallBlock->calledFunctions) { + auto it = distanceToTargetFunction.find(calledFunction); + if (it != distanceToTargetFunction.end() && distance > it->second + 1) + distance = it->second + 1; } } return distance != UINT_MAX; } -WeightResult -DistanceCalculator::tryGetLocalWeight(KBlock *kb, weight_type &weight, - const std::vector &localTargets, - KBlock *target) const { - KBlock *currentKB = kb; - const std::unordered_map &dist = - codeGraphInfo.getDistance(currentKB); +WeightResult DistanceCalculator::tryGetLocalWeight( + KBlock *kb, weight_type &weight, + const std::vector &localTargets) const { + const auto &dist = codeGraphInfo.getDistance(kb); weight = UINT_MAX; - for (auto &end : localTargets) { - if (dist.count(end) > 0) { - unsigned int w = dist.at(end); - weight = std::min(w, weight); - } + for (auto end : localTargets) { + auto it = dist.find(end->basicBlock); + if (it != dist.end()) + weight = std::min(it->second, weight); } if (weight == UINT_MAX) @@ -214,19 +181,18 @@ DistanceCalculator::tryGetLocalWeight(KBlock *kb, weight_type &weight, return Continue; } -WeightResult DistanceCalculator::tryGetPreTargetWeight( - KBlock *kb, weight_type &weight, - const std::unordered_map - &distanceToTargetFunction, - KBlock *target) const { +WeightResult DistanceCalculator::tryGetPreTargetWeight(KBlock *kb, + weight_type &weight, + KBlock *target) const { + auto &distanceToTargetFunction = + codeGraphInfo.getBackwardDistance(target->parent); KFunction *currentKF = kb->parent; std::vector localTargets; - for (auto &kCallBlock : currentKF->kCallBlocks) { - for (auto &calledFunction : kCallBlock->calledFunctions) { - KFunction *calledKFunction = - currentKF->parent->functionMap[calledFunction]; - if (distanceToTargetFunction.count(calledKFunction) > 0) { + for (auto kCallBlock : currentKF->kCallBlocks) { + for (auto calledFunction : kCallBlock->calledFunctions) { + if (distanceToTargetFunction.count(calledFunction)) { localTargets.push_back(kCallBlock); + break; } } } @@ -234,7 +200,7 @@ WeightResult DistanceCalculator::tryGetPreTargetWeight( if (localTargets.empty()) return Miss; - WeightResult res = tryGetLocalWeight(kb, weight, localTargets, target); + WeightResult res = tryGetLocalWeight(kb, weight, localTargets); return res == Done ? Continue : res; } @@ -247,7 +213,7 @@ WeightResult DistanceCalculator::tryGetPostTargetWeight(KBlock *kb, if (localTargets.empty()) return Miss; - WeightResult res = tryGetLocalWeight(kb, weight, localTargets, target); + WeightResult res = tryGetLocalWeight(kb, weight, localTargets); return res == Done ? Continue : res; } @@ -255,6 +221,6 @@ WeightResult DistanceCalculator::tryGetTargetWeight(KBlock *kb, weight_type &weight, KBlock *target) const { std::vector localTargets = {target}; - WeightResult res = tryGetLocalWeight(kb, weight, localTargets, target); + WeightResult res = tryGetLocalWeight(kb, weight, localTargets); return res; } diff --git a/lib/Core/DistanceCalculator.h b/lib/Core/DistanceCalculator.h index 77da2254f1..ed6b5170f8 100644 --- a/lib/Core/DistanceCalculator.h +++ b/lib/Core/DistanceCalculator.h @@ -11,6 +11,7 @@ #define KLEE_DISTANCE_CALCULATOR_H #include "ExecutionState.h" +#include "klee/Module/CodeGraphInfo.h" namespace llvm { class BasicBlock; @@ -107,22 +108,14 @@ class DistanceCalculator { KBlock *target) const; bool distanceInCallGraph(KFunction *kf, KBlock *kb, unsigned int &distance, - const std::unordered_map - &distanceToTargetFunction, - KBlock *target) const; - bool distanceInCallGraph(KFunction *kf, KBlock *kb, unsigned int &distance, - const std::unordered_map - &distanceToTargetFunction, + const FunctionDistanceMap &distanceToTargetFunction, KBlock *target, bool strictlyAfterKB) const; - WeightResult tryGetLocalWeight(KBlock *kb, weight_type &weight, - const std::vector &localTargets, - KBlock *target) const; WeightResult - tryGetPreTargetWeight(KBlock *kb, weight_type &weight, - const std::unordered_map - &distanceToTargetFunction, - KBlock *target) const; + tryGetLocalWeight(KBlock *kb, weight_type &weight, + const std::vector &localTargets) const; + WeightResult tryGetPreTargetWeight(KBlock *kb, weight_type &weight, + KBlock *target) const; WeightResult tryGetTargetWeight(KBlock *kb, weight_type &weight, KBlock *target) const; WeightResult tryGetPostTargetWeight(KBlock *kb, weight_type &weight, diff --git a/lib/Core/TargetedExecutionManager.cpp b/lib/Core/TargetedExecutionManager.cpp index a46a12e3c9..d323180908 100644 --- a/lib/Core/TargetedExecutionManager.cpp +++ b/lib/Core/TargetedExecutionManager.cpp @@ -379,18 +379,18 @@ bool TargetedExecutionManager::canReach(const ref &from, } const auto &blockDist = codeGraphInfo.getDistance(fromBlock); - if (blockDist.count(toBlock) != 0) { + if (blockDist.count(toBlock->basicBlock) != 0) { return true; } } else { const auto &funcDist = codeGraphInfo.getDistance(fromKf); - if (funcDist.count(toKf) != 0) { + if (funcDist.count(toKf->function) != 0) { return true; } const auto &backwardFuncDist = codeGraphInfo.getBackwardDistance(fromKf); - if (backwardFuncDist.count(toKf) != 0) { + if (backwardFuncDist.count(toKf->function) != 0) { return true; } } @@ -464,9 +464,9 @@ KFunction *TargetedExecutionManager::tryResolveEntryFunction( KFunction *curKf = nullptr; for (size_t m = 0; m < currKFs.size() && !curKf; ++m) { curKf = currKFs.at(m); - if (funcDist.count(curKf) == 0) { + if (funcDist.count(curKf->function) == 0) { const auto &curFuncDist = codeGraphInfo.getDistance(curKf); - if (curFuncDist.count(resKf) == 0) { + if (curFuncDist.count(resKf->function) == 0) { curKf = nullptr; } else { i = j; diff --git a/lib/Module/CodeGraphInfo.cpp b/lib/Module/CodeGraphInfo.cpp index a0df05e8c1..71bb259ee1 100644 --- a/lib/Module/CodeGraphInfo.cpp +++ b/lib/Module/CodeGraphInfo.cpp @@ -20,43 +20,47 @@ DISABLE_WARNING_POP using namespace klee; -void CodeGraphInfo::calculateDistance(KBlock *bb) { - auto blockMap = bb->parent->blockMap; - std::unordered_map &dist = blockDistance[bb]; - std::vector> &sort = blockSortedDistance[bb]; - std::deque nodes; +void CodeGraphInfo::calculateDistance(Block *bb) { + auto &dist = blockDistance[bb]; + auto &sort = blockSortedDistance[bb]; + std::deque nodes; nodes.push_back(bb); dist[bb] = 0; sort.push_back({bb, 0}); - while (!nodes.empty()) { - KBlock *currBB = nodes.front(); - for (auto const &succ : successors(currBB->basicBlock)) { - if (dist.count(blockMap[succ]) == 0) { - dist[blockMap[succ]] = dist[currBB] + 1; - sort.push_back({blockMap[succ], dist[currBB] + 1}); - nodes.push_back(blockMap[succ]); + bool hasCycle = false; + for (; !nodes.empty(); nodes.pop_front()) { + auto currBB = nodes.front(); + for (auto succ : successors(currBB)) { + if (succ == bb) { + hasCycle = true; + continue; } + if (dist.count(succ)) + continue; + auto d = dist[currBB] + 1; + dist.emplace(succ, d); + sort.push_back({succ, d}); + nodes.push_back(succ); } - nodes.pop_front(); } + if (hasCycle) + blockCycles.insert(bb); } -void CodeGraphInfo::calculateBackwardDistance(KBlock *bb) { - auto blockMap = bb->parent->blockMap; - std::unordered_map &bdist = blockBackwardDistance[bb]; - std::vector> &bsort = - blockSortedBackwardDistance[bb]; - std::deque nodes; +void CodeGraphInfo::calculateBackwardDistance(Block *bb) { + auto &bdist = blockBackwardDistance[bb]; + auto &bsort = blockSortedBackwardDistance[bb]; + std::deque nodes; nodes.push_back(bb); bdist[bb] = 0; bsort.push_back({bb, 0}); while (!nodes.empty()) { - KBlock *currBB = nodes.front(); - for (auto const &pred : predecessors(currBB->basicBlock)) { - if (bdist.count(blockMap[pred]) == 0) { - bdist[blockMap[pred]] = bdist[currBB] + 1; - bsort.push_back({blockMap[pred], bdist[currBB] + 1}); - nodes.push_back(blockMap[pred]); + auto currBB = nodes.front(); + for (auto const &pred : predecessors(currBB)) { + if (bdist.count(pred) == 0) { + bdist[pred] = bdist[currBB] + 1; + bsort.push_back({pred, bdist[currBB] + 1}); + nodes.push_back(pred); } } nodes.pop_front(); @@ -64,25 +68,25 @@ void CodeGraphInfo::calculateBackwardDistance(KBlock *bb) { } void CodeGraphInfo::calculateDistance(KFunction *kf) { + auto f = kf->function; auto &functionMap = kf->parent->functionMap; - std::unordered_map &dist = functionDistance[kf]; - std::vector> &sort = - functionSortedDistance[kf]; + auto &dist = functionDistance[f]; + auto &sort = functionSortedDistance[f]; std::deque nodes; nodes.push_back(kf); - dist[kf] = 0; - sort.push_back({kf, 0}); + dist[f] = 0; + sort.push_back({f, 0}); while (!nodes.empty()) { - KFunction *currKF = nodes.front(); - for (auto &callBlock : currKF->kCallBlocks) { - for (auto &calledFunction : callBlock->calledFunctions) { - if (!calledFunction || calledFunction->isDeclaration()) { + auto currKF = nodes.front(); + for (auto callBlock : currKF->kCallBlocks) { + for (auto calledFunction : callBlock->calledFunctions) { + if (!calledFunction || calledFunction->isDeclaration()) continue; - } - KFunction *callKF = functionMap[calledFunction]; - if (dist.count(callKF) == 0) { - dist[callKF] = dist[currKF] + 1; - sort.push_back({callKF, dist[currKF] + 1}); + if (dist.count(calledFunction) == 0) { + auto d = dist[currKF->function] + 1; + dist[calledFunction] = d; + sort.emplace_back(calledFunction, d); + auto callKF = functionMap[calledFunction]; nodes.push_back(callKF); } } @@ -92,30 +96,26 @@ void CodeGraphInfo::calculateDistance(KFunction *kf) { } void CodeGraphInfo::calculateBackwardDistance(KFunction *kf) { - auto &functionMap = kf->parent->functionMap; + auto f = kf->function; auto &callMap = kf->parent->callMap; - std::unordered_map &bdist = - functionBackwardDistance[kf]; - std::vector> &bsort = - functionSortedBackwardDistance[kf]; - std::deque nodes; - nodes.push_back(kf); - bdist[kf] = 0; - bsort.push_back({kf, 0}); - while (!nodes.empty()) { - KFunction *currKF = nodes.front(); - for (auto &cf : callMap[currKF->function]) { - if (cf->isDeclaration()) { + auto &bdist = functionBackwardDistance[f]; + auto &bsort = functionSortedBackwardDistance[f]; + std::deque nodes = {f}; + bdist[f] = 0; + bsort.emplace_back(f, 0); + for (; !nodes.empty(); nodes.pop_front()) { + auto currKF = nodes.front(); + for (auto cf : callMap[currKF]) { + if (cf->isDeclaration()) continue; - } - KFunction *callKF = functionMap[cf]; - if (bdist.count(callKF) == 0) { - bdist[callKF] = bdist[currKF] + 1; - bsort.push_back({callKF, bdist[currKF] + 1}); - nodes.push_back(callKF); + auto it = bdist.find(cf); + if (it == bdist.end()) { + auto d = bdist[currKF] + 1; + bdist.emplace_hint(it, cf, d); + bsort.emplace_back(cf, d); + nodes.push_back(cf); } } - nodes.pop_front(); } } @@ -151,60 +151,41 @@ void CodeGraphInfo::calculateFunctionBlocks(KFunction *kf) { } } -const std::unordered_map & -CodeGraphInfo::getDistance(KBlock *kb) { - if (blockDistance.count(kb) == 0) - calculateDistance(kb); - return blockDistance.at(kb); -} - -const std::unordered_map & -CodeGraphInfo::getBackwardDistance(KBlock *kb) { - if (blockBackwardDistance.count(kb) == 0) - calculateBackwardDistance(kb); - return blockBackwardDistance.at(kb); +const BlockDistanceMap &CodeGraphInfo::getDistance(Block *b) { + if (blockDistance.count(b) == 0) + calculateDistance(b); + return blockDistance.at(b); } -const std::vector> & -CodeGraphInfo::getSortedDistance(KBlock *kb) { - if (blockDistance.count(kb) == 0) - calculateDistance(kb); - return blockSortedDistance.at(kb); +bool CodeGraphInfo::hasCycle(KBlock *kb) { + auto b = kb->basicBlock; + if (!blockDistance.count(b)) + calculateDistance(b); + return blockCycles.count(b); } -const std::vector> & -CodeGraphInfo::getSortedBackwardDistance(KBlock *kb) { - if (blockBackwardDistance.count(kb) == 0) - calculateBackwardDistance(kb); - return blockSortedBackwardDistance.at(kb); +const BlockDistanceMap &CodeGraphInfo::getDistance(KBlock *kb) { + return getDistance(kb->basicBlock); } -const std::unordered_map & -CodeGraphInfo::getDistance(KFunction *kf) { - if (functionDistance.count(kf) == 0) - calculateDistance(kf); - return functionDistance.at(kf); -} - -const std::unordered_map & -CodeGraphInfo::getBackwardDistance(KFunction *kf) { - if (functionBackwardDistance.count(kf) == 0) - calculateBackwardDistance(kf); - return functionBackwardDistance.at(kf); +const BlockDistanceMap &CodeGraphInfo::getBackwardDistance(KBlock *kb) { + if (blockBackwardDistance.count(kb->basicBlock) == 0) + calculateBackwardDistance(kb->basicBlock); + return blockBackwardDistance.at(kb->basicBlock); } -const std::vector> & -CodeGraphInfo::getSortedDistance(KFunction *kf) { - if (functionDistance.count(kf) == 0) +const FunctionDistanceMap &CodeGraphInfo::getDistance(KFunction *kf) { + auto f = kf->function; + if (functionDistance.count(f) == 0) calculateDistance(kf); - return functionSortedDistance.at(kf); + return functionDistance.at(f); } -const std::vector> & -CodeGraphInfo::getSortedBackwardDistance(KFunction *kf) { - if (functionBackwardDistance.count(kf) == 0) +const FunctionDistanceMap &CodeGraphInfo::getBackwardDistance(KFunction *kf) { + auto f = kf->function; + if (functionBackwardDistance.count(f) == 0) calculateBackwardDistance(kf); - return functionSortedBackwardDistance.at(kf); + return functionBackwardDistance.at(f); } void CodeGraphInfo::getNearestPredicateSatisfying(KBlock *from, @@ -223,7 +204,7 @@ void CodeGraphInfo::getNearestPredicateSatisfying(KBlock *from, if (predicate(currBB) && currBB != from) { result.insert(currBB); } else { - for (auto const &succ : successors(currBB->basicBlock)) { + for (auto succ : successors(currBB->basicBlock)) { if (visited.count(blockMap[succ]) == 0) { nodes.push_back(blockMap[succ]); } diff --git a/lib/Module/KModule.cpp b/lib/Module/KModule.cpp index 946fd2f087..b08cd6c62a 100644 --- a/lib/Module/KModule.cpp +++ b/lib/Module/KModule.cpp @@ -422,7 +422,7 @@ void KModule::manifest(InterpreterHandler *ih, } for (auto &kfp : functions) { - for (auto kcb : kfp.get()->kCallBlocks) { + for (auto kcb : kfp->kCallBlocks) { bool isInlineAsm = false; const CallBase &cs = cast(*kcb->kcallInstruction->inst); if (isa(cs.getCalledOperand())) { @@ -430,12 +430,12 @@ void KModule::manifest(InterpreterHandler *ih, } if (kcb->calledFunctions.empty() && !isInlineAsm && (guidance != Interpreter::GuidanceKind::ErrorGuidance || - !inMainModule(*kfp.get()->function))) { + !inMainModule(*kfp->function))) { kcb->calledFunctions.insert(escapingFunctions.begin(), escapingFunctions.end()); } - for (auto &calledFunction : kcb->calledFunctions) { - callMap[calledFunction].insert(kfp.get()->function); + for (auto calledFunction : kcb->calledFunctions) { + callMap[calledFunction].insert(kfp->function); } } } From 4d9ad3ee12feff8eac5acd8602dcd8f87c1885f1 Mon Sep 17 00:00:00 2001 From: Yurii Kostyukov Date: Fri, 20 Oct 2023 13:51:23 +0300 Subject: [PATCH 046/103] [chore] Strip llvm.dbg.declare --- lib/Module/Optimize.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/Module/Optimize.cpp b/lib/Module/Optimize.cpp index cda430bd96..77e11b2e2d 100644 --- a/lib/Module/Optimize.cpp +++ b/lib/Module/Optimize.cpp @@ -72,6 +72,11 @@ static cl::opt cl::desc("Strip debugger symbol info from executable"), cl::init(false), cl::cat(klee::ModuleCat)); +static cl::opt + StripDebugDeclare("strip-debug-declare", + cl::desc("Strip all llvm.dbg.declare intrinsics"), + cl::init(true), cl::cat(klee::ModuleCat)); + static cl::alias A1("S", cl::desc("Alias for --strip-debug"), cl::aliasopt(StripDebug)); @@ -98,6 +103,8 @@ static void AddStandardCompilePasses(legacy::PassManager &PM) { // If the -strip-debug command line option was specified, do it. if (StripDebug) addPass(PM, createStripSymbolsPass(true)); + if (StripDebugDeclare) + addPass(PM, createStripDebugDeclarePass()); addPass(PM, createCFGSimplificationPass()); // Clean up disgusting code addPass(PM, createPromoteMemoryToRegisterPass()); // Kill useless allocas From d5ff4df463789268830c77a098f27292d9783902 Mon Sep 17 00:00:00 2001 From: Aleksei Babushkin Date: Fri, 20 Oct 2023 19:27:39 +0300 Subject: [PATCH 047/103] [fix] Compare exprs by height in simplifier --- include/klee/Expr/Expr.h | 25 +++++++++++++++++++++++++ lib/Expr/Constraints.cpp | 2 +- lib/Expr/Expr.cpp | 17 +++++++++++++++++ lib/Expr/Updates.cpp | 11 +++++++++++ 4 files changed, 54 insertions(+), 1 deletion(-) diff --git a/include/klee/Expr/Expr.h b/include/klee/Expr/Expr.h index ab6826e25d..9fdc8c5b21 100644 --- a/include/klee/Expr/Expr.h +++ b/include/klee/Expr/Expr.h @@ -260,6 +260,7 @@ class Expr { protected: unsigned hashValue; + unsigned heightValue; /// Compares `b` to `this` Expr and determines how they are ordered /// (ignoring their kid expressions - i.e. those returned by `getKid()`). @@ -304,10 +305,12 @@ class Expr { /// Returns the pre-computed hash of the current expression virtual unsigned hash() const { return hashValue; } + virtual unsigned height() const { return heightValue; } /// (Re)computes the hash of the current expression. /// Returns the hash value. virtual unsigned computeHash(); + virtual unsigned computeHeight(); /// Compares `b` to `this` Expr for structural equivalence. /// @@ -522,6 +525,7 @@ class NotOptimizedExpr : public NonConstantExpr { static ref alloc(const ref &src) { ref r(new NotOptimizedExpr(src)); r->computeHash(); + r->computeHeight(); return createCachedExpr(r); } @@ -557,6 +561,7 @@ class UpdateNode { // cache instead of recalc unsigned hashValue; + unsigned heightValue; public: const ref next; @@ -578,11 +583,13 @@ class UpdateNode { int compare(const UpdateNode &b) const; bool equals(const UpdateNode &b) const; unsigned hash() const { return hashValue; } + unsigned height() const { return heightValue; } UpdateNode() = delete; ~UpdateNode() = default; unsigned computeHash(); + unsigned computeHeight(); }; class Array { @@ -677,6 +684,7 @@ class UpdateList { bool operator<(const UpdateList &rhs) const { return compare(rhs) < 0; } unsigned hash() const; + unsigned height() const; }; /// Class representing a one byte read from an array. @@ -693,6 +701,7 @@ class ReadExpr : public NonConstantExpr { static ref alloc(const UpdateList &updates, const ref &index) { ref r(new ReadExpr(updates, index)); r->computeHash(); + r->computeHeight(); return createCachedExpr(r); } @@ -714,6 +723,7 @@ class ReadExpr : public NonConstantExpr { } virtual unsigned computeHash(); + virtual unsigned computeHeight(); private: ReadExpr(const UpdateList &_updates, const ref &_index) @@ -740,6 +750,7 @@ class SelectExpr : public NonConstantExpr { const ref &f) { ref r(new SelectExpr(c, t, f)); r->computeHash(); + r->computeHeight(); return createCachedExpr(r); } @@ -804,6 +815,7 @@ class ConcatExpr : public NonConstantExpr { static ref alloc(const ref &l, const ref &r) { ref c(new ConcatExpr(l, r)); c->computeHash(); + c->computeHeight(); return createCachedExpr(c); } @@ -874,6 +886,7 @@ class ExtractExpr : public NonConstantExpr { static ref alloc(const ref &e, unsigned o, Width w) { ref r(new ExtractExpr(e, o, w)); r->computeHash(); + r->computeHeight(); return createCachedExpr(r); } @@ -924,6 +937,7 @@ class NotExpr : public NonConstantExpr { static ref alloc(const ref &e) { ref r(new NotExpr(e)); r->computeHash(); + r->computeHeight(); return createCachedExpr(r); } @@ -997,6 +1011,7 @@ class CastExpr : public NonConstantExpr { static ref alloc(const ref &e, Width w) { \ ref r(new _class_kind##Expr(e, w)); \ r->computeHash(); \ + r->computeHeight(); \ return createCachedExpr(r); \ } \ static ref create(const ref &e, Width w); \ @@ -1030,6 +1045,7 @@ CAST_EXPR_CLASS(FPExt) llvm::APFloat::roundingMode rm) { \ ref r(new _class_kind##Expr(e, w, rm)); \ r->computeHash(); \ + r->computeHeight(); \ return createCachedExpr(r); \ } \ static ref create(const ref &e, Width w, \ @@ -1076,6 +1092,7 @@ FP_CAST_EXPR_CLASS(SIToFP) static ref alloc(const ref &l, const ref &r) { \ ref res(new _class_kind##Expr(l, r)); \ res->computeHash(); \ + res->computeHeight(); \ return createCachedExpr(res); \ } \ static ref create(const ref &l, const ref &r); \ @@ -1126,6 +1143,7 @@ ARITHMETIC_EXPR_CLASS(AShr) const llvm::APFloat::roundingMode rm) { \ ref res(new _class_kind##Expr(l, r, rm)); \ res->computeHash(); \ + res->computeHeight(); \ return createCachedExpr(res); \ } \ static ref create(const ref &l, const ref &r, \ @@ -1172,6 +1190,7 @@ FLOAT_ARITHMETIC_EXPR_CLASS(FMin) static ref alloc(const ref &l, const ref &r) { \ ref res(new _class_kind##Expr(l, r)); \ res->computeHash(); \ + res->computeHeight(); \ return createCachedExpr(res); \ } \ static ref create(const ref &l, const ref &r); \ @@ -1218,6 +1237,7 @@ COMPARISON_EXPR_CLASS(FOGe) static ref alloc(const ref &e) { \ ref r(new _class_kind##Expr(e)); \ r->computeHash(); \ + r->computeHeight(); \ return createCachedExpr(r); \ } \ static ref create(const ref &e); \ @@ -1263,6 +1283,7 @@ FP_PRED_EXPR_CLASS(IsSubnormal) const llvm::APFloat::roundingMode rm) { \ ref r(new _class_kind##Expr(e, rm)); \ r->computeHash(); \ + r->computeHeight(); \ return createCachedExpr(r); \ } \ static ref create(const ref &e, \ @@ -1309,6 +1330,7 @@ class FAbsExpr : public NonConstantExpr { static ref alloc(const ref &e) { ref r(new FAbsExpr(e)); r->computeHash(); + r->computeHeight(); return createCachedExpr(r); } static ref create(const ref &e); @@ -1341,6 +1363,7 @@ class FNegExpr : public NonConstantExpr { static ref alloc(const ref &e) { ref r(new FNegExpr(e)); r->computeHash(); + r->computeHeight(); return createCachedExpr(r); } static ref create(const ref &e); @@ -1447,12 +1470,14 @@ class ConstantExpr : public Expr { static ref alloc(const llvm::APInt &v) { ref r(new ConstantExpr(v)); r->computeHash(); + r->computeHeight(); return r; } static ref alloc(const llvm::APFloat &f) { ref r(new ConstantExpr(f)); r->computeHash(); + r->computeHeight(); return r; } diff --git a/lib/Expr/Constraints.cpp b/lib/Expr/Constraints.cpp index f14d612379..241c1a329b 100644 --- a/lib/Expr/Constraints.cpp +++ b/lib/Expr/Constraints.cpp @@ -425,7 +425,7 @@ Simplificator::simplifyExpr(const constraints_ty &constraints, if (const EqExpr *ee = dyn_cast(constraint)) { ref left = ee->left; ref right = ee->right; - if (right < left) { + if (right->height() < left->height()) { left = ee->right; right = ee->left; } diff --git a/lib/Expr/Expr.cpp b/lib/Expr/Expr.cpp index ccf6eab730..5d301e0d7c 100644 --- a/lib/Expr/Expr.cpp +++ b/lib/Expr/Expr.cpp @@ -260,6 +260,18 @@ unsigned Expr::computeHash() { return hashValue; } +unsigned Expr::computeHeight() { + unsigned maxKidHeight = 0; + + int n = getNumKids(); + for (int i = 0; i < n; i++) { + maxKidHeight = std::max(maxKidHeight, getKid(i)->height()); + } + + heightValue = maxKidHeight + 1; + return heightValue; +} + unsigned ConstantExpr::computeHash() { Expr::Width w = getWidth(); if (w <= 64) @@ -290,6 +302,11 @@ unsigned ReadExpr::computeHash() { return hashValue; } +unsigned ReadExpr::computeHeight() { + heightValue = std::max(index->height(), updates.height()) + 1; + return heightValue; +} + unsigned NotExpr::computeHash() { hashValue = expr->hash() * Expr::MAGIC_HASH_CONSTANT * Expr::Not; return hashValue; diff --git a/lib/Expr/Updates.cpp b/lib/Expr/Updates.cpp index 6b740e3a72..b7bbad8cbc 100644 --- a/lib/Expr/Updates.cpp +++ b/lib/Expr/Updates.cpp @@ -25,6 +25,7 @@ UpdateNode::UpdateNode(const ref &_next, const ref &_index, "Update value should be 8-bit wide."); */ computeHash(); + computeHeight(); size = next ? next->size + 1 : 1; } @@ -45,6 +46,14 @@ unsigned UpdateNode::computeHash() { return hashValue; } +unsigned UpdateNode::computeHeight() { + unsigned maxHeight = next ? next->height() : 0; + maxHeight = std::max(maxHeight, index->height()); + maxHeight = std::max(maxHeight, value->height()); + heightValue = maxHeight; + return heightValue; +} + /// UpdateList::UpdateList(const Array *_root, const ref &_head) @@ -95,3 +104,5 @@ unsigned UpdateList::hash() const { res = (res * Expr::MAGIC_HASH_CONSTANT) + head->hash(); return res; } + +unsigned UpdateList::height() const { return head ? head->height() : 0; } From c3553c0f84db4a0acc866d1780f519c577c98c4d Mon Sep 17 00:00:00 2001 From: Aleksei Babushkin Date: Tue, 17 Oct 2023 13:14:29 +0300 Subject: [PATCH 048/103] [feat] Uninitialized Memory [feat] Sizeless ObjectState [feat] STP and MetaSMT symsize array support --- include/klee/ADT/KTest.h | 1 + include/klee/ADT/Ref.h | 13 + include/klee/ADT/SparseStorage.h | 145 +- include/klee/Expr/ArrayCache.h | 5 +- include/klee/Expr/Assignment.h | 4 +- include/klee/Expr/Expr.h | 7 +- include/klee/Expr/Parser/Lexer.h | 2 + include/klee/Expr/SourceBuilder.h | 12 +- include/klee/Expr/SymbolicSource.h | 88 +- include/klee/Module/KInstruction.h | 43 +- include/klee/Module/KModule.h | 2 +- include/klee/Solver/SolverUtil.h | 6 +- include/klee/Support/PrintContext.h | 2 + lib/ADT/CMakeLists.txt | 16 + lib/ADT/SparseStorage.cpp | 86 + lib/CMakeLists.txt | 1 + lib/Core/AddressSpace.cpp | 34 +- lib/Core/AddressSpace.h | 10 +- lib/Core/Executor.cpp | 122 +- lib/Core/Executor.h | 2 +- lib/Core/Memory.cpp | 429 +- lib/Core/Memory.h | 72 +- lib/Expr/ArrayCache.cpp | 38 +- lib/Expr/ArrayExprOptimizer.cpp | 10 +- lib/Expr/Assignment.cpp | 11 +- lib/Expr/CMakeLists.txt | 4 + lib/Expr/Expr.cpp | 44 +- lib/Expr/ExprEvaluator.cpp | 9 +- lib/Expr/ExprPPrinter.cpp | 19 +- lib/Expr/ExprSMTLIBPrinter.cpp | 16 +- lib/Expr/IndependentSet.cpp | 2 - lib/Expr/Lexer.cpp | 8 + lib/Expr/Parser.cpp | 83 +- lib/Expr/SourceBuilder.cpp | 17 +- lib/Expr/SymbolicSource.cpp | 90 +- lib/Module/KInstruction.cpp | 4 + lib/Module/KModule.cpp | 2 +- lib/Solver/CexCachingSolver.cpp | 3 +- lib/Solver/FastCexSolver.cpp | 16 +- lib/Solver/MetaSMTBuilder.h | 42 +- lib/Solver/MetaSMTSolver.cpp | 10 +- lib/Solver/STPBuilder.cpp | 49 +- lib/Solver/STPSolver.cpp | 2 +- lib/Solver/Z3Builder.cpp | 38 +- lib/Solver/Z3Solver.cpp | 8 +- test/Expr/Evaluate.kquery | 2 +- test/Expr/print-smt-let.kquery | 10 +- test/Expr/print-smt-let.smt2.good | 182 +- test/Expr/print-smt-named.kquery | 10 +- test/Expr/print-smt-named.smt2.good | 182 +- test/Expr/print-smt-none.kquery | 10 +- test/Expr/print-smt-none.smt2.good | 182 +- test/Feature/MemoryLimit.c | 2 +- .../SymbolicSizes/FirstAndLastElements.c | 3 +- .../SymbolicSizes/ImplicitArrayExtension.c | 3 +- .../ImplicitSizeConcretization.c | 1 - test/Feature/SymbolicSizes/IntArray.c | 4 +- .../LazyInstantiationOfSymbolicSize.c | 3 +- test/Feature/SymbolicSizes/LowerOutOfBound.c | 3 +- test/Feature/SymbolicSizes/MinimizeSize.c | 3 +- .../SymbolicSizes/MultipleAllocations.c | 3 +- .../SymbolicSizes/NegativeIndexArray.c | 3 +- test/Feature/SymbolicSizes/NegativeSize.c | 5 +- .../SymbolicSizes/RecomputeModelTwoArrays.c | 3 +- .../Feature/SymbolicSizes/SegmentComparator.c | 3 +- .../SymbolicSizes/SymbolicArrayOnStack.c | 3 +- .../SymbolicArrayOnStackWithSkipSymbolics.c | 3 +- .../SymbolicSizes/UninitializedMemory.c | 24 + test/Feature/SymbolicSizes/VoidStar.c | 3 +- test/Feature/TwoUninitializedRegions.c | 23 + test/Feature/UninitializedConstantMemory.c | 29 + .../2016-04-12-array-parsing-bug.kquery | 4 +- test/Solver/Z3ConstantArray.c | 16 +- test/Solver/Z3LargeConstantArray.kquery | 2 +- test/lit.cfg | 4 + test/lit.site.cfg.in | 1 + .../2023-08-28-invalid-pointer-dereference.c | 22 + test/regression/2023-10-13-kbfiltr.i.cil-2.c | 3649 +++++++++++++++++ .../2023-10-13-uninitialized-memory.c | 21 + tools/klee/main.cpp | 50 +- unittests/Expr/ArrayExprTest.cpp | 4 +- unittests/Expr/ExprTest.cpp | 32 +- unittests/Solver/Z3SolverTest.cpp | 14 +- 83 files changed, 4973 insertions(+), 1175 deletions(-) create mode 100644 lib/ADT/CMakeLists.txt create mode 100644 lib/ADT/SparseStorage.cpp create mode 100644 test/Feature/SymbolicSizes/UninitializedMemory.c create mode 100644 test/Feature/TwoUninitializedRegions.c create mode 100644 test/Feature/UninitializedConstantMemory.c create mode 100644 test/regression/2023-08-28-invalid-pointer-dereference.c create mode 100644 test/regression/2023-10-13-kbfiltr.i.cil-2.c create mode 100644 test/regression/2023-10-13-uninitialized-memory.c diff --git a/include/klee/ADT/KTest.h b/include/klee/ADT/KTest.h index 66c68c3417..d4c08d640d 100644 --- a/include/klee/ADT/KTest.h +++ b/include/klee/ADT/KTest.h @@ -46,6 +46,7 @@ struct KTest { unsigned numObjects; KTestObject *objects; + unsigned uninitCoeff; }; /* returns the current .ktest file format version */ diff --git a/include/klee/ADT/Ref.h b/include/klee/ADT/Ref.h index 008580cc7e..eb082c2065 100644 --- a/include/klee/ADT/Ref.h +++ b/include/klee/ADT/Ref.h @@ -215,6 +215,19 @@ template class ref { bool operator!=(const ref &rhs) const { return !equals(rhs); } }; +template class OptionalRefEq { +public: + bool operator()(const ref &lhs, const ref &rhs) { + if (lhs.isNull() && rhs.isNull()) { + return true; + } + if (lhs.isNull() || rhs.isNull()) { + return false; + } + return lhs.get()->equals(*rhs.get()); + } +}; + template inline llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const ref &e) { os << *e; diff --git a/include/klee/ADT/SparseStorage.h b/include/klee/ADT/SparseStorage.h index 84170600da..307f8b671e 100644 --- a/include/klee/ADT/SparseStorage.h +++ b/include/klee/ADT/SparseStorage.h @@ -3,67 +3,56 @@ #include #include +#include #include #include +#include #include +namespace llvm { +class raw_ostream; +}; + namespace klee { -template class SparseStorage { +enum class Density { + Sparse, + Dense, +}; + +template > +class SparseStorage { private: - size_t capacity; - std::map internalStorage; + std::unordered_map internalStorage; ValueType defaultValue; + Eq eq; bool contains(size_t key) const { return internalStorage.count(key) != 0; } public: - struct Iterator { - using iterator_category = std::input_iterator_tag; - using difference_type = std::ptrdiff_t; - using value_type = ValueType; - using pointer = ValueType *; - using reference = ValueType &; - - private: - size_t idx; - const SparseStorage *owner; - - public: - Iterator(size_t idx, const SparseStorage *owner) : idx(idx), owner(owner) {} - - value_type operator*() const { return owner->load(idx); } - - Iterator &operator++() { - ++idx; - return *this; - } - - Iterator operator++(int) { - Iterator snap = *this; - ++(*this); - return snap; + SparseStorage(const ValueType &defaultValue = ValueType()) + : defaultValue(defaultValue) {} + + SparseStorage(const std::unordered_map &internalStorage, + const ValueType &defaultValue) + : defaultValue(defaultValue) { + for (auto &[index, value] : internalStorage) { + store(index, value); } - - bool operator==(const Iterator &other) const { return idx == other.idx; } - - bool operator!=(const Iterator &other) const { return !(*this == other); } - }; - - SparseStorage(size_t capacity = 0, - const ValueType &defaultValue = ValueType()) - : capacity(capacity), defaultValue(defaultValue) {} + } SparseStorage(const std::vector &values, const ValueType &defaultValue = ValueType()) - : capacity(values.capacity()), defaultValue(defaultValue) { - for (size_t idx = 0; idx < values.capacity(); ++idx) { - internalStorage[idx] = values[idx]; + : defaultValue(defaultValue) { + for (size_t idx = 0; idx < values.size(); ++idx) { + store(idx, values[idx]); } } void store(size_t idx, const ValueType &value) { - if (idx < capacity) { + if (eq(value, defaultValue)) { + internalStorage.erase(idx); + } else { internalStorage[idx] = value; } } @@ -77,32 +66,19 @@ template class SparseStorage { } ValueType load(size_t idx) const { - assert(idx < capacity && idx >= 0); return contains(idx) ? internalStorage.at(idx) : defaultValue; } - size_t size() const { return capacity; } - - void resize(size_t newCapacity) { - assert(newCapacity >= 0); - // Free to extend - if (newCapacity >= capacity) { - capacity = newCapacity; - return; - } - - // Truncate unnessecary elements - auto iterOnNewSize = internalStorage.lower_bound(newCapacity); - while (iterOnNewSize != internalStorage.end()) { - iterOnNewSize = internalStorage.erase(iterOnNewSize); + size_t sizeOfSetRange() const { + size_t sizeOfRange = 0; + for (auto i : internalStorage) { + sizeOfRange = std::max(i.first, sizeOfRange); } - - capacity = newCapacity; + return sizeOfRange; } bool operator==(const SparseStorage &another) const { - return size() == another.size() && defaultValue == another.defaultValue && - internalStorage == another.internalStorage; + return defaultValue == another.defaultValue && compare(another) == 0; } bool operator!=(const SparseStorage &another) const { @@ -110,22 +86,61 @@ template class SparseStorage { } bool operator<(const SparseStorage &another) const { - return internalStorage < another.internalStorage; + return compare(another) == -1; } bool operator>(const SparseStorage &another) const { - return internalStorage > another.internalStorage; + return compare(another) == 1; + } + + int compare(const SparseStorage &other) const { + auto ordered = calculateOrderedStorage(); + auto otherOrdered = other.calculateOrderedStorage(); + + if (ordered == otherOrdered) { + return 0; + } else { + return ordered < otherOrdered ? -1 : 1; + } + } + + std::map calculateOrderedStorage() const { + std::map ordered; + for (const auto &i : internalStorage) { + ordered.insert(i); + } + return ordered; + } + + std::vector getFirstNIndexes(size_t n) const { + std::vector vectorized(n); + for (size_t i = 0; i < n; i++) { + vectorized[i] = load(i); + } + return vectorized; + } + + const std::unordered_map &storage() const { + return internalStorage; + }; + + const ValueType &defaultV() const { return defaultValue; }; + + void reset() { internalStorage.clear(); } + + void reset(ValueType newDefault) { + defaultValue = newDefault; + internalStorage.clear(); } - Iterator begin() const { return Iterator(0, this); } - Iterator end() const { return Iterator(size(), this); } + void print(llvm::raw_ostream &os, Density) const; }; template SparseStorage sparseBytesFromValue(const U &value) { const unsigned char *valueUnsignedCharIterator = reinterpret_cast(&value); - SparseStorage result(sizeof(value)); + SparseStorage result; result.store(0, valueUnsignedCharIterator, valueUnsignedCharIterator + sizeof(value)); return result; diff --git a/include/klee/Expr/ArrayCache.h b/include/klee/Expr/ArrayCache.h index b46a1caab1..735b3d257b 100644 --- a/include/klee/Expr/ArrayCache.h +++ b/include/klee/Expr/ArrayCache.h @@ -61,10 +61,9 @@ class ArrayCache { klee::EquivArrayCmpFn> ArrayHashSet; ArrayHashSet cachedSymbolicArrays; - typedef std::vector ArrayPtrVec; - ArrayPtrVec concreteArrays; - unsigned getNextID() const; + // Number of arrays of each source allocated + std::unordered_map allocatedCount; }; } // namespace klee diff --git a/include/klee/Expr/Assignment.h b/include/klee/Expr/Assignment.h index 61376ff940..f72bb581b7 100644 --- a/include/klee/Expr/Assignment.h +++ b/include/klee/Expr/Assignment.h @@ -95,8 +95,10 @@ class AssignmentEvaluator : public ExprEvaluator { inline ref Assignment::evaluate(const Array *array, unsigned index, bool allowFreeValues) const { assert(array); + auto sizeExpr = evaluate(array->size); bindings_ty::iterator it = bindings.find(array); - if (it != bindings.end() && index < it->second.size()) { + if (it != bindings.end() && isa(sizeExpr) && + index < cast(sizeExpr)->getZExtValue()) { return ConstantExpr::alloc(it->second.load(index), array->getRange()); } else { if (allowFreeValues) { diff --git a/include/klee/Expr/Expr.h b/include/klee/Expr/Expr.h index 9fdc8c5b21..df98d892f9 100644 --- a/include/klee/Expr/Expr.h +++ b/include/klee/Expr/Expr.h @@ -415,7 +415,7 @@ struct Expr::CreateArg { // Comparison operators inline bool operator==(const Expr &lhs, const Expr &rhs) { - return lhs.compare(rhs) == 0; + return lhs.equals(rhs); } inline bool operator<(const Expr &lhs, const Expr &rhs) { @@ -636,10 +636,7 @@ class Array { public: bool isSymbolicArray() const { return !isConstantArray(); } - bool isConstantArray() const { - return isa(source) || - isa(source); - } + bool isConstantArray() const { return isa(source); } const std::string getName() const { return source->toString(); } const std::string getIdentifier() const { diff --git a/include/klee/Expr/Parser/Lexer.h b/include/klee/Expr/Parser/Lexer.h index 8b3fe53a30..dc4c111adc 100644 --- a/include/klee/Expr/Parser/Lexer.h +++ b/include/klee/Expr/Parser/Lexer.h @@ -32,6 +32,8 @@ struct Token { KWFalse, ///< 'false' KWQuery, ///< 'query' KWPath, ///< 'path' + KWDefault, ///< 'default' + KWNull, ///< 'null' KWReserved, ///< fp[0-9]+([.].*)?, i[0-9]+ KWSymbolic, ///< 'symbolic' KWTrue, ///< 'true' diff --git a/include/klee/Expr/SourceBuilder.h b/include/klee/Expr/SourceBuilder.h index 7b57e2f8c9..1747fab458 100644 --- a/include/klee/Expr/SourceBuilder.h +++ b/include/klee/Expr/SourceBuilder.h @@ -2,6 +2,7 @@ #define KLEE_SOURCEBUILDER_H #include "klee/ADT/Ref.h" +#include "klee/ADT/SparseStorage.h" #include "klee/Expr/SymbolicSource.h" #include "klee/Module/KModule.h" @@ -12,10 +13,13 @@ class SourceBuilder { SourceBuilder() = delete; static ref - constant(const std::vector> &constantValues); - static ref symbolicSizeConstant(unsigned defaultValue); - static ref symbolicSizeConstantAddress(unsigned defaultValue, - unsigned version); + constant(SparseStorage> constantValues); + + static ref uninitialized(unsigned version, + const KInstruction *allocSite); + static ref + symbolicSizeConstantAddress(unsigned version, const KInstruction *allocSite, + ref size); static ref makeSymbolic(const std::string &name, unsigned version); static ref lazyInitializationAddress(ref pointer); diff --git a/include/klee/Expr/SymbolicSource.h b/include/klee/Expr/SymbolicSource.h index be65580f7b..ded381bb00 100644 --- a/include/klee/Expr/SymbolicSource.h +++ b/include/klee/Expr/SymbolicSource.h @@ -3,11 +3,14 @@ #include "klee/ADT/Ref.h" +#include "klee/ADT/SparseStorage.h" #include "klee/Support/CompilerWarning.h" + DISABLE_WARNING_PUSH DISABLE_WARNING_DEPRECATED_DECLARATIONS #include "llvm/ADT/StringExtras.h" #include "llvm/IR/Argument.h" +#include "llvm/IR/GlobalVariable.h" #include "llvm/IR/Instruction.h" DISABLE_WARNING_POP @@ -21,6 +24,7 @@ class Array; class Expr; class ConstantExpr; class KModule; +struct KInstruction; class SymbolicSource { protected: @@ -33,7 +37,7 @@ class SymbolicSource { enum Kind { Constant = 3, - SymbolicSizeConstant, + Uninitialied, SymbolicSizeConstantAddress, MakeSymbolic, LazyInitializationContent, @@ -63,24 +67,26 @@ class SymbolicSource { class ConstantSource : public SymbolicSource { public: - /// constantValues - The constant initial values for this array, or empty for - /// a symbolic array. If non-empty, this size of this array is equivalent to - /// the array size. - const std::vector> constantValues; + const SparseStorage> constantValues; + + ConstantSource(SparseStorage> _constantValues) + : constantValues(std::move(_constantValues)) { + assert(constantValues.defaultV() && "Constant must be constant!"); + } - ConstantSource(const std::vector> &_constantValues) - : constantValues(_constantValues){}; Kind getKind() const override { return Kind::Constant; } - virtual std::string getName() const override { return "constant"; } - uint64_t size() const { return constantValues.size(); } + + std::string getName() const override { return "constant"; } static bool classof(const SymbolicSource *S) { return S->getKind() == Kind::Constant; } + static bool classof(const ConstantSource *) { return true; } - virtual unsigned computeHash() override; - virtual int internalCompare(const SymbolicSource &b) const override { + unsigned computeHash() override; + + int internalCompare(const SymbolicSource &b) const override { if (getKind() != b.getKind()) { return getKind() < b.getKind() ? -1 : 1; } @@ -92,43 +98,38 @@ class ConstantSource : public SymbolicSource { } }; -class SymbolicSizeConstantSource : public SymbolicSource { +class UninitializedSource : public SymbolicSource { public: - const unsigned defaultValue; - SymbolicSizeConstantSource(unsigned _defaultValue) - : defaultValue(_defaultValue) {} + const unsigned version; + const KInstruction *allocSite; - Kind getKind() const override { return Kind::SymbolicSizeConstant; } - virtual std::string getName() const override { - return "symbolicSizeConstant"; - } + UninitializedSource(unsigned version, const KInstruction *allocSite) + : version(version), allocSite(allocSite) {} + + Kind getKind() const override { return Kind::Uninitialied; } + + std::string getName() const override { return "uninitialized"; } static bool classof(const SymbolicSource *S) { - return S->getKind() == Kind::SymbolicSizeConstant; + return S->getKind() == Kind::Uninitialied; } - static bool classof(const SymbolicSizeConstantSource *) { return true; } - virtual unsigned computeHash() override; + static bool classof(const UninitializedSource *) { return true; } - virtual int internalCompare(const SymbolicSource &b) const override { - if (getKind() != b.getKind()) { - return getKind() < b.getKind() ? -1 : 1; - } - const SymbolicSizeConstantSource &ssb = - static_cast(b); - if (defaultValue != ssb.defaultValue) { - return defaultValue < ssb.defaultValue ? -1 : 1; - } - return 0; - } + unsigned computeHash() override; + + int internalCompare(const SymbolicSource &b) const override; }; class SymbolicSizeConstantAddressSource : public SymbolicSource { public: - const unsigned defaultValue; const unsigned version; - SymbolicSizeConstantAddressSource(unsigned _defaultValue, unsigned _version) - : defaultValue(_defaultValue), version(_version) {} + const KInstruction *allocSite; + ref size; + SymbolicSizeConstantAddressSource(unsigned _version, + const KInstruction *_allocSite, + ref _size) + : version(_version), allocSite(_allocSite), size(_size) {} Kind getKind() const override { return Kind::SymbolicSizeConstantAddress; } virtual std::string getName() const override { @@ -144,20 +145,7 @@ class SymbolicSizeConstantAddressSource : public SymbolicSource { virtual unsigned computeHash() override; - virtual int internalCompare(const SymbolicSource &b) const override { - if (getKind() != b.getKind()) { - return getKind() < b.getKind() ? -1 : 1; - } - const SymbolicSizeConstantAddressSource &ssb = - static_cast(b); - if (defaultValue != ssb.defaultValue) { - return defaultValue < ssb.defaultValue ? -1 : 1; - } - if (version != ssb.version) { - return version < ssb.version ? -1 : 1; - } - return 0; - } + virtual int internalCompare(const SymbolicSource &b) const override; }; class MakeSymbolicSource : public SymbolicSource { diff --git a/include/klee/Module/KInstruction.h b/include/klee/Module/KInstruction.h index 5c64de152c..a4ee2c9c44 100644 --- a/include/klee/Module/KInstruction.h +++ b/include/klee/Module/KInstruction.h @@ -13,7 +13,7 @@ #include "KModule.h" #include "klee/Config/Version.h" #include "klee/Support/CompilerWarning.h" - +#include "llvm/IR/Argument.h" DISABLE_WARNING_PUSH DISABLE_WARNING_DEPRECATED_DECLARATIONS #include "llvm/Support/DataTypes.h" @@ -31,10 +31,41 @@ namespace klee { class Executor; class KModule; struct KBlock; +struct KFunction; + +static const unsigned MAGIC_HASH_CONSTANT = 39; /// KInstruction - Intermediate instruction representation used /// during execution. struct KInstruction { + + struct Index { + unsigned long instID; + unsigned long blockID; + unsigned long funcID; + + bool operator==(const Index &other) const { + return std::tie(instID, blockID, funcID) == + std::tie(other.instID, other.blockID, other.funcID); + } + + bool operator<(const Index &other) const { + return std::tie(instID, blockID, funcID) < + std::tie(other.instID, other.blockID, other.funcID); + } + + unsigned hash() const { + unsigned res = instID; + res = res * MAGIC_HASH_CONSTANT + blockID; + res = res * MAGIC_HASH_CONSTANT + funcID; + return res; + } + + void print(llvm::raw_ostream &os) const { + os << "[" << instID << ", " << blockID << ", " << funcID << "]"; + } + }; + llvm::Instruction *inst; /// Value numbers for each operand. -1 is an invalid value, @@ -65,21 +96,31 @@ struct KInstruction { KInstruction() = delete; explicit KInstruction(const KInstruction &ki) = delete; virtual ~KInstruction(); + std::string getSourceLocation() const; [[nodiscard]] size_t getLine() const; [[nodiscard]] size_t getColumn() const; [[nodiscard]] std::string getSourceFilepath() const; + Index getID() const; [[nodiscard]] std::string getSourceLocationString() const; [[nodiscard]] std::string toString() const; + bool operator==(const KInstruction &other) const { + return getID() == other.getID(); + } [[nodiscard]] inline KBlock *getKBlock() const { return parent; } [[nodiscard]] inline KFunction *getKFunction() const { return getKBlock()->parent; } + bool operator<(const KInstruction &other) const { + return getID() < other.getID(); + } [[nodiscard]] inline KModule *getKModule() const { return getKFunction()->parent; } + + unsigned hash() const { return getID().hash(); } }; struct KGEPInstruction : KInstruction { diff --git a/include/klee/Module/KModule.h b/include/klee/Module/KModule.h index 50949908b6..83cef2cce5 100644 --- a/include/klee/Module/KModule.h +++ b/include/klee/Module/KModule.h @@ -296,7 +296,7 @@ class KModule { /// expected by KLEE's Executor hold. void checkModule(); - KBlock *getKBlock(llvm::BasicBlock *bb); + KBlock *getKBlock(const llvm::BasicBlock *bb); bool inMainModule(const llvm::Function &f); diff --git a/include/klee/Solver/SolverUtil.h b/include/klee/Solver/SolverUtil.h index bb66e7a179..d68d3ea77e 100644 --- a/include/klee/Solver/SolverUtil.h +++ b/include/klee/Solver/SolverUtil.h @@ -254,11 +254,7 @@ class InvalidResponse : public SolverResponse { if (result.bindings.count(object)) { values.push_back(result.bindings.at(object)); } else { - ref constantSize = - dyn_cast(result.evaluate(object->size)); - assert(constantSize); - values.push_back( - SparseStorage(constantSize->getZExtValue(), 0)); + values.push_back(SparseStorage(0)); } } return true; diff --git a/include/klee/Support/PrintContext.h b/include/klee/Support/PrintContext.h index e397367683..5196b9a35f 100644 --- a/include/klee/Support/PrintContext.h +++ b/include/klee/Support/PrintContext.h @@ -72,6 +72,8 @@ class PrintContext { return *this; } + llvm::raw_ostream &getStream() { return os; } + /// Pop the top off the indent stack /// \return The PrintContext object so the method is chainable PrintContext &popIndent() { diff --git a/lib/ADT/CMakeLists.txt b/lib/ADT/CMakeLists.txt new file mode 100644 index 0000000000..4afa541dd6 --- /dev/null +++ b/lib/ADT/CMakeLists.txt @@ -0,0 +1,16 @@ +#===------------------------------------------------------------------------===# +# +# The KLEE Symbolic Virtual Machine +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +#===------------------------------------------------------------------------===# +add_library(kleeADT + SparseStorage.cpp +) + +llvm_config(kleeADT "${USE_LLVM_SHARED}" support) +target_include_directories(kleeADT PRIVATE ${KLEE_INCLUDE_DIRS} ${LLVM_INCLUDE_DIRS}) +target_compile_options(kleeADT PRIVATE ${KLEE_COMPONENT_CXX_FLAGS}) +target_compile_definitions(kleeADT PRIVATE ${KLEE_COMPONENT_CXX_DEFINES}) diff --git a/lib/ADT/SparseStorage.cpp b/lib/ADT/SparseStorage.cpp new file mode 100644 index 0000000000..dc24e7d993 --- /dev/null +++ b/lib/ADT/SparseStorage.cpp @@ -0,0 +1,86 @@ +#include "klee/ADT/SparseStorage.h" +#include "klee/Expr/Expr.h" + +#include "llvm/ADT/StringExtras.h" +#include "llvm/Support/raw_ostream.h" + +namespace klee { + +template <> +void SparseStorage::print(llvm::raw_ostream &os, + Density d) const { + if (d == Density::Sparse) { + // "Sparse representation" + os << "{"; + bool firstPrinted = false; + auto ordered = calculateOrderedStorage(); + for (const auto &element : ordered) { + if (firstPrinted) { + os << ", "; + } + os << element.first << ": " << element.second; + firstPrinted = true; + } + os << "} default: "; + } else { + // "Dense representation" + os << "["; + bool firstPrinted = false; + for (size_t i = 0; i < sizeOfSetRange(); i++) { + if (firstPrinted) { + os << ", "; + } + os << llvm::utostr(load(i)); + firstPrinted = true; + } + os << "] default: "; + } + os << defaultValue; +} + +template <> +void SparseStorage>::print(llvm::raw_ostream &os, + Density d) const { + if (d == Density::Sparse) { + // "Sparse representation" + os << "{"; + bool firstPrinted = false; + auto ordered = calculateOrderedStorage(); + for (const auto &element : ordered) { + if (firstPrinted) { + os << ", "; + } + os << element.first << ": "; + if (element.second) { + os << element.second; + } else { + os << "null"; + } + firstPrinted = true; + } + os << "} default: "; + } else { + // "Dense representation" + os << "["; + bool firstPrinted = false; + for (size_t i = 0; i < sizeOfSetRange(); i++) { + if (firstPrinted) { + os << ", "; + } + auto expr = load(i); + if (expr) { + os << expr; + } else { + os << "null"; + } + firstPrinted = true; + } + os << "] default: "; + } + if (defaultValue) { + os << defaultValue; + } else { + os << "null"; + } +} +} // namespace klee diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 8a0749324a..cc0279a12e 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -6,6 +6,7 @@ # License. See LICENSE.TXT for details. # #===------------------------------------------------------------------------===# +add_subdirectory(ADT) add_subdirectory(Basic) add_subdirectory(Support) add_subdirectory(Expr) diff --git a/lib/Core/AddressSpace.cpp b/lib/Core/AddressSpace.cpp index 1d33e574fc..553b588bd3 100644 --- a/lib/Core/AddressSpace.cpp +++ b/lib/Core/AddressSpace.cpp @@ -364,30 +364,36 @@ bool AddressSpace::resolve(ExecutionState &state, TimingSolver *solver, // transparently avoid screwing up symbolics (if the byte is symbolic // then its concrete cache byte isn't being used) but is just a hack. -void AddressSpace::copyOutConcretes() { +void AddressSpace::copyOutConcretes(const Assignment &assignment) { for (const auto &object : objects) { auto &mo = object.first; auto &os = object.second; - if (!mo->isUserSpecified && !os->readOnly && os->size != 0) { - copyOutConcrete(mo, os.get()); + if (!mo->isUserSpecified && !os->readOnly && mo->size != 0) { + copyOutConcrete(mo, os.get(), assignment); } } } void AddressSpace::copyOutConcrete(const MemoryObject *mo, - const ObjectState *os) const { + const ObjectState *os, + const Assignment &assignment) const { auto address = reinterpret_cast(mo->address); - std::memcpy(address, os->concreteStore, mo->size); + std::vector concreteStore(mo->size); + for (size_t i = 0; i < mo->size; i++) { + auto byte = assignment.evaluate(os->read8(i), false); + concreteStore[i] = cast(byte)->getZExtValue(8); + } + std::memcpy(address, concreteStore.data(), mo->size); } -bool AddressSpace::copyInConcretes() { +bool AddressSpace::copyInConcretes(const Assignment &assignment) { for (auto &obj : objects) { const MemoryObject *mo = obj.first; if (!mo->isUserSpecified) { const auto &os = obj.second; - if (!copyInConcrete(mo, os.get(), mo->address)) + if (!copyInConcrete(mo, os.get(), mo->address, assignment)) return false; } } @@ -396,14 +402,22 @@ bool AddressSpace::copyInConcretes() { } bool AddressSpace::copyInConcrete(const MemoryObject *mo, const ObjectState *os, - uint64_t src_address) { + uint64_t src_address, + const Assignment &assignment) { auto address = reinterpret_cast(src_address); - if (memcmp(address, os->concreteStore, mo->size) != 0) { + std::vector concreteStore(mo->size); + for (size_t i = 0; i < mo->size; i++) { + auto byte = assignment.evaluate(os->read8(i), false); + concreteStore[i] = cast(byte)->getZExtValue(8); + } + if (memcmp(address, concreteStore.data(), mo->size) != 0) { if (os->readOnly) { return false; } else { ObjectState *wos = getWriteable(mo, os); - memcpy(wos->concreteStore, address, mo->size); + for (size_t i = 0; i < mo->size; i++) { + wos->write(i, ConstantExpr::create(address[i], Expr::Int8)); + } } } return true; diff --git a/lib/Core/AddressSpace.h b/lib/Core/AddressSpace.h index 0acd1c1208..11d2de8130 100644 --- a/lib/Core/AddressSpace.h +++ b/lib/Core/AddressSpace.h @@ -13,6 +13,7 @@ #include "Memory.h" #include "klee/ADT/ImmutableMap.h" +#include "klee/Expr/Assignment.h" #include "klee/Expr/Expr.h" #include "klee/System/Time.h" @@ -137,9 +138,10 @@ class AddressSpace { /// actual system memory location they were allocated at. /// Returns the (hypothetical) number of pages needed provided each written /// object occupies (at least) a single page. - void copyOutConcretes(); + void copyOutConcretes(const Assignment &assignment); - void copyOutConcrete(const MemoryObject *mo, const ObjectState *os) const; + void copyOutConcrete(const MemoryObject *mo, const ObjectState *os, + const Assignment &assignment) const; /// \brief Obtain an ObjectState suitable for writing. /// @@ -161,7 +163,7 @@ class AddressSpace { /// /// \retval true The copy succeeded. /// \retval false The copy failed because a read-only object was modified. - bool copyInConcretes(); + bool copyInConcretes(const Assignment &assignment); /// Updates the memory object with the raw memory from the address /// @@ -170,7 +172,7 @@ class AddressSpace { /// @param src_address the address to copy from /// @return bool copyInConcrete(const MemoryObject *mo, const ObjectState *os, - uint64_t src_address); + uint64_t src_address, const Assignment &assignment); }; } // namespace klee diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index 96f55a2b3a..dd34b18d5d 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -32,6 +32,7 @@ #include "TimingSolver.h" #include "TypeManager.h" #include "UserSearcher.h" +#include "klee/ADT/SparseStorage.h" #include "klee/Core/Context.h" #include "klee/ADT/KTest.h" @@ -254,6 +255,13 @@ cl::opt DelayCoverOnTheFly( "(default=10000)"), cl::cat(TestGenCat)); +cl::opt UninitMemoryTestMultiplier( + "uninit-memory-test-multiplier", cl::init(6), + cl::desc("Generate additional number of duplicate tests due to " + "irreproducibility of uninitialized memory " + "(default=6)"), + cl::cat(TestGenCat)); + /* Constraint solving options */ cl::opt MaxSymArraySize( @@ -744,10 +752,9 @@ void Executor::allocateGlobalObjects(ExecutionState &state) { true, nullptr, 8); errnoObj->isFixed = true; - // TODO: unused variable - ObjectState *os = bindObjectInState( - state, errnoObj, typeSystemManager->getWrappedType(pointerErrnoAddr), - false); + bindObjectInState(state, errnoObj, + typeSystemManager->getWrappedType(pointerErrnoAddr), + false); errno_addr = reinterpret_cast(errnoObj->address); } else { errno_addr = getErrnoLocation(state); @@ -900,7 +907,8 @@ void Executor::initializeGlobalObjects(ExecutionState &state) { for (const GlobalVariable &v : m->globals()) { MemoryObject *mo = globalObjects.find(&v)->second; ObjectState *os = bindObjectInState( - state, mo, typeSystemManager->getWrappedType(v.getType()), false); + state, mo, typeSystemManager->getWrappedType(v.getType()), false, + nullptr); if (v.isDeclaration() && mo->size) { // Program already running -> object already initialized. @@ -934,11 +942,9 @@ void Executor::initializeGlobalObjects(ExecutionState &state) { if (v.isConstant()) { os->setReadOnly(true); // initialise constant memory that may be used with external calls - state.addressSpace.copyOutConcrete(mo, os); + state.addressSpace.copyOutConcrete(mo, os, {}); } } - } else { - os->initializeToRandom(); } } } @@ -2339,7 +2345,7 @@ void Executor::executeCall(ExecutionState &state, KInstruction *ki, Function *f, const ObjectState *osarg = state.addressSpace.findObject(idObject).second; assert(osarg); - for (unsigned i = 0; i < osarg->size; i++) + for (unsigned i = 0; i < osarg->getObject()->size; i++) os->write(offsets[k] + i, osarg->read8(i)); } if (ati != f->arg_end()) { @@ -4870,19 +4876,7 @@ void Executor::callExternalFunction(ExecutionState &state, KInstruction *target, assert(success && "FIXME: Unhandled solver failure"); (void)success; ce->toMemory(&args[wordIndex]); - IDType result; addConstraint(state, EqExpr::create(ce, *ai)); - // Checking to see if the argument is a pointer to something - llvm::Type *argumentType = nullptr; - if (ati != functionType->param_end()) { - argumentType = const_cast(*ati); - } - if (ce->getWidth() == Context::get().getPointerWidth() && - state.addressSpace.resolveOne( - ce, typeSystemManager->getWrappedType(argumentType), result)) { - state.addressSpace.findObject(result).second->flushToConcreteStore( - solver.get(), state); - } wordIndex += (ce->getWidth() + 63) / 64; } else { ref arg = toUnique(state, *ai); @@ -4907,7 +4901,12 @@ void Executor::callExternalFunction(ExecutionState &state, KInstruction *target, } // Prepare external memory for invoking the function - state.addressSpace.copyOutConcretes(); + auto arrays = state.constraints.cs().gatherArrays(); + std::vector> values; + solver->getInitialValues(state.constraints.cs(), arrays, values, + state.queryMetaData); + Assignment assignment(arrays, values); + state.addressSpace.copyOutConcretes(assignment); #ifndef WINDOWS // Update external errno state with local state value IDType idResult; @@ -4979,7 +4978,7 @@ void Executor::callExternalFunction(ExecutionState &state, KInstruction *target, return; } - if (!state.addressSpace.copyInConcretes()) { + if (!state.addressSpace.copyInConcretes(assignment)) { terminateStateOnExecError(state, "external modified read-only object", StateTerminationType::External); return; @@ -4989,7 +4988,7 @@ void Executor::callExternalFunction(ExecutionState &state, KInstruction *target, // Update errno memory object with the errno value from the call int error = externalDispatcher->getLastErrno(); state.addressSpace.copyInConcrete(result.first, result.second, - (uint64_t)&error); + (uint64_t)&error, assignment); #endif Type *resultType = target->inst->getType(); @@ -5068,6 +5067,7 @@ void Executor::executeAlloc(ExecutionState &state, ref size, bool isLocal, KInstruction *target, KType *type, bool zeroMemory, const ObjectState *reallocFrom, size_t allocationAlignment, bool checkOutOfMemory) { + static unsigned allocations = 0; const llvm::Value *allocSite = state.prevPC->inst; if (allocationAlignment == 0) { allocationAlignment = getAllocationAlignment(allocSite); @@ -5109,12 +5109,15 @@ void Executor::executeAlloc(ExecutionState &state, ref size, bool isLocal, if (!mo) { bindLocal(target, state, Expr::createPointer(0)); } else { - ObjectState *os = bindObjectInState(state, mo, type, isLocal); + ref source = nullptr; if (zeroMemory) { - os->initializeToZero(); + source = SourceBuilder::constant( + SparseStorage(ConstantExpr::create(0, Expr::Int8))); } else { - os->initializeToRandom(); + source = SourceBuilder::uninitialized(allocations++, target); } + auto array = makeArray(size, source); + ObjectState *os = bindObjectInState(state, mo, type, isLocal, array); ref address = mo->getBaseExpr(); if (checkOutOfMemory) { @@ -5128,10 +5131,7 @@ void Executor::executeAlloc(ExecutionState &state, ref size, bool isLocal, bindLocal(target, state, address); if (reallocFrom) { - unsigned count = std::min(reallocFrom->size, os->size); - for (unsigned i = 0; i < count; i++) { - os->write(i, reallocFrom->read8(i)); - } + os->write(reallocFrom); state.removePointerResolutions(reallocFrom->getObject()); state.addressSpace.unbindObject(reallocFrom->getObject()); } @@ -5427,13 +5427,18 @@ MemoryObject *Executor::allocate(ExecutionState &state, ref size, Expr::Width pointerWidthInBits = Context::get().getPointerWidth(); /* Create symbol for array */ + KInstruction *ki = nullptr; + if (!lazyInitializationSource) { + auto inst = cast(allocSite); + ki = kmodule->getKBlock(inst->getParent())->parent->instructionMap[inst]; + } const Array *addressArray = makeArray( Expr::createPointer(pointerWidthInBits / CHAR_BIT), lazyInitializationSource ? SourceBuilder::lazyInitializationAddress(lazyInitializationSource) : SourceBuilder::symbolicSizeConstantAddress( - 0, updateNameVersion(state, "const_arr"))); + updateNameVersion(state, "const_arr"), ki, size)); ref addressExpr = Expr::createTempRead(addressArray, pointerWidthInBits); @@ -6412,19 +6417,21 @@ void Executor::updateStateWithSymcretes(ExecutionState &state, continue; } - ObjectPair oldOp = state.addressSpace.findObject(newMO->id); - ref oldMO(oldOp.first); - ref oldOS(oldOp.second); - if (!oldOS) { + ObjectPair op = state.addressSpace.findObject(newMO->id); + + if (!op.second) { continue; } + /* Create a new ObjectState with the new size and new owning memory * object. */ - /* Order of operations critical here. */ - state.addressSpace.unbindObject(oldMO.get()); - state.addressSpace.bindObject(newMO, new ObjectState(newMO, *oldOS.get())); + auto wos = new ObjectState( + *(state.addressSpace.getWriteable(op.first, op.second))); + wos->swapObjectHack(newMO); + state.addressSpace.unbindObject(op.first); + state.addressSpace.bindObject(newMO, wos); } } @@ -6453,8 +6460,8 @@ void Executor::executeMakeSymbolic(ExecutionState &state, ObjectState *os = bindObjectInState(state, mo, type, isLocal, array); if (AlignSymbolicPointers) { - if (ref alignmentRestrictions = - type->getContentRestrictions(os->read(0, os->size * CHAR_BIT))) { + if (ref alignmentRestrictions = type->getContentRestrictions( + os->read(0, os->getObject()->size * CHAR_BIT))) { addConstraint(state, alignmentRestrictions); } } @@ -6473,7 +6480,7 @@ void Executor::executeMakeSymbolic(ExecutionState &state, if (!obj) { if (ZeroSeedExtension) { si.assignment.bindings.replace( - {array, SparseStorage(mo->size, 0)}); + {array, SparseStorage(0)}); } else if (!AllowSeedExtension) { terminateStateOnUserError(state, "ran out of inputs during seeding"); @@ -6498,12 +6505,8 @@ void Executor::executeMakeSymbolic(ExecutionState &state, si.assignment.bindings.end()) { values = si.assignment.bindings.at(array); } - values.resize(std::min(mo->size, obj->numBytes)); values.store(0, obj->bytes, obj->bytes + std::min(obj->numBytes, mo->size)); - if (ZeroSeedExtension) { - values.resize(mo->size); - } si.assignment.bindings.replace({array, values}); } } @@ -7114,6 +7117,15 @@ bool isReproducible(const klee::Symbolic &symb) { return !bad; } +bool isUninitialized(const klee::Array *array) { + bool bad = isa(array->source); + if (bad) + klee_warning_once(array->source.get(), + "A uninitialized array %s reaches a test", + array->getIdentifier().c_str()); + return bad; +} + bool Executor::getSymbolicSolution(const ExecutionState &state, KTest &res) { solver->setTimeout(coreSolverTimeout); @@ -7150,6 +7162,13 @@ bool Executor::getSymbolicSolution(const ExecutionState &state, KTest &res) { } } + std::vector allObjects; + findSymbolicObjects(state.constraints.cs().cs().begin(), + state.constraints.cs().cs().end(), allObjects); + std::vector uninitObjects; + std::copy_if(allObjects.begin(), allObjects.end(), + std::back_inserter(uninitObjects), isUninitialized); + std::vector symbolics; std::copy_if(state.symbolics.begin(), state.symbolics.end(), std::back_inserter(symbolics), isReproducible); @@ -7161,6 +7180,7 @@ bool Executor::getSymbolicSolution(const ExecutionState &state, KTest &res) { } bool success = solver->getInitialValues(extendedConstraints.cs(), objects, values, state.queryMetaData); + Assignment assignment(objects, values); solver->setTimeout(time::Span()); if (!success) { klee_warning("unable to compute initial values (invalid constraints?)!"); @@ -7171,20 +7191,24 @@ bool Executor::getSymbolicSolution(const ExecutionState &state, KTest &res) { res.numObjects = symbolics.size(); res.objects = new KTestObject[res.numObjects]; + res.uninitCoeff = uninitObjects.size() * UninitMemoryTestMultiplier; { size_t i = 0; + // Remove mo->size, evaluate size expr in array for (auto &symbolic : symbolics) { auto mo = symbolic.memoryObject; KTestObject *o = &res.objects[i]; o->name = const_cast(mo->name.c_str()); o->address = mo->address; - o->numBytes = values[i].size(); + o->numBytes = mo->size; o->bytes = new unsigned char[o->numBytes]; - std::copy(values[i].begin(), values[i].end(), o->bytes); + for (size_t j = 0; j < mo->size; j++) { + o->bytes[j] = values[i].load(j); + } o->numPointers = 0; o->pointers = nullptr; - ++i; + i++; } } diff --git a/lib/Core/Executor.h b/lib/Core/Executor.h index a7e0df7160..5a4f8bc554 100644 --- a/lib/Core/Executor.h +++ b/lib/Core/Executor.h @@ -287,7 +287,7 @@ class Executor : public Interpreter { ObjectState *bindObjectInState(ExecutionState &state, const MemoryObject *mo, KType *dynamicType, bool IsAlloca, - const Array *array = 0); + const Array *array = nullptr); /// Resolve a pointer to the memory objects it could point to the /// start of, forking execution when necessary and generating errors diff --git a/lib/Core/Memory.cpp b/lib/Core/Memory.cpp index f85ea95b3b..dd8496baba 100644 --- a/lib/Core/Memory.cpp +++ b/lib/Core/Memory.cpp @@ -39,14 +39,6 @@ DISABLE_WARNING_POP using namespace llvm; using namespace klee; -namespace { -cl::opt - UseConstantArrays("use-constant-arrays", - cl::desc("Use constant arrays instead of updates when " - "possible (default=true)\n"), - cl::init(true), cl::cat(SolvingCat)); -} - /***/ IDType MemoryObject::counter = 1; @@ -81,99 +73,21 @@ void MemoryObject::getAllocInfo(std::string &result) const { /***/ -ObjectState::ObjectState(const MemoryObject *mo, KType *dt) - : copyOnWriteOwner(0), object(mo), concreteStore(new uint8_t[mo->size]), - concreteMask(nullptr), knownSymbolics(nullptr), unflushedMask(nullptr), - updates(nullptr, nullptr), lastUpdate(nullptr), dynamicType(dt), - size(mo->size), readOnly(false) { - if (!UseConstantArrays) { - static unsigned id = 0; - const Array *array = getArrayCache()->CreateArray( - mo->getSizeExpr(), SourceBuilder::makeSymbolic("tmp_arr", ++id)); - updates = UpdateList(array, 0); - } - memset(concreteStore, 0, size); -} - ObjectState::ObjectState(const MemoryObject *mo, const Array *array, KType *dt) - : copyOnWriteOwner(0), object(mo), concreteStore(new uint8_t[mo->size]), - concreteMask(nullptr), knownSymbolics(nullptr), unflushedMask(nullptr), - updates(array, nullptr), lastUpdate(nullptr), dynamicType(dt), - size(mo->size), readOnly(false) { - makeSymbolic(); - memset(concreteStore, 0, size); -} + : copyOnWriteOwner(0), object(mo), knownSymbolics(nullptr), + unflushedMask(false), updates(array, nullptr), lastUpdate(nullptr), + size(array->size), dynamicType(dt), readOnly(false) {} -ObjectState::ObjectState(const ObjectState &os) - : copyOnWriteOwner(0), object(os.object), - concreteStore(new uint8_t[os.size]), - concreteMask(os.concreteMask ? new BitArray(*os.concreteMask, os.size) - : nullptr), - knownSymbolics(nullptr), - unflushedMask(os.unflushedMask ? new BitArray(*os.unflushedMask, os.size) - : nullptr), - updates(os.updates), wasZeroInitialized(os.wasZeroInitialized), - lastUpdate(os.lastUpdate), dynamicType(os.dynamicType), size(os.size), - readOnly(os.readOnly) { - if (os.knownSymbolics) { - knownSymbolics = new ref[size]; - for (unsigned i = 0; i < size; i++) - knownSymbolics[i] = os.knownSymbolics[i]; - } - - memcpy(concreteStore, os.concreteStore, size * sizeof(*concreteStore)); -} - -ObjectState::ObjectState(const MemoryObject *mo, const ObjectState &os) - : copyOnWriteOwner(0), object(mo), concreteStore(new uint8_t[mo->size]), - concreteMask(os.concreteMask ? new BitArray(*os.concreteMask, mo->size) - : nullptr), - knownSymbolics(nullptr), - unflushedMask(os.unflushedMask ? new BitArray(*os.unflushedMask, mo->size) - : nullptr), - updates(os.updates), wasZeroInitialized(os.wasZeroInitialized), - lastUpdate(os.lastUpdate), dynamicType(os.getDynamicType()), - size(mo->size), readOnly(os.readOnly) { - /* This constructor should be used when we extend or truncate the memory - for MemoryObject and want to leave content from previous ObjectState. Maybe - it is good to make it a method, not a constructor. */ - unsigned copyingRange = std::min(size, os.size); - - if (os.knownSymbolics) { - knownSymbolics = new ref[size]; - for (unsigned i = 0; i < copyingRange; ++i) { - knownSymbolics[i] = os.knownSymbolics[i]; - } - } - - if (updates.root && - (isa_and_nonnull(updates.root->source) || - isa_and_nonnull( - updates.root->source))) { - /* As now we cannot make only a part of object symbolic, - we will mark all remain bytes as symbolic. */ - for (unsigned i = copyingRange; i < size; ++i) { - markByteSymbolic(i); - setKnownSymbolic(i, 0); - markByteFlushed(i); - } - } - - memcpy(concreteStore, os.concreteStore, - copyingRange * sizeof(*concreteStore)); - // FIXME: 0xAB is a magical number here... Move to constant. - memset(reinterpret_cast(concreteStore) + - copyingRange * sizeof(*concreteStore), - os.wasZeroInitialized ? 0 : 0xAB, - (size - copyingRange) * sizeof(*concreteStore)); -} +ObjectState::ObjectState(const MemoryObject *mo, KType *dt) + : copyOnWriteOwner(0), object(mo), knownSymbolics(nullptr), + unflushedMask(false), updates(nullptr, nullptr), lastUpdate(nullptr), + size(mo->getSizeExpr()), dynamicType(dt), readOnly(false) {} -ObjectState::~ObjectState() { - delete concreteMask; - delete unflushedMask; - delete[] knownSymbolics; - delete[] concreteStore; -} +ObjectState::ObjectState(const ObjectState &os) + : copyOnWriteOwner(0), object(os.object), knownSymbolics(os.knownSymbolics), + unflushedMask(os.unflushedMask), updates(os.updates), + lastUpdate(os.lastUpdate), size(os.size), dynamicType(os.dynamicType), + readOnly(os.readOnly) {} ArrayCache *ObjectState::getArrayCache() const { assert(object && "object was NULL"); @@ -184,248 +98,66 @@ ArrayCache *ObjectState::getArrayCache() const { const UpdateList &ObjectState::getUpdates() const { // Constant arrays are created lazily. - if (!updates.root) { - // Collect the list of writes, with the oldest writes first. - - // FIXME: We should be able to do this more efficiently, we just need to be - // careful to get the interaction with the cache right. In particular we - // should avoid creating UpdateNode instances we never use. - unsigned NumWrites = updates.head ? updates.head->getSize() : 0; - std::vector, ref>> Writes(NumWrites); - const auto *un = updates.head.get(); - for (unsigned i = NumWrites; i != 0; un = un->next.get()) { - --i; - Writes[i] = std::make_pair(un->index, un->value); - } - - /* For objects of symbolic size we will leave last constant - sizes for every index and create constant array (in terms of - Z3 solver) filled with zeros. This part is required for reads - from unitialzed memory. */ - std::vector> Contents(size); - - // Initialize to zeros. - for (unsigned i = 0, e = size; i != e; ++i) - Contents[i] = ConstantExpr::create(0, Expr::Int8); - - // Pull off as many concrete writes as we can. - unsigned Begin = 0, End = Writes.size(); - for (; Begin != End; ++Begin) { - // Push concrete writes into the constant array. - ConstantExpr *Index = dyn_cast(Writes[Begin].first); - if (!Index) - break; - - ConstantExpr *Value = dyn_cast(Writes[Begin].second); - if (!Value) - break; - - Contents[Index->getZExtValue()] = Value; - } - static unsigned id = 0; - std::string arrayName = "const_arr" + llvm::utostr(++id); - const Array *array = nullptr; - - if (object->hasSymbolicSize()) { - /* Extend updates with last written non-zero constant values. - ConstantValues must be empty in constant array. */ - array = getArrayCache()->CreateArray( - object->getSizeExpr(), SourceBuilder::symbolicSizeConstant(0)); - updates = UpdateList(array, 0); - for (unsigned idx = 0; idx < size; ++idx) { - if (!Contents[idx]->getZExtValue()) { - updates.extend(ConstantExpr::create(idx, Expr::Int32), Contents[idx]); + if (auto sizeExpr = dyn_cast(size)) { + auto size = sizeExpr->getZExtValue(); + if (knownSymbolics.storage().size() == size) { + SparseStorage> values( + ConstantExpr::create(0, Expr::Int8)); + UpdateList symbolicUpdates = UpdateList(nullptr, nullptr); + for (unsigned i = 0; i < size; i++) { + auto value = knownSymbolics.load(i); + assert(value); + if (isa(value)) { + values.store(i, cast(value)); + } else { + symbolicUpdates.extend(ConstantExpr::create(i, Expr::Int32), value); } } - } else { - array = getArrayCache()->CreateArray(object->getSizeExpr(), - SourceBuilder::constant(Contents)); - updates = UpdateList(array, 0); - } - - // Apply the remaining (non-constant) writes. - for (; Begin != End; ++Begin) - updates.extend(Writes[Begin].first, Writes[Begin].second); - } - - return updates; -} - -void ObjectState::flushToConcreteStore(TimingSolver *solver, - const ExecutionState &state) const { - for (unsigned i = 0; i < size; i++) { - if (isByteKnownSymbolic(i)) { - ref ce; - bool success = solver->getValue(state.constraints.cs(), read8(i), ce, - state.queryMetaData); - if (!success) - klee_warning("Solver timed out when getting a value for external call, " - "byte %p+%u will have random value", - (void *)object->address, i); - else - ce->toMemory(concreteStore + i); + auto array = getArrayCache()->CreateArray( + sizeExpr, SourceBuilder::constant(values)); + updates = UpdateList(array, symbolicUpdates.head); + knownSymbolics.reset(); + unflushedMask.reset(); } } -} - -void ObjectState::makeConcrete() { - delete concreteMask; - delete unflushedMask; - delete[] knownSymbolics; - concreteMask = nullptr; - unflushedMask = nullptr; - knownSymbolics = nullptr; -} - -void ObjectState::makeSymbolic() { - assert(!updates.head && - "XXX makeSymbolic of objects with symbolic values is unsupported"); - // XXX simplify this, can just delete various arrays I guess - for (unsigned i = 0; i < size; i++) { - markByteSymbolic(i); - setKnownSymbolic(i, 0); - markByteFlushed(i); - } -} -void ObjectState::initializeToZero() { - makeConcrete(); - wasZeroInitialized = true; - memset(concreteStore, 0, size); -} - -void ObjectState::initializeToRandom() { - makeConcrete(); - wasZeroInitialized = false; - memset(concreteStore, 0xAB, size); -} - -/* -Cache Invariants --- -isByteKnownSymbolic(i) => !isByteConcrete(i) -isByteConcrete(i) => !isByteKnownSymbolic(i) -isByteUnflushed(i) => (isByteConcrete(i) || isByteKnownSymbolic(i)) - */ - -void ObjectState::fastRangeCheckOffset(ref offset, unsigned *base_r, - unsigned *size_r) const { - *base_r = 0; - *size_r = size; -} - -void ObjectState::flushRangeForRead(unsigned rangeBase, - unsigned rangeSize) const { - if (!unflushedMask) - unflushedMask = new BitArray(size, true); - - for (unsigned offset = rangeBase; offset < rangeBase + rangeSize; offset++) { - if (isByteUnflushed(offset)) { - if (isByteConcrete(offset)) { - updates.extend(ConstantExpr::create(offset, Expr::Int32), - ConstantExpr::create(concreteStore[offset], Expr::Int8)); - } else { - assert(isByteKnownSymbolic(offset) && - "invalid bit set in unflushedMask"); - updates.extend(ConstantExpr::create(offset, Expr::Int32), - knownSymbolics[offset]); - } - - unflushedMask->unset(offset); - } - } -} - -void ObjectState::flushRangeForWrite(unsigned rangeBase, unsigned rangeSize) { - if (!unflushedMask) - unflushedMask = new BitArray(size, true); - - for (unsigned offset = rangeBase; offset < rangeBase + rangeSize; offset++) { - if (isByteUnflushed(offset)) { - if (isByteConcrete(offset)) { - updates.extend(ConstantExpr::create(offset, Expr::Int32), - ConstantExpr::create(concreteStore[offset], Expr::Int8)); - markByteSymbolic(offset); - } else { - assert(isByteKnownSymbolic(offset) && - "invalid bit set in unflushedMask"); - updates.extend(ConstantExpr::create(offset, Expr::Int32), - knownSymbolics[offset]); - setKnownSymbolic(offset, 0); - } - - unflushedMask->unset(offset); - } else { - // flushed bytes that are written over still need - // to be marked out - if (isByteConcrete(offset)) { - markByteSymbolic(offset); - } else if (isByteKnownSymbolic(offset)) { - setKnownSymbolic(offset, 0); - } - } + if (!updates.root) { + SparseStorage> values( + ConstantExpr::create(0, Expr::Int8)); + auto array = + getArrayCache()->CreateArray(size, SourceBuilder::constant(values)); + updates = UpdateList(array, updates.head); } -} - -bool ObjectState::isByteConcrete(unsigned offset) const { - return !concreteMask || concreteMask->get(offset); -} -bool ObjectState::isByteUnflushed(unsigned offset) const { - return !unflushedMask || unflushedMask->get(offset); -} - -bool ObjectState::isByteKnownSymbolic(unsigned offset) const { - return knownSymbolics && knownSymbolics[offset].get(); -} - -void ObjectState::markByteConcrete(unsigned offset) { - if (concreteMask) - concreteMask->set(offset); -} + assert(updates.root); -void ObjectState::markByteSymbolic(unsigned offset) { - if (!concreteMask) - concreteMask = new BitArray(size, true); - concreteMask->unset(offset); -} - -void ObjectState::markByteUnflushed(unsigned offset) { - if (unflushedMask) - unflushedMask->set(offset); + return updates; } -void ObjectState::markByteFlushed(unsigned offset) { - if (!unflushedMask) { - unflushedMask = new BitArray(size, false); - } else { - unflushedMask->unset(offset); +void ObjectState::flushForRead() const { + for (const auto &unflushed : unflushedMask.storage()) { + auto offset = unflushed.first; + assert(knownSymbolics.load(offset)); + updates.extend(ConstantExpr::create(offset, Expr::Int32), + knownSymbolics.load(offset)); } + unflushedMask.reset(false); } -void ObjectState::setKnownSymbolic(unsigned offset, - Expr *value /* can be null */) { - if (knownSymbolics) { - knownSymbolics[offset] = value; - } else { - if (value) { - knownSymbolics = new ref[size]; - knownSymbolics[offset] = value; - } - } +void ObjectState::flushForWrite() { + flushForRead(); + // The write is symbolic offset and might overwrite any byte + knownSymbolics.reset(nullptr); } /***/ ref ObjectState::read8(unsigned offset) const { - if (isByteConcrete(offset)) { - return ConstantExpr::create(concreteStore[offset], Expr::Int8); - } else if (isByteKnownSymbolic(offset)) { - return knownSymbolics[offset]; + if (auto byte = knownSymbolics.load(offset)) { + return byte; } else { - assert(!isByteUnflushed(offset) && "unflushed byte without cache value"); - + assert(!unflushedMask.load(offset) && "unflushed byte without cache value"); return ReadExpr::create(getUpdates(), ConstantExpr::create(offset, Expr::Int32)); } @@ -434,11 +166,9 @@ ref ObjectState::read8(unsigned offset) const { ref ObjectState::read8(ref offset) const { assert(!isa(offset) && "constant offset passed to symbolic read8"); - unsigned base, size; - fastRangeCheckOffset(offset, &base, &size); - flushRangeForRead(base, size); + flushForRead(); - if (size > 4096) { + if (object && object->size > 4096) { std::string allocInfo; object->getAllocInfo(allocInfo); klee_warning_once( @@ -446,19 +176,22 @@ ref ObjectState::read8(ref offset) const { "Symbolic memory access will send the following array of %d bytes to " "the constraint solver -- large symbolic arrays may cause significant " "performance issues: %s", - size, allocInfo.c_str()); + object->size, allocInfo.c_str()); } return ReadExpr::create(getUpdates(), ZExtExpr::create(offset, Expr::Int32)); } void ObjectState::write8(unsigned offset, uint8_t value) { - // assert(read_only == false && "writing to read-only object!"); - concreteStore[offset] = value; - setKnownSymbolic(offset, 0); - - markByteConcrete(offset); - markByteUnflushed(offset); + auto byte = knownSymbolics.load(offset); + if (byte) { + auto ce = dyn_cast(byte); + if (ce && ce->getZExtValue(8) == value) { + return; + } + } + knownSymbolics.store(offset, ConstantExpr::create(value, Expr::Int8)); + unflushedMask.store(offset, true); } void ObjectState::write8(unsigned offset, ref value) { @@ -466,21 +199,21 @@ void ObjectState::write8(unsigned offset, ref value) { if (ConstantExpr *CE = dyn_cast(value)) { write8(offset, (uint8_t)CE->getZExtValue(8)); } else { - setKnownSymbolic(offset, value.get()); - - markByteSymbolic(offset); - markByteUnflushed(offset); + auto byte = knownSymbolics.load(offset); + if (byte && byte == value) { + return; + } + knownSymbolics.store(offset, value); + unflushedMask.store(offset, true); } } void ObjectState::write8(ref offset, ref value) { assert(!isa(offset) && "constant offset passed to symbolic write8"); - unsigned base, size; - fastRangeCheckOffset(offset, &base, &size); - flushRangeForWrite(base, size); + flushForWrite(); - if (size > 4096) { + if (object && object->size > 4096) { std::string allocInfo; object->getAllocInfo(allocInfo); klee_warning_once( @@ -488,12 +221,19 @@ void ObjectState::write8(ref offset, ref value) { "Symbolic memory access will send the following array of %d bytes to " "the constraint solver -- large symbolic arrays may cause significant " "performance issues: %s", - size, allocInfo.c_str()); + object->size, allocInfo.c_str()); } updates.extend(ZExtExpr::create(offset, Expr::Int32), value); } +void ObjectState::write(ref os) { + knownSymbolics = os->knownSymbolics; + unflushedMask = os->unflushedMask; + updates = UpdateList(updates.root, os->updates.head); + lastUpdate = os->lastUpdate; +} + /***/ ref ObjectState::read(ref offset, Expr::Width width) const { @@ -642,14 +382,13 @@ void ObjectState::print() const { llvm::errs() << "-- ObjectState --\n"; llvm::errs() << "\tMemoryObject ID: " << object->id << "\n"; llvm::errs() << "\tRoot Object: " << updates.root << "\n"; - llvm::errs() << "\tSize: " << size << "\n"; + llvm::errs() << "\tSize: " << object->size << "\n"; llvm::errs() << "\tBytes:\n"; - for (unsigned i = 0; i < size; i++) { + for (unsigned i = 0; i < object->size; i++) { llvm::errs() << "\t\t[" << i << "]" - << " concrete? " << isByteConcrete(i) << " known-sym? " - << isByteKnownSymbolic(i) << " unflushed? " - << isByteUnflushed(i) << " = "; + << " known? " << !knownSymbolics.load(i).isNull() + << " unflushed? " << unflushedMask.load(i) << " = "; ref e = read8(i); llvm::errs() << e << "\n"; } diff --git a/lib/Core/Memory.h b/lib/Core/Memory.h index 503faca93a..7b072ddcf1 100644 --- a/lib/Core/Memory.h +++ b/lib/Core/Memory.h @@ -12,6 +12,8 @@ #include "MemoryManager.h" #include "TimingSolver.h" +#include "klee/ADT/Ref.h" +#include "klee/ADT/SparseStorage.h" #include "klee/Core/Context.h" #include "klee/Expr/Assignment.h" @@ -209,57 +211,42 @@ class ObjectState { ref object; - /// @brief Holds all known concrete bytes - uint8_t *concreteStore; - - /// @brief concreteMask[byte] is set if byte is known to be concrete - BitArray *concreteMask; - - /// knownSymbolics[byte] holds the symbolic expression for byte, - /// if byte is known to be symbolic - ref *knownSymbolics; + /// knownSymbolics[byte] holds the expression for byte, + /// if byte is known + mutable SparseStorage, OptionalRefEq> knownSymbolics; /// unflushedMask[byte] is set if byte is unflushed /// mutable because may need flushed during read of const - mutable BitArray *unflushedMask; + mutable SparseStorage unflushedMask; // mutable because we may need flush during read of const mutable UpdateList updates; - bool wasZeroInitialized = true; - ref lastUpdate; + ref size; + KType *dynamicType; public: - unsigned size; - bool readOnly; public: - /// Create a new object state for the given memory object with concrete - /// contents. The initial contents are undefined, it is the callers - /// responsibility to initialize the object contents appropriately. + /// Create a new object state for the given memory + // For objects in memory + ObjectState(const MemoryObject *mo, const Array *array, KType *dt); ObjectState(const MemoryObject *mo, KType *dt); - /// Create a new object state for the given memory object with symbolic - /// contents. - ObjectState(const MemoryObject *mo, const Array *array, KType *dt); - ObjectState(const MemoryObject *mo, const ObjectState &os); + // For symbolic objects not in memory (hack) ObjectState(const ObjectState &os); - ~ObjectState(); + ~ObjectState() = default; const MemoryObject *getObject() const { return object.get(); } void setReadOnly(bool ro) { readOnly = ro; } - /// Make contents all concrete and zero - void initializeToZero(); - - /// Make contents all concrete and random - void initializeToRandom(); + void swapObjectHack(MemoryObject *mo) { object = mo; } ref read(ref offset, Expr::Width width) const; ref read(unsigned offset, Expr::Width width) const; @@ -267,6 +254,7 @@ class ObjectState { void write(unsigned offset, ref value); void write(ref offset, ref value); + void write(ref os); void write8(unsigned offset, uint8_t value); void write16(unsigned offset, uint16_t value); @@ -274,13 +262,6 @@ class ObjectState { void write64(unsigned offset, uint64_t value); void print() const; - /* - Looks at all the symbolic bytes of this object, gets a value for them - from the solver and puts them in the concreteStore. - */ - void flushToConcreteStore(TimingSolver *solver, - const ExecutionState &state) const; - bool isAccessableFrom(KType *) const; KType *getDynamicType() const; @@ -290,31 +271,12 @@ class ObjectState { void makeConcrete(); - void makeSymbolic(); - ref read8(ref offset) const; void write8(unsigned offset, ref value); void write8(ref offset, ref value); - void fastRangeCheckOffset(ref offset, unsigned *base_r, - unsigned *size_r) const; - void flushRangeForRead(unsigned rangeBase, unsigned rangeSize) const; - void flushRangeForWrite(unsigned rangeBase, unsigned rangeSize); - - /// isByteConcrete ==> !isByteKnownSymbolic - bool isByteConcrete(unsigned offset) const; - - /// isByteKnownSymbolic ==> !isByteConcrete - bool isByteKnownSymbolic(unsigned offset) const; - - /// isByteUnflushed(i) => (isByteConcrete(i) || isByteKnownSymbolic(i)) - bool isByteUnflushed(unsigned offset) const; - - void markByteConcrete(unsigned offset); - void markByteSymbolic(unsigned offset); - void markByteFlushed(unsigned offset); - void markByteUnflushed(unsigned offset); - void setKnownSymbolic(unsigned offset, Expr *value); + void flushForRead() const; + void flushForWrite(); ArrayCache *getArrayCache() const; }; diff --git a/lib/Expr/ArrayCache.cpp b/lib/Expr/ArrayCache.cpp index afea585300..3962278f6c 100644 --- a/lib/Expr/ArrayCache.cpp +++ b/lib/Expr/ArrayCache.cpp @@ -11,41 +11,25 @@ ArrayCache::~ArrayCache() { ai != e; ++ai) { delete *ai; } - for (ArrayPtrVec::iterator ai = concreteArrays.begin(), - e = concreteArrays.end(); - ai != e; ++ai) { - delete *ai; - } } const Array *ArrayCache::CreateArray(ref _size, ref _source, Expr::Width _domain, Expr::Width _range) { - const Array *array = new Array(_size, _source, _domain, _range, getNextID()); - if (array->isSymbolicArray()) { - std::pair success = - cachedSymbolicArrays.insert(array); - if (success.second) { - // Cache miss - return array; - } - // Cache hit - delete array; - array = *(success.first); - assert(array->isSymbolicArray() && - "Cached symbolic array is no longer symbolic"); - return array; - } else { - // Treat every constant array as distinct so we never cache them - assert(array->isConstantArray()); - concreteArrays.push_back(array); // For deletion later + auto id = allocatedCount[_source->getKind()]; + const Array *array = new Array(_size, _source, _domain, _range, id); + std::pair success = + cachedSymbolicArrays.insert(array); + if (success.second) { + // Cache miss + allocatedCount[_source->getKind()]++; return array; } -} - -unsigned ArrayCache::getNextID() const { - return cachedSymbolicArrays.size() + concreteArrays.size(); + // Cache hit + delete array; + array = *(success.first); + return array; } } // namespace klee diff --git a/lib/Expr/ArrayExprOptimizer.cpp b/lib/Expr/ArrayExprOptimizer.cpp index d67bd3ddbd..205685fdd6 100644 --- a/lib/Expr/ArrayExprOptimizer.cpp +++ b/lib/Expr/ArrayExprOptimizer.cpp @@ -198,6 +198,7 @@ bool ExprOptimizer::computeIndexes(array2idx_ty &arrays, const ref &e, // For each constant array found for (auto &element : arrays) { const Array *arr = element.first; + auto arraySize = cast(arr->size)->getZExtValue(); assert(arr->isConstantArray() && "Array is not concrete"); assert(element.second.size() == 1 && "Multiple indexes on the same array"); @@ -224,8 +225,7 @@ bool ExprOptimizer::computeIndexes(array2idx_ty &arrays, const ref &e, // For each concrete value 'i' stored in the array if (ref constantSource = cast(arr->source)) { - for (size_t aIdx = 0; aIdx < constantSource->constantValues.size(); - aIdx += width) { + for (size_t aIdx = 0; aIdx < arraySize; aIdx += width) { auto *a = new Assignment(); std::vector objects; std::vector> values; @@ -302,7 +302,8 @@ ref ExprOptimizer::getSelectOptExpr( std::vector> arrayConstValues; if (ref constantSource = dyn_cast(read->updates.root->source)) { - arrayConstValues = constantSource->constantValues; + arrayConstValues = + constantSource->constantValues.getFirstNIndexes(size); } for (auto it = us.rbegin(); it != us.rend(); it++) { const UpdateNode *un = *it; @@ -377,7 +378,8 @@ ref ExprOptimizer::getSelectOptExpr( std::vector> arrayConstValues; if (ref constantSource = dyn_cast(read->updates.root->source)) { - arrayConstValues = constantSource->constantValues; + arrayConstValues = + constantSource->constantValues.getFirstNIndexes(size); } if (arrayConstValues.size() < size) { // We need to "force" initialization of the values diff --git a/lib/Expr/Assignment.cpp b/lib/Expr/Assignment.cpp index 1cc7a76e1c..860f1a0a50 100644 --- a/lib/Expr/Assignment.cpp +++ b/lib/Expr/Assignment.cpp @@ -22,10 +22,13 @@ void Assignment::dump() const { } for (bindings_ty::iterator i = bindings.begin(), e = bindings.end(); i != e; ++i) { - llvm::errs() << (*i).first->getName() << "\n["; - for (int j = 0, k = (*i).second.size(); j < k; ++j) - llvm::errs() << (int)(*i).second.load(j) << ","; - llvm::errs() << "]\n"; + llvm::errs() << (*i).first->getName() << "\n"; + Density d = + ((*i).second.storage().size() * 2 < (*i).second.sizeOfSetRange()) + ? Density::Sparse + : Density::Dense; + (*i).second.print(llvm::errs(), d); + llvm::errs() << "\n"; } } diff --git a/lib/Expr/CMakeLists.txt b/lib/Expr/CMakeLists.txt index 758a4ca743..03137ef820 100644 --- a/lib/Expr/CMakeLists.txt +++ b/lib/Expr/CMakeLists.txt @@ -32,6 +32,10 @@ add_library(kleaverExpr Updates.cpp ) +target_link_libraries(kleaverExpr PRIVATE + kleeADT +) + llvm_config(kleaverExpr "${USE_LLVM_SHARED}" support) target_include_directories(kleaverExpr PRIVATE ${KLEE_INCLUDE_DIRS} ${LLVM_INCLUDE_DIRS}) target_compile_options(kleaverExpr PRIVATE ${KLEE_COMPONENT_CXX_FLAGS}) diff --git a/lib/Expr/Expr.cpp b/lib/Expr/Expr.cpp index 5d301e0d7c..c889af5ed4 100644 --- a/lib/Expr/Expr.cpp +++ b/lib/Expr/Expr.cpp @@ -1482,22 +1482,7 @@ Array::Array(ref _size, ref _source, Expr::Width _domain, Expr::Width _range, unsigned _id) : size(_size), source(_source), domain(_domain), range(_range), id(_id) { ref constantSize = dyn_cast(size); - assert( - (!isa(_source) || - cast(_source)->size() == constantSize->getZExtValue()) && - "Invalid size for constant array!"); computeHash(); -#ifndef NDEBUG - if (isa(_source)) { - for (const ref * - it = cast(_source)->constantValues.data(), - *end = cast(_source)->constantValues.data() + - cast(_source)->constantValues.size(); - it != end; ++it) - assert((*it)->getWidth() == getRange() && - "Invalid initial constant value!"); - } -#endif // NDEBUG std::set allArrays = _source->getRelatedArrays(); std::vector sizeArrays; @@ -1546,6 +1531,22 @@ ref ReadExpr::create(const UpdateList &ul, ref index) { } } + // So that we return weird stuff like reads from consts that should have + // simplified to constant exprs if we read beyond size boundary. + if (auto source = dyn_cast(ul.root->source)) { + if (auto arraySizeExpr = dyn_cast(ul.root->size)) { + if (auto indexExpr = dyn_cast(index)) { + auto arraySize = arraySizeExpr->getZExtValue(); + auto concreteIndex = indexExpr->getZExtValue(); + if (concreteIndex >= arraySize) { + return ReadExpr::alloc(ul, index); + } + } + } else { + return ReadExpr::alloc(ul, index); + } + } + if (isa(ul.root->source) && !updateListHasSymbolicWrites) { // No updates with symbolic index to a constant array have been found if (ConstantExpr *CE = dyn_cast(index)) { @@ -1553,9 +1554,8 @@ ref ReadExpr::create(const UpdateList &ul, ref index) { ref constantSource = cast(ul.root->source); uint64_t concreteIndex = CE->getZExtValue(); - uint64_t size = constantSource->constantValues.size(); - if (concreteIndex < size) { - return constantSource->constantValues[concreteIndex]; + if (auto value = constantSource->constantValues.load(concreteIndex)) { + return value; } } } @@ -2268,12 +2268,14 @@ static ref TryConstArrayOpt(const ref &cl, ReadExpr *rd) { // for now, just assume standard "flushing" of a concrete array, // where the concrete array has one update for each index, in order + auto arraySize = dyn_cast(rd->updates.root->size); + assert(arraySize); + auto size = arraySize->getZExtValue(); ref res = ConstantExpr::alloc(0, Expr::Bool); if (ref constantSource = dyn_cast(rd->updates.root->source)) { - for (unsigned i = 0, e = constantSource->constantValues.size(); i != e; - ++i) { - if (cl == constantSource->constantValues[i]) { + for (unsigned i = 0, e = size; i != e; ++i) { + if (cl == constantSource->constantValues.load(i)) { // Arbitrary maximum on the size of disjunction. if (++numMatches > 100) return EqExpr_create(cl, rd); diff --git a/lib/Expr/ExprEvaluator.cpp b/lib/Expr/ExprEvaluator.cpp index bcadb59156..418640769a 100644 --- a/lib/Expr/ExprEvaluator.cpp +++ b/lib/Expr/ExprEvaluator.cpp @@ -32,15 +32,10 @@ ExprVisitor::Action ExprEvaluator::evalRead(const UpdateList &ul, if (ref constantSource = dyn_cast(ul.root->source)) { - if (index < constantSource->constantValues.size()) { - return Action::changeTo(constantSource->constantValues[index]); + if (auto value = constantSource->constantValues.load(index)) { + return Action::changeTo(value); } } - if (ref symbolicSizeConstantSource = - dyn_cast(ul.root->source)) { - return Action::changeTo(ConstantExpr::create( - symbolicSizeConstantSource->defaultValue, ul.root->getRange())); - } return Action::changeTo(getInitialValue(*ul.root, index)); } diff --git a/lib/Expr/ExprPPrinter.cpp b/lib/Expr/ExprPPrinter.cpp index 165b438025..46d4a1072b 100644 --- a/lib/Expr/ExprPPrinter.cpp +++ b/lib/Expr/ExprPPrinter.cpp @@ -385,19 +385,16 @@ class PPrinter : public ExprPPrinter { void printSource(ref source, PrintContext &PC) { PC << "("; PC << source->getName() << " "; + if (auto s = dyn_cast(source)) { - PC << " ["; - for (unsigned i = 0; i < s->constantValues.size(); i++) { - PC << s->constantValues[i]; - if (i != s->constantValues.size() - 1) { - PC << " "; - } - } - PC << "]"; - } else if (auto s = dyn_cast(source)) { - PC << s->defaultValue; + s->constantValues.print(PC.getStream(), Density::Sparse); } else if (auto s = dyn_cast(source)) { - PC << s->defaultValue << " " << s->version; + PC << s->version << " "; + s->allocSite->getID().print(PC.getStream()); + PC << " " << s->size; + } else if (auto s = dyn_cast(source)) { + PC << s->version << " "; + s->allocSite->getID().print(PC.getStream()); } else if (auto s = dyn_cast(source)) { PC << s->name << " " << s->version; } else if (auto s = dyn_cast(source)) { diff --git a/lib/Expr/ExprSMTLIBPrinter.cpp b/lib/Expr/ExprSMTLIBPrinter.cpp index e1a9b9aa89..ea0315ce4e 100644 --- a/lib/Expr/ExprSMTLIBPrinter.cpp +++ b/lib/Expr/ExprSMTLIBPrinter.cpp @@ -557,7 +557,11 @@ namespace { struct ArrayPtrsByName { bool operator()(const Array *a1, const Array *a2) const { - return a1->id < a2->id; + if (a1->source->getKind() != a2->source->getKind()) { + return a1->source->getKind() < a2->source->getKind(); + } else { + return a1->id < a2->id; + } } }; @@ -613,14 +617,8 @@ void ExprSMTLIBPrinter::printArrayDeclarations() { << " " << array->getDomain() << ") )"; printSeperator(); - if (ref symbolicSizeConstantSource = - dyn_cast(array->source)) { - printConstant(ConstantExpr::create( - symbolicSizeConstantSource->defaultValue, array->getRange())); - } else if (ref constantSource = - cast(array->source)) { - printConstant(constantSource->constantValues[byteIndex]); - } + auto source = dyn_cast(array->source); + printConstant(source->constantValues.load(byteIndex)); p->popIndent(); printSeperator(); diff --git a/lib/Expr/IndependentSet.cpp b/lib/Expr/IndependentSet.cpp index 3acca539c9..feb3d26583 100644 --- a/lib/Expr/IndependentSet.cpp +++ b/lib/Expr/IndependentSet.cpp @@ -90,8 +90,6 @@ void IndependentConstraintSet::addValuesToAssignment( for (unsigned i = 0; i < objects.size(); i++) { if (assign.bindings.count(objects[i])) { SparseStorage value = assign.bindings.at(objects[i]); - assert(value.size() == values[i].size() && - "we're talking about the same array here"); DenseSet ds = (elements.find(objects[i]))->second; for (std::set::iterator it2 = ds.begin(); it2 != ds.end(); it2++) { diff --git a/lib/Expr/Lexer.cpp b/lib/Expr/Lexer.cpp index 9be58ae5ce..acbb29b9dc 100644 --- a/lib/Expr/Lexer.cpp +++ b/lib/Expr/Lexer.cpp @@ -54,6 +54,10 @@ const char *Token::getKindName() const { return "KWQuery"; case KWPath: return "KWPath"; + case KWDefault: + return "KWDefault"; + case KWNull: + return "KWNull"; case KWReserved: return "KWReserved"; case KWSymbolic: @@ -180,6 +184,8 @@ Token &Lexer::SetIdentifierTokenKind(Token &Result) { return SetTokenKind(Result, Token::KWTrue); if (memcmp("path", Result.start, 4) == 0) return SetTokenKind(Result, Token::KWPath); + if (memcmp("null", Result.start, 4) == 0) + return SetTokenKind(Result, Token::KWNull); break; case 5: @@ -199,6 +205,8 @@ Token &Lexer::SetIdentifierTokenKind(Token &Result) { case 7: if (memcmp("declare", Result.start, 7) == 0) return SetTokenKind(Result, Token::KWReserved); + if (memcmp("default", Result.start, 7) == 0) + return SetTokenKind(Result, Token::KWDefault); break; case 8: diff --git a/lib/Expr/Parser.cpp b/lib/Expr/Parser.cpp index b072cec826..19b72f7321 100644 --- a/lib/Expr/Parser.cpp +++ b/lib/Expr/Parser.cpp @@ -322,7 +322,6 @@ class ParserImpl : public Parser { SourceResult ParseSource(); SourceResult ParseConstantSource(); - SourceResult ParseSymbolicSizeConstantSource(); SourceResult ParseSymbolicSizeConstantAddressSource(); SourceResult ParseMakeSymbolicSource(); SourceResult ParseLazyInitializationContentSource(); @@ -483,8 +482,6 @@ SourceResult ParserImpl::ParseSource() { SourceResult source; if (type == "constant") { source = ParseConstantSource(); - } else if (type == "symbolicSizeConstant") { - source = ParseSymbolicSizeConstantSource(); } else if (type == "symbolicSizeConstantAddress") { source = ParseSymbolicSizeConstantAddressSource(); } else if (type == "makeSymbolic") { @@ -509,39 +506,69 @@ SourceResult ParserImpl::ParseSource() { } SourceResult ParserImpl::ParseConstantSource() { - std::vector> Values; - ConsumeLSquare(); - while (Tok.kind != Token::RSquare) { - if (Tok.kind == Token::EndOfFile) { - Error("unexpected end of file."); - assert(0); + std::unordered_map> storage; + ref defaultValue = nullptr; + + if (Tok.kind == Token::LSquare) { + ConsumeLSquare(); + unsigned index = 0; + while (Tok.kind != Token::RSquare) { + if (Tok.kind == Token::EndOfFile) { + Error("unexpected end of file."); + assert(0); + } + ExprResult Res = ParseNumber(8).get(); // Should be Range Type + storage.insert({index, cast(Res.get())}); + if (Tok.kind == Token::Comma) { + ConsumeExpectedToken(Token::Comma); + } + index++; } - - ExprResult Res = ParseNumber(8); // Should be Range Type - if (Res.isValid()) - Values.push_back(cast(Res.get())); + ConsumeRSquare(); + } else if (Tok.kind == Token::LBrace) { + ConsumeExpectedToken(Token::LBrace); + while (Tok.kind != Token::RBrace) { + if (Tok.kind == Token::EndOfFile) { + Error("unexpected end of file."); + assert(0); + } + ExprResult Index = ParseNumber(64).get(); + ConsumeExpectedToken(Token::Colon); + ExprResult Res = ParseNumber(8).get(); // Should be Range Type + storage.insert({cast(Index.get())->getZExtValue(), + cast(Res.get())}); + if (Tok.kind == Token::Comma) { + ConsumeExpectedToken(Token::Comma); + } + } + ConsumeExpectedToken(Token::RBrace); + } else { + assert(0 && "Parsing error"); } - ConsumeRSquare(); - return SourceBuilder::constant(Values); -} -SourceResult ParserImpl::ParseSymbolicSizeConstantSource() { - auto valueExpr = ParseNumber(64).get(); - if (auto ce = dyn_cast(valueExpr)) { - return SourceBuilder::symbolicSizeConstant(ce->getZExtValue()); + ConsumeExpectedToken(Token::KWDefault); + ConsumeExpectedToken(Token::Colon); + + if (Tok.kind != Token::KWNull) { + ExprResult DV = ParseNumber(8).get(); // Should be Range Type + defaultValue = cast(DV.get()); } else { - assert(0); + ConsumeExpectedToken(Token::KWNull); } + + SparseStorage> Values(storage, defaultValue); + return SourceBuilder::constant(Values); } SourceResult ParserImpl::ParseSymbolicSizeConstantAddressSource() { - auto valueExpr = ParseNumber(64).get(); - auto versionExpr = ParseNumber(64).get(); - auto value = dyn_cast(valueExpr); - auto version = dyn_cast(versionExpr); - assert(value && version); - return SourceBuilder::symbolicSizeConstantAddress(value->getZExtValue(), - version->getZExtValue()); + assert(0 && "unimplemented"); + // auto valueExpr = ParseNumber(64).get(); + // auto versionExpr = ParseNumber(64).get(); + // auto value = dyn_cast(valueExpr); + // auto version = dyn_cast(versionExpr); + // assert(value && version); + // return SourceBuilder::symbolicSizeConstantAddress(value->getZExtValue(), + // version->getZExtValue()); } SourceResult ParserImpl::ParseMakeSymbolicSource() { diff --git a/lib/Expr/SourceBuilder.cpp b/lib/Expr/SourceBuilder.cpp index a667a19ba2..2a3a09908d 100644 --- a/lib/Expr/SourceBuilder.cpp +++ b/lib/Expr/SourceBuilder.cpp @@ -1,4 +1,5 @@ #include "klee/Expr/SourceBuilder.h" +#include "klee/ADT/SparseStorage.h" #include "klee/Expr/Expr.h" #include "klee/Expr/SymbolicSource.h" #include "klee/Module/KModule.h" @@ -6,23 +7,23 @@ using namespace klee; ref -SourceBuilder::constant(const std::vector> &constantValues) { +SourceBuilder::constant(SparseStorage> constantValues) { ref r(new ConstantSource(constantValues)); r->computeHash(); return r; } -ref SourceBuilder::symbolicSizeConstant(unsigned defaultValue) { - ref r(new SymbolicSizeConstantSource(defaultValue)); +ref +SourceBuilder::uninitialized(unsigned version, const KInstruction *allocSite) { + ref r(new UninitializedSource(version, allocSite)); r->computeHash(); return r; } -ref -SourceBuilder::symbolicSizeConstantAddress(unsigned defaultValue, - unsigned version) { +ref SourceBuilder::symbolicSizeConstantAddress( + unsigned version, const KInstruction *allocSite, ref size) { ref r( - new SymbolicSizeConstantAddressSource(defaultValue, version)); + new SymbolicSizeConstantAddressSource(version, allocSite, size)); r->computeHash(); return r; } @@ -86,4 +87,4 @@ ref SourceBuilder::irreproducible(const std::string &name) { ref r(new IrreproducibleSource(name + llvm::utostr(++id))); r->computeHash(); return r; -} \ No newline at end of file +} diff --git a/lib/Expr/SymbolicSource.cpp b/lib/Expr/SymbolicSource.cpp index 9d8d3b6e58..1f78147c2b 100644 --- a/lib/Expr/SymbolicSource.cpp +++ b/lib/Expr/SymbolicSource.cpp @@ -46,27 +46,74 @@ std::set LazyInitializationSource::getRelatedArrays() const { } unsigned ConstantSource::computeHash() { - unsigned res = 0; - for (unsigned i = 0, e = constantValues.size(); i != e; ++i) { - res = - (res * SymbolicSource::MAGIC_HASH_CONSTANT) + constantValues[i]->hash(); + auto defaultV = constantValues.defaultV(); + auto ordered = constantValues.calculateOrderedStorage(); + + unsigned res = (getKind() * SymbolicSource::MAGIC_HASH_CONSTANT) + + (defaultV ? defaultV->hash() : 0); + + for (auto kv : ordered) { + res = (res * SymbolicSource::MAGIC_HASH_CONSTANT) + kv.first; + res = (res * SymbolicSource::MAGIC_HASH_CONSTANT) + kv.second->hash(); } - res = (res * SymbolicSource::MAGIC_HASH_CONSTANT) + getKind(); + hashValue = res; return hashValue; } -unsigned SymbolicSizeConstantSource::computeHash() { - unsigned res = - (getKind() * SymbolicSource::MAGIC_HASH_CONSTANT) + defaultValue; +unsigned UninitializedSource::computeHash() { + unsigned res = getKind(); + res = res * SymbolicSource::MAGIC_HASH_CONSTANT + version; + res = res * SymbolicSource::MAGIC_HASH_CONSTANT + allocSite->hash(); hashValue = res; return hashValue; } +int UninitializedSource::internalCompare(const SymbolicSource &b) const { + if (getKind() != b.getKind()) { + return getKind() < b.getKind() ? -1 : 1; + } + const UninitializedSource &ub = static_cast(b); + + if (version != ub.version) { + return version < ub.version ? -1 : 1; + } + + if (allocSite != ub.allocSite) { + return allocSite->getGlobalIndex() < ub.allocSite->getGlobalIndex() ? -1 + : 1; + } + + return 0; +} + +int SymbolicSizeConstantAddressSource::internalCompare( + const SymbolicSource &b) const { + if (getKind() != b.getKind()) { + return getKind() < b.getKind() ? -1 : 1; + } + const SymbolicSizeConstantAddressSource &ub = + static_cast(b); + + if (version != ub.version) { + return version < ub.version ? -1 : 1; + } + if (size != ub.size) { + return size < ub.size ? -1 : 1; + } + if (allocSite != ub.allocSite) { + return allocSite->getGlobalIndex() < ub.allocSite->getGlobalIndex() ? -1 + : 1; + } + + return 0; +} + unsigned SymbolicSizeConstantAddressSource::computeHash() { - unsigned res = - (getKind() * SymbolicSource::MAGIC_HASH_CONSTANT) + defaultValue; - res = (res * SymbolicSource::MAGIC_HASH_CONSTANT) + version; + unsigned res = getKind(); + res = res * MAGIC_HASH_CONSTANT + version; + res = res * MAGIC_HASH_CONSTANT + allocSite->hash(); + res = res * MAGIC_HASH_CONSTANT + size->hash(); hashValue = res; return hashValue; } @@ -117,21 +164,14 @@ int InstructionSource::internalCompare(const SymbolicSource &b) const { } assert(km == ib.km); auto function = allocSite.getParent()->getParent(); - auto bFunction = ib.allocSite.getParent()->getParent(); - if (km->getFunctionId(function) != km->getFunctionId(bFunction)) { - return km->getFunctionId(function) < km->getFunctionId(bFunction) ? -1 : 1; - } auto kf = km->functionMap.at(function); - auto block = allocSite.getParent(); - auto bBlock = ib.allocSite.getParent(); - if (kf->blockMap[block]->getId() != kf->blockMap[bBlock]->getId()) { - return kf->blockMap[block]->getId() < kf->blockMap[bBlock]->getId() ? -1 - : 1; - } - if (kf->instructionMap[&allocSite]->getIndex() != - kf->instructionMap[&ib.allocSite]->getIndex()) { - return kf->instructionMap[&allocSite]->getIndex() < - kf->instructionMap[&ib.allocSite]->getIndex() + auto bfunction = ib.allocSite.getParent()->getParent(); + auto bkf = km->functionMap.at(bfunction); + + if (kf->instructionMap[&allocSite]->getGlobalIndex() != + bkf->instructionMap[&ib.allocSite]->getGlobalIndex()) { + return kf->instructionMap[&allocSite]->getGlobalIndex() < + bkf->instructionMap[&ib.allocSite]->getGlobalIndex() ? -1 : 1; } diff --git a/lib/Module/KInstruction.cpp b/lib/Module/KInstruction.cpp index b5c33fe41d..09497d344c 100644 --- a/lib/Module/KInstruction.cpp +++ b/lib/Module/KInstruction.cpp @@ -115,3 +115,7 @@ unsigned KInstruction::getDest() const { return parent->parent->getNumArgs() + getIndex() + (parent->instructions - parent->parent->instructions); } + +KInstruction::Index KInstruction::getID() const { + return {getGlobalIndex(), parent->getId(), parent->parent->id}; +} diff --git a/lib/Module/KModule.cpp b/lib/Module/KModule.cpp index b08cd6c62a..343974b472 100644 --- a/lib/Module/KModule.cpp +++ b/lib/Module/KModule.cpp @@ -482,7 +482,7 @@ void KModule::checkModule() { } } -KBlock *KModule::getKBlock(llvm::BasicBlock *bb) { +KBlock *KModule::getKBlock(const llvm::BasicBlock *bb) { return functionMap[bb->getParent()]->blockMap[bb]; } diff --git a/lib/Solver/CexCachingSolver.cpp b/lib/Solver/CexCachingSolver.cpp index 98a9f58149..20d35f8bd6 100644 --- a/lib/Solver/CexCachingSolver.cpp +++ b/lib/Solver/CexCachingSolver.cpp @@ -425,8 +425,7 @@ bool CexCachingSolver::computeInitialValues( cast(a)->evaluate(os->size); assert(arrayConstantSize && "Array of symbolic size had not receive value for size!"); - values[i] = - SparseStorage(arrayConstantSize->getZExtValue(), 0); + values[i] = SparseStorage(0); } else { values[i] = it->second; } diff --git a/lib/Solver/FastCexSolver.cpp b/lib/Solver/FastCexSolver.cpp index 3276b3d1be..f4c1b377aa 100644 --- a/lib/Solver/FastCexSolver.cpp +++ b/lib/Solver/FastCexSolver.cpp @@ -389,13 +389,9 @@ class CexRangeEvaluator : public ExprRangeEvaluator { if (array.isConstantArray() && index.isFixed()) { if (ref constantSource = dyn_cast(array.source)) { - if (index.min() < constantSource->constantValues.size()) { - return ValueRange( - constantSource->constantValues[index.min()]->getZExtValue(8)); + if (auto value = constantSource->constantValues.load(index.min())) { + return ValueRange(value->getZExtValue(8)); } - } else if (ref symbolicSizeConstantSource = - dyn_cast(array.source)) { - return ValueRange(symbolicSizeConstantSource->defaultValue); } } return ValueRange(0, 255); @@ -896,10 +892,11 @@ class CexData { if (ref constantSource = dyn_cast(array->source)) { // Verify the range. - propagateExactValues(constantSource->constantValues[index.min()], + if (!isa(array->size)) { + assert(0 && "Unimplemented"); + } + propagateExactValues(constantSource->constantValues.load(index.min()), range); - } else if (isa(array->source)) { - assert(0 && "not implemented"); } else { CexValueData cvd = cod.getExactValues(index.min()); if (range.min() > cvd.min()) { @@ -1195,7 +1192,6 @@ bool FastCexSolver::computeInitialValues( dyn_cast(cd.evaluatePossible(array->size)); assert(arrayConstantSize && "Array of symbolic size had not receive value for size!"); - data.resize(arrayConstantSize->getZExtValue()); for (unsigned i = 0; i < arrayConstantSize->getZExtValue(); i++) { ref read = ReadExpr::create( diff --git a/lib/Solver/MetaSMTBuilder.h b/lib/Solver/MetaSMTBuilder.h index b2418b8f91..6944402788 100644 --- a/lib/Solver/MetaSMTBuilder.h +++ b/lib/Solver/MetaSMTBuilder.h @@ -216,10 +216,11 @@ MetaSMTBuilder::getInitialArray(const Array *root) { bool hashed = _arr_hash.lookupArrayExpr(root, array_expr); if (!hashed) { - if (isa(root->source)) { - llvm::report_fatal_error("MetaSMT does not support constant arrays or " - "quantifiers to instantiate " - "constant array of symbolic size!"); + if (ref constantSource = + dyn_cast(root->source)) { + if (!isa(root->size)) { + assert(0 && "MetaSMT does not support symsize constant arrays"); + } } array_expr = @@ -227,14 +228,14 @@ MetaSMTBuilder::getInitialArray(const Array *root) { if (ref constantSource = dyn_cast(root->source)) { - uint64_t constantSize = cast(root->size)->getZExtValue(); - for (unsigned i = 0, e = constantSize; i != e; ++i) { + auto constantSize = cast(root->size)->getZExtValue(); + for (unsigned i = 0; i < constantSize; ++i) { typename SolverContext::result_type tmp = evaluate( _solver, metaSMT::logic::Array::store( array_expr, construct(ConstantExpr::alloc(i, root->getDomain()), 0), - construct(constantSource->constantValues[i], 0))); + construct(constantSource->constantValues.load(i), 0))); array_expr = tmp; } } @@ -705,6 +706,33 @@ MetaSMTBuilder::constructActual(ref e, int *width_out) { ReadExpr *re = cast(e); assert(re && re->updates.root); *width_out = re->updates.root->getRange(); + + if (auto constantSource = + dyn_cast(re->updates.root->source)) { + if (!isa(re->updates.root->size)) { + ref selectExpr = constantSource->constantValues.defaultV(); + for (const auto &[index, value] : + constantSource->constantValues.storage()) { + selectExpr = SelectExpr::create( + EqExpr::create(re->index, ConstantExpr::create( + index, re->index->getWidth())), + value, selectExpr); + } + std::vector update_nodes; + auto un = re->updates.head.get(); + for (; un; un = un->next.get()) { + update_nodes.push_back(un); + } + + for (auto it = update_nodes.rbegin(); it != update_nodes.rend(); ++it) { + selectExpr = + SelectExpr::create(EqExpr::create(re->index, (*it)->index), + (*it)->value, selectExpr); + } + return construct(selectExpr, width_out); + } + } + // FixMe call method of Array res = evaluate(_solver, metaSMT::logic::Array::select( getArrayForUpdate(re->updates.root, diff --git a/lib/Solver/MetaSMTSolver.cpp b/lib/Solver/MetaSMTSolver.cpp index f162013864..55ba6a4b4a 100644 --- a/lib/Solver/MetaSMTSolver.cpp +++ b/lib/Solver/MetaSMTSolver.cpp @@ -261,14 +261,7 @@ SolverImpl::SolverRunStatus MetaSMTSolverImpl::runAndGetCex( typename SolverContext::result_type array_exp = _builder->getInitialArray(array); - size_t constantSize = 0; - if (ref sizeExpr = dyn_cast(array->size)) { - constantSize = sizeExpr->getZExtValue(); - } else { - constantSize = - read_value(_meta_solver, _builder->construct(array->size)); - } - SparseStorage data(constantSize, 0); + SparseStorage data(0); for (unsigned offset : readOffsets.at(array)) { typename SolverContext::result_type elem_exp = evaluate( @@ -415,7 +408,6 @@ MetaSMTSolverImpl::runAndGetCexForked( values = std::vector>(objects.size()); for (unsigned i = 0; i < objects.size(); ++i) { SparseStorage &data = values[i]; - data.resize(shared_memory_sizes_ptr[i]); data.store(0, pos, pos + shared_memory_sizes_ptr[i]); pos += shared_memory_sizes_ptr[i]; } diff --git a/lib/Solver/STPBuilder.cpp b/lib/Solver/STPBuilder.cpp index 3ee8fbe2b7..b766111ed7 100644 --- a/lib/Solver/STPBuilder.cpp +++ b/lib/Solver/STPBuilder.cpp @@ -426,6 +426,14 @@ ExprHandle STPBuilder::constructSDivByConstant(ExprHandle expr_n, ::VCExpr STPBuilder::getInitialArray(const Array *root) { assert(root); + + if (ref constantSource = + dyn_cast(root->source)) { + if (!isa(root->size)) { + assert(0 && "STP does not support symsize constant arrays"); + } + } + ::VCExpr array_expr; bool hashed = _arr_hash.lookupArrayExpr(root, array_expr); @@ -433,13 +441,7 @@ ::VCExpr STPBuilder::getInitialArray(const Array *root) { // STP uniques arrays by name, so we make sure the name is unique by // using the size of the array hash as a counter. std::string unique_id = llvm::utostr(_arr_hash._array_hash.size()); - std::string unique_name = root->getName() + unique_id; - - if (isa(root->source)) { - llvm::report_fatal_error( - "STP does not support constant arrays or quantifiers to instantiate " - "constant array of symbolic size!"); - } + std::string unique_name = root->getIdentifier() + unique_id; array_expr = buildArray(unique_name.c_str(), root->getDomain(), root->getRange()); @@ -450,13 +452,13 @@ ::VCExpr STPBuilder::getInitialArray(const Array *root) { // using assertions, which is much faster, but we need to fix the caching // to work correctly in that case. + auto constSize = cast(root->size)->getZExtValue(); // TODO: usage of `constantValues.size()` seems unconvinient. - for (unsigned i = 0, e = constantSource->constantValues.size(); i != e; - ++i) { + for (unsigned i = 0; i < constSize; i++) { ::VCExpr prev = array_expr; array_expr = vc_writeExpr( vc, prev, construct(ConstantExpr::alloc(i, root->getDomain()), 0), - construct(constantSource->constantValues[i], 0)); + construct(constantSource->constantValues.load(i), 0)); vc_DeleteExpr(prev); } } @@ -568,6 +570,33 @@ ExprHandle STPBuilder::constructActual(ref e, int *width_out) { ReadExpr *re = cast(e); assert(re && re->updates.root); *width_out = re->updates.root->getRange(); + + if (auto constantSource = + dyn_cast(re->updates.root->source)) { + if (!isa(re->updates.root->size)) { + ref selectExpr = constantSource->constantValues.defaultV(); + for (const auto &[index, value] : + constantSource->constantValues.storage()) { + selectExpr = SelectExpr::create( + EqExpr::create(re->index, ConstantExpr::create( + index, re->index->getWidth())), + value, selectExpr); + } + std::vector update_nodes; + auto un = re->updates.head.get(); + for (; un; un = un->next.get()) { + update_nodes.push_back(un); + } + + for (auto it = update_nodes.rbegin(); it != update_nodes.rend(); ++it) { + selectExpr = + SelectExpr::create(EqExpr::create(re->index, (*it)->index), + (*it)->value, selectExpr); + } + return construct(selectExpr, width_out); + } + } + return vc_readExpr( vc, getArrayForUpdate(re->updates.root, re->updates.head.get()), construct(re->index, 0)); diff --git a/lib/Solver/STPSolver.cpp b/lib/Solver/STPSolver.cpp index 5927a90038..86679cc898 100644 --- a/lib/Solver/STPSolver.cpp +++ b/lib/Solver/STPSolver.cpp @@ -392,7 +392,7 @@ runAndGetCexForked(::VC vc, STPBuilder *builder, ::VCExpr q, values.reserve(objects.size()); for (unsigned idx = 0; idx < objects.size(); ++idx) { uint64_t objectSize = shared_memory_object_sizes[idx]; - values.emplace_back(objectSize, 0); + values.emplace_back(0); values.back().store(0, pos, pos + objectSize); pos += objectSize; } diff --git a/lib/Solver/Z3Builder.cpp b/lib/Solver/Z3Builder.cpp index e80feae88c..c26d8fb372 100644 --- a/lib/Solver/Z3Builder.cpp +++ b/lib/Solver/Z3Builder.cpp @@ -252,35 +252,47 @@ Z3ASTHandle Z3Builder::getInitialArray(const Array *root) { // using the size of the array hash as a counter. std::string unique_id = llvm::utostr(_arr_hash._array_hash.size()); std::string unique_name = root->getIdentifier() + unique_id; - if (ref symbolicSizeConstantSource = - dyn_cast(root->source)) { + + auto source = dyn_cast(root->source); + auto value = (source ? source->constantValues.defaultV() : nullptr); + if (source) { + assert(value); + } + + if (source && !isa(root->size)) { array_expr = buildConstantArray(unique_name.c_str(), root->getDomain(), - root->getRange(), - symbolicSizeConstantSource->defaultValue); + root->getRange(), value->getZExtValue(8)); } else { array_expr = buildArray(unique_name.c_str(), root->getDomain(), root->getRange()); } - if (root->isConstantArray() && constant_array_assertions.count(root) == 0) { - std::vector array_assertions; - if (ref constantSource = - dyn_cast(root->source)) { - for (unsigned i = 0, e = constantSource->constantValues.size(); i != e; - ++i) { + if (source) { + if (auto constSize = dyn_cast(root->size)) { + std::vector array_assertions; + for (size_t i = 0; i < constSize->getZExtValue(); i++) { + auto value = source->constantValues.load(i); // construct(= (select i root) root->value[i]) to be asserted in // Z3Solver.cpp int width_out; - Z3ASTHandle array_value = - construct(constantSource->constantValues[i], &width_out); + Z3ASTHandle array_value = construct(value, &width_out); assert(width_out == (int)root->getRange() && "Value doesn't match root range"); array_assertions.push_back( eqExpr(readExpr(array_expr, bvConst32(root->getDomain(), i)), array_value)); } + constant_array_assertions[root] = std::move(array_assertions); + } else { + for (auto [index, value] : source->constantValues.storage()) { + int width_out; + Z3ASTHandle array_value = construct(value, &width_out); + assert(width_out == (int)root->getRange() && + "Value doesn't match root range"); + array_expr = writeExpr( + array_expr, bvConst32(root->getDomain(), index), array_value); + } } - constant_array_assertions[root] = std::move(array_assertions); } _arr_hash.hashArrayExpr(root, array_expr); diff --git a/lib/Solver/Z3Solver.cpp b/lib/Solver/Z3Solver.cpp index d5f2232a6e..a485ebe83e 100644 --- a/lib/Solver/Z3Solver.cpp +++ b/lib/Solver/Z3Solver.cpp @@ -551,8 +551,8 @@ bool Z3SolverImpl::internalRunSolver( } for (auto constant_array : constant_arrays_in_query.results) { - assert(builder->constant_array_assertions.count(constant_array) == 1 && - "Constant array found in query, but not handled by Z3Builder"); + // assert(builder->constant_array_assertions.count(constant_array) == 1 && + // "Constant array found in query, but not handled by Z3Builder"); if (all_constant_arrays_in_query.count(constant_array)) continue; all_constant_arrays_in_query.insert(constant_array); @@ -701,7 +701,6 @@ SolverImpl::SolverRunStatus Z3SolverImpl::handleSolverResponse( Z3_get_numeral_uint64(builder->ctx, arraySizeExpr, &arraySize); assert(success && "Failed to get size"); - data.resize(arraySize); if (env.usedArrayBytes.count(array)) { std::unordered_set offsetValues; for (const ref &offsetExpr : env.usedArrayBytes.at(array)) { @@ -853,7 +852,8 @@ class Z3NonIncSolverImpl final : public Z3SolverImpl { auto arrays = query.gatherArrays(); bool forceTactic = true; for (auto array : arrays) { - if (isa(array->source)) { + if (isa(array->source) && + !isa(array->size)) { forceTactic = false; break; } diff --git a/test/Expr/Evaluate.kquery b/test/Expr/Evaluate.kquery index e6b0d1e1a4..b2fc41d746 100644 --- a/test/Expr/Evaluate.kquery +++ b/test/Expr/Evaluate.kquery @@ -17,7 +17,7 @@ arr12 : (array (w64 8) (makeSymbolic arr1 0)) # RUN: grep "Query 2: VALID" %t.log # Query 2 -constant0 : (array (w64 4) (constant [ 1 2 3 5 ])) +constant0 : (array (w64 4) (constant [1, 2, 3, 5] default: 0)) (query [] (Eq (Add w8 (Read w8 0 constant0) (Read w8 3 constant0)) 6)) diff --git a/test/Expr/print-smt-let.kquery b/test/Expr/print-smt-let.kquery index 871e6e4f29..974112a37c 100644 --- a/test/Expr/print-smt-let.kquery +++ b/test/Expr/print-smt-let.kquery @@ -1069,7 +1069,7 @@ makeSymbolic0 : (array (w64 4) (makeSymbolic unnamed_1 0)) [makeSymbolic0]) # Query 72 -- Type: InitialValues, Instructions: 30 -constant2 : (array (w64 4) (constant [121 101 115 0])) +constant2 : (array (w64 4) (constant [121, 101, 115, 0] default: 0)) makeSymbolic1 : (array (w64 4) (makeSymbolic unnamed 0)) makeSymbolic0 : (array (w64 4) (makeSymbolic unnamed_1 0)) (query [(Eq false @@ -1105,7 +1105,7 @@ makeSymbolic0 : (array (w64 4) (makeSymbolic unnamed_1 0)) # Query 74 -- Type: InitialValues, Instructions: 37 makeSymbolic1 : (array (w64 4) (makeSymbolic unnamed 0)) makeSymbolic0 : (array (w64 4) (makeSymbolic unnamed_1 0)) -constant2 : (array (w64 4) (constant [171 171 171 171])) +constant2 : (array (w64 4) (constant [171, 171, 171, 171] default: 0)) (query [(Eq false (Ult N0:(Mul w64 4 (SExt w64 (ReadLSB w32 0 makeSymbolic0))) @@ -1128,7 +1128,7 @@ constant2 : (array (w64 4) (constant [171 171 171 171])) # Query 75 -- Type: InitialValues, Instructions: 40 makeSymbolic1 : (array (w64 4) (makeSymbolic unnamed 0)) makeSymbolic0 : (array (w64 4) (makeSymbolic unnamed_1 0)) -constant2 : (array (w64 16) (constant [12 0 0 0 13 0 0 0 14 0 0 0 15 0 0 0])) +constant2 : (array (w64 16) (constant {0: 12, 4: 13, 8: 14, 12: 15} default: 0)) (query [(Ult N0:(Mul w64 4 (SExt w64 (ReadLSB w32 0 makeSymbolic0))) 13)] @@ -1141,7 +1141,7 @@ constant2 : (array (w64 16) (constant [12 0 0 0 13 0 0 0 14 0 0 0 15 0 0 0])) # Query 76 -- Type: InitialValues, Instructions: 50 makeSymbolic1 : (array (w64 4) (makeSymbolic unnamed 0)) makeSymbolic0 : (array (w64 4) (makeSymbolic unnamed_1 0)) -constant2 : (array (w64 4) (constant [171 171 171 171])) +constant2 : (array (w64 4) (constant [171, 171, 171, 171] default: 0)) (query [(Eq false (Ult N0:(Mul w64 4 (SExt w64 (ReadLSB w32 0 makeSymbolic0))) @@ -1160,7 +1160,7 @@ constant2 : (array (w64 4) (constant [171 171 171 171])) # Query 77 -- Type: InitialValues, Instructions: 51 makeSymbolic1 : (array (w64 4) (makeSymbolic unnamed 0)) makeSymbolic0 : (array (w64 4) (makeSymbolic unnamed_1 0)) -constant2 : (array (w64 16) (constant [12 0 0 0 13 0 0 0 14 0 0 0 15 0 0 0])) +constant2 : (array (w64 16) (constant {0: 12, 4: 13, 8: 14, 12: 15} default: 0)) (query [(Eq false (Ult N0:(Mul w64 4 (SExt w64 (ReadLSB w32 0 makeSymbolic0))) diff --git a/test/Expr/print-smt-let.smt2.good b/test/Expr/print-smt-let.smt2.good index d0ce68b168..05ea45d94e 100644 --- a/test/Expr/print-smt-let.smt2.good +++ b/test/Expr/print-smt-let.smt2.good @@ -859,19 +859,19 @@ ;SMTLIBv2 Query 72 (set-option :produce-models true) (set-logic QF_AUFBV ) +(declare-fun constant0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) (declare-fun makeSymbolic0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun constant1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun makeSymbolic2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(assert (= (select constant1 (_ bv0 32) ) (_ bv121 8) ) ) -(assert (= (select constant1 (_ bv1 32) ) (_ bv101 8) ) ) -(assert (= (select constant1 (_ bv2 32) ) (_ bv115 8) ) ) -(assert (= (select constant1 (_ bv3 32) ) (_ bv0 8) ) ) -(assert (let ( (?B1 (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) (let ( (?B2 (bvadd (_ bv31312 64) ?B1 ) ) ) (let ( (?B3 ((_ extract 31 0) ?B2 ) ) ) (and (and (not (= false (= (concat (select makeSymbolic2 (_ bv3 32) ) (concat (select makeSymbolic2 (_ bv2 32) ) (concat (select makeSymbolic2 (_ bv1 32) ) (select makeSymbolic2 (_ bv0 32) ) ) ) ) (concat (select constant1 (bvadd (_ bv3 32) ?B3 ) ) (concat (select constant1 (bvadd (_ bv2 32) ?B3 ) ) (concat (select constant1 (bvadd (_ bv1 32) ?B3 ) ) (select constant1 ?B3 ) ) ) ) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (bvult ?B2 (_ bv1 64) ) ) ) ) ) ) +(declare-fun makeSymbolic1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) +(assert (= (select constant0 (_ bv0 32) ) (_ bv121 8) ) ) +(assert (= (select constant0 (_ bv1 32) ) (_ bv101 8) ) ) +(assert (= (select constant0 (_ bv2 32) ) (_ bv115 8) ) ) +(assert (= (select constant0 (_ bv3 32) ) (_ bv0 8) ) ) +(assert (let ( (?B1 (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) (let ( (?B2 (bvadd (_ bv31312 64) ?B1 ) ) ) (let ( (?B3 ((_ extract 31 0) ?B2 ) ) ) (and (and (not (= false (= (concat (select makeSymbolic1 (_ bv3 32) ) (concat (select makeSymbolic1 (_ bv2 32) ) (concat (select makeSymbolic1 (_ bv1 32) ) (select makeSymbolic1 (_ bv0 32) ) ) ) ) (concat (select constant0 (bvadd (_ bv3 32) ?B3 ) ) (concat (select constant0 (bvadd (_ bv2 32) ?B3 ) ) (concat (select constant0 (bvadd (_ bv1 32) ?B3 ) ) (select constant0 ?B3 ) ) ) ) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (bvult ?B2 (_ bv1 64) ) ) ) ) ) ) (check-sat) -(get-value ( (select makeSymbolic2 (_ bv0 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv1 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv2 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv3 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv0 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv1 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv2 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv3 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv0 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv1 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv2 32) ) ) ) @@ -882,69 +882,69 @@ (set-option :produce-models true) (set-logic QF_AUFBV ) (declare-fun makeSymbolic0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun makeSymbolic2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(assert (let ( (?B1 (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) (let ( (?B2 (bvadd (_ bv18446744073709533360 64) ?B1 ) ) ) (let ( (?B3 ((_ extract 31 0) ?B2 ) ) ) (and (and (and (and (and (not (= (concat (select makeSymbolic2 (_ bv3 32) ) (concat (select makeSymbolic2 (_ bv2 32) ) (concat (select makeSymbolic2 (_ bv1 32) ) (select makeSymbolic2 (_ bv0 32) ) ) ) ) (concat (select makeSymbolic2 (bvadd (_ bv3 32) ?B3 ) ) (concat (select makeSymbolic2 (bvadd (_ bv2 32) ?B3 ) ) (concat (select makeSymbolic2 (bvadd (_ bv1 32) ?B3 ) ) (select makeSymbolic2 ?B3 ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) ?B1 ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv111120 64) ?B1 ) (_ bv1 64) ) ) ) (bvult ?B2 (_ bv1 64) ) ) ) ) ) ) +(declare-fun makeSymbolic1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) +(assert (let ( (?B1 (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) (let ( (?B2 (bvadd (_ bv18446744073709533360 64) ?B1 ) ) ) (let ( (?B3 ((_ extract 31 0) ?B2 ) ) ) (and (and (and (and (and (not (= (concat (select makeSymbolic1 (_ bv3 32) ) (concat (select makeSymbolic1 (_ bv2 32) ) (concat (select makeSymbolic1 (_ bv1 32) ) (select makeSymbolic1 (_ bv0 32) ) ) ) ) (concat (select makeSymbolic1 (bvadd (_ bv3 32) ?B3 ) ) (concat (select makeSymbolic1 (bvadd (_ bv2 32) ?B3 ) ) (concat (select makeSymbolic1 (bvadd (_ bv1 32) ?B3 ) ) (select makeSymbolic1 ?B3 ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) ?B1 ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv111120 64) ?B1 ) (_ bv1 64) ) ) ) (bvult ?B2 (_ bv1 64) ) ) ) ) ) ) (check-sat) (get-value ( (select makeSymbolic0 (_ bv0 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv1 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv2 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv3 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv0 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv1 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv2 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv3 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv0 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv1 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv2 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv3 32) ) ) ) (exit) ;SMTLIBv2 Query 74 (set-option :produce-models true) (set-logic QF_AUFBV ) +(declare-fun constant1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) (declare-fun makeSymbolic0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun makeSymbolic2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun constant3 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(assert (= (select constant3 (_ bv0 32) ) (_ bv171 8) ) ) -(assert (= (select constant3 (_ bv1 32) ) (_ bv171 8) ) ) -(assert (= (select constant3 (_ bv2 32) ) (_ bv171 8) ) ) -(assert (= (select constant3 (_ bv3 32) ) (_ bv171 8) ) ) -(assert (let ( (?B1 (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) (let ( (?B2 (bvadd (_ bv18446744073709533328 64) ?B1 ) ) ) (let ( (?B3 ((_ extract 31 0) ?B2 ) ) ) (and (and (and (and (and (and (not (= false (= (concat (select makeSymbolic2 (_ bv3 32) ) (concat (select makeSymbolic2 (_ bv2 32) ) (concat (select makeSymbolic2 (_ bv1 32) ) (select makeSymbolic2 (_ bv0 32) ) ) ) ) (concat (select constant3 (bvadd (_ bv3 32) ?B3 ) ) (concat (select constant3 (bvadd (_ bv2 32) ?B3 ) ) (concat (select constant3 (bvadd (_ bv1 32) ?B3 ) ) (select constant3 ?B3 ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) ?B1 ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv18446744073709533360 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult (bvadd (_ bv111120 64) ?B1 ) (_ bv1 64) ) ) ) (bvult ?B2 (_ bv1 64) ) ) ) ) ) ) +(declare-fun makeSymbolic1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) +(assert (= (select constant1 (_ bv0 32) ) (_ bv171 8) ) ) +(assert (= (select constant1 (_ bv1 32) ) (_ bv171 8) ) ) +(assert (= (select constant1 (_ bv2 32) ) (_ bv171 8) ) ) +(assert (= (select constant1 (_ bv3 32) ) (_ bv171 8) ) ) +(assert (let ( (?B1 (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) (let ( (?B2 (bvadd (_ bv18446744073709533328 64) ?B1 ) ) ) (let ( (?B3 ((_ extract 31 0) ?B2 ) ) ) (and (and (and (and (and (and (not (= false (= (concat (select makeSymbolic1 (_ bv3 32) ) (concat (select makeSymbolic1 (_ bv2 32) ) (concat (select makeSymbolic1 (_ bv1 32) ) (select makeSymbolic1 (_ bv0 32) ) ) ) ) (concat (select constant1 (bvadd (_ bv3 32) ?B3 ) ) (concat (select constant1 (bvadd (_ bv2 32) ?B3 ) ) (concat (select constant1 (bvadd (_ bv1 32) ?B3 ) ) (select constant1 ?B3 ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) ?B1 ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv18446744073709533360 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult (bvadd (_ bv111120 64) ?B1 ) (_ bv1 64) ) ) ) (bvult ?B2 (_ bv1 64) ) ) ) ) ) ) (check-sat) (get-value ( (select makeSymbolic0 (_ bv0 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv1 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv2 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv3 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv0 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv1 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv2 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv3 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv0 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv1 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv2 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv3 32) ) ) ) (exit) ;SMTLIBv2 Query 75 (set-option :produce-models true) (set-logic QF_AUFBV ) +(declare-fun constant2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) (declare-fun makeSymbolic0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun makeSymbolic2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun constant4 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(assert (= (select constant4 (_ bv0 32) ) (_ bv12 8) ) ) -(assert (= (select constant4 (_ bv1 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv2 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv3 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv4 32) ) (_ bv13 8) ) ) -(assert (= (select constant4 (_ bv5 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv6 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv7 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv8 32) ) (_ bv14 8) ) ) -(assert (= (select constant4 (_ bv9 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv10 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv11 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv12 32) ) (_ bv15 8) ) ) -(assert (= (select constant4 (_ bv13 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv14 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv15 32) ) (_ bv0 8) ) ) -(assert (let ( (?B1 (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) (let ( (?B2 ((_ extract 31 0) ?B1 ) ) ) (and (not (= false (= (concat (select makeSymbolic2 (_ bv3 32) ) (concat (select makeSymbolic2 (_ bv2 32) ) (concat (select makeSymbolic2 (_ bv1 32) ) (select makeSymbolic2 (_ bv0 32) ) ) ) ) (concat (select constant4 (bvadd (_ bv3 32) ?B2 ) ) (concat (select constant4 (bvadd (_ bv2 32) ?B2 ) ) (concat (select constant4 (bvadd (_ bv1 32) ?B2 ) ) (select constant4 ?B2 ) ) ) ) ) ) ) (bvult ?B1 (_ bv13 64) ) ) ) ) ) +(declare-fun makeSymbolic1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) +(assert (= (select constant2 (_ bv0 32) ) (_ bv12 8) ) ) +(assert (= (select constant2 (_ bv1 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv2 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv3 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv4 32) ) (_ bv13 8) ) ) +(assert (= (select constant2 (_ bv5 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv6 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv7 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv8 32) ) (_ bv14 8) ) ) +(assert (= (select constant2 (_ bv9 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv10 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv11 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv12 32) ) (_ bv15 8) ) ) +(assert (= (select constant2 (_ bv13 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv14 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv15 32) ) (_ bv0 8) ) ) +(assert (let ( (?B1 (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) (let ( (?B2 ((_ extract 31 0) ?B1 ) ) ) (and (not (= false (= (concat (select makeSymbolic1 (_ bv3 32) ) (concat (select makeSymbolic1 (_ bv2 32) ) (concat (select makeSymbolic1 (_ bv1 32) ) (select makeSymbolic1 (_ bv0 32) ) ) ) ) (concat (select constant2 (bvadd (_ bv3 32) ?B2 ) ) (concat (select constant2 (bvadd (_ bv2 32) ?B2 ) ) (concat (select constant2 (bvadd (_ bv1 32) ?B2 ) ) (select constant2 ?B2 ) ) ) ) ) ) ) (bvult ?B1 (_ bv13 64) ) ) ) ) ) (check-sat) -(get-value ( (select makeSymbolic2 (_ bv0 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv1 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv2 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv3 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv0 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv1 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv2 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv3 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv0 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv1 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv2 32) ) ) ) @@ -954,53 +954,53 @@ ;SMTLIBv2 Query 76 (set-option :produce-models true) (set-logic QF_AUFBV ) +(declare-fun constant1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) (declare-fun makeSymbolic0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun makeSymbolic2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun constant5 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(assert (= (select constant5 (_ bv0 32) ) (_ bv171 8) ) ) -(assert (= (select constant5 (_ bv1 32) ) (_ bv171 8) ) ) -(assert (= (select constant5 (_ bv2 32) ) (_ bv171 8) ) ) -(assert (= (select constant5 (_ bv3 32) ) (_ bv171 8) ) ) -(assert (let ( (?B1 (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) (let ( (?B2 (bvadd (_ bv111120 64) ?B1 ) ) ) (let ( (?B3 ((_ extract 31 0) ?B2 ) ) ) (and (and (and (and (not (= false (= (concat (select makeSymbolic2 (_ bv3 32) ) (concat (select makeSymbolic2 (_ bv2 32) ) (concat (select makeSymbolic2 (_ bv1 32) ) (select makeSymbolic2 (_ bv0 32) ) ) ) ) (concat (select constant5 (bvadd (_ bv3 32) ?B3 ) ) (concat (select constant5 (bvadd (_ bv2 32) ?B3 ) ) (concat (select constant5 (bvadd (_ bv1 32) ?B3 ) ) (select constant5 ?B3 ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) ?B1 ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (bvult ?B2 (_ bv1 64) ) ) ) ) ) ) +(declare-fun makeSymbolic1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) +(assert (= (select constant1 (_ bv0 32) ) (_ bv171 8) ) ) +(assert (= (select constant1 (_ bv1 32) ) (_ bv171 8) ) ) +(assert (= (select constant1 (_ bv2 32) ) (_ bv171 8) ) ) +(assert (= (select constant1 (_ bv3 32) ) (_ bv171 8) ) ) +(assert (let ( (?B1 (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) (let ( (?B2 (bvadd (_ bv111120 64) ?B1 ) ) ) (let ( (?B3 ((_ extract 31 0) ?B2 ) ) ) (and (and (and (and (not (= false (= (concat (select makeSymbolic1 (_ bv3 32) ) (concat (select makeSymbolic1 (_ bv2 32) ) (concat (select makeSymbolic1 (_ bv1 32) ) (select makeSymbolic1 (_ bv0 32) ) ) ) ) (concat (select constant1 (bvadd (_ bv3 32) ?B3 ) ) (concat (select constant1 (bvadd (_ bv2 32) ?B3 ) ) (concat (select constant1 (bvadd (_ bv1 32) ?B3 ) ) (select constant1 ?B3 ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) ?B1 ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (bvult ?B2 (_ bv1 64) ) ) ) ) ) ) (check-sat) (get-value ( (select makeSymbolic0 (_ bv0 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv1 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv2 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv3 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv0 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv1 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv2 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv3 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv0 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv1 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv2 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv3 32) ) ) ) (exit) ;SMTLIBv2 Query 77 (set-option :produce-models true) (set-logic QF_AUFBV ) +(declare-fun constant2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) (declare-fun makeSymbolic0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun makeSymbolic2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun constant6 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(assert (= (select constant6 (_ bv0 32) ) (_ bv12 8) ) ) -(assert (= (select constant6 (_ bv1 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv2 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv3 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv4 32) ) (_ bv13 8) ) ) -(assert (= (select constant6 (_ bv5 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv6 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv7 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv8 32) ) (_ bv14 8) ) ) -(assert (= (select constant6 (_ bv9 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv10 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv11 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv12 32) ) (_ bv15 8) ) ) -(assert (= (select constant6 (_ bv13 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv14 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv15 32) ) (_ bv0 8) ) ) -(assert (let ( (?B1 (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) (let ( (?B2 (bvadd (_ bv31760 64) ?B1 ) ) ) (let ( (?B3 ((_ extract 31 0) ?B2 ) ) ) (and (and (and (not (= false (= (concat (select makeSymbolic2 (_ bv3 32) ) (concat (select makeSymbolic2 (_ bv2 32) ) (concat (select makeSymbolic2 (_ bv1 32) ) (select makeSymbolic2 (_ bv0 32) ) ) ) ) (concat (select constant6 (bvadd (_ bv3 32) ?B3 ) ) (concat (select constant6 (bvadd (_ bv2 32) ?B3 ) ) (concat (select constant6 (bvadd (_ bv1 32) ?B3 ) ) (select constant6 ?B3 ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31312 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (bvult ?B2 (_ bv13 64) ) ) ) ) ) ) +(declare-fun makeSymbolic1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) +(assert (= (select constant2 (_ bv0 32) ) (_ bv12 8) ) ) +(assert (= (select constant2 (_ bv1 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv2 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv3 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv4 32) ) (_ bv13 8) ) ) +(assert (= (select constant2 (_ bv5 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv6 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv7 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv8 32) ) (_ bv14 8) ) ) +(assert (= (select constant2 (_ bv9 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv10 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv11 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv12 32) ) (_ bv15 8) ) ) +(assert (= (select constant2 (_ bv13 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv14 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv15 32) ) (_ bv0 8) ) ) +(assert (let ( (?B1 (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) (let ( (?B2 (bvadd (_ bv31760 64) ?B1 ) ) ) (let ( (?B3 ((_ extract 31 0) ?B2 ) ) ) (and (and (and (not (= false (= (concat (select makeSymbolic1 (_ bv3 32) ) (concat (select makeSymbolic1 (_ bv2 32) ) (concat (select makeSymbolic1 (_ bv1 32) ) (select makeSymbolic1 (_ bv0 32) ) ) ) ) (concat (select constant2 (bvadd (_ bv3 32) ?B3 ) ) (concat (select constant2 (bvadd (_ bv2 32) ?B3 ) ) (concat (select constant2 (bvadd (_ bv1 32) ?B3 ) ) (select constant2 ?B3 ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31312 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (bvult ?B2 (_ bv13 64) ) ) ) ) ) ) (check-sat) -(get-value ( (select makeSymbolic2 (_ bv0 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv1 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv2 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv3 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv0 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv1 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv2 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv3 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv0 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv1 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv2 32) ) ) ) @@ -1011,15 +1011,15 @@ (set-option :produce-models true) (set-logic QF_AUFBV ) (declare-fun makeSymbolic0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun makeSymbolic2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(assert (let ( (?B1 (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) (let ( (?B2 (bvadd (_ bv18446744073709532800 64) ?B1 ) ) ) (let ( (?B3 ((_ extract 31 0) ?B2 ) ) ) (and (and (and (and (and (and (and (not (= false (= (concat (select makeSymbolic2 (_ bv3 32) ) (concat (select makeSymbolic2 (_ bv2 32) ) (concat (select makeSymbolic2 (_ bv1 32) ) (select makeSymbolic2 (_ bv0 32) ) ) ) ) (concat (select makeSymbolic0 (bvadd (_ bv3 32) ?B3 ) ) (concat (select makeSymbolic0 (bvadd (_ bv2 32) ?B3 ) ) (concat (select makeSymbolic0 (bvadd (_ bv1 32) ?B3 ) ) (select makeSymbolic0 ?B3 ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) ?B1 ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv18446744073709533360 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult (bvadd (_ bv18446744073709533328 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult (bvadd (_ bv111120 64) ?B1 ) (_ bv1 64) ) ) ) (bvult ?B2 (_ bv1 64) ) ) ) ) ) ) +(declare-fun makeSymbolic1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) +(assert (let ( (?B1 (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) (let ( (?B2 (bvadd (_ bv18446744073709532800 64) ?B1 ) ) ) (let ( (?B3 ((_ extract 31 0) ?B2 ) ) ) (and (and (and (and (and (and (and (not (= false (= (concat (select makeSymbolic1 (_ bv3 32) ) (concat (select makeSymbolic1 (_ bv2 32) ) (concat (select makeSymbolic1 (_ bv1 32) ) (select makeSymbolic1 (_ bv0 32) ) ) ) ) (concat (select makeSymbolic0 (bvadd (_ bv3 32) ?B3 ) ) (concat (select makeSymbolic0 (bvadd (_ bv2 32) ?B3 ) ) (concat (select makeSymbolic0 (bvadd (_ bv1 32) ?B3 ) ) (select makeSymbolic0 ?B3 ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) ?B1 ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv18446744073709533360 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult (bvadd (_ bv18446744073709533328 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult (bvadd (_ bv111120 64) ?B1 ) (_ bv1 64) ) ) ) (bvult ?B2 (_ bv1 64) ) ) ) ) ) ) (check-sat) (get-value ( (select makeSymbolic0 (_ bv0 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv1 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv2 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv3 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv0 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv1 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv2 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv3 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv0 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv1 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv2 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv3 32) ) ) ) (exit) diff --git a/test/Expr/print-smt-named.kquery b/test/Expr/print-smt-named.kquery index 5e0112b2b7..78bbbd4ef1 100644 --- a/test/Expr/print-smt-named.kquery +++ b/test/Expr/print-smt-named.kquery @@ -1068,7 +1068,7 @@ makeSymbolic0 : (array (w64 4) (makeSymbolic unnamed_1 0)) [makeSymbolic0]) # Query 72 -- Type: InitialValues, Instructions: 30 -constant2 : (array (w64 4) (constant [121 101 115 0])) +constant2 : (array (w64 4) (constant [121, 101, 115, 0] default: 0)) makeSymbolic1 : (array (w64 4) (makeSymbolic unnamed 0)) makeSymbolic0 : (array (w64 4) (makeSymbolic unnamed_1 0)) (query [(Eq false @@ -1104,7 +1104,7 @@ makeSymbolic0 : (array (w64 4) (makeSymbolic unnamed_1 0)) # Query 74 -- Type: InitialValues, Instructions: 37 makeSymbolic1 : (array (w64 4) (makeSymbolic unnamed 0)) makeSymbolic0 : (array (w64 4) (makeSymbolic unnamed_1 0)) -constant2 : (array (w64 4) (constant [171 171 171 171])) +constant2 : (array (w64 4) (constant [171, 171, 171, 171] default: 0)) (query [(Eq false (Ult N0:(Mul w64 4 (SExt w64 (ReadLSB w32 0 makeSymbolic0))) @@ -1127,7 +1127,7 @@ constant2 : (array (w64 4) (constant [171 171 171 171])) # Query 75 -- Type: InitialValues, Instructions: 40 makeSymbolic1 : (array (w64 4) (makeSymbolic unnamed 0)) makeSymbolic0 : (array (w64 4) (makeSymbolic unnamed_1 0)) -constant2 : (array (w64 16) (constant [12 0 0 0 13 0 0 0 14 0 0 0 15 0 0 0])) +constant2 : (array (w64 16) (constant {0: 12, 4: 13, 8: 14, 12: 15} default: 0)) (query [(Ult N0:(Mul w64 4 (SExt w64 (ReadLSB w32 0 makeSymbolic0))) 13)] @@ -1140,7 +1140,7 @@ constant2 : (array (w64 16) (constant [12 0 0 0 13 0 0 0 14 0 0 0 15 0 0 0])) # Query 76 -- Type: InitialValues, Instructions: 50 makeSymbolic1 : (array (w64 4) (makeSymbolic unnamed 0)) makeSymbolic0 : (array (w64 4) (makeSymbolic unnamed_1 0)) -constant2 : (array (w64 4) (constant [171 171 171 171])) +constant2 : (array (w64 4) (constant [171, 171, 171, 171] default: 0)) (query [(Eq false (Ult N0:(Mul w64 4 (SExt w64 (ReadLSB w32 0 makeSymbolic0))) @@ -1159,7 +1159,7 @@ constant2 : (array (w64 4) (constant [171 171 171 171])) # Query 77 -- Type: InitialValues, Instructions: 51 makeSymbolic1 : (array (w64 4) (makeSymbolic unnamed 0)) makeSymbolic0 : (array (w64 4) (makeSymbolic unnamed_1 0)) -constant2 : (array (w64 16) (constant [12 0 0 0 13 0 0 0 14 0 0 0 15 0 0 0])) +constant2 : (array (w64 16) (constant {0: 12, 4: 13, 8: 14, 12: 15} default: 0)) (query [(Eq false (Ult N0:(Mul w64 4 (SExt w64 (ReadLSB w32 0 makeSymbolic0))) diff --git a/test/Expr/print-smt-named.smt2.good b/test/Expr/print-smt-named.smt2.good index 455fbc0dfd..fd7e2061ee 100644 --- a/test/Expr/print-smt-named.smt2.good +++ b/test/Expr/print-smt-named.smt2.good @@ -859,19 +859,19 @@ ;SMTLIBv2 Query 72 (set-option :produce-models true) (set-logic QF_AUFBV ) +(declare-fun constant0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) (declare-fun makeSymbolic0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun constant1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun makeSymbolic2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(assert (= (select constant1 (_ bv0 32) ) (_ bv121 8) ) ) -(assert (= (select constant1 (_ bv1 32) ) (_ bv101 8) ) ) -(assert (= (select constant1 (_ bv2 32) ) (_ bv115 8) ) ) -(assert (= (select constant1 (_ bv3 32) ) (_ bv0 8) ) ) -(assert (and (and (not (= false (= (concat (select makeSymbolic2 (_ bv3 32) ) (concat (select makeSymbolic2 (_ bv2 32) ) (concat (select makeSymbolic2 (_ bv1 32) ) (select makeSymbolic2 (_ bv0 32) ) ) ) ) (concat (select constant1 (bvadd (_ bv3 32) (! ((_ extract 31 0) (! (bvadd (_ bv31312 64) (! (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) :named ?B1) ) :named ?B2) ) :named ?B3) ) ) (concat (select constant1 (bvadd (_ bv2 32) ?B3 ) ) (concat (select constant1 (bvadd (_ bv1 32) ?B3 ) ) (select constant1 ?B3 ) ) ) ) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (bvult ?B2 (_ bv1 64) ) ) ) +(declare-fun makeSymbolic1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) +(assert (= (select constant0 (_ bv0 32) ) (_ bv121 8) ) ) +(assert (= (select constant0 (_ bv1 32) ) (_ bv101 8) ) ) +(assert (= (select constant0 (_ bv2 32) ) (_ bv115 8) ) ) +(assert (= (select constant0 (_ bv3 32) ) (_ bv0 8) ) ) +(assert (and (and (not (= false (= (concat (select makeSymbolic1 (_ bv3 32) ) (concat (select makeSymbolic1 (_ bv2 32) ) (concat (select makeSymbolic1 (_ bv1 32) ) (select makeSymbolic1 (_ bv0 32) ) ) ) ) (concat (select constant0 (bvadd (_ bv3 32) (! ((_ extract 31 0) (! (bvadd (_ bv31312 64) (! (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) :named ?B1) ) :named ?B2) ) :named ?B3) ) ) (concat (select constant0 (bvadd (_ bv2 32) ?B3 ) ) (concat (select constant0 (bvadd (_ bv1 32) ?B3 ) ) (select constant0 ?B3 ) ) ) ) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (bvult ?B2 (_ bv1 64) ) ) ) (check-sat) -(get-value ( (select makeSymbolic2 (_ bv0 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv1 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv2 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv3 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv0 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv1 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv2 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv3 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv0 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv1 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv2 32) ) ) ) @@ -882,69 +882,69 @@ (set-option :produce-models true) (set-logic QF_AUFBV ) (declare-fun makeSymbolic0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun makeSymbolic2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(assert (and (and (and (and (and (not (= (concat (select makeSymbolic2 (_ bv3 32) ) (concat (select makeSymbolic2 (_ bv2 32) ) (concat (select makeSymbolic2 (_ bv1 32) ) (select makeSymbolic2 (_ bv0 32) ) ) ) ) (concat (select makeSymbolic2 (bvadd (_ bv3 32) (! ((_ extract 31 0) (! (bvadd (_ bv18446744073709533360 64) (! (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) :named ?B1) ) :named ?B2) ) :named ?B3) ) ) (concat (select makeSymbolic2 (bvadd (_ bv2 32) ?B3 ) ) (concat (select makeSymbolic2 (bvadd (_ bv1 32) ?B3 ) ) (select makeSymbolic2 ?B3 ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) ?B1 ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv111120 64) ?B1 ) (_ bv1 64) ) ) ) (bvult ?B2 (_ bv1 64) ) ) ) +(declare-fun makeSymbolic1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) +(assert (and (and (and (and (and (not (= (concat (select makeSymbolic1 (_ bv3 32) ) (concat (select makeSymbolic1 (_ bv2 32) ) (concat (select makeSymbolic1 (_ bv1 32) ) (select makeSymbolic1 (_ bv0 32) ) ) ) ) (concat (select makeSymbolic1 (bvadd (_ bv3 32) (! ((_ extract 31 0) (! (bvadd (_ bv18446744073709533360 64) (! (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) :named ?B1) ) :named ?B2) ) :named ?B3) ) ) (concat (select makeSymbolic1 (bvadd (_ bv2 32) ?B3 ) ) (concat (select makeSymbolic1 (bvadd (_ bv1 32) ?B3 ) ) (select makeSymbolic1 ?B3 ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) ?B1 ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv111120 64) ?B1 ) (_ bv1 64) ) ) ) (bvult ?B2 (_ bv1 64) ) ) ) (check-sat) (get-value ( (select makeSymbolic0 (_ bv0 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv1 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv2 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv3 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv0 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv1 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv2 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv3 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv0 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv1 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv2 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv3 32) ) ) ) (exit) ;SMTLIBv2 Query 74 (set-option :produce-models true) (set-logic QF_AUFBV ) +(declare-fun constant1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) (declare-fun makeSymbolic0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun makeSymbolic2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun constant3 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(assert (= (select constant3 (_ bv0 32) ) (_ bv171 8) ) ) -(assert (= (select constant3 (_ bv1 32) ) (_ bv171 8) ) ) -(assert (= (select constant3 (_ bv2 32) ) (_ bv171 8) ) ) -(assert (= (select constant3 (_ bv3 32) ) (_ bv171 8) ) ) -(assert (and (and (and (and (and (and (not (= false (= (concat (select makeSymbolic2 (_ bv3 32) ) (concat (select makeSymbolic2 (_ bv2 32) ) (concat (select makeSymbolic2 (_ bv1 32) ) (select makeSymbolic2 (_ bv0 32) ) ) ) ) (concat (select constant3 (bvadd (_ bv3 32) (! ((_ extract 31 0) (! (bvadd (_ bv18446744073709533328 64) (! (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) :named ?B1) ) :named ?B2) ) :named ?B3) ) ) (concat (select constant3 (bvadd (_ bv2 32) ?B3 ) ) (concat (select constant3 (bvadd (_ bv1 32) ?B3 ) ) (select constant3 ?B3 ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) ?B1 ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv18446744073709533360 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult (bvadd (_ bv111120 64) ?B1 ) (_ bv1 64) ) ) ) (bvult ?B2 (_ bv1 64) ) ) ) +(declare-fun makeSymbolic1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) +(assert (= (select constant1 (_ bv0 32) ) (_ bv171 8) ) ) +(assert (= (select constant1 (_ bv1 32) ) (_ bv171 8) ) ) +(assert (= (select constant1 (_ bv2 32) ) (_ bv171 8) ) ) +(assert (= (select constant1 (_ bv3 32) ) (_ bv171 8) ) ) +(assert (and (and (and (and (and (and (not (= false (= (concat (select makeSymbolic1 (_ bv3 32) ) (concat (select makeSymbolic1 (_ bv2 32) ) (concat (select makeSymbolic1 (_ bv1 32) ) (select makeSymbolic1 (_ bv0 32) ) ) ) ) (concat (select constant1 (bvadd (_ bv3 32) (! ((_ extract 31 0) (! (bvadd (_ bv18446744073709533328 64) (! (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) :named ?B1) ) :named ?B2) ) :named ?B3) ) ) (concat (select constant1 (bvadd (_ bv2 32) ?B3 ) ) (concat (select constant1 (bvadd (_ bv1 32) ?B3 ) ) (select constant1 ?B3 ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) ?B1 ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv18446744073709533360 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult (bvadd (_ bv111120 64) ?B1 ) (_ bv1 64) ) ) ) (bvult ?B2 (_ bv1 64) ) ) ) (check-sat) (get-value ( (select makeSymbolic0 (_ bv0 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv1 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv2 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv3 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv0 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv1 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv2 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv3 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv0 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv1 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv2 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv3 32) ) ) ) (exit) ;SMTLIBv2 Query 75 (set-option :produce-models true) (set-logic QF_AUFBV ) +(declare-fun constant2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) (declare-fun makeSymbolic0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun makeSymbolic2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun constant4 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(assert (= (select constant4 (_ bv0 32) ) (_ bv12 8) ) ) -(assert (= (select constant4 (_ bv1 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv2 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv3 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv4 32) ) (_ bv13 8) ) ) -(assert (= (select constant4 (_ bv5 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv6 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv7 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv8 32) ) (_ bv14 8) ) ) -(assert (= (select constant4 (_ bv9 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv10 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv11 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv12 32) ) (_ bv15 8) ) ) -(assert (= (select constant4 (_ bv13 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv14 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv15 32) ) (_ bv0 8) ) ) -(assert (and (not (= false (= (concat (select makeSymbolic2 (_ bv3 32) ) (concat (select makeSymbolic2 (_ bv2 32) ) (concat (select makeSymbolic2 (_ bv1 32) ) (select makeSymbolic2 (_ bv0 32) ) ) ) ) (concat (select constant4 (bvadd (_ bv3 32) (! ((_ extract 31 0) (! (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) :named ?B1) ) :named ?B2) ) ) (concat (select constant4 (bvadd (_ bv2 32) ?B2 ) ) (concat (select constant4 (bvadd (_ bv1 32) ?B2 ) ) (select constant4 ?B2 ) ) ) ) ) ) ) (bvult ?B1 (_ bv13 64) ) ) ) +(declare-fun makeSymbolic1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) +(assert (= (select constant2 (_ bv0 32) ) (_ bv12 8) ) ) +(assert (= (select constant2 (_ bv1 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv2 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv3 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv4 32) ) (_ bv13 8) ) ) +(assert (= (select constant2 (_ bv5 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv6 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv7 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv8 32) ) (_ bv14 8) ) ) +(assert (= (select constant2 (_ bv9 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv10 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv11 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv12 32) ) (_ bv15 8) ) ) +(assert (= (select constant2 (_ bv13 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv14 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv15 32) ) (_ bv0 8) ) ) +(assert (and (not (= false (= (concat (select makeSymbolic1 (_ bv3 32) ) (concat (select makeSymbolic1 (_ bv2 32) ) (concat (select makeSymbolic1 (_ bv1 32) ) (select makeSymbolic1 (_ bv0 32) ) ) ) ) (concat (select constant2 (bvadd (_ bv3 32) (! ((_ extract 31 0) (! (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) :named ?B1) ) :named ?B2) ) ) (concat (select constant2 (bvadd (_ bv2 32) ?B2 ) ) (concat (select constant2 (bvadd (_ bv1 32) ?B2 ) ) (select constant2 ?B2 ) ) ) ) ) ) ) (bvult ?B1 (_ bv13 64) ) ) ) (check-sat) -(get-value ( (select makeSymbolic2 (_ bv0 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv1 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv2 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv3 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv0 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv1 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv2 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv3 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv0 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv1 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv2 32) ) ) ) @@ -954,53 +954,53 @@ ;SMTLIBv2 Query 76 (set-option :produce-models true) (set-logic QF_AUFBV ) +(declare-fun constant1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) (declare-fun makeSymbolic0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun makeSymbolic2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun constant5 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(assert (= (select constant5 (_ bv0 32) ) (_ bv171 8) ) ) -(assert (= (select constant5 (_ bv1 32) ) (_ bv171 8) ) ) -(assert (= (select constant5 (_ bv2 32) ) (_ bv171 8) ) ) -(assert (= (select constant5 (_ bv3 32) ) (_ bv171 8) ) ) -(assert (and (and (and (and (not (= false (= (concat (select makeSymbolic2 (_ bv3 32) ) (concat (select makeSymbolic2 (_ bv2 32) ) (concat (select makeSymbolic2 (_ bv1 32) ) (select makeSymbolic2 (_ bv0 32) ) ) ) ) (concat (select constant5 (bvadd (_ bv3 32) (! ((_ extract 31 0) (! (bvadd (_ bv111120 64) (! (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) :named ?B1) ) :named ?B2) ) :named ?B3) ) ) (concat (select constant5 (bvadd (_ bv2 32) ?B3 ) ) (concat (select constant5 (bvadd (_ bv1 32) ?B3 ) ) (select constant5 ?B3 ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) ?B1 ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (bvult ?B2 (_ bv1 64) ) ) ) +(declare-fun makeSymbolic1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) +(assert (= (select constant1 (_ bv0 32) ) (_ bv171 8) ) ) +(assert (= (select constant1 (_ bv1 32) ) (_ bv171 8) ) ) +(assert (= (select constant1 (_ bv2 32) ) (_ bv171 8) ) ) +(assert (= (select constant1 (_ bv3 32) ) (_ bv171 8) ) ) +(assert (and (and (and (and (not (= false (= (concat (select makeSymbolic1 (_ bv3 32) ) (concat (select makeSymbolic1 (_ bv2 32) ) (concat (select makeSymbolic1 (_ bv1 32) ) (select makeSymbolic1 (_ bv0 32) ) ) ) ) (concat (select constant1 (bvadd (_ bv3 32) (! ((_ extract 31 0) (! (bvadd (_ bv111120 64) (! (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) :named ?B1) ) :named ?B2) ) :named ?B3) ) ) (concat (select constant1 (bvadd (_ bv2 32) ?B3 ) ) (concat (select constant1 (bvadd (_ bv1 32) ?B3 ) ) (select constant1 ?B3 ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) ?B1 ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (bvult ?B2 (_ bv1 64) ) ) ) (check-sat) (get-value ( (select makeSymbolic0 (_ bv0 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv1 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv2 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv3 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv0 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv1 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv2 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv3 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv0 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv1 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv2 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv3 32) ) ) ) (exit) ;SMTLIBv2 Query 77 (set-option :produce-models true) (set-logic QF_AUFBV ) +(declare-fun constant2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) (declare-fun makeSymbolic0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun makeSymbolic2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun constant6 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(assert (= (select constant6 (_ bv0 32) ) (_ bv12 8) ) ) -(assert (= (select constant6 (_ bv1 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv2 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv3 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv4 32) ) (_ bv13 8) ) ) -(assert (= (select constant6 (_ bv5 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv6 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv7 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv8 32) ) (_ bv14 8) ) ) -(assert (= (select constant6 (_ bv9 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv10 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv11 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv12 32) ) (_ bv15 8) ) ) -(assert (= (select constant6 (_ bv13 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv14 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv15 32) ) (_ bv0 8) ) ) -(assert (and (and (and (not (= false (= (concat (select makeSymbolic2 (_ bv3 32) ) (concat (select makeSymbolic2 (_ bv2 32) ) (concat (select makeSymbolic2 (_ bv1 32) ) (select makeSymbolic2 (_ bv0 32) ) ) ) ) (concat (select constant6 (bvadd (_ bv3 32) (! ((_ extract 31 0) (! (bvadd (_ bv31760 64) (! (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) :named ?B1) ) :named ?B2) ) :named ?B3) ) ) (concat (select constant6 (bvadd (_ bv2 32) ?B3 ) ) (concat (select constant6 (bvadd (_ bv1 32) ?B3 ) ) (select constant6 ?B3 ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31312 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (bvult ?B2 (_ bv13 64) ) ) ) +(declare-fun makeSymbolic1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) +(assert (= (select constant2 (_ bv0 32) ) (_ bv12 8) ) ) +(assert (= (select constant2 (_ bv1 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv2 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv3 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv4 32) ) (_ bv13 8) ) ) +(assert (= (select constant2 (_ bv5 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv6 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv7 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv8 32) ) (_ bv14 8) ) ) +(assert (= (select constant2 (_ bv9 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv10 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv11 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv12 32) ) (_ bv15 8) ) ) +(assert (= (select constant2 (_ bv13 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv14 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv15 32) ) (_ bv0 8) ) ) +(assert (and (and (and (not (= false (= (concat (select makeSymbolic1 (_ bv3 32) ) (concat (select makeSymbolic1 (_ bv2 32) ) (concat (select makeSymbolic1 (_ bv1 32) ) (select makeSymbolic1 (_ bv0 32) ) ) ) ) (concat (select constant2 (bvadd (_ bv3 32) (! ((_ extract 31 0) (! (bvadd (_ bv31760 64) (! (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) :named ?B1) ) :named ?B2) ) :named ?B3) ) ) (concat (select constant2 (bvadd (_ bv2 32) ?B3 ) ) (concat (select constant2 (bvadd (_ bv1 32) ?B3 ) ) (select constant2 ?B3 ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31312 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (bvult ?B2 (_ bv13 64) ) ) ) (check-sat) -(get-value ( (select makeSymbolic2 (_ bv0 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv1 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv2 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv3 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv0 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv1 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv2 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv3 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv0 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv1 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv2 32) ) ) ) @@ -1011,15 +1011,15 @@ (set-option :produce-models true) (set-logic QF_AUFBV ) (declare-fun makeSymbolic0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun makeSymbolic2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(assert (and (and (and (and (and (and (and (not (= false (= (concat (select makeSymbolic2 (_ bv3 32) ) (concat (select makeSymbolic2 (_ bv2 32) ) (concat (select makeSymbolic2 (_ bv1 32) ) (select makeSymbolic2 (_ bv0 32) ) ) ) ) (concat (select makeSymbolic0 (bvadd (_ bv3 32) (! ((_ extract 31 0) (! (bvadd (_ bv18446744073709532800 64) (! (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) :named ?B1) ) :named ?B2) ) :named ?B3) ) ) (concat (select makeSymbolic0 (bvadd (_ bv2 32) ?B3 ) ) (concat (select makeSymbolic0 (bvadd (_ bv1 32) ?B3 ) ) (select makeSymbolic0 ?B3 ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) ?B1 ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv18446744073709533360 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult (bvadd (_ bv18446744073709533328 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult (bvadd (_ bv111120 64) ?B1 ) (_ bv1 64) ) ) ) (bvult ?B2 (_ bv1 64) ) ) ) +(declare-fun makeSymbolic1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) +(assert (and (and (and (and (and (and (and (not (= false (= (concat (select makeSymbolic1 (_ bv3 32) ) (concat (select makeSymbolic1 (_ bv2 32) ) (concat (select makeSymbolic1 (_ bv1 32) ) (select makeSymbolic1 (_ bv0 32) ) ) ) ) (concat (select makeSymbolic0 (bvadd (_ bv3 32) (! ((_ extract 31 0) (! (bvadd (_ bv18446744073709532800 64) (! (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) :named ?B1) ) :named ?B2) ) :named ?B3) ) ) (concat (select makeSymbolic0 (bvadd (_ bv2 32) ?B3 ) ) (concat (select makeSymbolic0 (bvadd (_ bv1 32) ?B3 ) ) (select makeSymbolic0 ?B3 ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) ?B1 ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult ?B1 (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv18446744073709533360 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult (bvadd (_ bv18446744073709533328 64) ?B1 ) (_ bv1 64) ) ) ) (= false (bvult (bvadd (_ bv111120 64) ?B1 ) (_ bv1 64) ) ) ) (bvult ?B2 (_ bv1 64) ) ) ) (check-sat) (get-value ( (select makeSymbolic0 (_ bv0 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv1 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv2 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv3 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv0 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv1 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv2 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv3 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv0 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv1 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv2 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv3 32) ) ) ) (exit) diff --git a/test/Expr/print-smt-none.kquery b/test/Expr/print-smt-none.kquery index 90c0bce0e7..9b002c3862 100644 --- a/test/Expr/print-smt-none.kquery +++ b/test/Expr/print-smt-none.kquery @@ -1068,7 +1068,7 @@ makeSymbolic0 : (array (w64 4) (makeSymbolic unnamed_1 0)) [makeSymbolic0]) # Query 72 -- Type: InitialValues, Instructions: 30 -constant2 : (array (w64 4) (constant [121 101 115 0])) +constant2 : (array (w64 4) (constant [121, 101, 115, 0] default: 0)) makeSymbolic1 : (array (w64 4) (makeSymbolic unnamed 0)) makeSymbolic0 : (array (w64 4) (makeSymbolic unnamed_1 0)) (query [(Eq false @@ -1104,7 +1104,7 @@ makeSymbolic0 : (array (w64 4) (makeSymbolic unnamed_1 0)) # Query 74 -- Type: InitialValues, Instructions: 37 makeSymbolic1 : (array (w64 4) (makeSymbolic unnamed 0)) makeSymbolic0 : (array (w64 4) (makeSymbolic unnamed_1 0)) -constant2 : (array (w64 4) (constant [171 171 171 171])) +constant2 : (array (w64 4) (constant [171, 171, 171, 171] default: 0)) (query [(Eq false (Ult N0:(Mul w64 4 (SExt w64 (ReadLSB w32 0 makeSymbolic0))) @@ -1127,7 +1127,7 @@ constant2 : (array (w64 4) (constant [171 171 171 171])) # Query 75 -- Type: InitialValues, Instructions: 40 makeSymbolic1 : (array (w64 4) (makeSymbolic unnamed 0)) makeSymbolic0 : (array (w64 4) (makeSymbolic unnamed_1 0)) -constant2 : (array (w64 16) (constant [12 0 0 0 13 0 0 0 14 0 0 0 15 0 0 0])) +constant2 : (array (w64 16) (constant {0: 12, 4: 13, 8: 14, 12: 15} default: 0)) (query [(Ult N0:(Mul w64 4 (SExt w64 (ReadLSB w32 0 makeSymbolic0))) 13)] @@ -1140,7 +1140,7 @@ constant2 : (array (w64 16) (constant [12 0 0 0 13 0 0 0 14 0 0 0 15 0 0 0])) # Query 76 -- Type: InitialValues, Instructions: 50 makeSymbolic1 : (array (w64 4) (makeSymbolic unnamed 0)) makeSymbolic0 : (array (w64 4) (makeSymbolic unnamed_1 0)) -constant2 : (array (w64 4) (constant [171 171 171 171])) +constant2 : (array (w64 4) (constant [171, 171, 171, 171] default: 0)) (query [(Eq false (Ult N0:(Mul w64 4 (SExt w64 (ReadLSB w32 0 makeSymbolic0))) @@ -1159,7 +1159,7 @@ constant2 : (array (w64 4) (constant [171 171 171 171])) # Query 77 -- Type: InitialValues, Instructions: 51 makeSymbolic1 : (array (w64 4) (makeSymbolic unnamed 0)) makeSymbolic0 : (array (w64 4) (makeSymbolic unnamed_1 0)) -constant2 : (array (w64 16) (constant [12 0 0 0 13 0 0 0 14 0 0 0 15 0 0 0])) +constant2 : (array (w64 16) (constant {0: 12, 4: 13, 8: 14, 12: 15} default: 0)) (query [(Eq false (Ult N0:(Mul w64 4 (SExt w64 (ReadLSB w32 0 makeSymbolic0))) diff --git a/test/Expr/print-smt-none.smt2.good b/test/Expr/print-smt-none.smt2.good index 3a4d2e0ce6..1fe23264f3 100644 --- a/test/Expr/print-smt-none.smt2.good +++ b/test/Expr/print-smt-none.smt2.good @@ -859,19 +859,19 @@ ;SMTLIBv2 Query 72 (set-option :produce-models true) (set-logic QF_AUFBV ) +(declare-fun constant0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) (declare-fun makeSymbolic0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun constant1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun makeSymbolic2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(assert (= (select constant1 (_ bv0 32) ) (_ bv121 8) ) ) -(assert (= (select constant1 (_ bv1 32) ) (_ bv101 8) ) ) -(assert (= (select constant1 (_ bv2 32) ) (_ bv115 8) ) ) -(assert (= (select constant1 (_ bv3 32) ) (_ bv0 8) ) ) -(assert (and (and (not (= false (= (concat (select makeSymbolic2 (_ bv3 32) ) (concat (select makeSymbolic2 (_ bv2 32) ) (concat (select makeSymbolic2 (_ bv1 32) ) (select makeSymbolic2 (_ bv0 32) ) ) ) ) (concat (select constant1 (bvadd (_ bv3 32) ((_ extract 31 0) (bvadd (_ bv31312 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select constant1 (bvadd (_ bv2 32) ((_ extract 31 0) (bvadd (_ bv31312 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select constant1 (bvadd (_ bv1 32) ((_ extract 31 0) (bvadd (_ bv31312 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (select constant1 ((_ extract 31 0) (bvadd (_ bv31312 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) (= false (bvult (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) (_ bv13 64) ) ) ) (bvult (bvadd (_ bv31312 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) +(declare-fun makeSymbolic1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) +(assert (= (select constant0 (_ bv0 32) ) (_ bv121 8) ) ) +(assert (= (select constant0 (_ bv1 32) ) (_ bv101 8) ) ) +(assert (= (select constant0 (_ bv2 32) ) (_ bv115 8) ) ) +(assert (= (select constant0 (_ bv3 32) ) (_ bv0 8) ) ) +(assert (and (and (not (= false (= (concat (select makeSymbolic1 (_ bv3 32) ) (concat (select makeSymbolic1 (_ bv2 32) ) (concat (select makeSymbolic1 (_ bv1 32) ) (select makeSymbolic1 (_ bv0 32) ) ) ) ) (concat (select constant0 (bvadd (_ bv3 32) ((_ extract 31 0) (bvadd (_ bv31312 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select constant0 (bvadd (_ bv2 32) ((_ extract 31 0) (bvadd (_ bv31312 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select constant0 (bvadd (_ bv1 32) ((_ extract 31 0) (bvadd (_ bv31312 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (select constant0 ((_ extract 31 0) (bvadd (_ bv31312 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) (= false (bvult (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) (_ bv13 64) ) ) ) (bvult (bvadd (_ bv31312 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (check-sat) -(get-value ( (select makeSymbolic2 (_ bv0 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv1 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv2 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv3 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv0 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv1 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv2 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv3 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv0 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv1 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv2 32) ) ) ) @@ -882,69 +882,69 @@ (set-option :produce-models true) (set-logic QF_AUFBV ) (declare-fun makeSymbolic0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun makeSymbolic2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(assert (and (and (and (and (and (not (= (concat (select makeSymbolic2 (_ bv3 32) ) (concat (select makeSymbolic2 (_ bv2 32) ) (concat (select makeSymbolic2 (_ bv1 32) ) (select makeSymbolic2 (_ bv0 32) ) ) ) ) (concat (select makeSymbolic2 (bvadd (_ bv3 32) ((_ extract 31 0) (bvadd (_ bv18446744073709533360 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select makeSymbolic2 (bvadd (_ bv2 32) ((_ extract 31 0) (bvadd (_ bv18446744073709533360 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select makeSymbolic2 (bvadd (_ bv1 32) ((_ extract 31 0) (bvadd (_ bv18446744073709533360 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (select makeSymbolic2 ((_ extract 31 0) (bvadd (_ bv18446744073709533360 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (= false (bvult (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv111120 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (bvult (bvadd (_ bv18446744073709533360 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) +(declare-fun makeSymbolic1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) +(assert (and (and (and (and (and (not (= (concat (select makeSymbolic1 (_ bv3 32) ) (concat (select makeSymbolic1 (_ bv2 32) ) (concat (select makeSymbolic1 (_ bv1 32) ) (select makeSymbolic1 (_ bv0 32) ) ) ) ) (concat (select makeSymbolic1 (bvadd (_ bv3 32) ((_ extract 31 0) (bvadd (_ bv18446744073709533360 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select makeSymbolic1 (bvadd (_ bv2 32) ((_ extract 31 0) (bvadd (_ bv18446744073709533360 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select makeSymbolic1 (bvadd (_ bv1 32) ((_ extract 31 0) (bvadd (_ bv18446744073709533360 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (select makeSymbolic1 ((_ extract 31 0) (bvadd (_ bv18446744073709533360 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (= false (bvult (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv111120 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (bvult (bvadd (_ bv18446744073709533360 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (check-sat) (get-value ( (select makeSymbolic0 (_ bv0 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv1 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv2 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv3 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv0 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv1 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv2 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv3 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv0 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv1 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv2 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv3 32) ) ) ) (exit) ;SMTLIBv2 Query 74 (set-option :produce-models true) (set-logic QF_AUFBV ) +(declare-fun constant1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) (declare-fun makeSymbolic0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun makeSymbolic2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun constant3 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(assert (= (select constant3 (_ bv0 32) ) (_ bv171 8) ) ) -(assert (= (select constant3 (_ bv1 32) ) (_ bv171 8) ) ) -(assert (= (select constant3 (_ bv2 32) ) (_ bv171 8) ) ) -(assert (= (select constant3 (_ bv3 32) ) (_ bv171 8) ) ) -(assert (and (and (and (and (and (and (not (= false (= (concat (select makeSymbolic2 (_ bv3 32) ) (concat (select makeSymbolic2 (_ bv2 32) ) (concat (select makeSymbolic2 (_ bv1 32) ) (select makeSymbolic2 (_ bv0 32) ) ) ) ) (concat (select constant3 (bvadd (_ bv3 32) ((_ extract 31 0) (bvadd (_ bv18446744073709533328 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select constant3 (bvadd (_ bv2 32) ((_ extract 31 0) (bvadd (_ bv18446744073709533328 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select constant3 (bvadd (_ bv1 32) ((_ extract 31 0) (bvadd (_ bv18446744073709533328 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (select constant3 ((_ extract 31 0) (bvadd (_ bv18446744073709533328 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (= false (bvult (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv18446744073709533360 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (= false (bvult (bvadd (_ bv111120 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (bvult (bvadd (_ bv18446744073709533328 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) +(declare-fun makeSymbolic1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) +(assert (= (select constant1 (_ bv0 32) ) (_ bv171 8) ) ) +(assert (= (select constant1 (_ bv1 32) ) (_ bv171 8) ) ) +(assert (= (select constant1 (_ bv2 32) ) (_ bv171 8) ) ) +(assert (= (select constant1 (_ bv3 32) ) (_ bv171 8) ) ) +(assert (and (and (and (and (and (and (not (= false (= (concat (select makeSymbolic1 (_ bv3 32) ) (concat (select makeSymbolic1 (_ bv2 32) ) (concat (select makeSymbolic1 (_ bv1 32) ) (select makeSymbolic1 (_ bv0 32) ) ) ) ) (concat (select constant1 (bvadd (_ bv3 32) ((_ extract 31 0) (bvadd (_ bv18446744073709533328 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select constant1 (bvadd (_ bv2 32) ((_ extract 31 0) (bvadd (_ bv18446744073709533328 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select constant1 (bvadd (_ bv1 32) ((_ extract 31 0) (bvadd (_ bv18446744073709533328 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (select constant1 ((_ extract 31 0) (bvadd (_ bv18446744073709533328 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (= false (bvult (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv18446744073709533360 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (= false (bvult (bvadd (_ bv111120 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (bvult (bvadd (_ bv18446744073709533328 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (check-sat) (get-value ( (select makeSymbolic0 (_ bv0 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv1 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv2 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv3 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv0 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv1 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv2 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv3 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv0 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv1 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv2 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv3 32) ) ) ) (exit) ;SMTLIBv2 Query 75 (set-option :produce-models true) (set-logic QF_AUFBV ) +(declare-fun constant2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) (declare-fun makeSymbolic0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun makeSymbolic2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun constant4 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(assert (= (select constant4 (_ bv0 32) ) (_ bv12 8) ) ) -(assert (= (select constant4 (_ bv1 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv2 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv3 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv4 32) ) (_ bv13 8) ) ) -(assert (= (select constant4 (_ bv5 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv6 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv7 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv8 32) ) (_ bv14 8) ) ) -(assert (= (select constant4 (_ bv9 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv10 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv11 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv12 32) ) (_ bv15 8) ) ) -(assert (= (select constant4 (_ bv13 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv14 32) ) (_ bv0 8) ) ) -(assert (= (select constant4 (_ bv15 32) ) (_ bv0 8) ) ) -(assert (and (not (= false (= (concat (select makeSymbolic2 (_ bv3 32) ) (concat (select makeSymbolic2 (_ bv2 32) ) (concat (select makeSymbolic2 (_ bv1 32) ) (select makeSymbolic2 (_ bv0 32) ) ) ) ) (concat (select constant4 (bvadd (_ bv3 32) ((_ extract 31 0) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) (concat (select constant4 (bvadd (_ bv2 32) ((_ extract 31 0) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) (concat (select constant4 (bvadd (_ bv1 32) ((_ extract 31 0) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) (select constant4 ((_ extract 31 0) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) ) ) ) ) (bvult (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) (_ bv13 64) ) ) ) +(declare-fun makeSymbolic1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) +(assert (= (select constant2 (_ bv0 32) ) (_ bv12 8) ) ) +(assert (= (select constant2 (_ bv1 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv2 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv3 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv4 32) ) (_ bv13 8) ) ) +(assert (= (select constant2 (_ bv5 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv6 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv7 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv8 32) ) (_ bv14 8) ) ) +(assert (= (select constant2 (_ bv9 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv10 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv11 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv12 32) ) (_ bv15 8) ) ) +(assert (= (select constant2 (_ bv13 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv14 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv15 32) ) (_ bv0 8) ) ) +(assert (and (not (= false (= (concat (select makeSymbolic1 (_ bv3 32) ) (concat (select makeSymbolic1 (_ bv2 32) ) (concat (select makeSymbolic1 (_ bv1 32) ) (select makeSymbolic1 (_ bv0 32) ) ) ) ) (concat (select constant2 (bvadd (_ bv3 32) ((_ extract 31 0) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) (concat (select constant2 (bvadd (_ bv2 32) ((_ extract 31 0) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) (concat (select constant2 (bvadd (_ bv1 32) ((_ extract 31 0) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) (select constant2 ((_ extract 31 0) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) ) ) ) ) (bvult (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) (_ bv13 64) ) ) ) (check-sat) -(get-value ( (select makeSymbolic2 (_ bv0 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv1 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv2 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv3 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv0 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv1 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv2 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv3 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv0 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv1 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv2 32) ) ) ) @@ -954,53 +954,53 @@ ;SMTLIBv2 Query 76 (set-option :produce-models true) (set-logic QF_AUFBV ) +(declare-fun constant1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) (declare-fun makeSymbolic0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun makeSymbolic2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun constant5 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(assert (= (select constant5 (_ bv0 32) ) (_ bv171 8) ) ) -(assert (= (select constant5 (_ bv1 32) ) (_ bv171 8) ) ) -(assert (= (select constant5 (_ bv2 32) ) (_ bv171 8) ) ) -(assert (= (select constant5 (_ bv3 32) ) (_ bv171 8) ) ) -(assert (and (and (and (and (not (= false (= (concat (select makeSymbolic2 (_ bv3 32) ) (concat (select makeSymbolic2 (_ bv2 32) ) (concat (select makeSymbolic2 (_ bv1 32) ) (select makeSymbolic2 (_ bv0 32) ) ) ) ) (concat (select constant5 (bvadd (_ bv3 32) ((_ extract 31 0) (bvadd (_ bv111120 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select constant5 (bvadd (_ bv2 32) ((_ extract 31 0) (bvadd (_ bv111120 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select constant5 (bvadd (_ bv1 32) ((_ extract 31 0) (bvadd (_ bv111120 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (select constant5 ((_ extract 31 0) (bvadd (_ bv111120 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (= false (bvult (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) (_ bv13 64) ) ) ) (bvult (bvadd (_ bv111120 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) +(declare-fun makeSymbolic1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) +(assert (= (select constant1 (_ bv0 32) ) (_ bv171 8) ) ) +(assert (= (select constant1 (_ bv1 32) ) (_ bv171 8) ) ) +(assert (= (select constant1 (_ bv2 32) ) (_ bv171 8) ) ) +(assert (= (select constant1 (_ bv3 32) ) (_ bv171 8) ) ) +(assert (and (and (and (and (not (= false (= (concat (select makeSymbolic1 (_ bv3 32) ) (concat (select makeSymbolic1 (_ bv2 32) ) (concat (select makeSymbolic1 (_ bv1 32) ) (select makeSymbolic1 (_ bv0 32) ) ) ) ) (concat (select constant1 (bvadd (_ bv3 32) ((_ extract 31 0) (bvadd (_ bv111120 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select constant1 (bvadd (_ bv2 32) ((_ extract 31 0) (bvadd (_ bv111120 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select constant1 (bvadd (_ bv1 32) ((_ extract 31 0) (bvadd (_ bv111120 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (select constant1 ((_ extract 31 0) (bvadd (_ bv111120 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (= false (bvult (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) (_ bv13 64) ) ) ) (bvult (bvadd (_ bv111120 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (check-sat) (get-value ( (select makeSymbolic0 (_ bv0 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv1 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv2 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv3 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv0 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv1 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv2 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv3 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv0 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv1 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv2 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv3 32) ) ) ) (exit) ;SMTLIBv2 Query 77 (set-option :produce-models true) (set-logic QF_AUFBV ) +(declare-fun constant2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) (declare-fun makeSymbolic0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun makeSymbolic2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun constant6 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(assert (= (select constant6 (_ bv0 32) ) (_ bv12 8) ) ) -(assert (= (select constant6 (_ bv1 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv2 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv3 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv4 32) ) (_ bv13 8) ) ) -(assert (= (select constant6 (_ bv5 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv6 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv7 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv8 32) ) (_ bv14 8) ) ) -(assert (= (select constant6 (_ bv9 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv10 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv11 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv12 32) ) (_ bv15 8) ) ) -(assert (= (select constant6 (_ bv13 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv14 32) ) (_ bv0 8) ) ) -(assert (= (select constant6 (_ bv15 32) ) (_ bv0 8) ) ) -(assert (and (and (and (not (= false (= (concat (select makeSymbolic2 (_ bv3 32) ) (concat (select makeSymbolic2 (_ bv2 32) ) (concat (select makeSymbolic2 (_ bv1 32) ) (select makeSymbolic2 (_ bv0 32) ) ) ) ) (concat (select constant6 (bvadd (_ bv3 32) ((_ extract 31 0) (bvadd (_ bv31760 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select constant6 (bvadd (_ bv2 32) ((_ extract 31 0) (bvadd (_ bv31760 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select constant6 (bvadd (_ bv1 32) ((_ extract 31 0) (bvadd (_ bv31760 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (select constant6 ((_ extract 31 0) (bvadd (_ bv31760 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31312 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (= false (bvult (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) (_ bv13 64) ) ) ) (bvult (bvadd (_ bv31760 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv13 64) ) ) ) +(declare-fun makeSymbolic1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) +(assert (= (select constant2 (_ bv0 32) ) (_ bv12 8) ) ) +(assert (= (select constant2 (_ bv1 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv2 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv3 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv4 32) ) (_ bv13 8) ) ) +(assert (= (select constant2 (_ bv5 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv6 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv7 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv8 32) ) (_ bv14 8) ) ) +(assert (= (select constant2 (_ bv9 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv10 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv11 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv12 32) ) (_ bv15 8) ) ) +(assert (= (select constant2 (_ bv13 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv14 32) ) (_ bv0 8) ) ) +(assert (= (select constant2 (_ bv15 32) ) (_ bv0 8) ) ) +(assert (and (and (and (not (= false (= (concat (select makeSymbolic1 (_ bv3 32) ) (concat (select makeSymbolic1 (_ bv2 32) ) (concat (select makeSymbolic1 (_ bv1 32) ) (select makeSymbolic1 (_ bv0 32) ) ) ) ) (concat (select constant2 (bvadd (_ bv3 32) ((_ extract 31 0) (bvadd (_ bv31760 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select constant2 (bvadd (_ bv2 32) ((_ extract 31 0) (bvadd (_ bv31760 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select constant2 (bvadd (_ bv1 32) ((_ extract 31 0) (bvadd (_ bv31760 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (select constant2 ((_ extract 31 0) (bvadd (_ bv31760 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31312 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (= false (bvult (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) (_ bv13 64) ) ) ) (bvult (bvadd (_ bv31760 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv13 64) ) ) ) (check-sat) -(get-value ( (select makeSymbolic2 (_ bv0 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv1 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv2 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv3 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv0 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv1 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv2 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv3 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv0 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv1 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv2 32) ) ) ) @@ -1011,15 +1011,15 @@ (set-option :produce-models true) (set-logic QF_AUFBV ) (declare-fun makeSymbolic0 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(declare-fun makeSymbolic2 () (Array (_ BitVec 32) (_ BitVec 8) ) ) -(assert (and (and (and (and (and (and (and (not (= false (= (concat (select makeSymbolic2 (_ bv3 32) ) (concat (select makeSymbolic2 (_ bv2 32) ) (concat (select makeSymbolic2 (_ bv1 32) ) (select makeSymbolic2 (_ bv0 32) ) ) ) ) (concat (select makeSymbolic0 (bvadd (_ bv3 32) ((_ extract 31 0) (bvadd (_ bv18446744073709532800 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select makeSymbolic0 (bvadd (_ bv2 32) ((_ extract 31 0) (bvadd (_ bv18446744073709532800 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select makeSymbolic0 (bvadd (_ bv1 32) ((_ extract 31 0) (bvadd (_ bv18446744073709532800 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (select makeSymbolic0 ((_ extract 31 0) (bvadd (_ bv18446744073709532800 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (= false (bvult (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv18446744073709533360 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (= false (bvult (bvadd (_ bv18446744073709533328 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (= false (bvult (bvadd (_ bv111120 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (bvult (bvadd (_ bv18446744073709532800 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) +(declare-fun makeSymbolic1 () (Array (_ BitVec 32) (_ BitVec 8) ) ) +(assert (and (and (and (and (and (and (and (not (= false (= (concat (select makeSymbolic1 (_ bv3 32) ) (concat (select makeSymbolic1 (_ bv2 32) ) (concat (select makeSymbolic1 (_ bv1 32) ) (select makeSymbolic1 (_ bv0 32) ) ) ) ) (concat (select makeSymbolic0 (bvadd (_ bv3 32) ((_ extract 31 0) (bvadd (_ bv18446744073709532800 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select makeSymbolic0 (bvadd (_ bv2 32) ((_ extract 31 0) (bvadd (_ bv18446744073709532800 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (concat (select makeSymbolic0 (bvadd (_ bv1 32) ((_ extract 31 0) (bvadd (_ bv18446744073709532800 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) (select makeSymbolic0 ((_ extract 31 0) (bvadd (_ bv18446744073709532800 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) (= false (bvult (bvadd (_ bv31760 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv31312 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (= false (bvult (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) (_ bv13 64) ) ) ) (= false (bvult (bvadd (_ bv18446744073709533360 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (= false (bvult (bvadd (_ bv18446744073709533328 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (= false (bvult (bvadd (_ bv111120 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (bvult (bvadd (_ bv18446744073709532800 64) (bvmul (_ bv4 64) ((_ sign_extend 32) (concat (select makeSymbolic0 (_ bv3 32) ) (concat (select makeSymbolic0 (_ bv2 32) ) (concat (select makeSymbolic0 (_ bv1 32) ) (select makeSymbolic0 (_ bv0 32) ) ) ) ) ) ) ) (_ bv1 64) ) ) ) (check-sat) (get-value ( (select makeSymbolic0 (_ bv0 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv1 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv2 32) ) ) ) (get-value ( (select makeSymbolic0 (_ bv3 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv0 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv1 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv2 32) ) ) ) -(get-value ( (select makeSymbolic2 (_ bv3 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv0 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv1 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv2 32) ) ) ) +(get-value ( (select makeSymbolic1 (_ bv3 32) ) ) ) (exit) diff --git a/test/Feature/MemoryLimit.c b/test/Feature/MemoryLimit.c index 330b2547ea..a24a16993e 100644 --- a/test/Feature/MemoryLimit.c +++ b/test/Feature/MemoryLimit.c @@ -44,7 +44,7 @@ int main() { malloc_failed |= (p == 0); // Ensure we hit the periodic check // Use the pointer to be not optimized out by the compiler - for (j = 0; j < 10000; j++) + for (j = 0; j < 100; j++) x += (long)p; } #endif diff --git a/test/Feature/SymbolicSizes/FirstAndLastElements.c b/test/Feature/SymbolicSizes/FirstAndLastElements.c index da74d0569b..10ba4c5784 100644 --- a/test/Feature/SymbolicSizes/FirstAndLastElements.c +++ b/test/Feature/SymbolicSizes/FirstAndLastElements.c @@ -1,7 +1,6 @@ -// REQUIRES: z3 // RUN: %clang %s -g -emit-llvm %O0opt -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --solver-backend=z3 --check-out-of-memory --use-sym-size-alloc --use-merged-pointer-dereference=true %t1.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --check-out-of-memory --use-sym-size-alloc --use-merged-pointer-dereference=true %t1.bc 2>&1 | FileCheck %s #include "klee/klee.h" #include diff --git a/test/Feature/SymbolicSizes/ImplicitArrayExtension.c b/test/Feature/SymbolicSizes/ImplicitArrayExtension.c index 604d137360..273334c84f 100644 --- a/test/Feature/SymbolicSizes/ImplicitArrayExtension.c +++ b/test/Feature/SymbolicSizes/ImplicitArrayExtension.c @@ -1,7 +1,6 @@ -// REQUIRES: z3 // RUN: %clang %s -g -emit-llvm %O0opt -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --check-out-of-memory --use-sym-size-alloc --solver-backend=z3 %t1.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --check-out-of-memory --use-sym-size-alloc %t1.bc 2>&1 | FileCheck %s #include "klee/klee.h" #include diff --git a/test/Feature/SymbolicSizes/ImplicitSizeConcretization.c b/test/Feature/SymbolicSizes/ImplicitSizeConcretization.c index 0ca567204c..6b4e09d0ee 100644 --- a/test/Feature/SymbolicSizes/ImplicitSizeConcretization.c +++ b/test/Feature/SymbolicSizes/ImplicitSizeConcretization.c @@ -1,4 +1,3 @@ -// REQUIRES: z3 // RUN: %clang %s -g -emit-llvm %O0opt -c -o %t1.bc // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --check-out-of-memory --use-sym-size-alloc --use-merged-pointer-dereference=true %t1.bc 2>&1 | FileCheck %s diff --git a/test/Feature/SymbolicSizes/IntArray.c b/test/Feature/SymbolicSizes/IntArray.c index e820df0a04..ddad754c44 100644 --- a/test/Feature/SymbolicSizes/IntArray.c +++ b/test/Feature/SymbolicSizes/IntArray.c @@ -1,7 +1,7 @@ -// REQUIRES: z3 +// REQUIRES: not-metasmt // RUN: %clang %s -g -emit-llvm %O0opt -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --solver-backend=z3 --use-sym-size-alloc --use-sym-size-li --min-number-elements-li=1 --skip-not-lazy-initialized %t1.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --use-sym-size-alloc --use-sym-size-li --min-number-elements-li=1 --skip-not-lazy-initialized %t1.bc 2>&1 | FileCheck %s #include "klee/klee.h" #include diff --git a/test/Feature/SymbolicSizes/LazyInstantiationOfSymbolicSize.c b/test/Feature/SymbolicSizes/LazyInstantiationOfSymbolicSize.c index 51ad20892e..be244f9ae0 100644 --- a/test/Feature/SymbolicSizes/LazyInstantiationOfSymbolicSize.c +++ b/test/Feature/SymbolicSizes/LazyInstantiationOfSymbolicSize.c @@ -1,7 +1,6 @@ -// REQUIRES: z3 // RUN: %clang %s -g -emit-llvm %O0opt -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --solver-backend=z3 --use-sym-size-alloc --use-sym-size-li --min-number-elements-li=1 --skip-not-lazy-initialized %t1.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --use-sym-size-alloc --use-sym-size-li --min-number-elements-li=1 --skip-not-lazy-initialized %t1.bc 2>&1 | FileCheck %s #include "klee/klee.h" #include diff --git a/test/Feature/SymbolicSizes/LowerOutOfBound.c b/test/Feature/SymbolicSizes/LowerOutOfBound.c index 0a97e5c63a..41064df671 100644 --- a/test/Feature/SymbolicSizes/LowerOutOfBound.c +++ b/test/Feature/SymbolicSizes/LowerOutOfBound.c @@ -1,7 +1,6 @@ -// REQUIRES: z3 // RUN: %clang %s -g -emit-llvm %O0opt -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --solver-backend=z3 --use-sym-size-alloc %t1.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --use-sym-size-alloc %t1.bc 2>&1 | FileCheck %s #include "klee/klee.h" #include diff --git a/test/Feature/SymbolicSizes/MinimizeSize.c b/test/Feature/SymbolicSizes/MinimizeSize.c index 5da9f65c0f..c767ff6a97 100644 --- a/test/Feature/SymbolicSizes/MinimizeSize.c +++ b/test/Feature/SymbolicSizes/MinimizeSize.c @@ -1,7 +1,6 @@ -// REQUIRES: z3 // RUN: %clang %s -g -emit-llvm %O0opt -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --check-out-of-memory --solver-backend=z3 --use-sym-size-alloc --use-merged-pointer-dereference=true %t1.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --check-out-of-memory --use-sym-size-alloc --use-merged-pointer-dereference=true %t1.bc 2>&1 | FileCheck %s #include "klee/klee.h" #include diff --git a/test/Feature/SymbolicSizes/MultipleAllocations.c b/test/Feature/SymbolicSizes/MultipleAllocations.c index 4ef3193a47..d953192616 100644 --- a/test/Feature/SymbolicSizes/MultipleAllocations.c +++ b/test/Feature/SymbolicSizes/MultipleAllocations.c @@ -1,7 +1,6 @@ -// REQUIRES: z3 // RUN: %clang %s -g -emit-llvm %O0opt -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --check-out-of-memory --use-sym-size-alloc --solver-backend=z3 %t1.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --check-out-of-memory --use-sym-size-alloc %t1.bc 2>&1 | FileCheck %s #include "klee/klee.h" #include diff --git a/test/Feature/SymbolicSizes/NegativeIndexArray.c b/test/Feature/SymbolicSizes/NegativeIndexArray.c index 2d4e0a6368..6f5f7e904e 100644 --- a/test/Feature/SymbolicSizes/NegativeIndexArray.c +++ b/test/Feature/SymbolicSizes/NegativeIndexArray.c @@ -1,7 +1,6 @@ -// REQUIRES: z3 // RUN: %clang %s -g -emit-llvm %O0opt -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --solver-backend=z3 --check-out-of-memory --use-sym-size-alloc --use-merged-pointer-dereference=true %t1.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --check-out-of-memory --use-sym-size-alloc --use-merged-pointer-dereference=true %t1.bc 2>&1 | FileCheck %s #include "klee/klee.h" #include "stdlib.h" diff --git a/test/Feature/SymbolicSizes/NegativeSize.c b/test/Feature/SymbolicSizes/NegativeSize.c index 72c0b9c4c7..c7f59e8b49 100644 --- a/test/Feature/SymbolicSizes/NegativeSize.c +++ b/test/Feature/SymbolicSizes/NegativeSize.c @@ -1,7 +1,6 @@ -// REQUIRES: z3 // RUN: %clang %s -g -emit-llvm %O0opt -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --check-out-of-memory --use-sym-size-alloc --solver-backend=z3 %t1.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --check-out-of-memory --use-sym-size-alloc %t1.bc 2>&1 | FileCheck %s #include "klee/klee.h" #include @@ -22,7 +21,7 @@ int main() { s1[1] = 10; // n == -2 // CHECK: NegativeSize.c:[[@LINE+1]]: memory error: out of bound pointer s2[2] = 20; // m == 3 - // CHECK: NegativeSize.c:[[@LINE+1]]: ASSERTION FAIL: 0 + // CHECK: NegativeSize.c:[[@LINE+1]]: ASSERTION FAIL assert(0); } } diff --git a/test/Feature/SymbolicSizes/RecomputeModelTwoArrays.c b/test/Feature/SymbolicSizes/RecomputeModelTwoArrays.c index 7d3bab5940..885cc518dc 100644 --- a/test/Feature/SymbolicSizes/RecomputeModelTwoArrays.c +++ b/test/Feature/SymbolicSizes/RecomputeModelTwoArrays.c @@ -1,7 +1,6 @@ -// REQUIRES: z3 // RUN: %clang %s -g -emit-llvm %O0opt -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --check-out-of-memory --use-sym-size-alloc --solver-backend=z3 --use-merged-pointer-dereference=true %t1.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --check-out-of-memory --use-sym-size-alloc --use-merged-pointer-dereference=true %t1.bc 2>&1 | FileCheck %s #include "klee/klee.h" #include diff --git a/test/Feature/SymbolicSizes/SegmentComparator.c b/test/Feature/SymbolicSizes/SegmentComparator.c index 3a7f16db76..614610b76a 100644 --- a/test/Feature/SymbolicSizes/SegmentComparator.c +++ b/test/Feature/SymbolicSizes/SegmentComparator.c @@ -1,7 +1,6 @@ -// REQUIRES: z3 // RUN: %clang %s -g -emit-llvm %O0opt -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --solver-backend=z3 --use-sym-size-alloc --skip-not-lazy-initialized %t1.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --use-sym-size-alloc --skip-not-lazy-initialized %t1.bc 2>&1 | FileCheck %s #include "klee/klee.h" #include diff --git a/test/Feature/SymbolicSizes/SymbolicArrayOnStack.c b/test/Feature/SymbolicSizes/SymbolicArrayOnStack.c index acf086a65f..daa6bec34f 100644 --- a/test/Feature/SymbolicSizes/SymbolicArrayOnStack.c +++ b/test/Feature/SymbolicSizes/SymbolicArrayOnStack.c @@ -1,7 +1,6 @@ -// REQUIRES: z3 // RUN: %clang %s -emit-llvm %O0opt -c -g -o %t.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --check-out-of-memory --solver-backend=z3 --use-sym-size-alloc --use-merged-pointer-dereference=true %t.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --check-out-of-memory --use-sym-size-alloc --use-merged-pointer-dereference=true %t.bc 2>&1 | FileCheck %s #include "klee/klee.h" diff --git a/test/Feature/SymbolicSizes/SymbolicArrayOnStackWithSkipSymbolics.c b/test/Feature/SymbolicSizes/SymbolicArrayOnStackWithSkipSymbolics.c index dbb2331aac..725dc56785 100644 --- a/test/Feature/SymbolicSizes/SymbolicArrayOnStackWithSkipSymbolics.c +++ b/test/Feature/SymbolicSizes/SymbolicArrayOnStackWithSkipSymbolics.c @@ -1,7 +1,6 @@ -// REQUIRES: z3 // RUN: %clang %s -emit-llvm %O0opt -c -g -o %t.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --solver-backend=z3 --check-out-of-memory --use-sym-size-alloc --skip-not-symbolic-objects --use-merged-pointer-dereference=true %t.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --check-out-of-memory --use-sym-size-alloc --skip-not-symbolic-objects --use-merged-pointer-dereference=true %t.bc 2>&1 | FileCheck %s #include "klee/klee.h" diff --git a/test/Feature/SymbolicSizes/UninitializedMemory.c b/test/Feature/SymbolicSizes/UninitializedMemory.c new file mode 100644 index 0000000000..f0501d3893 --- /dev/null +++ b/test/Feature/SymbolicSizes/UninitializedMemory.c @@ -0,0 +1,24 @@ +// RUN: %clang %s -emit-llvm %O0opt -c -g -o %t.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --use-sym-size-alloc --skip-not-symbolic-objects --use-merged-pointer-dereference=true %t.bc 2>&1 | FileCheck %s +#include "klee/klee.h" + +#include +#include +#include + +int main() { + int n; + klee_make_symbolic(&n, sizeof(n), "n"); + + char *s = (char *)malloc(n); + s[2] = 10; + if (s[0] == 0) { + printf("1) 0\n"); + } else { + printf("1) not 0\n"); + } + + // CHECK-DAG: 1) 0 + // CHECK-DAG: 1) not 0 +} diff --git a/test/Feature/SymbolicSizes/VoidStar.c b/test/Feature/SymbolicSizes/VoidStar.c index 48924f7b69..8770065d7a 100644 --- a/test/Feature/SymbolicSizes/VoidStar.c +++ b/test/Feature/SymbolicSizes/VoidStar.c @@ -1,7 +1,6 @@ -// REQUIRES: z3 // RUN: %clang %s -g -emit-llvm %O0opt -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --solver-backend=z3 --check-out-of-memory --use-sym-size-alloc --skip-not-lazy-initialized --use-merged-pointer-dereference=true %t1.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --check-out-of-memory --use-sym-size-alloc --skip-not-lazy-initialized --use-merged-pointer-dereference=true %t1.bc 2>&1 | FileCheck %s #include "klee/klee.h" #include diff --git a/test/Feature/TwoUninitializedRegions.c b/test/Feature/TwoUninitializedRegions.c new file mode 100644 index 0000000000..a772e4d549 --- /dev/null +++ b/test/Feature/TwoUninitializedRegions.c @@ -0,0 +1,23 @@ +// RUN: %clang %s -emit-llvm %O0opt -c -g -o %t.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out %t.bc 2>&1 | FileCheck %s + +#include "klee/klee.h" + +#include +#include +#include + +int main() { + char arr1[3]; + char arr2[3]; + + if (arr1[0] == arr2[0]) { + printf("1) equal\n"); + } else { + printf("1) not equal\n"); + } + + // CHECK-DAG: 1) equal + // CHECK-DAG: 1) not equal +} diff --git a/test/Feature/UninitializedConstantMemory.c b/test/Feature/UninitializedConstantMemory.c new file mode 100644 index 0000000000..ee8eb5cc92 --- /dev/null +++ b/test/Feature/UninitializedConstantMemory.c @@ -0,0 +1,29 @@ +// RUN: %clang %s -emit-llvm %O0opt -c -g -o %t.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out %t.bc 2>&1 | FileCheck %s +#include "klee/klee.h" + +#include +#include +#include + +int main() { + char arr[3]; + + if (arr[0] == 0) { + printf("1) 0\n"); + } else { + printf("1) not 0\n"); + } + + char *zero_arr = (char *)calloc(3, sizeof(char)); + if (zero_arr[1] == 0) { + return 0; + } else { + // CHECK-NOT: ASSERTION FAIL + assert(0); + } + + // CHECK-DAG: 1) 0 + // CHECK-DAG: 1) not 0 +} diff --git a/test/Solver/2016-04-12-array-parsing-bug.kquery b/test/Solver/2016-04-12-array-parsing-bug.kquery index 044144ba6a..2fe11893e5 100644 --- a/test/Solver/2016-04-12-array-parsing-bug.kquery +++ b/test/Solver/2016-04-12-array-parsing-bug.kquery @@ -5,8 +5,8 @@ makeSymbolic0 : (array (w64 8) (makeSymbolic A_data 0)) makeSymbolic1 : (array (w64 144) (makeSymbolic A_data_stat 0)) makeSymbolic2 : (array (w64 3) (makeSymbolic arg0 0)) makeSymbolic3 : (array (w64 3) (makeSymbolic arg1 0)) -constant4 : (array (w64 768) (constant [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 3 32 2 32 2 32 2 32 2 32 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 1 96 4 192 4 192 4 192 4 192 4 192 4 192 4 192 4 192 4 192 4 192 4 192 4 192 4 192 4 192 4 192 8 216 8 216 8 216 8 216 8 216 8 216 8 216 8 216 8 216 8 216 4 192 4 192 4 192 4 192 4 192 4 192 4 192 8 213 8 213 8 213 8 213 8 213 8 213 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 4 192 4 192 4 192 4 192 4 192 4 192 8 214 8 214 8 214 8 214 8 214 8 214 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 4 192 4 192 4 192 4 192 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0])) -constant5 : (array (w64 277) (constant [0 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 24 2 2 25 2 2 2 2 2 2 2 2 2 2 23 2 2 2 2 2 22 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21])) +constant4 : (array (w64 768) (constant [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 3 32 2 32 2 32 2 32 2 32 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 2 0 1 96 4 192 4 192 4 192 4 192 4 192 4 192 4 192 4 192 4 192 4 192 4 192 4 192 4 192 4 192 4 192 8 216 8 216 8 216 8 216 8 216 8 216 8 216 8 216 8 216 8 216 4 192 4 192 4 192 4 192 4 192 4 192 4 192 8 213 8 213 8 213 8 213 8 213 8 213 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 8 197 4 192 4 192 4 192 4 192 4 192 4 192 8 214 8 214 8 214 8 214 8 214 8 214 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 8 198 4 192 4 192 4 192 4 192 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] default: 0)) +constant5 : (array (w64 277) (constant [0 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 24 2 2 25 2 2 2 2 2 2 2 2 2 2 23 2 2 2 2 2 22 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21] default: 0)) makeSymbolic6 : (array (w64 4) (makeSymbolic model_version 0)) makeSymbolic7 : (array (w64 4) (makeSymbolic n_args 0)) makeSymbolic8 : (array (w64 4) (makeSymbolic n_args_1 0)) diff --git a/test/Solver/Z3ConstantArray.c b/test/Solver/Z3ConstantArray.c index e0452e3106..419c67d124 100644 --- a/test/Solver/Z3ConstantArray.c +++ b/test/Solver/Z3ConstantArray.c @@ -9,14 +9,14 @@ #include "klee/klee.h" int main(int argc, char **argv) { - // CHECK-DAG: (assert (= (select constant11 #x00000000) #x67)) - // CHECK-DAG: (assert (= (select constant11 #x00000001) #x79)) - // CHECK-DAG: (assert (= (select constant11 #x00000002) #x7a)) - // CHECK-DAG: (assert (= (select constant11 #x00000003) #x00)) - // TEST-CASE-DAG: (assert (= (select constant1 (_ bv0 32) ) (_ bv103 8) ) ) - // TEST-CASE-DAG: (assert (= (select constant1 (_ bv1 32) ) (_ bv121 8) ) ) - // TEST-CASE-DAG: (assert (= (select constant1 (_ bv2 32) ) (_ bv122 8) ) ) - // TEST-CASE-DAG: (assert (= (select constant1 (_ bv3 32) ) (_ bv0 8) ) ) + // CHECK-DAG: (assert (= (select constant01 #x00000000) #x67)) + // CHECK-DAG: (assert (= (select constant01 #x00000001) #x79)) + // CHECK-DAG: (assert (= (select constant01 #x00000002) #x7a)) + // CHECK-DAG: (assert (= (select constant01 #x00000003) #x00)) + // TEST-CASE-DAG: (assert (= (select constant0 (_ bv0 32) ) (_ bv103 8) ) ) + // TEST-CASE-DAG: (assert (= (select constant0 (_ bv1 32) ) (_ bv121 8) ) ) + // TEST-CASE-DAG: (assert (= (select constant0 (_ bv2 32) ) (_ bv122 8) ) ) + // TEST-CASE-DAG: (assert (= (select constant0 (_ bv3 32) ) (_ bv0 8) ) ) char c[4] = {'g', 'y', 'z', '\0'}; unsigned i; klee_make_symbolic(&i, sizeof i, "i"); diff --git a/test/Solver/Z3LargeConstantArray.kquery b/test/Solver/Z3LargeConstantArray.kquery index d3ccf51e4a..898edd9e22 100644 --- a/test/Solver/Z3LargeConstantArray.kquery +++ b/test/Solver/Z3LargeConstantArray.kquery @@ -1,7 +1,7 @@ # REQUIRES: z3 # RUN: %kleaver --solver-backend=z3 -max-solver-time=20 -debug-z3-dump-queries=%t.smt2 %s &> /dev/null # RUN: grep '(assert (= (select constant0' %t.smt2 -c | grep 3770 -constant0 : (array (w64 3770) (constant [32 0 0 0 192 193 124 5 0 0 0 0 64 242 107 41 0 0 0 0 48 235 107 41 0 0 0 0 0 0 0 0 0 0 0 0 144 0 0 0 14 0 0 0 0 0 0 0 10 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 144 33 0 0 65 42 0 0 5 0 0 0 0 0 0 0 7 136 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 16 146 162 90 0 0 0 0 55 110 115 21 0 0 0 0 83 146 162 90 0 0 0 0 55 110 115 21 0 0 0 0 75 204 147 90 0 0 0 0 55 110 115 21 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 121 0 0 0 100 101 102 105 110 101 40 96 98 39 44 32 96 117 39 41 10 100 101 102 105 110 101 40 96 104 39 44 32 96 108 39 41 10 100 101 102 105 110 101 40 96 105 39 44 32 96 107 39 41 10 100 101 102 105 110 101 40 96 121 39 44 32 96 107 39 41 10 100 101 102 105 110 101 40 96 65 39 44 32 96 108 39 41 10 100 101 102 105 110 101 40 96 110 39 44 32 50 41 10 100 101 102 105 110 101 40 96 80 39 44 32 50 41 10 0 10 0 10 0 10 128 2 0 0 3 0 0 0 0 0 0 0 200 67 198 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 0 0 0 0 0 0 0 0 249 77 23 3 0 0 0 0 160 42 129 41 0 0 0 0 252 255 255 255 255 255 255 255 0 0 0 0 255 255 255 255 252 255 255 255 255 255 255 255 0 0 0 0 0 0 0 0 252 255 255 255 255 255 255 255 0 0 0 0 0 0 0 0 252 255 255 255 255 255 255 255 0 0 0 0 0 0 0 0 252 255 255 255 255 255 255 255 64 13 129 41 0 0 0 0 56 217 22 3 0 0 0 0 96 168 132 41 0 0 0 0 255 255 255 255 255 255 255 255 33 4 0 0 0 0 0 0 48 24 129 41 0 0 0 0 80 43 125 41 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 248 255 255 255 255 255 255 255 176 23 129 41 0 0 0 0 252 255 255 255 255 255 255 255 16 14 129 41 0 0 0 0 252 255 255 255 255 255 255 255 32 227 132 41 0 0 0 0 252 255 255 255 255 255 255 255 208 251 132 41 0 0 0 0 252 255 255 255 255 255 255 255 144 16 129 41 0 0 0 0 252 255 255 255 255 255 255 255 192 3 133 41 0 0 0 0 252 255 255 255 255 255 255 255 96 3 133 41 0 0 0 0 252 255 255 255 255 255 255 255 176 26 124 41 0 0 0 0 252 255 255 255 255 255 255 255 16 27 124 41 0 0 0 0 252 255 255 255 255 255 255 255 16 51 124 41 0 0 0 0 252 255 255 255 255 255 255 255 48 59 129 41 0 0 0 0 252 255 255 255 255 255 255 255 0 68 0 0 0 105 110 116 101 114 110 97 108 32 101 114 114 111 114 32 100 101 116 101 99 116 101 100 59 32 112 108 101 97 115 101 32 114 101 112 111 114 116 32 116 104 105 115 32 98 117 103 32 116 111 32 60 98 117 103 45 109 52 64 103 110 117 46 111 114 103 62 0 19 0 0 0 83 101 103 109 101 110 116 97 116 105 111 110 32 102 97 117 108 116 0 8 0 0 0 65 98 111 114 116 101 100 0 20 0 0 0 73 108 108 101 103 97 108 32 105 110 115 116 114 117 99 116 105 111 110 0 25 0 0 0 70 108 111 97 116 105 110 103 32 112 111 105 110 116 32 101 120 99 101 112 116 105 111 110 0 10 0 0 0 66 117 115 32 101 114 114 111 114 0 2 0 0 0 96 0 2 0 0 0 39 0 2 0 0 0 35 0 2 0 0 0 10 0 40 0 0 0 32 136 117 41 0 0 0 0 24 107 198 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 40 1 0 0 20 25 100 59 116 43 0 0 2 27 100 59 116 43 0 0 223 24 100 59 116 43 0 0 0 0 0 0 0 0 0 0 189 22 100 59 116 43 0 0 181 25 100 59 116 43 0 0 140 30 100 59 116 43 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 58 24 100 59 116 43 0 0 228 29 100 59 116 43 0 0 242 22 100 59 116 43 0 0 5 24 100 59 116 43 0 0 0 0 0 0 0 0 0 0 1 29 100 59 116 43 0 0 167 24 100 59 116 43 0 0 148 23 100 59 116 43 0 0 134 22 100 59 116 43 0 0 114 27 100 59 116 43 0 0 219 21 100 59 116 43 0 0 96 23 100 59 116 43 0 0 0 0 0 0 0 0 0 0 236 25 100 59 116 43 0 0 0 0 0 0 0 0 0 0 60 29 100 59 116 43 0 0 126 25 100 59 116 43 0 0 37 26 100 59 116 43 0 0 0 0 0 0 0 0 0 0 28 30 100 59 116 43 0 0 41 23 100 59 116 43 0 0 116 29 100 59 116 43 0 0 81 22 100 59 116 43 0 0 148 26 100 59 116 43 0 0 0 0 0 0 0 0 0 0 224 27 100 59 116 43 0 0 74 25 100 59 116 43 0 0 84 30 100 59 116 43 0 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 22 100 59 116 43 0 0 2 0 0 0 0 48 0 0 248 158 196 4 0 0 0 0 10 0 0 0 99 104 97 110 103 101 99 111 109 0 40 0 0 0 204 23 100 59 116 43 0 0 0 0 128 48 0 0 0 0 65 22 100 59 116 43 0 0 2 0 0 0 170 133 41 0 248 160 196 4 0 0 0 0 12 0 0 0 99 104 97 110 103 101 113 117 111 116 101 0 40 0 0 0 172 29 100 59 116 43 0 0 8 0 0 0 0 0 0 0 125 22 100 59 116 43 0 0 2 0 0 0 0 0 0 38 200 163 196 4 0 0 0 0 5 0 0 0 100 101 99 114 0 40 0 0 0 0 0 0 0 0 0 0 0 12 0 80 120 0 0 0 0 178 22 100 59 116 43 0 0 2 0 0 0 0 0 0 0 152 166 196 4 0 0 0 0 7 0 0 0 100 101 102 105 110 101 0 40 0 0 0 25 28 100 59 116 43 0 0 8 0 0 0 0 0 0 0 233 22 100 59 116 43 0 0 2 0 0 0 17 148 64 0 88 170 196 4 0 0 0 0 5 0 0 0 100 101 102 110 0 40 0 0 0 112 24 100 59 116 43 0 0 0 0 0 0 0 0 0 0 30 23 100 59 116 43 0 0 2 0 0 0 160 0 32 7 56 172 196 4 0 0 0 0 7 0 0 0 100 105 118 101 114 116 0 40 0 0 0 81 28 100 59 116 43 0 0 0 0 0 0 0 0 0 0 85 23 100 59 116 43 0 0 2 0 0 0 0 0 0 48 40 173 196 4 0 0 0 0 7 0 0 0 100 105 118 110 117 109 0 40 0 0 0 93 26 100 59 116 43 0 0 0 154 4 0 0 0 0 0 140 23 100 59 116 43 0 0 2 0 0 0 0 0 0 0 24 174 196 4 0 0 0 0 4 0 0 0 100 110 108 0 40 0 0 0 59 27 100 59 116 43 0 0 0 121 34 0 0 0 0 0 192 23 100 59 116 43 0 0 2 0 0 0 160 176 133 41 8 175 196 4 0 0 0 0 8 0 0 0 100 117 109 112 100 101 102 0 40 0 0 0 138 28 100 59 116 43 0 0 8 0 0 0 0 0 0 0 248 23 100 59 116 43 0 0 2 0 0 0 0 0 0 0 24 236 197 4 0 0 0 0 9 0 0 0 101 114 114 112 114 105 110 116 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 64 0 0 0 0 49 24 100 59 116 43 0 0 2 0 0 0 1 0 0 0 24 242 197 4 0 0 0 0 5 0 0 0 101 118 97 108 0 40 0 0 0 0 0 0 0 0 0 0 0 8 41 0 0 0 0 0 0 102 24 100 59 116 43 0 0 2 0 0 0 0 0 73 1 152 243 197 4 0 0 0 0 6 0 0 0 105 102 100 101 102 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 156 24 100 59 116 43 0 0 2 0 0 0 0 0 0 0 88 244 197 4 0 0 0 0 7 0 0 0 105 102 101 108 115 101 0 40 0 0 0 0 0 0 0 0 0 0 0 8 203 0 0 0 0 0 0 211 24 100 59 116 43 0 0 2 0 0 0 0 0 0 0 24 245 197 4 0 0 0 0 8 0 0 0 105 110 99 108 117 100 101 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 11 25 100 59 116 43 0 0 2 0 0 0 0 0 0 0 152 246 197 4 0 0 0 0 5 0 0 0 105 110 99 114 0 40 0 0 0 195 28 100 59 116 43 0 0 8 0 0 0 0 0 0 0 64 25 100 59 116 43 0 0 2 0 0 0 96 176 133 41 88 247 197 4 0 0 0 0 6 0 0 0 105 110 100 101 120 0 40 0 0 0 204 26 100 59 116 43 0 0 8 0 0 0 0 0 0 0 118 25 100 59 116 43 0 0 2 0 0 0 0 0 0 0 152 249 197 4 0 0 0 0 4 0 0 0 108 101 110 0 40 0 0 0 0 0 0 0 0 0 0 0 0 52 33 0 0 0 0 0 170 25 100 59 116 43 0 0 2 0 0 0 9 63 116 43 88 250 197 4 0 0 0 0 7 0 0 0 109 52 101 120 105 116 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 176 0 0 0 0 225 25 100 59 116 43 0 0 2 0 0 0 0 0 0 0 72 251 197 4 0 0 0 0 7 0 0 0 109 52 119 114 97 112 0 40 0 0 0 169 27 100 59 116 43 0 0 8 0 0 0 0 0 0 0 24 26 100 59 116 43 0 0 2 0 0 0 20 0 0 30 88 118 196 4 0 0 0 0 9 0 0 0 109 97 107 101 116 101 109 112 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 176 0 0 0 0 81 26 100 59 116 43 0 0 2 0 0 0 8 0 0 0 40 121 196 4 0 0 0 0 8 0 0 0 109 107 115 116 101 109 112 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 137 26 100 59 116 43 0 0 2 0 0 0 0 0 0 0 168 7 198 4 0 0 0 0 7 0 0 0 112 111 112 100 101 102 0 40 0 0 0 0 0 0 0 0 0 0 0 12 0 0 64 0 0 0 0 192 26 100 59 116 43 0 0 2 0 0 0 192 122 127 41 152 8 198 4 0 0 0 0 8 0 0 0 112 117 115 104 100 101 102 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 248 26 100 59 116 43 0 0 2 0 0 0 0 0 0 0 120 10 198 4 0 0 0 0 6 0 0 0 115 104 105 102 116 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 46 27 100 59 116 43 0 0 2 0 0 0 0 0 52 0 104 11 198 4 0 0 0 0 9 0 0 0 115 105 110 99 108 117 100 101 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 103 27 100 59 116 43 0 0 2 0 0 0 0 0 0 0 88 12 198 4 0 0 0 0 7 0 0 0 115 117 98 115 116 114 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 158 27 100 59 116 43 0 0 2 0 0 0 0 0 64 11 72 13 198 4 0 0 0 0 7 0 0 0 115 121 115 99 109 100 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 213 27 100 59 116 43 0 0 2 0 0 0 0 0 0 48 56 14 198 4 0 0 0 0 7 0 0 0 115 121 115 118 97 108 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 64 0 0 0 0 12 28 100 59 116 43 0 0 2 0 0 0 0 0 0 0 40 15 198 4 0 0 0 0 9 0 0 0 116 114 97 99 101 111 102 102 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 69 28 100 59 116 43 0 0 2 0 0 0 0 0 0 0 8 234 197 4 0 0 0 0 8 0 0 0 116 114 97 99 101 111 110 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 125 28 100 59 116 43 0 0 2 0 0 0 0 0 0 192 248 234 197 4 0 0 0 0 9 0 0 0 116 114 97 110 115 108 105 116 0 40 0 0 0 0 0 0 0 0 0 0 0 8 41 0 0 0 0 0 0 182 28 100 59 116 43 0 0 2 0 0 0 0 0 0 0 200 22 198 4 0 0 0 0 9 0 0 0 117 110 100 101 102 105 110 101 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 239 28 100 59 116 43 0 0 2 0 0 0 0 112 8 0 184 23 198 4 0 0 0 0 9 0 0 0 117 110 100 105 118 101 114 116 0 1 0 0 0 0 40 0 0 0 0 0 0 0 0 0 0 0 0 99 8 0 0 0 0 0 45 29 100 59 116 43 0 0 1 0 0 0 0 0 0 224 252 28 100 59 116 43 0 0 5 0 0 0 117 110 105 120 0 2 0 0 0 117 0 40 0 0 0 0 0 0 0 0 0 0 0 0 255 95 52 0 0 0 0 104 29 100 59 116 43 0 0 1 0 0 0 240 43 134 41 54 29 100 59 116 43 0 0 2 0 0 0 98 0 2 0 0 0 108 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 160 29 100 59 116 43 0 0 1 0 0 0 87 0 0 0 110 29 100 59 116 43 0 0 2 0 0 0 104 0 2 0 0 0 107 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 216 29 100 59 116 43 0 0 1 0 0 0 3 24 0 128 166 29 100 59 116 43 0 0 2 0 0 0 105 0 2 0 0 0 107 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 16 30 100 59 116 43 0 0 1 0 0 0 64 236 0 0 222 29 100 59 116 43 0 0 2 0 0 0 121 0 2 0 0 0 108 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 72 30 100 59 116 43 0 0 1 0 0 0 48 0 0 0 22 30 100 59 116 43 0 0 2 0 0 0 65 0 2 0 0 0 50 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 128 30 100 59 116 43 0 0 1 0 0 0 48 120 134 41 78 30 100 59 116 43 0 0 2 0 0 0 110 0 2 0 0 0 50 0 40 0 0 0 21 22 100 59 116 43 0 0 0 0 0 0 0 0 0 0 184 30 100 59 116 43 0 0 1 0 0 0 0 0 0 0 134 30 100 59 116 43 0 0 2 0 0 0 80 0])) +constant0 : (array (w64 3770) (constant [32 0 0 0 192 193 124 5 0 0 0 0 64 242 107 41 0 0 0 0 48 235 107 41 0 0 0 0 0 0 0 0 0 0 0 0 144 0 0 0 14 0 0 0 0 0 0 0 10 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 144 33 0 0 65 42 0 0 5 0 0 0 0 0 0 0 7 136 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 16 146 162 90 0 0 0 0 55 110 115 21 0 0 0 0 83 146 162 90 0 0 0 0 55 110 115 21 0 0 0 0 75 204 147 90 0 0 0 0 55 110 115 21 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 121 0 0 0 100 101 102 105 110 101 40 96 98 39 44 32 96 117 39 41 10 100 101 102 105 110 101 40 96 104 39 44 32 96 108 39 41 10 100 101 102 105 110 101 40 96 105 39 44 32 96 107 39 41 10 100 101 102 105 110 101 40 96 121 39 44 32 96 107 39 41 10 100 101 102 105 110 101 40 96 65 39 44 32 96 108 39 41 10 100 101 102 105 110 101 40 96 110 39 44 32 50 41 10 100 101 102 105 110 101 40 96 80 39 44 32 50 41 10 0 10 0 10 0 10 128 2 0 0 3 0 0 0 0 0 0 0 200 67 198 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 248 255 255 255 255 255 255 255 252 255 255 255 255 255 255 255 0 0 0 0 0 0 0 0 249 77 23 3 0 0 0 0 160 42 129 41 0 0 0 0 252 255 255 255 255 255 255 255 0 0 0 0 255 255 255 255 252 255 255 255 255 255 255 255 0 0 0 0 0 0 0 0 252 255 255 255 255 255 255 255 0 0 0 0 0 0 0 0 252 255 255 255 255 255 255 255 0 0 0 0 0 0 0 0 252 255 255 255 255 255 255 255 64 13 129 41 0 0 0 0 56 217 22 3 0 0 0 0 96 168 132 41 0 0 0 0 255 255 255 255 255 255 255 255 33 4 0 0 0 0 0 0 48 24 129 41 0 0 0 0 80 43 125 41 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 248 255 255 255 255 255 255 255 176 23 129 41 0 0 0 0 252 255 255 255 255 255 255 255 16 14 129 41 0 0 0 0 252 255 255 255 255 255 255 255 32 227 132 41 0 0 0 0 252 255 255 255 255 255 255 255 208 251 132 41 0 0 0 0 252 255 255 255 255 255 255 255 144 16 129 41 0 0 0 0 252 255 255 255 255 255 255 255 192 3 133 41 0 0 0 0 252 255 255 255 255 255 255 255 96 3 133 41 0 0 0 0 252 255 255 255 255 255 255 255 176 26 124 41 0 0 0 0 252 255 255 255 255 255 255 255 16 27 124 41 0 0 0 0 252 255 255 255 255 255 255 255 16 51 124 41 0 0 0 0 252 255 255 255 255 255 255 255 48 59 129 41 0 0 0 0 252 255 255 255 255 255 255 255 0 68 0 0 0 105 110 116 101 114 110 97 108 32 101 114 114 111 114 32 100 101 116 101 99 116 101 100 59 32 112 108 101 97 115 101 32 114 101 112 111 114 116 32 116 104 105 115 32 98 117 103 32 116 111 32 60 98 117 103 45 109 52 64 103 110 117 46 111 114 103 62 0 19 0 0 0 83 101 103 109 101 110 116 97 116 105 111 110 32 102 97 117 108 116 0 8 0 0 0 65 98 111 114 116 101 100 0 20 0 0 0 73 108 108 101 103 97 108 32 105 110 115 116 114 117 99 116 105 111 110 0 25 0 0 0 70 108 111 97 116 105 110 103 32 112 111 105 110 116 32 101 120 99 101 112 116 105 111 110 0 10 0 0 0 66 117 115 32 101 114 114 111 114 0 2 0 0 0 96 0 2 0 0 0 39 0 2 0 0 0 35 0 2 0 0 0 10 0 40 0 0 0 32 136 117 41 0 0 0 0 24 107 198 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 40 1 0 0 20 25 100 59 116 43 0 0 2 27 100 59 116 43 0 0 223 24 100 59 116 43 0 0 0 0 0 0 0 0 0 0 189 22 100 59 116 43 0 0 181 25 100 59 116 43 0 0 140 30 100 59 116 43 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 58 24 100 59 116 43 0 0 228 29 100 59 116 43 0 0 242 22 100 59 116 43 0 0 5 24 100 59 116 43 0 0 0 0 0 0 0 0 0 0 1 29 100 59 116 43 0 0 167 24 100 59 116 43 0 0 148 23 100 59 116 43 0 0 134 22 100 59 116 43 0 0 114 27 100 59 116 43 0 0 219 21 100 59 116 43 0 0 96 23 100 59 116 43 0 0 0 0 0 0 0 0 0 0 236 25 100 59 116 43 0 0 0 0 0 0 0 0 0 0 60 29 100 59 116 43 0 0 126 25 100 59 116 43 0 0 37 26 100 59 116 43 0 0 0 0 0 0 0 0 0 0 28 30 100 59 116 43 0 0 41 23 100 59 116 43 0 0 116 29 100 59 116 43 0 0 81 22 100 59 116 43 0 0 148 26 100 59 116 43 0 0 0 0 0 0 0 0 0 0 224 27 100 59 116 43 0 0 74 25 100 59 116 43 0 0 84 30 100 59 116 43 0 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 22 100 59 116 43 0 0 2 0 0 0 0 48 0 0 248 158 196 4 0 0 0 0 10 0 0 0 99 104 97 110 103 101 99 111 109 0 40 0 0 0 204 23 100 59 116 43 0 0 0 0 128 48 0 0 0 0 65 22 100 59 116 43 0 0 2 0 0 0 170 133 41 0 248 160 196 4 0 0 0 0 12 0 0 0 99 104 97 110 103 101 113 117 111 116 101 0 40 0 0 0 172 29 100 59 116 43 0 0 8 0 0 0 0 0 0 0 125 22 100 59 116 43 0 0 2 0 0 0 0 0 0 38 200 163 196 4 0 0 0 0 5 0 0 0 100 101 99 114 0 40 0 0 0 0 0 0 0 0 0 0 0 12 0 80 120 0 0 0 0 178 22 100 59 116 43 0 0 2 0 0 0 0 0 0 0 152 166 196 4 0 0 0 0 7 0 0 0 100 101 102 105 110 101 0 40 0 0 0 25 28 100 59 116 43 0 0 8 0 0 0 0 0 0 0 233 22 100 59 116 43 0 0 2 0 0 0 17 148 64 0 88 170 196 4 0 0 0 0 5 0 0 0 100 101 102 110 0 40 0 0 0 112 24 100 59 116 43 0 0 0 0 0 0 0 0 0 0 30 23 100 59 116 43 0 0 2 0 0 0 160 0 32 7 56 172 196 4 0 0 0 0 7 0 0 0 100 105 118 101 114 116 0 40 0 0 0 81 28 100 59 116 43 0 0 0 0 0 0 0 0 0 0 85 23 100 59 116 43 0 0 2 0 0 0 0 0 0 48 40 173 196 4 0 0 0 0 7 0 0 0 100 105 118 110 117 109 0 40 0 0 0 93 26 100 59 116 43 0 0 0 154 4 0 0 0 0 0 140 23 100 59 116 43 0 0 2 0 0 0 0 0 0 0 24 174 196 4 0 0 0 0 4 0 0 0 100 110 108 0 40 0 0 0 59 27 100 59 116 43 0 0 0 121 34 0 0 0 0 0 192 23 100 59 116 43 0 0 2 0 0 0 160 176 133 41 8 175 196 4 0 0 0 0 8 0 0 0 100 117 109 112 100 101 102 0 40 0 0 0 138 28 100 59 116 43 0 0 8 0 0 0 0 0 0 0 248 23 100 59 116 43 0 0 2 0 0 0 0 0 0 0 24 236 197 4 0 0 0 0 9 0 0 0 101 114 114 112 114 105 110 116 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 64 0 0 0 0 49 24 100 59 116 43 0 0 2 0 0 0 1 0 0 0 24 242 197 4 0 0 0 0 5 0 0 0 101 118 97 108 0 40 0 0 0 0 0 0 0 0 0 0 0 8 41 0 0 0 0 0 0 102 24 100 59 116 43 0 0 2 0 0 0 0 0 73 1 152 243 197 4 0 0 0 0 6 0 0 0 105 102 100 101 102 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 156 24 100 59 116 43 0 0 2 0 0 0 0 0 0 0 88 244 197 4 0 0 0 0 7 0 0 0 105 102 101 108 115 101 0 40 0 0 0 0 0 0 0 0 0 0 0 8 203 0 0 0 0 0 0 211 24 100 59 116 43 0 0 2 0 0 0 0 0 0 0 24 245 197 4 0 0 0 0 8 0 0 0 105 110 99 108 117 100 101 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 11 25 100 59 116 43 0 0 2 0 0 0 0 0 0 0 152 246 197 4 0 0 0 0 5 0 0 0 105 110 99 114 0 40 0 0 0 195 28 100 59 116 43 0 0 8 0 0 0 0 0 0 0 64 25 100 59 116 43 0 0 2 0 0 0 96 176 133 41 88 247 197 4 0 0 0 0 6 0 0 0 105 110 100 101 120 0 40 0 0 0 204 26 100 59 116 43 0 0 8 0 0 0 0 0 0 0 118 25 100 59 116 43 0 0 2 0 0 0 0 0 0 0 152 249 197 4 0 0 0 0 4 0 0 0 108 101 110 0 40 0 0 0 0 0 0 0 0 0 0 0 0 52 33 0 0 0 0 0 170 25 100 59 116 43 0 0 2 0 0 0 9 63 116 43 88 250 197 4 0 0 0 0 7 0 0 0 109 52 101 120 105 116 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 176 0 0 0 0 225 25 100 59 116 43 0 0 2 0 0 0 0 0 0 0 72 251 197 4 0 0 0 0 7 0 0 0 109 52 119 114 97 112 0 40 0 0 0 169 27 100 59 116 43 0 0 8 0 0 0 0 0 0 0 24 26 100 59 116 43 0 0 2 0 0 0 20 0 0 30 88 118 196 4 0 0 0 0 9 0 0 0 109 97 107 101 116 101 109 112 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 176 0 0 0 0 81 26 100 59 116 43 0 0 2 0 0 0 8 0 0 0 40 121 196 4 0 0 0 0 8 0 0 0 109 107 115 116 101 109 112 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 137 26 100 59 116 43 0 0 2 0 0 0 0 0 0 0 168 7 198 4 0 0 0 0 7 0 0 0 112 111 112 100 101 102 0 40 0 0 0 0 0 0 0 0 0 0 0 12 0 0 64 0 0 0 0 192 26 100 59 116 43 0 0 2 0 0 0 192 122 127 41 152 8 198 4 0 0 0 0 8 0 0 0 112 117 115 104 100 101 102 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 248 26 100 59 116 43 0 0 2 0 0 0 0 0 0 0 120 10 198 4 0 0 0 0 6 0 0 0 115 104 105 102 116 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 46 27 100 59 116 43 0 0 2 0 0 0 0 0 52 0 104 11 198 4 0 0 0 0 9 0 0 0 115 105 110 99 108 117 100 101 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 103 27 100 59 116 43 0 0 2 0 0 0 0 0 0 0 88 12 198 4 0 0 0 0 7 0 0 0 115 117 98 115 116 114 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 158 27 100 59 116 43 0 0 2 0 0 0 0 0 64 11 72 13 198 4 0 0 0 0 7 0 0 0 115 121 115 99 109 100 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 213 27 100 59 116 43 0 0 2 0 0 0 0 0 0 48 56 14 198 4 0 0 0 0 7 0 0 0 115 121 115 118 97 108 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 64 0 0 0 0 12 28 100 59 116 43 0 0 2 0 0 0 0 0 0 0 40 15 198 4 0 0 0 0 9 0 0 0 116 114 97 99 101 111 102 102 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 69 28 100 59 116 43 0 0 2 0 0 0 0 0 0 0 8 234 197 4 0 0 0 0 8 0 0 0 116 114 97 99 101 111 110 0 40 0 0 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 125 28 100 59 116 43 0 0 2 0 0 0 0 0 0 192 248 234 197 4 0 0 0 0 9 0 0 0 116 114 97 110 115 108 105 116 0 40 0 0 0 0 0 0 0 0 0 0 0 8 41 0 0 0 0 0 0 182 28 100 59 116 43 0 0 2 0 0 0 0 0 0 0 200 22 198 4 0 0 0 0 9 0 0 0 117 110 100 101 102 105 110 101 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 239 28 100 59 116 43 0 0 2 0 0 0 0 112 8 0 184 23 198 4 0 0 0 0 9 0 0 0 117 110 100 105 118 101 114 116 0 1 0 0 0 0 40 0 0 0 0 0 0 0 0 0 0 0 0 99 8 0 0 0 0 0 45 29 100 59 116 43 0 0 1 0 0 0 0 0 0 224 252 28 100 59 116 43 0 0 5 0 0 0 117 110 105 120 0 2 0 0 0 117 0 40 0 0 0 0 0 0 0 0 0 0 0 0 255 95 52 0 0 0 0 104 29 100 59 116 43 0 0 1 0 0 0 240 43 134 41 54 29 100 59 116 43 0 0 2 0 0 0 98 0 2 0 0 0 108 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 160 29 100 59 116 43 0 0 1 0 0 0 87 0 0 0 110 29 100 59 116 43 0 0 2 0 0 0 104 0 2 0 0 0 107 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 216 29 100 59 116 43 0 0 1 0 0 0 3 24 0 128 166 29 100 59 116 43 0 0 2 0 0 0 105 0 2 0 0 0 107 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 16 30 100 59 116 43 0 0 1 0 0 0 64 236 0 0 222 29 100 59 116 43 0 0 2 0 0 0 121 0 2 0 0 0 108 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 72 30 100 59 116 43 0 0 1 0 0 0 48 0 0 0 22 30 100 59 116 43 0 0 2 0 0 0 65 0 2 0 0 0 50 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 128 30 100 59 116 43 0 0 1 0 0 0 48 120 134 41 78 30 100 59 116 43 0 0 2 0 0 0 110 0 2 0 0 0 50 0 40 0 0 0 21 22 100 59 116 43 0 0 0 0 0 0 0 0 0 0 184 30 100 59 116 43 0 0 1 0 0 0 0 0 0 0 134 30 100 59 116 43 0 0 2 0 0 0 80 0] default: 0)) makeSymbolic1 : (array (w64 121) (makeSymbolic stdin 0)) diff --git a/test/lit.cfg b/test/lit.cfg index 75978e47b7..8c01d8fc36 100644 --- a/test/lit.cfg +++ b/test/lit.cfg @@ -198,6 +198,10 @@ if config.enable_z3: config.available_features.add('z3') else: config.available_features.add('not-z3') +if config.enable_metasmt: + config.available_features.add('metasmt') +else: + config.available_features.add('not-metasmt') # Zlib config.available_features.add('zlib' if config.enable_zlib else 'not-zlib') diff --git a/test/lit.site.cfg.in b/test/lit.site.cfg.in index 15bc4a20a5..0712644706 100644 --- a/test/lit.site.cfg.in +++ b/test/lit.site.cfg.in @@ -51,6 +51,7 @@ config.enable_eh_cxx = True if @SUPPORT_KLEE_EH_CXX@ == 1 else False config.have_selinux = True if @HAVE_SELINUX@ == 1 else False config.enable_stp = True if @ENABLE_STP@ == 1 else False config.enable_z3 = True if @ENABLE_Z3@ == 1 else False +config.enable_metasmt = True if @ENABLE_METASMT@ == 1 else False config.enable_zlib = True if @HAVE_ZLIB_H@ == 1 else False config.have_asan = True if @IS_ASAN_BUILD@ == 1 else False config.have_ubsan = True if @IS_UBSAN_BUILD@ == 1 else False diff --git a/test/regression/2023-08-28-invalid-pointer-dereference.c b/test/regression/2023-08-28-invalid-pointer-dereference.c new file mode 100644 index 0000000000..cdd8388e71 --- /dev/null +++ b/test/regression/2023-08-28-invalid-pointer-dereference.c @@ -0,0 +1,22 @@ +// RUN: %clang %s -g -emit-llvm %O0opt -c -o %t.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --use-sym-size-alloc --output-dir=%t.klee-out %t.bc 2>&1 | FileCheck %s + +#pragma clang attribute push(__attribute__((optnone)), apply_to = function) + +int main() { + int length1 = klee_int("len"); + int length2 = klee_int("len"); + if (length1 < 1) { + length1 = 1; + } + if (length2 < 1) { + length2 = 1; + } + char *nondetString1 = (char *)__builtin_alloca(length1 * sizeof(char)); + char *nondetString2 = (char *)__builtin_alloca(length2 * sizeof(char)); + nondetString1[length1 - 1] = '\0'; + // CHECK-NOT: memory error: out of bound pointer + nondetString2[length2 - 1] = '\0'; +} +#pragma clang attribute pop diff --git a/test/regression/2023-10-13-kbfiltr.i.cil-2.c b/test/regression/2023-10-13-kbfiltr.i.cil-2.c new file mode 100644 index 0000000000..8a3d658124 --- /dev/null +++ b/test/regression/2023-10-13-kbfiltr.i.cil-2.c @@ -0,0 +1,3649 @@ +// REQUIRES: geq-llvm-14.0 +// RUN: %clang -Wno-everything %s -emit-llvm %O0opt -g -c -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --optimize=true --mock-all-externals --external-calls=all --use-forked-solver=false --max-memory=6008 --skip-not-lazy-initialized --istats-write-interval=90s --use-sym-size-alloc=true --cex-cache-validity-cores --symbolic-allocation-threshold=8192 --write-kqueries --write-xml-tests --only-output-states-covering-new=true --dump-states-on-halt=true --emit-all-errors=true --search=bfs %t1.bc + +// RUN: test -f %t.klee-out/test000023_1.xml +#include "klee-test-comp.c" + +extern void abort(void); +extern void __assert_fail(const char *, const char *, unsigned int, const char *) __attribute__((__nothrow__, __leaf__)) __attribute__((__noreturn__)); +void reach_error() { __assert_fail("0", "kbfiltr.i.cil-2.c", 3, "reach_error"); } + +extern char __VERIFIER_nondet_char(void); +extern int __VERIFIER_nondet_int(void); +extern long __VERIFIER_nondet_long(void); +extern unsigned long __VERIFIER_nondet_ulong(void); +extern void abort(void); +void assume_abort_if_not(int cond) { + if (!cond) { + abort(); + } +} +/* Generated by CIL v. 1.3.6 */ +/* print_CIL_Input is true */ + +#pragma pack(push, 8) +#pragma pack(pop) +typedef unsigned short wchar_t; +typedef unsigned long ULONG_PTR; +typedef unsigned long *PULONG_PTR; +typedef ULONG_PTR SIZE_T; +typedef void *PVOID; +typedef char CHAR; +typedef short SHORT; +typedef long LONG; +typedef wchar_t WCHAR; +typedef WCHAR *PWSTR; +typedef WCHAR const *PCWSTR; +typedef CHAR *PCHAR; +typedef LONG *PLONG; +typedef unsigned char UCHAR; +typedef unsigned short USHORT; +typedef unsigned long ULONG; +typedef UCHAR *PUCHAR; +typedef ULONG *PULONG; +typedef void *HANDLE; +typedef HANDLE *PHANDLE; +typedef char CCHAR; +typedef short CSHORT; +typedef ULONG LCID; +typedef LONG NTSTATUS; +typedef long long LONGLONG; +struct __anonstruct____missing_field_name_1 { + ULONG LowPart; + LONG HighPart; +}; +struct __anonstruct_u_2 { + ULONG LowPart; + LONG HighPart; +}; +union _LARGE_INTEGER { + struct __anonstruct____missing_field_name_1 __annonCompField1; + struct __anonstruct_u_2 u; + LONGLONG QuadPart; +}; +typedef union _LARGE_INTEGER LARGE_INTEGER; +typedef LARGE_INTEGER *PLARGE_INTEGER; +struct _LUID { + ULONG LowPart; + LONG HighPart; +}; +typedef struct _LUID LUID; +typedef LARGE_INTEGER PHYSICAL_ADDRESS; +enum _EVENT_TYPE { + NotificationEvent = 0, + SynchronizationEvent = 1 +}; +typedef enum _EVENT_TYPE EVENT_TYPE; +typedef char const *PCSZ; +struct _STRING { + USHORT Length; + USHORT MaximumLength; + PCHAR Buffer; +}; +typedef struct _STRING STRING; +typedef STRING *PSTRING; +typedef PSTRING PANSI_STRING; +struct _UNICODE_STRING { + USHORT Length; + USHORT MaximumLength; + PWSTR Buffer; +}; +typedef struct _UNICODE_STRING UNICODE_STRING; +typedef UNICODE_STRING *PUNICODE_STRING; +typedef UCHAR BOOLEAN; +typedef BOOLEAN *PBOOLEAN; +struct _LIST_ENTRY { + struct _LIST_ENTRY *Flink; + struct _LIST_ENTRY *Blink; +}; +typedef struct _LIST_ENTRY LIST_ENTRY; +typedef struct _LIST_ENTRY *PLIST_ENTRY; +struct _OBJECT_ATTRIBUTES { + ULONG Length; + HANDLE RootDirectory; + PUNICODE_STRING ObjectName; + ULONG Attributes; + PVOID SecurityDescriptor; + PVOID SecurityQualityOfService; +}; +typedef struct _OBJECT_ATTRIBUTES OBJECT_ATTRIBUTES; +typedef OBJECT_ATTRIBUTES *POBJECT_ATTRIBUTES; +struct _GUID { + unsigned long Data1; + unsigned short Data2; + unsigned short Data3; + unsigned char Data4[8]; +}; +typedef struct _GUID GUID; +typedef unsigned int size_t; +typedef UCHAR KIRQL; +struct _KTHREAD; +typedef struct _KTHREAD *PKTHREAD; +struct _ETHREAD; +typedef struct _ETHREAD *PETHREAD; +struct _EPROCESS; +typedef struct _EPROCESS *PEPROCESS; +struct _IO_TIMER; +typedef struct _IO_TIMER *PIO_TIMER; +struct _OBJECT_TYPE; +typedef struct _OBJECT_TYPE *POBJECT_TYPE; +typedef CCHAR KPROCESSOR_MODE; +struct _KAPC; +struct _KAPC; +typedef void (*PKNORMAL_ROUTINE)(PVOID NormalContext, PVOID SystemArgument1, PVOID SystemArgument2); +struct _KAPC { + CSHORT Type; + CSHORT Size; + ULONG Spare0; + struct _KTHREAD *Thread; + LIST_ENTRY ApcListEntry; + void (*KernelRoutine)(struct _KAPC *Apc, PKNORMAL_ROUTINE *NormalRoutine, PVOID *NormalContext, + PVOID *SystemArgument1, PVOID *SystemArgument2); + void (*RundownRoutine)(struct _KAPC *Apc); + void (*NormalRoutine)(PVOID NormalContext, PVOID SystemArgument1, PVOID SystemArgument2); + PVOID NormalContext; + PVOID SystemArgument1; + PVOID SystemArgument2; + CCHAR ApcStateIndex; + KPROCESSOR_MODE ApcMode; + BOOLEAN Inserted; +}; +typedef struct _KAPC KAPC; +struct _KDPC; +struct _KDPC; +struct _KDPC { + CSHORT Type; + UCHAR Number; + UCHAR Importance; + LIST_ENTRY DpcListEntry; + void (*DeferredRoutine)(struct _KDPC *Dpc, PVOID DeferredContext, PVOID SystemArgument1, + PVOID SystemArgument2); + PVOID DeferredContext; + PVOID SystemArgument1; + PVOID SystemArgument2; + PULONG_PTR Lock; +}; +typedef struct _KDPC KDPC; +typedef struct _KDPC *PKDPC; +struct _MDL { + struct _MDL *Next; + CSHORT Size; + CSHORT MdlFlags; + struct _EPROCESS *Process; + PVOID MappedSystemVa; + PVOID StartVa; + ULONG ByteCount; + ULONG ByteOffset; +}; +typedef struct _MDL MDL; +typedef struct _MDL *PMDL; +typedef PVOID PACCESS_TOKEN; +typedef PVOID PSECURITY_DESCRIPTOR; +typedef ULONG ACCESS_MASK; +#pragma pack(push, 4) +struct _LUID_AND_ATTRIBUTES { + LUID Luid; + ULONG Attributes; +}; +typedef struct _LUID_AND_ATTRIBUTES LUID_AND_ATTRIBUTES; +#pragma pack(pop) +struct _PRIVILEGE_SET { + ULONG PrivilegeCount; + ULONG Control; + LUID_AND_ATTRIBUTES Privilege[1]; +}; +typedef struct _PRIVILEGE_SET PRIVILEGE_SET; +enum _SECURITY_IMPERSONATION_LEVEL { + SecurityAnonymous = 0, + SecurityIdentification = 1, + SecurityImpersonation = 2, + SecurityDelegation = 3 +}; +typedef enum _SECURITY_IMPERSONATION_LEVEL SECURITY_IMPERSONATION_LEVEL; +typedef BOOLEAN SECURITY_CONTEXT_TRACKING_MODE; +struct _SECURITY_QUALITY_OF_SERVICE { + ULONG Length; + SECURITY_IMPERSONATION_LEVEL ImpersonationLevel; + SECURITY_CONTEXT_TRACKING_MODE ContextTrackingMode; + BOOLEAN EffectiveOnly; +}; +typedef struct _SECURITY_QUALITY_OF_SERVICE *PSECURITY_QUALITY_OF_SERVICE; +typedef ULONG SECURITY_INFORMATION; +typedef LONG KPRIORITY; +typedef ULONG_PTR KSPIN_LOCK; +typedef KSPIN_LOCK *PKSPIN_LOCK; +struct _RTL_QUERY_REGISTRY_TABLE { + NTSTATUS(*QueryRoutine) + (PWSTR ValueName, ULONG ValueType, + PVOID ValueData, ULONG ValueLength, + PVOID Context, PVOID EntryContext); + ULONG Flags; + PWSTR Name; + PVOID EntryContext; + ULONG DefaultType; + PVOID DefaultData; + ULONG DefaultLength; +}; +typedef struct _RTL_QUERY_REGISTRY_TABLE *PRTL_QUERY_REGISTRY_TABLE; +union __anonunion____missing_field_name_6 { + NTSTATUS Status; + PVOID Pointer; +}; +struct _IO_STATUS_BLOCK { + union __anonunion____missing_field_name_6 __annonCompField4; + ULONG_PTR Information; +}; +typedef struct _IO_STATUS_BLOCK IO_STATUS_BLOCK; +typedef struct _IO_STATUS_BLOCK *PIO_STATUS_BLOCK; +enum _FILE_INFORMATION_CLASS { + FileDirectoryInformation = 1, + FileFullDirectoryInformation = 2, + FileBothDirectoryInformation = 3, + FileBasicInformation = 4, + FileStandardInformation = 5, + FileInternalInformation = 6, + FileEaInformation = 7, + FileAccessInformation = 8, + FileNameInformation = 9, + FileRenameInformation = 10, + FileLinkInformation = 11, + FileNamesInformation = 12, + FileDispositionInformation = 13, + FilePositionInformation = 14, + FileFullEaInformation = 15, + FileModeInformation = 16, + FileAlignmentInformation = 17, + FileAllInformation = 18, + FileAllocationInformation = 19, + FileEndOfFileInformation = 20, + FileAlternateNameInformation = 21, + FileStreamInformation = 22, + FilePipeInformation = 23, + FilePipeLocalInformation = 24, + FilePipeRemoteInformation = 25, + FileMailslotQueryInformation = 26, + FileMailslotSetInformation = 27, + FileCompressionInformation = 28, + FileObjectIdInformation = 29, + FileCompletionInformation = 30, + FileMoveClusterInformation = 31, + FileQuotaInformation = 32, + FileReparsePointInformation = 33, + FileNetworkOpenInformation = 34, + FileAttributeTagInformation = 35, + FileTrackingInformation = 36, + FileMaximumInformation = 37 +}; +typedef enum _FILE_INFORMATION_CLASS FILE_INFORMATION_CLASS; +struct _FILE_BASIC_INFORMATION { + LARGE_INTEGER CreationTime; + LARGE_INTEGER LastAccessTime; + LARGE_INTEGER LastWriteTime; + LARGE_INTEGER ChangeTime; + ULONG FileAttributes; +}; +typedef struct _FILE_BASIC_INFORMATION *PFILE_BASIC_INFORMATION; +struct _FILE_STANDARD_INFORMATION { + LARGE_INTEGER AllocationSize; + LARGE_INTEGER EndOfFile; + ULONG NumberOfLinks; + BOOLEAN DeletePending; + BOOLEAN Directory; +}; +typedef struct _FILE_STANDARD_INFORMATION *PFILE_STANDARD_INFORMATION; +struct _FILE_NETWORK_OPEN_INFORMATION { + LARGE_INTEGER CreationTime; + LARGE_INTEGER LastAccessTime; + LARGE_INTEGER LastWriteTime; + LARGE_INTEGER ChangeTime; + LARGE_INTEGER AllocationSize; + LARGE_INTEGER EndOfFile; + ULONG FileAttributes; +}; +typedef struct _FILE_NETWORK_OPEN_INFORMATION *PFILE_NETWORK_OPEN_INFORMATION; +enum _FSINFOCLASS { + FileFsVolumeInformation = 1, + FileFsLabelInformation = 2, + FileFsSizeInformation = 3, + FileFsDeviceInformation = 4, + FileFsAttributeInformation = 5, + FileFsControlInformation = 6, + FileFsFullSizeInformation = 7, + FileFsObjectIdInformation = 8, + FileFsMaximumInformation = 9 +}; +typedef enum _FSINFOCLASS FS_INFORMATION_CLASS; +enum _INTERFACE_TYPE { + InterfaceTypeUndefined = -1, + Internal = 0, + Isa = 1, + Eisa = 2, + MicroChannel = 3, + TurboChannel = 4, + PCIBus = 5, + VMEBus = 6, + NuBus = 7, + PCMCIABus = 8, + CBus = 9, + MPIBus = 10, + MPSABus = 11, + ProcessorInternal = 12, + InternalPowerBus = 13, + PNPISABus = 14, + PNPBus = 15, + MaximumInterfaceType = 16 +}; +typedef enum _INTERFACE_TYPE INTERFACE_TYPE; +typedef enum _INTERFACE_TYPE *PINTERFACE_TYPE; +struct _IO_ERROR_LOG_PACKET { + UCHAR MajorFunctionCode; + UCHAR RetryCount; + USHORT DumpDataSize; + USHORT NumberOfStrings; + USHORT StringOffset; + USHORT EventCategory; + NTSTATUS ErrorCode; + ULONG UniqueErrorValue; + NTSTATUS FinalStatus; + ULONG SequenceNumber; + ULONG IoControlCode; + LARGE_INTEGER DeviceOffset; + ULONG DumpData[1]; +}; +typedef struct _IO_ERROR_LOG_PACKET IO_ERROR_LOG_PACKET; +struct _KEY_VALUE_FULL_INFORMATION { + ULONG TitleIndex; + ULONG Type; + ULONG DataOffset; + ULONG DataLength; + ULONG NameLength; + WCHAR Name[1]; +}; +typedef struct _KEY_VALUE_FULL_INFORMATION *PKEY_VALUE_FULL_INFORMATION; +struct _CLIENT_ID { + HANDLE UniqueProcess; + HANDLE UniqueThread; +}; +typedef struct _CLIENT_ID CLIENT_ID; +typedef CLIENT_ID *PCLIENT_ID; +enum _SYSTEM_POWER_STATE { + PowerSystemUnspecified = 0, + PowerSystemWorking = 1, + PowerSystemSleeping1 = 2, + PowerSystemSleeping2 = 3, + PowerSystemSleeping3 = 4, + PowerSystemHibernate = 5, + PowerSystemShutdown = 6, + PowerSystemMaximum = 7 +}; +typedef enum _SYSTEM_POWER_STATE SYSTEM_POWER_STATE; +enum __anonenum_POWER_ACTION_11 { + PowerActionNone = 0, + PowerActionReserved = 1, + PowerActionSleep = 2, + PowerActionHibernate = 3, + PowerActionShutdown = 4, + PowerActionShutdownReset = 5, + PowerActionShutdownOff = 6, + PowerActionWarmEject = 7 +}; +typedef enum __anonenum_POWER_ACTION_11 POWER_ACTION; +enum _DEVICE_POWER_STATE { + PowerDeviceUnspecified = 0, + PowerDeviceD0 = 1, + PowerDeviceD1 = 2, + PowerDeviceD2 = 3, + PowerDeviceD3 = 4, + PowerDeviceMaximum = 5 +}; +typedef enum _DEVICE_POWER_STATE DEVICE_POWER_STATE; +union _POWER_STATE { + SYSTEM_POWER_STATE SystemState; + DEVICE_POWER_STATE DeviceState; +}; +typedef union _POWER_STATE POWER_STATE; +enum _POWER_STATE_TYPE { + SystemPowerState = 0, + DevicePowerState = 1 +}; +typedef enum _POWER_STATE_TYPE POWER_STATE_TYPE; +typedef PVOID PASSIGNED_RESOURCE; +#pragma pack(push, 4) +struct __anonstruct_Generic_16 { + PHYSICAL_ADDRESS Start; + ULONG Length; +}; +struct __anonstruct_Port_17 { + PHYSICAL_ADDRESS Start; + ULONG Length; +}; +struct __anonstruct_Interrupt_18 { + ULONG Level; + ULONG Vector; + ULONG Affinity; +}; +struct __anonstruct_Memory_19 { + PHYSICAL_ADDRESS Start; + ULONG Length; +}; +struct __anonstruct_Dma_20 { + ULONG Channel; + ULONG Port; + ULONG Reserved1; +}; +struct __anonstruct_DevicePrivate_21 { + ULONG Data[3]; +}; +struct __anonstruct_BusNumber_22 { + ULONG Start; + ULONG Length; + ULONG Reserved; +}; +struct __anonstruct_DeviceSpecificData_23 { + ULONG DataSize; + ULONG Reserved1; + ULONG Reserved2; +}; +union __anonunion_u_15 { + struct __anonstruct_Generic_16 Generic; + struct __anonstruct_Port_17 Port; + struct __anonstruct_Interrupt_18 Interrupt; + struct __anonstruct_Memory_19 Memory; + struct __anonstruct_Dma_20 Dma; + struct __anonstruct_DevicePrivate_21 DevicePrivate; + struct __anonstruct_BusNumber_22 BusNumber; + struct __anonstruct_DeviceSpecificData_23 DeviceSpecificData; +}; +struct _CM_PARTIAL_RESOURCE_DESCRIPTOR { + UCHAR Type; + UCHAR ShareDisposition; + USHORT Flags; + union __anonunion_u_15 u; +}; +typedef struct _CM_PARTIAL_RESOURCE_DESCRIPTOR CM_PARTIAL_RESOURCE_DESCRIPTOR; +#pragma pack(pop) +struct _CM_PARTIAL_RESOURCE_LIST { + USHORT Version; + USHORT Revision; + ULONG Count; + CM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptors[1]; +}; +typedef struct _CM_PARTIAL_RESOURCE_LIST CM_PARTIAL_RESOURCE_LIST; +struct _CM_FULL_RESOURCE_DESCRIPTOR { + INTERFACE_TYPE InterfaceType; + ULONG BusNumber; + CM_PARTIAL_RESOURCE_LIST PartialResourceList; +}; +typedef struct _CM_FULL_RESOURCE_DESCRIPTOR CM_FULL_RESOURCE_DESCRIPTOR; +struct _CM_RESOURCE_LIST { + ULONG Count; + CM_FULL_RESOURCE_DESCRIPTOR List[1]; +}; +typedef struct _CM_RESOURCE_LIST *PCM_RESOURCE_LIST; +#pragma pack(push, 1) +#pragma pack(pop) +struct __anonstruct_Port_25 { + ULONG Length; + ULONG Alignment; + PHYSICAL_ADDRESS MinimumAddress; + PHYSICAL_ADDRESS MaximumAddress; +}; +struct __anonstruct_Memory_26 { + ULONG Length; + ULONG Alignment; + PHYSICAL_ADDRESS MinimumAddress; + PHYSICAL_ADDRESS MaximumAddress; +}; +struct __anonstruct_Interrupt_27 { + ULONG MinimumVector; + ULONG MaximumVector; +}; +struct __anonstruct_Dma_28 { + ULONG MinimumChannel; + ULONG MaximumChannel; +}; +struct __anonstruct_Generic_29 { + ULONG Length; + ULONG Alignment; + PHYSICAL_ADDRESS MinimumAddress; + PHYSICAL_ADDRESS MaximumAddress; +}; +struct __anonstruct_DevicePrivate_30 { + ULONG Data[3]; +}; +struct __anonstruct_BusNumber_31 { + ULONG Length; + ULONG MinBusNumber; + ULONG MaxBusNumber; + ULONG Reserved; +}; +struct __anonstruct_AssignedResource_32 { + PASSIGNED_RESOURCE AssignedResource; +}; +struct __anonstruct_SubAllocateFrom_33 { + UCHAR Type; + UCHAR Reserved[3]; + PASSIGNED_RESOURCE AssignedResource; + PHYSICAL_ADDRESS Transformation; +}; +struct __anonstruct_ConfigData_34 { + ULONG Priority; + ULONG Reserved1; + ULONG Reserved2; +}; +union __anonunion_u_24 { + struct __anonstruct_Port_25 Port; + struct __anonstruct_Memory_26 Memory; + struct __anonstruct_Interrupt_27 Interrupt; + struct __anonstruct_Dma_28 Dma; + struct __anonstruct_Generic_29 Generic; + struct __anonstruct_DevicePrivate_30 DevicePrivate; + struct __anonstruct_BusNumber_31 BusNumber; + struct __anonstruct_AssignedResource_32 AssignedResource; + struct __anonstruct_SubAllocateFrom_33 SubAllocateFrom; + struct __anonstruct_ConfigData_34 ConfigData; +}; +struct _IO_RESOURCE_DESCRIPTOR { + UCHAR Option; + UCHAR Type; + UCHAR ShareDisposition; + UCHAR Spare1; + USHORT Flags; + USHORT Spare2; + union __anonunion_u_24 u; +}; +typedef struct _IO_RESOURCE_DESCRIPTOR IO_RESOURCE_DESCRIPTOR; +struct _IO_RESOURCE_LIST { + USHORT Version; + USHORT Revision; + ULONG Count; + IO_RESOURCE_DESCRIPTOR Descriptors[1]; +}; +typedef struct _IO_RESOURCE_LIST IO_RESOURCE_LIST; +struct _IO_RESOURCE_REQUIREMENTS_LIST { + ULONG ListSize; + INTERFACE_TYPE InterfaceType; + ULONG BusNumber; + ULONG SlotNumber; + ULONG Reserved[3]; + ULONG AlternativeLists; + IO_RESOURCE_LIST List[1]; +}; +typedef struct _IO_RESOURCE_REQUIREMENTS_LIST *PIO_RESOURCE_REQUIREMENTS_LIST; +enum _CONFIGURATION_TYPE { + ArcSystem = 0, + CentralProcessor = 1, + FloatingPointProcessor = 2, + PrimaryIcache = 3, + PrimaryDcache = 4, + SecondaryIcache = 5, + SecondaryDcache = 6, + SecondaryCache = 7, + EisaAdapter = 8, + TcAdapter = 9, + ScsiAdapter = 10, + DtiAdapter = 11, + MultiFunctionAdapter = 12, + DiskController = 13, + TapeController = 14, + CdromController = 15, + WormController = 16, + SerialController = 17, + NetworkController = 18, + DisplayController = 19, + ParallelController = 20, + PointerController = 21, + KeyboardController = 22, + AudioController = 23, + OtherController = 24, + DiskPeripheral = 25, + FloppyDiskPeripheral = 26, + TapePeripheral = 27, + ModemPeripheral = 28, + MonitorPeripheral = 29, + PrinterPeripheral = 30, + PointerPeripheral = 31, + KeyboardPeripheral = 32, + TerminalPeripheral = 33, + OtherPeripheral = 34, + LinePeripheral = 35, + NetworkPeripheral = 36, + SystemMemory = 37, + DockingInformation = 38, + RealModeIrqRoutingTable = 39, + MaximumType = 40 +}; +typedef enum _CONFIGURATION_TYPE CONFIGURATION_TYPE; +typedef enum _CONFIGURATION_TYPE *PCONFIGURATION_TYPE; +enum _KWAIT_REASON { + Executive = 0, + FreePage = 1, + PageIn = 2, + PoolAllocation = 3, + DelayExecution = 4, + Suspended = 5, + UserRequest = 6, + WrExecutive = 7, + WrFreePage = 8, + WrPageIn = 9, + WrPoolAllocation = 10, + WrDelayExecution = 11, + WrSuspended = 12, + WrUserRequest = 13, + WrEventPair = 14, + WrQueue = 15, + WrLpcReceive = 16, + WrLpcReply = 17, + WrVirtualMemory = 18, + WrPageOut = 19, + WrRendezvous = 20, + Spare2 = 21, + Spare3 = 22, + Spare4 = 23, + Spare5 = 24, + Spare6 = 25, + WrKernel = 26, + MaximumWaitReason = 27 +}; +typedef enum _KWAIT_REASON KWAIT_REASON; +struct _DISPATCHER_HEADER { + UCHAR Type; + UCHAR Absolute; + UCHAR Size; + UCHAR Inserted; + LONG SignalState; + LIST_ENTRY WaitListHead; +}; +typedef struct _DISPATCHER_HEADER DISPATCHER_HEADER; +struct _KDEVICE_QUEUE { + CSHORT Type; + CSHORT Size; + LIST_ENTRY DeviceListHead; + KSPIN_LOCK Lock; + BOOLEAN Busy; +}; +typedef struct _KDEVICE_QUEUE KDEVICE_QUEUE; +struct _KDEVICE_QUEUE_ENTRY { + LIST_ENTRY DeviceListEntry; + ULONG SortKey; + BOOLEAN Inserted; +}; +typedef struct _KDEVICE_QUEUE_ENTRY KDEVICE_QUEUE_ENTRY; +struct _KEVENT { + DISPATCHER_HEADER Header; +}; +typedef struct _KEVENT KEVENT; +typedef struct _KEVENT *PKEVENT; +typedef struct _KEVENT *PRKEVENT; +struct _KSEMAPHORE { + DISPATCHER_HEADER Header; + LONG Limit; +}; +typedef struct _KSEMAPHORE *PKSEMAPHORE; +typedef struct _KSEMAPHORE *PRKSEMAPHORE; +enum _MEMORY_CACHING_TYPE { + MmNonCached = 0, + MmCached = 1, + MmWriteCombined = 2, + MmHardwareCoherentCached = 3, + MmNonCachedUnordered = 4, + MmUSWCCached = 5, + MmMaximumCacheType = 6 +}; +typedef enum _MEMORY_CACHING_TYPE MEMORY_CACHING_TYPE; +enum _POOL_TYPE { + NonPagedPool = 0, + PagedPool = 1, + NonPagedPoolMustSucceed = 2, + DontUseThisType = 3, + NonPagedPoolCacheAligned = 4, + PagedPoolCacheAligned = 5, + NonPagedPoolCacheAlignedMustS = 6, + MaxPoolType = 7, + NonPagedPoolSession = 32, + PagedPoolSession = 33, + NonPagedPoolMustSucceedSession = 34, + DontUseThisTypeSession = 35, + NonPagedPoolCacheAlignedSession = 36, + PagedPoolCacheAlignedSession = 37, + NonPagedPoolCacheAlignedMustSSession = 38 +}; +typedef enum _POOL_TYPE POOL_TYPE; +struct _FAST_MUTEX { + LONG Count; + PKTHREAD Owner; + ULONG Contention; + KEVENT Event; + ULONG OldIrql; +}; +typedef struct _FAST_MUTEX *PFAST_MUTEX; +typedef ULONG_PTR ERESOURCE_THREAD; +union __anonunion____missing_field_name_38 { + LONG OwnerCount; + ULONG TableSize; +}; +struct _OWNER_ENTRY { + ERESOURCE_THREAD OwnerThread; + union __anonunion____missing_field_name_38 __annonCompField10; +}; +typedef struct _OWNER_ENTRY OWNER_ENTRY; +typedef struct _OWNER_ENTRY *POWNER_ENTRY; +union __anonunion____missing_field_name_39 { + PVOID Address; + ULONG_PTR CreatorBackTraceIndex; +}; +struct _ERESOURCE { + LIST_ENTRY SystemResourcesList; + POWNER_ENTRY OwnerTable; + SHORT ActiveCount; + USHORT Flag; + PKSEMAPHORE SharedWaiters; + PKEVENT ExclusiveWaiters; + OWNER_ENTRY OwnerThreads[2]; + ULONG ContentionCount; + USHORT NumberOfSharedWaiters; + USHORT NumberOfExclusiveWaiters; + union __anonunion____missing_field_name_39 __annonCompField11; + KSPIN_LOCK SpinLock; +}; +enum _MM_PAGE_PRIORITY { + LowPagePriority = 0, + NormalPagePriority = 16, + HighPagePriority = 32 +}; +typedef enum _MM_PAGE_PRIORITY MM_PAGE_PRIORITY; +struct _DRIVER_OBJECT; +struct _DRIVER_OBJECT; +struct _SECURITY_SUBJECT_CONTEXT { + PACCESS_TOKEN ClientToken; + SECURITY_IMPERSONATION_LEVEL ImpersonationLevel; + PACCESS_TOKEN PrimaryToken; + PVOID ProcessAuditId; +}; +typedef struct _SECURITY_SUBJECT_CONTEXT SECURITY_SUBJECT_CONTEXT; +struct _INITIAL_PRIVILEGE_SET { + ULONG PrivilegeCount; + ULONG Control; + LUID_AND_ATTRIBUTES Privilege[3]; +}; +typedef struct _INITIAL_PRIVILEGE_SET INITIAL_PRIVILEGE_SET; +union __anonunion_Privileges_40 { + INITIAL_PRIVILEGE_SET InitialPrivilegeSet; + PRIVILEGE_SET PrivilegeSet; +}; +struct _ACCESS_STATE { + LUID OperationID; + BOOLEAN SecurityEvaluated; + BOOLEAN GenerateAudit; + BOOLEAN GenerateOnClose; + BOOLEAN PrivilegesAllocated; + ULONG Flags; + ACCESS_MASK RemainingDesiredAccess; + ACCESS_MASK PreviouslyGrantedAccess; + ACCESS_MASK OriginalDesiredAccess; + SECURITY_SUBJECT_CONTEXT SubjectSecurityContext; + PSECURITY_DESCRIPTOR SecurityDescriptor; + PVOID AuxData; + union __anonunion_Privileges_40 Privileges; + BOOLEAN AuditPrivileges; + UNICODE_STRING ObjectName; + UNICODE_STRING ObjectTypeName; +}; +typedef struct _ACCESS_STATE *PACCESS_STATE; +struct _DEVICE_OBJECT; +struct _DEVICE_OBJECT; +struct _DRIVER_OBJECT; +struct _FILE_OBJECT; +struct _FILE_OBJECT; +struct _IRP; +struct _IRP; +struct _SCSI_REQUEST_BLOCK; +struct _SCSI_REQUEST_BLOCK; +typedef NTSTATUS (*PDRIVER_DISPATCH)(struct _DEVICE_OBJECT *DeviceObject, struct _IRP *Irp); +struct _COMPRESSED_DATA_INFO; +struct _FAST_IO_DISPATCH { + ULONG SizeOfFastIoDispatch; + BOOLEAN(*FastIoCheckIfPossible) + (struct _FILE_OBJECT *FileObject, PLARGE_INTEGER FileOffset, + ULONG Length, BOOLEAN Wait, ULONG LockKey, + BOOLEAN CheckForReadOperation, PIO_STATUS_BLOCK IoStatus, + struct _DEVICE_OBJECT *DeviceObject); + BOOLEAN(*FastIoRead) + (struct _FILE_OBJECT *FileObject, PLARGE_INTEGER FileOffset, + ULONG Length, BOOLEAN Wait, ULONG LockKey, PVOID Buffer, + PIO_STATUS_BLOCK IoStatus, struct _DEVICE_OBJECT *DeviceObject); + BOOLEAN(*FastIoWrite) + (struct _FILE_OBJECT *FileObject, PLARGE_INTEGER FileOffset, + ULONG Length, BOOLEAN Wait, ULONG LockKey, PVOID Buffer, + PIO_STATUS_BLOCK IoStatus, struct _DEVICE_OBJECT *DeviceObject); + BOOLEAN(*FastIoQueryBasicInfo) + (struct _FILE_OBJECT *FileObject, BOOLEAN Wait, + PFILE_BASIC_INFORMATION Buffer, PIO_STATUS_BLOCK IoStatus, + struct _DEVICE_OBJECT *DeviceObject); + BOOLEAN(*FastIoQueryStandardInfo) + (struct _FILE_OBJECT *FileObject, BOOLEAN Wait, + PFILE_STANDARD_INFORMATION Buffer, PIO_STATUS_BLOCK IoStatus, + struct _DEVICE_OBJECT *DeviceObject); + BOOLEAN(*FastIoLock) + (struct _FILE_OBJECT *FileObject, PLARGE_INTEGER FileOffset, + PLARGE_INTEGER Length, PEPROCESS ProcessId, ULONG Key, + BOOLEAN FailImmediately, BOOLEAN ExclusiveLock, PIO_STATUS_BLOCK IoStatus, + struct _DEVICE_OBJECT *DeviceObject); + BOOLEAN(*FastIoUnlockSingle) + (struct _FILE_OBJECT *FileObject, PLARGE_INTEGER FileOffset, + PLARGE_INTEGER Length, PEPROCESS ProcessId, ULONG Key, + PIO_STATUS_BLOCK IoStatus, struct _DEVICE_OBJECT *DeviceObject); + BOOLEAN(*FastIoUnlockAll) + (struct _FILE_OBJECT *FileObject, PEPROCESS ProcessId, + PIO_STATUS_BLOCK IoStatus, struct _DEVICE_OBJECT *DeviceObject); + BOOLEAN(*FastIoUnlockAllByKey) + (struct _FILE_OBJECT *FileObject, PVOID ProcessId, + ULONG Key, PIO_STATUS_BLOCK IoStatus, struct _DEVICE_OBJECT *DeviceObject); + BOOLEAN(*FastIoDeviceControl) + (struct _FILE_OBJECT *FileObject, BOOLEAN Wait, + PVOID InputBuffer, ULONG InputBufferLength, PVOID OutputBuffer, + ULONG OutputBufferLength, ULONG IoControlCode, + PIO_STATUS_BLOCK IoStatus, struct _DEVICE_OBJECT *DeviceObject); + void (*AcquireFileForNtCreateSection)(struct _FILE_OBJECT *FileObject); + void (*ReleaseFileForNtCreateSection)(struct _FILE_OBJECT *FileObject); + void (*FastIoDetachDevice)(struct _DEVICE_OBJECT *SourceDevice, struct _DEVICE_OBJECT *TargetDevice); + BOOLEAN(*FastIoQueryNetworkOpenInfo) + (struct _FILE_OBJECT *FileObject, BOOLEAN Wait, + struct _FILE_NETWORK_OPEN_INFORMATION *Buffer, + struct _IO_STATUS_BLOCK *IoStatus, struct _DEVICE_OBJECT *DeviceObject); + NTSTATUS(*AcquireForModWrite) + (struct _FILE_OBJECT *FileObject, PLARGE_INTEGER EndingOffset, + struct _ERESOURCE **ResourceToRelease, struct _DEVICE_OBJECT *DeviceObject); + BOOLEAN(*MdlRead) + (struct _FILE_OBJECT *FileObject, PLARGE_INTEGER FileOffset, + ULONG Length, ULONG LockKey, PMDL *MdlChain, PIO_STATUS_BLOCK IoStatus, + struct _DEVICE_OBJECT *DeviceObject); + BOOLEAN(*MdlReadComplete) + (struct _FILE_OBJECT *FileObject, PMDL MdlChain, struct _DEVICE_OBJECT *DeviceObject); + BOOLEAN(*PrepareMdlWrite) + (struct _FILE_OBJECT *FileObject, PLARGE_INTEGER FileOffset, + ULONG Length, ULONG LockKey, PMDL *MdlChain, PIO_STATUS_BLOCK IoStatus, + struct _DEVICE_OBJECT *DeviceObject); + BOOLEAN(*MdlWriteComplete) + (struct _FILE_OBJECT *FileObject, PLARGE_INTEGER FileOffset, + PMDL MdlChain, struct _DEVICE_OBJECT *DeviceObject); + BOOLEAN(*FastIoReadCompressed) + (struct _FILE_OBJECT *FileObject, PLARGE_INTEGER FileOffset, + ULONG Length, ULONG LockKey, PVOID Buffer, PMDL *MdlChain, + PIO_STATUS_BLOCK IoStatus, struct _COMPRESSED_DATA_INFO *CompressedDataInfo, + ULONG CompressedDataInfoLength, struct _DEVICE_OBJECT *DeviceObject); + BOOLEAN(*FastIoWriteCompressed) + (struct _FILE_OBJECT *FileObject, PLARGE_INTEGER FileOffset, + ULONG Length, ULONG LockKey, PVOID Buffer, + PMDL *MdlChain, PIO_STATUS_BLOCK IoStatus, struct _COMPRESSED_DATA_INFO *CompressedDataInfo, + ULONG CompressedDataInfoLength, struct _DEVICE_OBJECT *DeviceObject); + BOOLEAN(*MdlReadCompleteCompressed) + (struct _FILE_OBJECT *FileObject, PMDL MdlChain, + struct _DEVICE_OBJECT *DeviceObject); + BOOLEAN(*MdlWriteCompleteCompressed) + (struct _FILE_OBJECT *FileObject, PLARGE_INTEGER FileOffset, + PMDL MdlChain, struct _DEVICE_OBJECT *DeviceObject); + BOOLEAN(*FastIoQueryOpen) + (struct _IRP *Irp, PFILE_NETWORK_OPEN_INFORMATION NetworkInformation, + struct _DEVICE_OBJECT *DeviceObject); + NTSTATUS(*ReleaseForModWrite) + (struct _FILE_OBJECT *FileObject, struct _ERESOURCE *ResourceToRelease, + struct _DEVICE_OBJECT *DeviceObject); + NTSTATUS(*AcquireForCcFlush) + (struct _FILE_OBJECT *FileObject, struct _DEVICE_OBJECT *DeviceObject); + NTSTATUS(*ReleaseForCcFlush) + (struct _FILE_OBJECT *FileObject, struct _DEVICE_OBJECT *DeviceObject); +}; +typedef struct _FAST_IO_DISPATCH *PFAST_IO_DISPATCH; +enum _IO_ALLOCATION_ACTION { + KeepObject = 1, + DeallocateObject = 2, + DeallocateObjectKeepRegisters = 3 +}; +typedef enum _IO_ALLOCATION_ACTION IO_ALLOCATION_ACTION; +struct _IO_SECURITY_CONTEXT { + PSECURITY_QUALITY_OF_SERVICE SecurityQos; + PACCESS_STATE AccessState; + ACCESS_MASK DesiredAccess; + ULONG FullCreateOptions; +}; +typedef struct _IO_SECURITY_CONTEXT *PIO_SECURITY_CONTEXT; +struct _VPB { + CSHORT Type; + CSHORT Size; + USHORT Flags; + USHORT VolumeLabelLength; + struct _DEVICE_OBJECT *DeviceObject; + struct _DEVICE_OBJECT *RealDevice; + ULONG SerialNumber; + ULONG ReferenceCount; + WCHAR VolumeLabel[(32U * sizeof(WCHAR)) / sizeof(WCHAR)]; +}; +typedef struct _VPB *PVPB; +struct _WAIT_CONTEXT_BLOCK { + KDEVICE_QUEUE_ENTRY WaitQueueEntry; + IO_ALLOCATION_ACTION(*DeviceRoutine) + (struct _DEVICE_OBJECT *DeviceObject, struct _IRP *Irp, + PVOID MapRegisterBase, PVOID Context); + PVOID DeviceContext; + ULONG NumberOfMapRegisters; + PVOID DeviceObject; + PVOID CurrentIrp; + PKDPC BufferChainingDpc; +}; +typedef struct _WAIT_CONTEXT_BLOCK WAIT_CONTEXT_BLOCK; +union __anonunion_Queue_43 { + LIST_ENTRY ListEntry; + WAIT_CONTEXT_BLOCK Wcb; +}; +struct _DEVOBJ_EXTENSION; +struct _DEVICE_OBJECT { + CSHORT Type; + USHORT Size; + LONG ReferenceCount; + struct _DRIVER_OBJECT *DriverObject; + struct _DEVICE_OBJECT *NextDevice; + struct _DEVICE_OBJECT *AttachedDevice; + struct _IRP *CurrentIrp; + PIO_TIMER Timer; + ULONG Flags; + ULONG Characteristics; + PVPB Vpb; + PVOID DeviceExtension; + ULONG DeviceType; + CCHAR StackSize; + union __anonunion_Queue_43 Queue; + ULONG AlignmentRequirement; + KDEVICE_QUEUE DeviceQueue; + KDPC Dpc; + ULONG ActiveThreadCount; + PSECURITY_DESCRIPTOR SecurityDescriptor; + KEVENT DeviceLock; + USHORT SectorSize; + USHORT Spare1; + struct _DEVOBJ_EXTENSION *DeviceObjectExtension; + PVOID Reserved; +}; +typedef struct _DEVICE_OBJECT DEVICE_OBJECT; +typedef struct _DEVICE_OBJECT *PDEVICE_OBJECT; +struct _DEVOBJ_EXTENSION { + CSHORT Type; + USHORT Size; + PDEVICE_OBJECT DeviceObject; +}; +struct _DRIVER_EXTENSION { + struct _DRIVER_OBJECT *DriverObject; + NTSTATUS(*AddDevice) + (struct _DRIVER_OBJECT *DriverObject, struct _DEVICE_OBJECT *PhysicalDeviceObject); + ULONG Count; + UNICODE_STRING ServiceKeyName; +}; +typedef struct _DRIVER_EXTENSION *PDRIVER_EXTENSION; +struct _DRIVER_OBJECT { + CSHORT Type; + CSHORT Size; + PDEVICE_OBJECT DeviceObject; + ULONG Flags; + PVOID DriverStart; + ULONG DriverSize; + PVOID DriverSection; + PDRIVER_EXTENSION DriverExtension; + UNICODE_STRING DriverName; + PUNICODE_STRING HardwareDatabase; + PFAST_IO_DISPATCH FastIoDispatch; + NTSTATUS(*DriverInit) + (struct _DRIVER_OBJECT *DriverObject, PUNICODE_STRING RegistryPath); + void (*DriverStartIo)(struct _DEVICE_OBJECT *DeviceObject, struct _IRP *Irp); + void (*DriverUnload)(struct _DRIVER_OBJECT *DriverObject); + PDRIVER_DISPATCH MajorFunction[28]; +}; +typedef struct _DRIVER_OBJECT DRIVER_OBJECT; +typedef struct _DRIVER_OBJECT *PDRIVER_OBJECT; +struct _SECTION_OBJECT_POINTERS { + PVOID DataSectionObject; + PVOID SharedCacheMap; + PVOID ImageSectionObject; +}; +typedef struct _SECTION_OBJECT_POINTERS SECTION_OBJECT_POINTERS; +typedef SECTION_OBJECT_POINTERS *PSECTION_OBJECT_POINTERS; +struct _IO_COMPLETION_CONTEXT { + PVOID Port; + PVOID Key; +}; +typedef struct _IO_COMPLETION_CONTEXT *PIO_COMPLETION_CONTEXT; +struct _FILE_OBJECT { + CSHORT Type; + CSHORT Size; + PDEVICE_OBJECT DeviceObject; + PVPB Vpb; + PVOID FsContext; + PVOID FsContext2; + PSECTION_OBJECT_POINTERS SectionObjectPointer; + PVOID PrivateCacheMap; + NTSTATUS FinalStatus; + struct _FILE_OBJECT *RelatedFileObject; + BOOLEAN LockOperation; + BOOLEAN DeletePending; + BOOLEAN ReadAccess; + BOOLEAN WriteAccess; + BOOLEAN DeleteAccess; + BOOLEAN SharedRead; + BOOLEAN SharedWrite; + BOOLEAN SharedDelete; + ULONG Flags; + UNICODE_STRING FileName; + LARGE_INTEGER CurrentByteOffset; + ULONG Waiters; + ULONG Busy; + PVOID LastLock; + KEVENT Lock; + KEVENT Event; + PIO_COMPLETION_CONTEXT CompletionContext; +}; +typedef struct _FILE_OBJECT *PFILE_OBJECT; +union __anonunion_AssociatedIrp_44 { + struct _IRP *MasterIrp; + LONG IrpCount; + PVOID SystemBuffer; +}; +struct __anonstruct_AsynchronousParameters_46 { + void (*UserApcRoutine)(PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, + ULONG Reserved); + PVOID UserApcContext; +}; +union __anonunion_Overlay_45 { + struct __anonstruct_AsynchronousParameters_46 AsynchronousParameters; + LARGE_INTEGER AllocationSize; +}; +struct __anonstruct____missing_field_name_50 { + PVOID DriverContext[4]; +}; +union __anonunion____missing_field_name_49 { + KDEVICE_QUEUE_ENTRY DeviceQueueEntry; + struct __anonstruct____missing_field_name_50 __annonCompField14; +}; +struct _IO_STACK_LOCATION; +union __anonunion____missing_field_name_52 { + struct _IO_STACK_LOCATION *CurrentStackLocation; + ULONG PacketType; +}; +struct __anonstruct____missing_field_name_51 { + LIST_ENTRY ListEntry; + union __anonunion____missing_field_name_52 __annonCompField16; +}; +struct __anonstruct_Overlay_48 { + union __anonunion____missing_field_name_49 __annonCompField15; + PETHREAD Thread; + PCHAR AuxiliaryBuffer; + struct __anonstruct____missing_field_name_51 __annonCompField17; + PFILE_OBJECT OriginalFileObject; +}; +union __anonunion_Tail_47 { + struct __anonstruct_Overlay_48 Overlay; + KAPC Apc; + PVOID CompletionKey; +}; +struct _IRP { + CSHORT Type; + USHORT Size; + PMDL MdlAddress; + ULONG Flags; + union __anonunion_AssociatedIrp_44 AssociatedIrp; + LIST_ENTRY ThreadListEntry; + IO_STATUS_BLOCK IoStatus; + KPROCESSOR_MODE RequestorMode; + BOOLEAN PendingReturned; + CHAR StackCount; + CHAR CurrentLocation; + BOOLEAN Cancel; + KIRQL CancelIrql; + CCHAR ApcEnvironment; + UCHAR AllocationFlags; + PIO_STATUS_BLOCK UserIosb; + PKEVENT UserEvent; + union __anonunion_Overlay_45 Overlay; + void (*CancelRoutine)(struct _DEVICE_OBJECT *DeviceObject, struct _IRP *Irp); + PVOID UserBuffer; + union __anonunion_Tail_47 Tail; +}; +typedef struct _IRP IRP; +typedef struct _IRP *PIRP; +enum _DEVICE_RELATION_TYPE { + BusRelations = 0, + EjectionRelations = 1, + PowerRelations = 2, + RemovalRelations = 3, + TargetDeviceRelation = 4 +}; +typedef enum _DEVICE_RELATION_TYPE DEVICE_RELATION_TYPE; +enum _DEVICE_USAGE_NOTIFICATION_TYPE { + DeviceUsageTypeUndefined = 0, + DeviceUsageTypePaging = 1, + DeviceUsageTypeHibernation = 2, + DeviceUsageTypeDumpFile = 3 +}; +typedef enum _DEVICE_USAGE_NOTIFICATION_TYPE DEVICE_USAGE_NOTIFICATION_TYPE; +struct _INTERFACE { + USHORT Size; + USHORT Version; + PVOID Context; + void (*InterfaceReference)(PVOID Context); + void (*InterfaceDereference)(PVOID Context); +}; +typedef struct _INTERFACE *PINTERFACE; +struct _DEVICE_CAPABILITIES { + USHORT Size; + USHORT Version; + ULONG DeviceD1 : 1; + ULONG DeviceD2 : 1; + ULONG LockSupported : 1; + ULONG EjectSupported : 1; + ULONG Removable : 1; + ULONG DockDevice : 1; + ULONG UniqueID : 1; + ULONG SilentInstall : 1; + ULONG RawDeviceOK : 1; + ULONG SurpriseRemovalOK : 1; + ULONG WakeFromD0 : 1; + ULONG WakeFromD1 : 1; + ULONG WakeFromD2 : 1; + ULONG WakeFromD3 : 1; + ULONG HardwareDisabled : 1; + ULONG NonDynamic : 1; + ULONG WarmEjectSupported : 1; + ULONG Reserved : 15; + ULONG Address; + ULONG UINumber; + DEVICE_POWER_STATE DeviceState[7]; + SYSTEM_POWER_STATE SystemWake; + DEVICE_POWER_STATE DeviceWake; + ULONG D1Latency; + ULONG D2Latency; + ULONG D3Latency; +}; +typedef struct _DEVICE_CAPABILITIES *PDEVICE_CAPABILITIES; +struct _POWER_SEQUENCE { + ULONG SequenceD1; + ULONG SequenceD2; + ULONG SequenceD3; +}; +typedef struct _POWER_SEQUENCE *PPOWER_SEQUENCE; +enum __anonenum_BUS_QUERY_ID_TYPE_53 { + BusQueryDeviceID = 0, + BusQueryHardwareIDs = 1, + BusQueryCompatibleIDs = 2, + BusQueryInstanceID = 3, + BusQueryDeviceSerialNumber = 4 +}; +typedef enum __anonenum_BUS_QUERY_ID_TYPE_53 BUS_QUERY_ID_TYPE; +enum __anonenum_DEVICE_TEXT_TYPE_54 { + DeviceTextDescription = 0, + DeviceTextLocationInformation = 1 +}; +typedef enum __anonenum_DEVICE_TEXT_TYPE_54 DEVICE_TEXT_TYPE; +#pragma pack(push, 4) +struct __anonstruct_Create_56 { + PIO_SECURITY_CONTEXT SecurityContext; + ULONG Options; + USHORT FileAttributes; + USHORT ShareAccess; + ULONG EaLength; +}; +struct __anonstruct_Read_57 { + ULONG Length; + ULONG Key; + LARGE_INTEGER ByteOffset; +}; +struct __anonstruct_Write_58 { + ULONG Length; + ULONG Key; + LARGE_INTEGER ByteOffset; +}; +struct __anonstruct_QueryFile_59 { + ULONG Length; + FILE_INFORMATION_CLASS FileInformationClass; +}; +struct __anonstruct____missing_field_name_62 { + BOOLEAN ReplaceIfExists; + BOOLEAN AdvanceOnly; +}; +union __anonunion____missing_field_name_61 { + struct __anonstruct____missing_field_name_62 __annonCompField18; + ULONG ClusterCount; + HANDLE DeleteHandle; +}; +struct __anonstruct_SetFile_60 { + ULONG Length; + FILE_INFORMATION_CLASS FileInformationClass; + PFILE_OBJECT FileObject; + union __anonunion____missing_field_name_61 __annonCompField19; +}; +struct __anonstruct_QueryVolume_63 { + ULONG Length; + FS_INFORMATION_CLASS FsInformationClass; +}; +struct __anonstruct_DeviceIoControl_64 { + ULONG OutputBufferLength; + ULONG InputBufferLength; + ULONG IoControlCode; + PVOID Type3InputBuffer; +}; +struct __anonstruct_QuerySecurity_65 { + SECURITY_INFORMATION SecurityInformation; + ULONG Length; +}; +struct __anonstruct_SetSecurity_66 { + SECURITY_INFORMATION SecurityInformation; + PSECURITY_DESCRIPTOR SecurityDescriptor; +}; +struct __anonstruct_MountVolume_67 { + PVPB Vpb; + PDEVICE_OBJECT DeviceObject; +}; +struct __anonstruct_VerifyVolume_68 { + PVPB Vpb; + PDEVICE_OBJECT DeviceObject; +}; +struct __anonstruct_Scsi_69 { + struct _SCSI_REQUEST_BLOCK *Srb; +}; +struct __anonstruct_QueryDeviceRelations_70 { + DEVICE_RELATION_TYPE Type; +}; +struct __anonstruct_QueryInterface_71 { + GUID const *InterfaceType; + USHORT Size; + USHORT Version; + PINTERFACE Interface; + PVOID InterfaceSpecificData; +}; +struct __anonstruct_DeviceCapabilities_72 { + PDEVICE_CAPABILITIES Capabilities; +}; +struct __anonstruct_FilterResourceRequirements_73 { + PIO_RESOURCE_REQUIREMENTS_LIST IoResourceRequirementList; +}; +struct __anonstruct_ReadWriteConfig_74 { + ULONG WhichSpace; + PVOID Buffer; + ULONG Offset; + ULONG Length; +}; +struct __anonstruct_SetLock_75 { + BOOLEAN Lock; +}; +struct __anonstruct_QueryId_76 { + BUS_QUERY_ID_TYPE IdType; +}; +struct __anonstruct_QueryDeviceText_77 { + DEVICE_TEXT_TYPE DeviceTextType; + LCID LocaleId; +}; +struct __anonstruct_UsageNotification_78 { + BOOLEAN InPath; + BOOLEAN Reserved[3]; + DEVICE_USAGE_NOTIFICATION_TYPE Type; +}; +struct __anonstruct_WaitWake_79 { + SYSTEM_POWER_STATE PowerState; +}; +struct __anonstruct_PowerSequence_80 { + PPOWER_SEQUENCE PowerSequence; +}; +struct __anonstruct_Power_81 { + ULONG SystemContext; + POWER_STATE_TYPE Type; + POWER_STATE State; + POWER_ACTION ShutdownType; +}; +struct __anonstruct_StartDevice_82 { + PCM_RESOURCE_LIST AllocatedResources; + PCM_RESOURCE_LIST AllocatedResourcesTranslated; +}; +struct __anonstruct_WMI_83 { + ULONG_PTR ProviderId; + PVOID DataPath; + ULONG BufferSize; + PVOID Buffer; +}; +struct __anonstruct_Others_84 { + PVOID Argument1; + PVOID Argument2; + PVOID Argument3; + PVOID Argument4; +}; +union __anonunion_Parameters_55 { + struct __anonstruct_Create_56 Create; + struct __anonstruct_Read_57 Read; + struct __anonstruct_Write_58 Write; + struct __anonstruct_QueryFile_59 QueryFile; + struct __anonstruct_SetFile_60 SetFile; + struct __anonstruct_QueryVolume_63 QueryVolume; + struct __anonstruct_DeviceIoControl_64 DeviceIoControl; + struct __anonstruct_QuerySecurity_65 QuerySecurity; + struct __anonstruct_SetSecurity_66 SetSecurity; + struct __anonstruct_MountVolume_67 MountVolume; + struct __anonstruct_VerifyVolume_68 VerifyVolume; + struct __anonstruct_Scsi_69 Scsi; + struct __anonstruct_QueryDeviceRelations_70 QueryDeviceRelations; + struct __anonstruct_QueryInterface_71 QueryInterface; + struct __anonstruct_DeviceCapabilities_72 DeviceCapabilities; + struct __anonstruct_FilterResourceRequirements_73 FilterResourceRequirements; + struct __anonstruct_ReadWriteConfig_74 ReadWriteConfig; + struct __anonstruct_SetLock_75 SetLock; + struct __anonstruct_QueryId_76 QueryId; + struct __anonstruct_QueryDeviceText_77 QueryDeviceText; + struct __anonstruct_UsageNotification_78 UsageNotification; + struct __anonstruct_WaitWake_79 WaitWake; + struct __anonstruct_PowerSequence_80 PowerSequence; + struct __anonstruct_Power_81 Power; + struct __anonstruct_StartDevice_82 StartDevice; + struct __anonstruct_WMI_83 WMI; + struct __anonstruct_Others_84 Others; +}; +struct _IO_STACK_LOCATION { + UCHAR MajorFunction; + UCHAR MinorFunction; + UCHAR Flags; + UCHAR Control; + union __anonunion_Parameters_55 Parameters; + PDEVICE_OBJECT DeviceObject; + PFILE_OBJECT FileObject; + NTSTATUS(*CompletionRoutine) + (PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context); + PVOID Context; +}; +typedef struct _IO_STACK_LOCATION IO_STACK_LOCATION; +typedef struct _IO_STACK_LOCATION *PIO_STACK_LOCATION; +#pragma pack(pop) +struct _CONFIGURATION_INFORMATION { + ULONG DiskCount; + ULONG FloppyCount; + ULONG CdRomCount; + ULONG TapeCount; + ULONG ScsiPortCount; + ULONG SerialCount; + ULONG ParallelCount; + BOOLEAN AtDiskPrimaryAddressClaimed; + BOOLEAN AtDiskSecondaryAddressClaimed; + ULONG Version; + ULONG MediumChangerCount; +}; +typedef struct _CONFIGURATION_INFORMATION CONFIGURATION_INFORMATION; +typedef struct _CONFIGURATION_INFORMATION *PCONFIGURATION_INFORMATION; +struct _OBJECT_HANDLE_INFORMATION { + ULONG HandleAttributes; + ACCESS_MASK GrantedAccess; +}; +typedef struct _OBJECT_HANDLE_INFORMATION *POBJECT_HANDLE_INFORMATION; +struct _KEYBOARD_INPUT_DATA { + USHORT UnitId; + USHORT MakeCode; + USHORT Flags; + USHORT Reserved; + ULONG ExtraInformation; +}; +typedef struct _KEYBOARD_INPUT_DATA *PKEYBOARD_INPUT_DATA; +struct _CONNECT_DATA { + PDEVICE_OBJECT ClassDeviceObject; + PVOID ClassService; +}; +typedef struct _CONNECT_DATA CONNECT_DATA; +typedef struct _CONNECT_DATA *PCONNECT_DATA; +enum _TRANSMIT_STATE { + Idle = 0, + SendingBytes = 1 +}; +typedef enum _TRANSMIT_STATE TRANSMIT_STATE; +struct _OUTPUT_PACKET { + PUCHAR Bytes; + ULONG CurrentByte; + ULONG ByteCount; + TRANSMIT_STATE State; +}; +typedef struct _OUTPUT_PACKET *POUTPUT_PACKET; +enum _KEYBOARD_SCAN_STATE { + Normal = 0, + GotE0 = 1, + GotE1 = 2 +}; +typedef enum _KEYBOARD_SCAN_STATE *PKEYBOARD_SCAN_STATE; +struct _INTERNAL_I8042_HOOK_KEYBOARD { + PVOID Context; + NTSTATUS(*InitializationRoutine) + (PVOID InitializationContext, PVOID SynchFuncContext, + NTSTATUS (*ReadPort)(PVOID Context, PUCHAR Value, + BOOLEAN WaitForACK), + NTSTATUS (*WritePort)(PVOID Context, + UCHAR Value, + BOOLEAN WaitForACK), + PBOOLEAN TurnTranslationOn); + BOOLEAN(*IsrRoutine) + (PVOID IsrContext, PKEYBOARD_INPUT_DATA CurrentInput, POUTPUT_PACKET CurrentOutput, + UCHAR StatusByte, PUCHAR Byte, PBOOLEAN ContinueProcessing, + PKEYBOARD_SCAN_STATE ScanState); + void (*IsrWritePort)(PVOID Context, UCHAR Value); + void (*QueueKeyboardPacket)(PVOID Context); + PVOID CallContext; +}; +typedef struct _INTERNAL_I8042_HOOK_KEYBOARD INTERNAL_I8042_HOOK_KEYBOARD; +typedef struct _INTERNAL_I8042_HOOK_KEYBOARD *PINTERNAL_I8042_HOOK_KEYBOARD; +struct _DEVICE_EXTENSION { + PDEVICE_OBJECT Self; + PDEVICE_OBJECT PDO; + PDEVICE_OBJECT TopOfStack; + LONG EnableCount; + CONNECT_DATA UpperConnectData; + PVOID UpperContext; + NTSTATUS(*UpperInitializationRoutine) + (PVOID InitializationContext, PVOID SynchFuncContext, + NTSTATUS (*ReadPort)(PVOID Context, PUCHAR Value, + BOOLEAN WaitForACK), + NTSTATUS (*WritePort)(PVOID Context, UCHAR Value, + BOOLEAN WaitForACK), + PBOOLEAN TurnTranslationOn); + BOOLEAN(*UpperIsrHook) + (PVOID IsrContext, PKEYBOARD_INPUT_DATA CurrentInput, + POUTPUT_PACKET CurrentOutput, UCHAR StatusByte, PUCHAR Byte, + PBOOLEAN ContinueProcessing, PKEYBOARD_SCAN_STATE ScanState); + void (*IsrWritePort)(PVOID Context, UCHAR Value); + void (*QueueKeyboardPacket)(PVOID Context); + PVOID CallContext; + DEVICE_POWER_STATE DeviceState; + BOOLEAN Started; + BOOLEAN SurpriseRemoved; + BOOLEAN Removed; +}; +typedef struct _DEVICE_EXTENSION DEVICE_EXTENSION; +typedef struct _DEVICE_EXTENSION *PDEVICE_EXTENSION; +#pragma pack(push, 8) +#pragma pack(pop) +struct _KAPC; +struct _KDPC; +#pragma pack(push, 4) +#pragma pack(pop) +#pragma pack(push, 4) +#pragma pack(pop) +#pragma pack(push, 1) +#pragma pack(pop) +struct _DRIVER_OBJECT; +struct _DEVICE_OBJECT; +struct _DRIVER_OBJECT; +struct _FILE_OBJECT; +struct _IRP; +struct _SCSI_REQUEST_BLOCK; +#pragma pack(push, 4) +#pragma pack(pop) +#pragma warning(push) +#pragma warning(disable : 4035) +#pragma warning(pop) +extern void *memcpy(void *, void const *, size_t); +extern void *memmove(void *, void const *, size_t); +extern void *memset(void *, int, size_t); +#pragma warning(disable : 4103) +#pragma warning(disable : 4103) +NTSTATUS RtlQueryRegistryValues(ULONG RelativeTo, + PCWSTR Path, + PRTL_QUERY_REGISTRY_TABLE QueryTable, + PVOID Context, + PVOID Environment); +NTSTATUS RtlDeleteRegistryValue(ULONG RelativeTo, + PCWSTR Path, + PCWSTR ValueName); +void RtlInitString(PSTRING DestinationString, + PCSZ SourceString); +void RtlInitUnicodeString(PUNICODE_STRING DestinationString, + PCWSTR SourceString); +NTSTATUS RtlAnsiStringToUnicodeString(PUNICODE_STRING DestinationString, + PANSI_STRING SourceString, + BOOLEAN AllocateDestinationString); +void RtlCopyUnicodeString(PUNICODE_STRING DestinationString, + PUNICODE_STRING SourceString); +void RtlFreeUnicodeString(PUNICODE_STRING UnicodeString); +SIZE_T RtlCompareMemory(void const *Source1, + void const *Source2, + SIZE_T Length); +#pragma warning(push) +#pragma warning(disable : 4035) +#pragma warning(pop) +LONG InterlockedIncrement(PLONG Addend) { + return ++(*Addend); +} +LONG InterlockedDecrement(PLONG Addend) { + return --(*Addend); +} +#pragma warning(disable : 4035) +#pragma warning(push) +#pragma warning(disable : 4164) +#pragma function(_enable) +#pragma function(_disable) +#pragma warning(pop) +#pragma warning(disable : 4103) +#pragma warning(disable : 4103) +#pragma warning(disable : 4103) +#pragma warning(disable : 4103) +void KeInitializeEvent(PRKEVENT Event, EVENT_TYPE Type, + BOOLEAN State); +LONG KeSetEvent(PRKEVENT Event, KPRIORITY Increment, + BOOLEAN Wait); +void KeInitializeSemaphore(PRKSEMAPHORE Semaphore, + LONG Count, LONG Limit); +LONG KeReleaseSemaphore(PRKSEMAPHORE Semaphore, KPRIORITY Increment, + LONG Adjustment, BOOLEAN Wait); +NTSTATUS KeDelayExecutionThread(KPROCESSOR_MODE WaitMode, + BOOLEAN Alertable, + PLARGE_INTEGER Interval); +NTSTATUS KeWaitForSingleObject(PVOID Object, KWAIT_REASON WaitReason, + KPROCESSOR_MODE WaitMode, + BOOLEAN Alertable, + PLARGE_INTEGER Timeout); +void KeInitializeSpinLock(PKSPIN_LOCK SpinLock); +void KfReleaseSpinLock(PKSPIN_LOCK SpinLock, + KIRQL NewIrql); +PVOID ExAllocatePoolWithTag(POOL_TYPE PoolType, + SIZE_T NumberOfBytes, + ULONG Tag); +void ExFreePool(PVOID P); +void ExAcquireFastMutex(PFAST_MUTEX FastMutex); +void ExReleaseFastMutex(PFAST_MUTEX FastMutex); +PLIST_ENTRY ExfInterlockedInsertHeadList(PLIST_ENTRY ListHead, + PLIST_ENTRY ListEntry, + PKSPIN_LOCK Lock); +PLIST_ENTRY ExfInterlockedInsertTailList(PLIST_ENTRY ListHead, + PLIST_ENTRY ListEntry, + PKSPIN_LOCK Lock); +PLIST_ENTRY ExfInterlockedRemoveHeadList(PLIST_ENTRY ListHead, + PKSPIN_LOCK Lock); +void MmUnlockPages(PMDL MemoryDescriptorList); +PVOID MmMapLockedPagesSpecifyCache(PMDL MemoryDescriptorList, + KPROCESSOR_MODE AccessMode, + MEMORY_CACHING_TYPE CacheType, + PVOID BaseAddress, + ULONG BugCheckOnFailure, + MM_PAGE_PRIORITY Priority); +PVOID MmAllocateContiguousMemory(SIZE_T NumberOfBytes, + PHYSICAL_ADDRESS HighestAcceptableAddress); +void MmFreeContiguousMemory(PVOID BaseAddress); +void MmResetDriverPaging(PVOID AddressWithinSection); +PVOID MmPageEntireDriver(PVOID AddressWithinSection); +NTSTATUS PsCreateSystemThread(PHANDLE ThreadHandle, + ULONG DesiredAccess, + POBJECT_ATTRIBUTES ObjectAttributes, + HANDLE ProcessHandle, + PCLIENT_ID ClientId, + void (*StartRoutine)(PVOID StartContext), + PVOID StartContext); +NTSTATUS PsTerminateSystemThread(NTSTATUS ExitStatus); +#pragma warning(disable : 4103) +#pragma warning(disable : 4103) +PMDL IoAllocateMdl(PVOID VirtualAddress, ULONG Length, + BOOLEAN SecondaryBuffer, BOOLEAN ChargeQuota, + PIRP Irp); +PDEVICE_OBJECT IoAttachDeviceToDeviceStack(PDEVICE_OBJECT SourceDevice, + PDEVICE_OBJECT TargetDevice); +PIRP IoBuildAsynchronousFsdRequest(ULONG MajorFunction, + PDEVICE_OBJECT DeviceObject, + PVOID Buffer, + ULONG Length, + PLARGE_INTEGER StartingOffset, + PIO_STATUS_BLOCK IoStatusBlock); +PIRP IoBuildDeviceIoControlRequest(ULONG IoControlCode, + PDEVICE_OBJECT DeviceObject, + PVOID InputBuffer, + ULONG InputBufferLength, + PVOID OutputBuffer, + ULONG OutputBufferLength, + BOOLEAN InternalDeviceIoControl, + PKEVENT Event, + PIO_STATUS_BLOCK IoStatusBlock); +NTSTATUS IofCallDriver(PDEVICE_OBJECT DeviceObject, + PIRP Irp); +void IofCompleteRequest(PIRP Irp, + CCHAR PriorityBoost); +NTSTATUS IoCreateDevice(PDRIVER_OBJECT DriverObject, + ULONG DeviceExtensionSize, + PUNICODE_STRING DeviceName, + ULONG DeviceType, ULONG DeviceCharacteristics, + BOOLEAN Exclusive, PDEVICE_OBJECT *DeviceObject); +NTSTATUS IoCreateSymbolicLink(PUNICODE_STRING SymbolicLinkName, + PUNICODE_STRING DeviceName); +void IoDeleteDevice(PDEVICE_OBJECT DeviceObject); +NTSTATUS IoDeleteSymbolicLink(PUNICODE_STRING SymbolicLinkName); +void IoDetachDevice(PDEVICE_OBJECT TargetDevice); +void IoFreeIrp(PIRP Irp); +void IoFreeMdl(PMDL Mdl); +PCONFIGURATION_INFORMATION IoGetConfigurationInformation(void); +NTSTATUS IoQueryDeviceDescription(PINTERFACE_TYPE BusType, + PULONG BusNumber, + PCONFIGURATION_TYPE ControllerType, + PULONG ControllerNumber, + PCONFIGURATION_TYPE PeripheralType, + PULONG PeripheralNumber, + NTSTATUS (*CalloutRoutine)(PVOID Context, + PUNICODE_STRING PathName, + INTERFACE_TYPE BusType, + ULONG BusNumber, + PKEY_VALUE_FULL_INFORMATION *BusInformation, + CONFIGURATION_TYPE ControllerType, + ULONG ControllerNumber, + PKEY_VALUE_FULL_INFORMATION *ControllerInformation, + CONFIGURATION_TYPE PeripheralType, + ULONG PeripheralNumber, + PKEY_VALUE_FULL_INFORMATION *PeripheralInformation), + PVOID Context); +void IoReleaseCancelSpinLock(KIRQL Irql); +void IoSetHardErrorOrVerifyDevice(PIRP Irp, PDEVICE_OBJECT DeviceObject); +NTSTATUS IoRegisterDeviceInterface(PDEVICE_OBJECT PhysicalDeviceObject, + GUID const *InterfaceClassGuid, + PUNICODE_STRING ReferenceString, + PUNICODE_STRING SymbolicLinkName); +NTSTATUS IoSetDeviceInterfaceState(PUNICODE_STRING SymbolicLinkName, + BOOLEAN Enable); +#pragma warning(disable : 4200) +#pragma warning(default : 4200) +NTSTATUS PoCallDriver(PDEVICE_OBJECT DeviceObject, + PIRP Irp); +void PoStartNextPowerIrp(PIRP Irp); +NTSTATUS ObReferenceObjectByHandle(HANDLE Handle, + ACCESS_MASK DesiredAccess, + POBJECT_TYPE ObjectType, + KPROCESSOR_MODE AccessMode, + PVOID *Object, + POBJECT_HANDLE_INFORMATION HandleInformation); +void ObfDereferenceObject(PVOID Object); +NTSTATUS ZwClose(HANDLE Handle); +NTSTATUS KbFilter_AddDevice(PDRIVER_OBJECT Driver, PDEVICE_OBJECT PDO); +NTSTATUS KbFilter_CreateClose(PDEVICE_OBJECT DeviceObject, PIRP Irp); +NTSTATUS KbFilter_DispatchPassThrough(PDEVICE_OBJECT DeviceObject, PIRP Irp); +NTSTATUS KbFilter_InternIoCtl(PDEVICE_OBJECT DeviceObject, PIRP Irp); +NTSTATUS KbFilter_IoCtl(PDEVICE_OBJECT DeviceObject, PIRP Irp) { + if (__VERIFIER_nondet_int()) { + return 0L; + } else if (__VERIFIER_nondet_int()) { + return -1L; + } else { + return 259L; + } +} +NTSTATUS KbFilter_PnP(PDEVICE_OBJECT DeviceObject, PIRP Irp); +NTSTATUS KbFilter_Power(PDEVICE_OBJECT DeviceObject, PIRP Irp); +NTSTATUS KbFilter_InitializationRoutine(PDEVICE_OBJECT DeviceObject, PVOID SynchFuncContext, + NTSTATUS (*ReadPort)(PVOID Context, PUCHAR Value, + BOOLEAN WaitForACK), + NTSTATUS (*WritePort)(PVOID Context, UCHAR Value, + BOOLEAN WaitForACK), + PBOOLEAN TurnTranslationOn); +BOOLEAN KbFilter_IsrHook(PDEVICE_OBJECT DeviceObject, PKEYBOARD_INPUT_DATA CurrentInput, + POUTPUT_PACKET CurrentOutput, UCHAR StatusByte, PUCHAR DataByte, + PBOOLEAN ContinueProcessing, PKEYBOARD_SCAN_STATE ScanState); +void KbFilter_ServiceCallback(PDEVICE_OBJECT DeviceObject, PKEYBOARD_INPUT_DATA InputDataStart, + PKEYBOARD_INPUT_DATA InputDataEnd, PULONG InputDataConsumed); +void KbFilter_Unload(PDRIVER_OBJECT Driver); +NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath); +#pragma alloc_text(INIT, DriverEntry) +#pragma alloc_text(PAGE, KbFilter_AddDevice) +#pragma alloc_text(PAGE, KbFilter_CreateClose) +#pragma alloc_text(PAGE, KbFilter_IoCtl) +#pragma alloc_text(PAGE, KbFilter_InternIoCtl) +#pragma alloc_text(PAGE, KbFilter_Unload) +#pragma alloc_text(PAGE, KbFilter_DispatchPassThrough) +#pragma alloc_text(PAGE, KbFilter_PnP) +#pragma alloc_text(PAGE, KbFilter_Power) +extern void *malloc(size_t); +void errorFn(void) { + + { + ERROR : { + reach_error(); + abort(); + } + } +} +int s; +int UNLOADED; +int NP; +int DC; +int SKIP1; +int SKIP2; +int MPR1; +int MPR3; +int IPC; +int pended; +NTSTATUS(*compFptr) +(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context); +int compRegistered; +int lowerDriverReturn; +int setEventCalled; +int customIrp; +int myStatus; +void _BLAST_init(void) { + + { + UNLOADED = 0; + NP = 1; + DC = 2; + SKIP1 = 3; + SKIP2 = 4; + MPR1 = 5; + MPR3 = 6; + IPC = 7; + s = UNLOADED; + pended = 0; + compFptr = 0; + compRegistered = 0; + lowerDriverReturn = 0; + setEventCalled = 0; + customIrp = 0; + return; + } +} +NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) { + ULONG i = __VERIFIER_nondet_long(); + assume_abort_if_not(i < 28); + + { + DriverObject->MajorFunction[i] = &KbFilter_DispatchPassThrough; + DriverObject->MajorFunction[0] = &KbFilter_CreateClose; + DriverObject->MajorFunction[2] = &KbFilter_CreateClose; + DriverObject->MajorFunction[27] = &KbFilter_PnP; + DriverObject->MajorFunction[22] = &KbFilter_Power; + DriverObject->MajorFunction[15] = &KbFilter_InternIoCtl; + DriverObject->DriverUnload = &KbFilter_Unload; + (DriverObject->DriverExtension)->AddDevice = &KbFilter_AddDevice; + return (0L); + } +} +NTSTATUS KbFilter_AddDevice(PDRIVER_OBJECT Driver, PDEVICE_OBJECT PDO) { + PDEVICE_EXTENSION devExt; + PDEVICE_OBJECT device; + NTSTATUS status; + + { + { + status = 0L; + status = IoCreateDevice(Driver, sizeof(DEVICE_EXTENSION), (void *)0, 11, 0, 0, + &device); + } + if (!(status >= 0L)) { + return (status); + } else { + } + { + memset(device->DeviceExtension, 0, sizeof(DEVICE_EXTENSION)); + devExt = (struct _DEVICE_EXTENSION *)device->DeviceExtension; + devExt->TopOfStack = IoAttachDeviceToDeviceStack(device, PDO); + devExt->Self = device; + devExt->PDO = PDO; + devExt->DeviceState = 1; + devExt->SurpriseRemoved = 0; + devExt->Removed = 0; + devExt->Started = 0; + device->Flags |= 8196UL; + device->Flags &= 4294967167UL; + } + return (status); + } +} +NTSTATUS KbFilter_Complete(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context) { + PKEVENT event; + + { + { + event = (struct _KEVENT *)Context; + KeSetEvent(event, 0, 0); + } + return (-1073741802L); + } +} +NTSTATUS KbFilter_CreateClose(PDEVICE_OBJECT DeviceObject, PIRP Irp) { + PIO_STACK_LOCATION irpStack; + NTSTATUS status; + PDEVICE_EXTENSION devExt; + LONG tmp; + LONG tmp___0; + NTSTATUS tmp___1; + + { + irpStack = Irp->Tail.Overlay.__annonCompField17.__annonCompField16.CurrentStackLocation; + devExt = (struct _DEVICE_EXTENSION *)DeviceObject->DeviceExtension; + status = Irp->IoStatus.__annonCompField4.Status; + status = myStatus; + if (irpStack->MajorFunction == 0) { + goto switch_0_0; + } else { + if (irpStack->MajorFunction == 2) { + goto switch_0_2; + } else { + if (0) { + switch_0_0: /* CIL Label */; + if ((unsigned int)((void *)0) == (unsigned int)devExt->UpperConnectData.ClassService) { + status = -1073741436L; + } else { + { + tmp = InterlockedIncrement(&devExt->EnableCount); + } + if (1L == tmp) { + + } else { + } + } + goto switch_0_break; + switch_0_2 : /* CIL Label */ + { + tmp___0 = InterlockedDecrement(&devExt->EnableCount); + } + if (0L == tmp___0) { + + } else { + } + goto switch_0_break; + } else { + switch_0_break: /* CIL Label */; + } + } + } + { + Irp->IoStatus.__annonCompField4.Status = status; + myStatus = status; + tmp___1 = KbFilter_DispatchPassThrough(DeviceObject, Irp); + } + return (tmp___1); + } +} +NTSTATUS KbFilter_DispatchPassThrough(PDEVICE_OBJECT DeviceObject, PIRP Irp) { + PIO_STACK_LOCATION irpStack; + NTSTATUS tmp; + + { + irpStack = Irp->Tail.Overlay.__annonCompField17.__annonCompField16.CurrentStackLocation; + if (s == NP) { + s = SKIP1; + } else { + { + errorFn(); + } + } + { + Irp->CurrentLocation = (CHAR)((int)Irp->CurrentLocation + 1); + Irp->Tail.Overlay.__annonCompField17.__annonCompField16.CurrentStackLocation += 1; + tmp = IofCallDriver(((struct _DEVICE_EXTENSION *)DeviceObject->DeviceExtension)->TopOfStack, + Irp); + } + return (tmp); + } +} +NTSTATUS KbFilter_InternIoCtl(PDEVICE_OBJECT DeviceObject, PIRP Irp) { + PIO_STACK_LOCATION irpStack; + PDEVICE_EXTENSION devExt; + PINTERNAL_I8042_HOOK_KEYBOARD hookKeyboard; + PCONNECT_DATA connectData; + NTSTATUS status; + NTSTATUS tmp; + + { + status = 0L; + devExt = (struct _DEVICE_EXTENSION *)DeviceObject->DeviceExtension; + Irp->IoStatus.Information = 0; + irpStack = Irp->Tail.Overlay.__annonCompField17.__annonCompField16.CurrentStackLocation; + if (irpStack->Parameters.DeviceIoControl.IoControlCode == (((11 << 16) | (128 << 2)) | 3)) { + goto switch_1_exp_0; + } else { + if (irpStack->Parameters.DeviceIoControl.IoControlCode == (((11 << 16) | (256 << 2)) | 3)) { + goto switch_1_exp_1; + } else { + if (irpStack->Parameters.DeviceIoControl.IoControlCode == (((11 << 16) | (4080 << 2)) | 3)) { + goto switch_1_exp_2; + } else { + if (irpStack->Parameters.DeviceIoControl.IoControlCode == 11 << 16) { + goto switch_1_exp_3; + } else { + if (irpStack->Parameters.DeviceIoControl.IoControlCode == ((11 << 16) | (32 << 2))) { + goto switch_1_exp_4; + } else { + if (irpStack->Parameters.DeviceIoControl.IoControlCode == ((11 << 16) | (16 << 2))) { + goto switch_1_exp_5; + } else { + if (irpStack->Parameters.DeviceIoControl.IoControlCode == ((11 << 16) | (2 << 2))) { + goto switch_1_exp_6; + } else { + if (irpStack->Parameters.DeviceIoControl.IoControlCode == ((11 << 16) | (8 << 2))) { + goto switch_1_exp_7; + } else { + if (irpStack->Parameters.DeviceIoControl.IoControlCode == ((11 << 16) | (1 << 2))) { + goto switch_1_exp_8; + } else { + if (0) { + switch_1_exp_0: /* CIL Label */; + if ((unsigned int)devExt->UpperConnectData.ClassService != (unsigned int)((void *)0)) { + status = -1073741757L; + goto switch_1_break; + } else { + if (irpStack->Parameters.DeviceIoControl.InputBufferLength < (ULONG)sizeof(CONNECT_DATA)) { + status = -1073741811L; + goto switch_1_break; + } else { + } + } + connectData = (struct _CONNECT_DATA *)irpStack->Parameters.DeviceIoControl.Type3InputBuffer; + devExt->UpperConnectData = *connectData; + connectData->ClassDeviceObject = devExt->Self; + connectData->ClassService = &KbFilter_ServiceCallback; + goto switch_1_break; + switch_1_exp_1: /* CIL Label */ + status = -1073741822L; + goto switch_1_break; + switch_1_exp_2: /* CIL Label */; + if (irpStack->Parameters.DeviceIoControl.InputBufferLength < (ULONG)sizeof(INTERNAL_I8042_HOOK_KEYBOARD)) { + status = -1073741811L; + goto switch_1_break; + } else { + } + hookKeyboard = (struct _INTERNAL_I8042_HOOK_KEYBOARD *)irpStack->Parameters.DeviceIoControl.Type3InputBuffer; + devExt->UpperContext = hookKeyboard->Context; + hookKeyboard->Context = (void *)DeviceObject; + if (hookKeyboard->InitializationRoutine) { + devExt->UpperInitializationRoutine = hookKeyboard->InitializationRoutine; + } else { + } + hookKeyboard->InitializationRoutine = (NTSTATUS(*)(PVOID InitializationContext, + PVOID SynchFuncContext, + NTSTATUS(*ReadPort)(PVOID Context, + PUCHAR Value, + BOOLEAN WaitForACK), + NTSTATUS(*WritePort)(PVOID Context, + UCHAR Value, + BOOLEAN WaitForACK), + PBOOLEAN TurnTranslationOn))(&KbFilter_InitializationRoutine); + if (hookKeyboard->IsrRoutine) { + devExt->UpperIsrHook = hookKeyboard->IsrRoutine; + } else { + } + hookKeyboard->IsrRoutine = (BOOLEAN(*)(PVOID IsrContext, PKEYBOARD_INPUT_DATA CurrentInput, + POUTPUT_PACKET CurrentOutput, + UCHAR StatusByte, PUCHAR Byte, + PBOOLEAN ContinueProcessing, + PKEYBOARD_SCAN_STATE ScanState))(&KbFilter_IsrHook); + devExt->IsrWritePort = hookKeyboard->IsrWritePort; + devExt->QueueKeyboardPacket = hookKeyboard->QueueKeyboardPacket; + devExt->CallContext = hookKeyboard->CallContext; + status = 0L; + goto switch_1_break; + switch_1_exp_3: /* CIL Label */; + switch_1_exp_4: /* CIL Label */; + switch_1_exp_5: /* CIL Label */; + switch_1_exp_6: /* CIL Label */; + switch_1_exp_7: /* CIL Label */; + switch_1_exp_8: /* CIL Label */; + goto switch_1_break; + } else { + switch_1_break: /* CIL Label */; + } + } + } + } + } + } + } + } + } + } + if (!(status >= 0L)) { + { + Irp->IoStatus.__annonCompField4.Status = status; + myStatus = status; + IofCompleteRequest(Irp, 0); + } + return (status); + } else { + } + { + tmp = KbFilter_DispatchPassThrough(DeviceObject, Irp); + } + return (tmp); + } +} +NTSTATUS KbFilter_PnP(PDEVICE_OBJECT DeviceObject, PIRP Irp) { + PDEVICE_EXTENSION devExt; + PIO_STACK_LOCATION irpStack; + NTSTATUS status; + KEVENT event; + PIO_STACK_LOCATION irpSp; + PIO_STACK_LOCATION nextIrpSp; + PIO_STACK_LOCATION irpSp___0; + + { + status = 0L; + devExt = (struct _DEVICE_EXTENSION *)DeviceObject->DeviceExtension; + irpStack = Irp->Tail.Overlay.__annonCompField17.__annonCompField16.CurrentStackLocation; + if (irpStack->MinorFunction == 0) { + goto switch_2_0; + } else { + if (irpStack->MinorFunction == 23) { + goto switch_2_23; + } else { + if (irpStack->MinorFunction == 2) { + goto switch_2_2; + } else { + if (irpStack->MinorFunction == 1) { + goto switch_2_1; + } else { + if (irpStack->MinorFunction == 5) { + goto switch_2_5; + } else { + if (irpStack->MinorFunction == 3) { + goto switch_2_3; + } else { + if (irpStack->MinorFunction == 6) { + goto switch_2_6; + } else { + if (irpStack->MinorFunction == 13) { + goto switch_2_13; + } else { + if (irpStack->MinorFunction == 4) { + goto switch_2_4; + } else { + if (irpStack->MinorFunction == 7) { + goto switch_2_7; + } else { + if (irpStack->MinorFunction == 8) { + goto switch_2_8; + } else { + if (irpStack->MinorFunction == 9) { + goto switch_2_9; + } else { + if (irpStack->MinorFunction == 12) { + goto switch_2_12; + } else { + if (irpStack->MinorFunction == 10) { + goto switch_2_10; + } else { + if (irpStack->MinorFunction == 11) { + goto switch_2_11; + } else { + if (irpStack->MinorFunction == 15) { + goto switch_2_15; + } else { + if (irpStack->MinorFunction == 16) { + goto switch_2_16; + } else { + if (irpStack->MinorFunction == 17) { + goto switch_2_17; + } else { + if (irpStack->MinorFunction == 18) { + goto switch_2_18; + } else { + if (irpStack->MinorFunction == 19) { + goto switch_2_19; + } else { + if (irpStack->MinorFunction == 20) { + goto switch_2_20; + } else { + { + goto switch_2_default; + if (0) { + switch_2_0 : /* CIL Label */ + { + irpSp = Irp->Tail.Overlay.__annonCompField17.__annonCompField16.CurrentStackLocation; + nextIrpSp = Irp->Tail.Overlay.__annonCompField17.__annonCompField16.CurrentStackLocation - 1; + memmove(nextIrpSp, irpSp, (long)(&((IO_STACK_LOCATION *)0)->CompletionRoutine)); + nextIrpSp->Control = 0; + /* KeInitializeEvent(& event, 0, 0); */ /* INLINED */ + } + if (s != NP) { + { + errorFn(); + } + } else { + if (compRegistered != 0) { + { + errorFn(); + } + } else { + compRegistered = 1; + compFptr = &KbFilter_Complete; + } + } + { + irpSp___0 = Irp->Tail.Overlay.__annonCompField17.__annonCompField16.CurrentStackLocation - 1; + irpSp___0->CompletionRoutine = &KbFilter_Complete; + irpSp___0->Context = &event; + irpSp___0->Control = 0; + irpSp___0->Control = 64; + irpSp___0->Control = (int)irpSp___0->Control | 128; + irpSp___0->Control = (int)irpSp___0->Control | 32; + status = IofCallDriver(devExt->TopOfStack, + Irp); + } + if (259L == status) { + { + KeWaitForSingleObject(&event, 0, + 0, 0, (void *)0); + } + } else { + } + if (status >= 0L) { + if ((long)myStatus >= 0L) { + devExt->Started = 1; + devExt->Removed = 0; + devExt->SurpriseRemoved = 0; + } else { + } + } else { + } + { + Irp->IoStatus.__annonCompField4.Status = status; + myStatus = status; + Irp->IoStatus.Information = 0; + IofCompleteRequest(Irp, 0); + } + goto switch_2_break; + switch_2_23: /* CIL Label */ + devExt->SurpriseRemoved = 1; + if (s == NP) { + s = SKIP1; + } else { + { + errorFn(); + } + } + { + Irp->CurrentLocation = (CHAR)((int)Irp->CurrentLocation + 1); + Irp->Tail.Overlay.__annonCompField17.__annonCompField16.CurrentStackLocation += 1; + status = IofCallDriver(devExt->TopOfStack, + Irp); + } + goto switch_2_break; + switch_2_2: /* CIL Label */ + devExt->Removed = 1; + if (s == NP) { + s = SKIP1; + } else { + { + errorFn(); + } + } + { + Irp->CurrentLocation = (CHAR)((int)Irp->CurrentLocation + 1); + Irp->Tail.Overlay.__annonCompField17.__annonCompField16.CurrentStackLocation += 1; + IofCallDriver(devExt->TopOfStack, Irp); + /* IoDetachDevice(devExt->TopOfStack); */ /* INLINED */ + /* IoDeleteDevice(DeviceObject); */ /* INLINED */ + status = 0L; + } + goto switch_2_break; + switch_2_1: /* CIL Label */; + switch_2_5: /* CIL Label */; + switch_2_3: /* CIL Label */; + switch_2_6: /* CIL Label */; + switch_2_13: /* CIL Label */; + switch_2_4: /* CIL Label */; + switch_2_7: /* CIL Label */; + switch_2_8: /* CIL Label */; + switch_2_9: /* CIL Label */; + switch_2_12: /* CIL Label */; + switch_2_10: /* CIL Label */; + switch_2_11: /* CIL Label */; + switch_2_15: /* CIL Label */; + switch_2_16: /* CIL Label */; + switch_2_17: /* CIL Label */; + switch_2_18: /* CIL Label */; + switch_2_19: /* CIL Label */; + switch_2_20: /* CIL Label */; + switch_2_default: /* CIL Label */; + if (s == NP) { + s = SKIP1; + } else { + { + errorFn(); + } + } + { + Irp->CurrentLocation = (CHAR)((int)Irp->CurrentLocation + 1); + Irp->Tail.Overlay.__annonCompField17.__annonCompField16.CurrentStackLocation += 1; + status = IofCallDriver(devExt->TopOfStack, + Irp); + } + goto switch_2_break; + } else { + switch_2_break: /* CIL Label */; + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + return (status); + } +} +NTSTATUS KbFilter_Power(PDEVICE_OBJECT DeviceObject, PIRP Irp) { + PIO_STACK_LOCATION irpStack; + PDEVICE_EXTENSION devExt; + POWER_STATE powerState; + POWER_STATE_TYPE powerType; + NTSTATUS tmp; + + { + devExt = (struct _DEVICE_EXTENSION *)DeviceObject->DeviceExtension; + irpStack = Irp->Tail.Overlay.__annonCompField17.__annonCompField16.CurrentStackLocation; + powerType = irpStack->Parameters.Power.Type; + powerState = irpStack->Parameters.Power.State; + if (irpStack->MinorFunction == 2) { + goto switch_3_2; + } else { + if (irpStack->MinorFunction == 1) { + goto switch_3_1; + } else { + if (irpStack->MinorFunction == 0) { + goto switch_3_0; + } else { + if (irpStack->MinorFunction == 3) { + goto switch_3_3; + } else { + { + goto switch_3_default; + if (0) { + switch_3_2: /* CIL Label */; + if ((int)powerType == 1) { + devExt->DeviceState = powerState.DeviceState; + } else { + } + switch_3_1: /* CIL Label */; + switch_3_0: /* CIL Label */; + switch_3_3: /* CIL Label */; + switch_3_default: /* CIL Label */; + goto switch_3_break; + } else { + switch_3_break: /* CIL Label */; + } + } + } + } + } + } + { + /* PoStartNextPowerIrp(Irp); */ /* INLINED */ + } + if (s == NP) { + s = SKIP1; + } else { + { + errorFn(); + } + } + { + Irp->CurrentLocation = (CHAR)((int)Irp->CurrentLocation + 1); + Irp->Tail.Overlay.__annonCompField17.__annonCompField16.CurrentStackLocation += 1; + tmp = PoCallDriver(devExt->TopOfStack, Irp); + } + return (tmp); + } +} +NTSTATUS KbFilter_InitializationRoutine(PDEVICE_OBJECT DeviceObject, PVOID SynchFuncContext, + NTSTATUS (*ReadPort)(PVOID Context, PUCHAR Value, + BOOLEAN WaitForACK), + NTSTATUS (*WritePort)(PVOID Context, UCHAR Value, + BOOLEAN WaitForACK), + PBOOLEAN TurnTranslationOn) { + PDEVICE_EXTENSION devExt; + NTSTATUS status; + + { + status = 0L; + devExt = DeviceObject->DeviceExtension; + if (devExt->UpperInitializationRoutine) { + { + status = (*(devExt->UpperInitializationRoutine))(devExt->UpperContext, SynchFuncContext, + ReadPort, WritePort, TurnTranslationOn); + } + if (!(status >= 0L)) { + return (status); + } else { + } + } else { + } + *TurnTranslationOn = 1; + return (status); + } +} +BOOLEAN KbFilter_IsrHook(PDEVICE_OBJECT DeviceObject, PKEYBOARD_INPUT_DATA CurrentInput, + POUTPUT_PACKET CurrentOutput, UCHAR StatusByte, PUCHAR DataByte, + PBOOLEAN ContinueProcessing, PKEYBOARD_SCAN_STATE ScanState) { + PDEVICE_EXTENSION devExt; + BOOLEAN retVal; + + { + retVal = 1; + devExt = DeviceObject->DeviceExtension; + if (devExt->UpperIsrHook) { + { + retVal = (*(devExt->UpperIsrHook))(devExt->UpperContext, CurrentInput, CurrentOutput, + StatusByte, DataByte, ContinueProcessing, ScanState); + } + if (!retVal) { + return (retVal); + } else { + if (!*ContinueProcessing) { + return (retVal); + } else { + } + } + } else { + } + *ContinueProcessing = 1; + return (retVal); + } +} +void KbFilter_ServiceCallback(PDEVICE_OBJECT DeviceObject, PKEYBOARD_INPUT_DATA InputDataStart, + PKEYBOARD_INPUT_DATA InputDataEnd, PULONG InputDataConsumed) { + PDEVICE_EXTENSION devExt; + + { + { + devExt = (struct _DEVICE_EXTENSION *)DeviceObject->DeviceExtension; + (*((void (*)(PVOID NormalContext, PVOID SystemArgument1, PVOID SystemArgument2, + PVOID SystemArgument3))devExt->UpperConnectData.ClassService))(devExt->UpperConnectData.ClassDeviceObject, + InputDataStart, + InputDataEnd, + InputDataConsumed); + } + return; + } +} +void KbFilter_Unload(PDRIVER_OBJECT Driver) { + + { + return; + } +} +#pragma warning(push) +#pragma warning(disable : 4035) +#pragma warning(pop) +#pragma warning(disable : 4103) +#pragma warning(disable : 4103) +#pragma warning(push) +#pragma warning(disable : 4035) +#pragma warning(pop) +#pragma warning(disable : 4035) +#pragma warning(push) +#pragma warning(disable : 4164) +#pragma function(_enable) +#pragma function(_disable) +#pragma warning(pop) +#pragma warning(disable : 4103) +#pragma warning(disable : 4103) +#pragma warning(disable : 4103) +#pragma warning(disable : 4103) +#pragma warning(disable : 4103) +#pragma warning(disable : 4103) +#pragma warning(disable : 4200) +#pragma warning(default : 4200) +IRP *pirp; +void stub_driver_init(void) { + + { + s = NP; + pended = 0; + compFptr = 0; + compRegistered = 0; + lowerDriverReturn = 0; + setEventCalled = 0; + customIrp = 0; + return; + } +} +extern unsigned char __VERIFIER_nondet_uchar(void); +int main(void) { + DRIVER_OBJECT d; + UNICODE_STRING u; + NTSTATUS status; + int we_should_unload = __VERIFIER_nondet_int(); + IRP irp; + int __BLAST_NONDET = __VERIFIER_nondet_int(); + int irp_choice = __VERIFIER_nondet_int(); + DEVICE_EXTENSION devext; + DEVICE_OBJECT devobj; + devobj.DeviceExtension = &devext; + struct _DRIVER_EXTENSION ext; + d.DriverExtension = &ext; + + INTERNAL_I8042_HOOK_KEYBOARD hookkb; + struct _IO_STACK_LOCATION stack[3]; + + stack[0].MajorFunction = __VERIFIER_nondet_uchar(); + stack[1].MajorFunction = __VERIFIER_nondet_uchar(); + stack[2].MajorFunction = __VERIFIER_nondet_uchar(); + stack[0].MinorFunction = __VERIFIER_nondet_uchar(); + stack[1].MinorFunction = __VERIFIER_nondet_uchar(); + stack[2].MinorFunction = __VERIFIER_nondet_uchar(); + + stack[0].Parameters.DeviceIoControl.Type3InputBuffer = &hookkb; + stack[1].Parameters.DeviceIoControl.Type3InputBuffer = &hookkb; + stack[2].Parameters.DeviceIoControl.Type3InputBuffer = &hookkb; + + stack[0].Parameters.DeviceIoControl.InputBufferLength = __VERIFIER_nondet_ulong(); + stack[1].Parameters.DeviceIoControl.InputBufferLength = __VERIFIER_nondet_ulong(); + stack[2].Parameters.DeviceIoControl.InputBufferLength = __VERIFIER_nondet_ulong(); + + stack[0].Parameters.DeviceIoControl.IoControlCode = __VERIFIER_nondet_ulong(); + stack[1].Parameters.DeviceIoControl.IoControlCode = __VERIFIER_nondet_ulong(); + stack[2].Parameters.DeviceIoControl.IoControlCode = __VERIFIER_nondet_ulong(); + + irp.Tail.Overlay.__annonCompField17.__annonCompField16.CurrentStackLocation = &stack[1]; + + { + { + pirp = &irp; + _BLAST_init(); + status = DriverEntry(&d, &u); + } + if (status >= 0L) { + s = NP; + customIrp = 0; + setEventCalled = customIrp; + lowerDriverReturn = setEventCalled; + compRegistered = lowerDriverReturn; + compFptr = compRegistered; + pended = compFptr; + pirp->IoStatus.__annonCompField4.Status = 0L; + myStatus = 0L; + if (irp_choice == 0) { + pirp->IoStatus.__annonCompField4.Status = -1073741637L; + myStatus = -1073741637L; + } else { + } + { + status = KbFilter_AddDevice(&d, &devobj); + stub_driver_init(); + } + if (!(status >= 0L)) { + return (-1); + } else { + } + if (__BLAST_NONDET == 0) { + goto switch_4_0; + } else { + if (__BLAST_NONDET == 1) { + goto switch_4_1; + } else { + if (__BLAST_NONDET == 2) { + goto switch_4_2; + } else { + if (__BLAST_NONDET == 3) { + goto switch_4_3; + } else { + if (__BLAST_NONDET == 4) { + goto switch_4_4; + } else { + if (__BLAST_NONDET == 8) { + goto switch_4_8; + } else { + { + goto switch_4_default; + if (0) { + switch_4_0 : /* CIL Label */ + { + status = KbFilter_CreateClose(&devobj, pirp); + } + goto switch_4_break; + switch_4_1 : /* CIL Label */ + { + status = KbFilter_CreateClose(&devobj, pirp); + } + goto switch_4_break; + switch_4_2 : /* CIL Label */ + { + status = KbFilter_IoCtl(&devobj, pirp); + } + goto switch_4_break; + switch_4_3 : /* CIL Label */ + { + status = KbFilter_PnP(&devobj, pirp); + } + goto switch_4_break; + switch_4_4 : /* CIL Label */ + { + status = KbFilter_Power(&devobj, pirp); + } + goto switch_4_break; + switch_4_8 : /* CIL Label */ + { + status = KbFilter_InternIoCtl(&devobj, pirp); + } + goto switch_4_break; + switch_4_default: /* CIL Label */; + return (-1); + } else { + switch_4_break: /* CIL Label */; + } + } + } + } + } + } + } + } + if (we_should_unload) { + { + /* KbFilter_Unload(& d); */ /* INLINED */ + } + } else { + } + } else { + } + if (pended == 1) { + if (s == NP) { + s = NP; + } else { + goto _L___2; + } + } else { + _L___2: /* CIL Label */ + if (pended == 1) { + if (s == MPR3) { + s = MPR3; + } else { + goto _L___1; + } + } else { + _L___1: /* CIL Label */ + if (s == UNLOADED) { + + } else { + if (status == -1L) { + + } else { + if (s != SKIP2) { + if (s != IPC) { + if (s != DC) { + + } else { + goto _L___0; + } + } else { + goto _L___0; + } + } else { + _L___0: /* CIL Label */ + if (pended == 1) { + if (status != 259L) { + { + errorFn(); + } + } else { + } + } else { + if (s == DC) { + if (status == 259L) { + { + errorFn(); + } + } else { + } + } else { + if (status != (NTSTATUS)lowerDriverReturn) { + + } else { + } + } + } + } + } + } + } + } + return (status); + } +} +char _SLAM_alloc_dummy; +void ExAcquireFastMutex(PFAST_MUTEX FastMutex); +void ExAcquireFastMutex(PFAST_MUTEX FastMutex) { + + { + return; + } +} +void ExReleaseFastMutex(PFAST_MUTEX FastMutex); +void ExReleaseFastMutex(PFAST_MUTEX FastMutex) { + + { + return; + } +} +PVOID ExAllocatePoolWithTag(POOL_TYPE PoolType, + SIZE_T NumberOfBytes, + ULONG Tag); +PVOID ExAllocatePoolWithTag(POOL_TYPE PoolType, SIZE_T NumberOfBytes, + ULONG Tag) { + PVOID x; + char *tmp; + + { + { + tmp = malloc(NumberOfBytes); + x = tmp; + } + return (x); + } +} +void ExFreePool(PVOID P); +void ExFreePool(PVOID P) { + + { + return; + } +} +PLIST_ENTRY ExfInterlockedInsertHeadList(PLIST_ENTRY ListHead, + PLIST_ENTRY ListEntry, + PKSPIN_LOCK Lock); +PLIST_ENTRY ExfInterlockedInsertHeadList(PLIST_ENTRY ListHead, + PLIST_ENTRY ListEntry, + PKSPIN_LOCK Lock) { + + { + return ((void *)0); + } +} +PLIST_ENTRY ExfInterlockedInsertTailList(PLIST_ENTRY ListHead, + PLIST_ENTRY ListEntry, + PKSPIN_LOCK Lock); +PLIST_ENTRY ExfInterlockedInsertTailList(PLIST_ENTRY ListHead, + PLIST_ENTRY ListEntry, + PKSPIN_LOCK Lock) { + + { + return ((void *)0); + } +} +PLIST_ENTRY ExfInterlockedRemoveHeadList(PLIST_ENTRY ListHead, + PKSPIN_LOCK Lock); +PLIST_ENTRY ExfInterlockedRemoveHeadList(PLIST_ENTRY ListHead, + PKSPIN_LOCK Lock) { + + { + return ((void *)0); + } +} +PMDL IoAllocateMdl(PVOID VirtualAddress, ULONG Length, + BOOLEAN SecondaryBuffer, BOOLEAN ChargeQuota, + PIRP Irp); +PMDL IoAllocateMdl(PVOID VirtualAddress, ULONG Length, BOOLEAN SecondaryBuffer, + BOOLEAN ChargeQuota, PIRP Irp) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + char *tmp; + + { + if (__BLAST_NONDET == 0) { + goto switch_5_0; + } else { + { + goto switch_5_default; + if (0) { + switch_5_0 : /* CIL Label */ + { + tmp = malloc(sizeof(MDL)); + } + return ((void *)tmp); + switch_5_default: /* CIL Label */; + return ((void *)0); + } else { + switch_5_break: /* CIL Label */; + } + } + } + } +} +PDEVICE_OBJECT IoAttachDeviceToDeviceStack(PDEVICE_OBJECT SourceDevice, + PDEVICE_OBJECT TargetDevice); +PDEVICE_OBJECT IoAttachDeviceToDeviceStack(PDEVICE_OBJECT SourceDevice, PDEVICE_OBJECT TargetDevice) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + + { + if (__BLAST_NONDET == 0) { + goto switch_6_0; + } else { + { + goto switch_6_default; + if (0) { + switch_6_0: /* CIL Label */; + return (TargetDevice); + switch_6_default: /* CIL Label */; + return ((void *)0); + } else { + switch_6_break: /* CIL Label */; + } + } + } + } +} +PIRP IoBuildAsynchronousFsdRequest(ULONG MajorFunction, + PDEVICE_OBJECT DeviceObject, + PVOID Buffer, + ULONG Length, + PLARGE_INTEGER StartingOffset, + PIO_STATUS_BLOCK IoStatusBlock); +PIRP IoBuildAsynchronousFsdRequest(ULONG MajorFunction, PDEVICE_OBJECT DeviceObject, + PVOID Buffer, ULONG Length, PLARGE_INTEGER StartingOffset, + PIO_STATUS_BLOCK IoStatusBlock) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + char *tmp; + + { + customIrp = 1; + if (__BLAST_NONDET == 0) { + goto switch_7_0; + } else { + { + goto switch_7_default; + if (0) { + switch_7_0 : /* CIL Label */ + { + tmp = malloc(sizeof(IRP)); + } + return ((void *)tmp); + switch_7_default: /* CIL Label */; + return ((void *)0); + } else { + switch_7_break: /* CIL Label */; + } + } + } + } +} +PIRP IoBuildDeviceIoControlRequest(ULONG IoControlCode, + PDEVICE_OBJECT DeviceObject, + PVOID InputBuffer, + ULONG InputBufferLength, + PVOID OutputBuffer, + ULONG OutputBufferLength, + BOOLEAN InternalDeviceIoControl, + PKEVENT Event, + PIO_STATUS_BLOCK IoStatusBlock); +PIRP IoBuildDeviceIoControlRequest(ULONG IoControlCode, PDEVICE_OBJECT DeviceObject, + PVOID InputBuffer, ULONG InputBufferLength, PVOID OutputBuffer, + ULONG OutputBufferLength, BOOLEAN InternalDeviceIoControl, + PKEVENT Event, PIO_STATUS_BLOCK IoStatusBlock) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + char *tmp; + + { + customIrp = 1; + if (__BLAST_NONDET == 0) { + goto switch_8_0; + } else { + { + goto switch_8_default; + if (0) { + switch_8_0 : /* CIL Label */ + { + tmp = malloc(sizeof(IRP)); + } + return ((void *)tmp); + switch_8_default: /* CIL Label */; + return ((void *)0); + } else { + switch_8_break: /* CIL Label */; + } + } + } + } +} +NTSTATUS IoCreateDevice(PDRIVER_OBJECT DriverObject, + ULONG DeviceExtensionSize, + PUNICODE_STRING DeviceName, + ULONG DeviceType, ULONG DeviceCharacteristics, + BOOLEAN Exclusive, PDEVICE_OBJECT *DeviceObject); +NTSTATUS IoCreateDevice(PDRIVER_OBJECT DriverObject, ULONG DeviceExtensionSize, + PUNICODE_STRING DeviceName, ULONG DeviceType, ULONG DeviceCharacteristics, + BOOLEAN Exclusive, PDEVICE_OBJECT *DeviceObject) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + char *tmp; + + { + if (__BLAST_NONDET == 0) { + goto switch_9_0; + } else { + { + goto switch_9_default; + if (0) { + switch_9_0 : /* CIL Label */ + { + tmp = malloc(sizeof(DEVICE_OBJECT)); + *DeviceObject = (void *)tmp; + (*DeviceObject)->DeviceExtension = malloc(DeviceExtensionSize); + } + return (0L); + switch_9_default: /* CIL Label */; + return (-1073741823L); + } else { + switch_9_break: /* CIL Label */; + } + } + } + } +} +NTSTATUS IoCreateSymbolicLink(PUNICODE_STRING SymbolicLinkName, + PUNICODE_STRING DeviceName); +NTSTATUS IoCreateSymbolicLink(PUNICODE_STRING SymbolicLinkName, PUNICODE_STRING DeviceName) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + + { + if (__BLAST_NONDET == 0) { + goto switch_10_0; + } else { + { + goto switch_10_default; + if (0) { + switch_10_0: /* CIL Label */; + return (0L); + switch_10_default: /* CIL Label */; + return (-1073741823L); + } else { + switch_10_break: /* CIL Label */; + } + } + } + } +} +void IoDeleteDevice(PDEVICE_OBJECT DeviceObject); +void IoDeleteDevice(PDEVICE_OBJECT DeviceObject) { + + { + return; + } +} +NTSTATUS IoDeleteSymbolicLink(PUNICODE_STRING SymbolicLinkName); +NTSTATUS IoDeleteSymbolicLink(PUNICODE_STRING SymbolicLinkName) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + + { + if (__BLAST_NONDET == 0) { + goto switch_11_0; + } else { + { + goto switch_11_default; + if (0) { + switch_11_0: /* CIL Label */; + return (0L); + switch_11_default: /* CIL Label */; + return (-1073741823L); + } else { + switch_11_break: /* CIL Label */; + } + } + } + } +} +void IoDetachDevice(PDEVICE_OBJECT TargetDevice); +void IoDetachDevice(PDEVICE_OBJECT TargetDevice) { + + { + return; + } +} +void IoFreeIrp(PIRP Irp); +void IoFreeIrp(PIRP Irp) { + + { + return; + } +} +void IoFreeMdl(PMDL Mdl); +void IoFreeMdl(PMDL Mdl) { + + { + return; + } +} +PCONFIGURATION_INFORMATION IoGetConfigurationInformation(void); +PCONFIGURATION_INFORMATION IoGetConfigurationInformation(void) { + char *tmp; + + { + { + tmp = malloc(sizeof(CONFIGURATION_INFORMATION)); + } + return ((void *)tmp); + } +} +NTSTATUS IoQueryDeviceDescription(PINTERFACE_TYPE BusType, + PULONG BusNumber, + PCONFIGURATION_TYPE ControllerType, + PULONG ControllerNumber, + PCONFIGURATION_TYPE PeripheralType, + PULONG PeripheralNumber, + NTSTATUS (*CalloutRoutine)(PVOID Context, + PUNICODE_STRING PathName, + INTERFACE_TYPE BusType, + ULONG BusNumber, + PKEY_VALUE_FULL_INFORMATION *BusInformation, + CONFIGURATION_TYPE ControllerType, + ULONG ControllerNumber, + PKEY_VALUE_FULL_INFORMATION *ControllerInformation, + CONFIGURATION_TYPE PeripheralType, + ULONG PeripheralNumber, + PKEY_VALUE_FULL_INFORMATION *PeripheralInformation), + PVOID Context); +NTSTATUS IoQueryDeviceDescription(PINTERFACE_TYPE BusType, PULONG BusNumber, PCONFIGURATION_TYPE ControllerType, + PULONG ControllerNumber, PCONFIGURATION_TYPE PeripheralType, + PULONG PeripheralNumber, NTSTATUS (*CalloutRoutine)(PVOID Context, PUNICODE_STRING PathName, INTERFACE_TYPE BusType, ULONG BusNumber, PKEY_VALUE_FULL_INFORMATION *BusInformation, CONFIGURATION_TYPE ControllerType, ULONG ControllerNumber, PKEY_VALUE_FULL_INFORMATION *ControllerInformation, CONFIGURATION_TYPE PeripheralType, ULONG PeripheralNumber, PKEY_VALUE_FULL_INFORMATION *PeripheralInformation), + PVOID Context) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + + { + if (__BLAST_NONDET == 0) { + goto switch_12_0; + } else { + { + goto switch_12_default; + if (0) { + switch_12_0: /* CIL Label */; + return (0L); + switch_12_default: /* CIL Label */; + return (-1073741823L); + } else { + switch_12_break: /* CIL Label */; + } + } + } + } +} +NTSTATUS IoRegisterDeviceInterface(PDEVICE_OBJECT PhysicalDeviceObject, + GUID const *InterfaceClassGuid, + PUNICODE_STRING ReferenceString, + PUNICODE_STRING SymbolicLinkName); +NTSTATUS IoRegisterDeviceInterface(PDEVICE_OBJECT PhysicalDeviceObject, + GUID const *InterfaceClassGuid, + PUNICODE_STRING ReferenceString, + PUNICODE_STRING SymbolicLinkName) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + + { + if (__BLAST_NONDET == 0) { + goto switch_13_0; + } else { + { + goto switch_13_default; + if (0) { + switch_13_0: /* CIL Label */; + return (0L); + switch_13_default: /* CIL Label */; + return (-1073741808L); + } else { + switch_13_break: /* CIL Label */; + } + } + } + } +} +void IoReleaseCancelSpinLock(KIRQL Irql); +void IoReleaseCancelSpinLock(KIRQL Irql) { + + { + return; + } +} +NTSTATUS IoSetDeviceInterfaceState(PUNICODE_STRING SymbolicLinkName, + BOOLEAN Enable); +NTSTATUS IoSetDeviceInterfaceState(PUNICODE_STRING SymbolicLinkName, BOOLEAN Enable) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + + { + if (__BLAST_NONDET == 0) { + goto switch_14_0; + } else { + { + goto switch_14_default; + if (0) { + switch_14_0: /* CIL Label */; + return (0L); + switch_14_default: /* CIL Label */; + return (-1073741823L); + } else { + switch_14_break: /* CIL Label */; + } + } + } + } +} +void IoSetHardErrorOrVerifyDevice(PIRP Irp, PDEVICE_OBJECT DeviceObject); +void IoSetHardErrorOrVerifyDevice(PIRP Irp, PDEVICE_OBJECT DeviceObject) { + + { + return; + } +} +void stubMoreProcessingRequired(void) { + + { + if (s == NP) { + s = MPR1; + } else { + { + errorFn(); + } + } + return; + } +} +NTSTATUS IofCallDriver(PDEVICE_OBJECT DeviceObject, + PIRP Irp); +NTSTATUS IofCallDriver(PDEVICE_OBJECT DeviceObject, + PIRP Irp) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + NTSTATUS returnVal2; + int compRetStatus; + PVOID lcontext = 0; + NTSTATUS tmp; + + { + if (compRegistered) { + { + tmp = KbFilter_Complete(DeviceObject, Irp, lcontext); + compRetStatus = tmp; + } + if ((long)compRetStatus == -1073741802L) { + { + stubMoreProcessingRequired(); + } + } else { + } + } else { + } + if (__BLAST_NONDET == 0) { + goto switch_15_0; + } else { + if (__BLAST_NONDET == 1) { + goto switch_15_1; + } else { + { + goto switch_15_default; + if (0) { + switch_15_0: /* CIL Label */ + returnVal2 = 0L; + goto switch_15_break; + switch_15_1: /* CIL Label */ + returnVal2 = -1073741823L; + goto switch_15_break; + switch_15_default: /* CIL Label */ + returnVal2 = 259L; + goto switch_15_break; + } else { + switch_15_break: /* CIL Label */; + } + } + } + } + if (s == NP) { + s = IPC; + lowerDriverReturn = returnVal2; + } else { + if (s == MPR1) { + if (returnVal2 == 259L) { + s = MPR3; + lowerDriverReturn = returnVal2; + } else { + s = NP; + lowerDriverReturn = returnVal2; + } + } else { + if (s == SKIP1) { + s = SKIP2; + lowerDriverReturn = returnVal2; + } else { + { + errorFn(); + } + } + } + } + return (returnVal2); + } +} +void IofCompleteRequest(PIRP Irp, + CCHAR PriorityBoost); +void IofCompleteRequest(PIRP Irp, CCHAR PriorityBoost) { + + { + if (s == NP) { + s = DC; + } else { + { + errorFn(); + } + } + return; + } +} +KIRQL KeAcquireSpinLockRaiseToDpc(PKSPIN_LOCK SpinLock); +KIRQL KeAcquireSpinLockRaiseToDpc(PKSPIN_LOCK SpinLock) { + + { + return ((unsigned char)0); + } +} +NTSTATUS KeDelayExecutionThread(KPROCESSOR_MODE WaitMode, + BOOLEAN Alertable, + PLARGE_INTEGER Interval); +NTSTATUS KeDelayExecutionThread(KPROCESSOR_MODE WaitMode, BOOLEAN Alertable, PLARGE_INTEGER Interval) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + + { + if (__BLAST_NONDET == 0) { + goto switch_16_0; + } else { + { + goto switch_16_default; + if (0) { + switch_16_0: /* CIL Label */; + return (0L); + switch_16_default: /* CIL Label */; + return (-1073741823L); + } else { + switch_16_break: /* CIL Label */; + } + } + } + } +} +void KeInitializeEvent(PRKEVENT Event, EVENT_TYPE Type, + BOOLEAN State); +void KeInitializeEvent(PRKEVENT Event, EVENT_TYPE Type, BOOLEAN State) { + + { + return; + } +} +void KeInitializeSemaphore(PRKSEMAPHORE Semaphore, + LONG Count, LONG Limit); +void KeInitializeSemaphore(PRKSEMAPHORE Semaphore, LONG Count, LONG Limit) { + + { + return; + } +} +void KeInitializeSpinLock(PKSPIN_LOCK SpinLock); +void KeInitializeSpinLock(PKSPIN_LOCK SpinLock) { + + { + return; + } +} +LONG KeReleaseSemaphore(PRKSEMAPHORE Semaphore, KPRIORITY Increment, + LONG Adjustment, BOOLEAN Wait); +LONG KeReleaseSemaphore(PRKSEMAPHORE Semaphore, KPRIORITY Increment, LONG Adjustment, + BOOLEAN Wait) { + LONG r = __VERIFIER_nondet_long(); + + { + return (r); + } +} +void KfReleaseSpinLock(PKSPIN_LOCK SpinLock, + KIRQL NewIrql); +void KfReleaseSpinLock(PKSPIN_LOCK SpinLock, KIRQL NewIrql) { + + { + return; + } +} +LONG KeSetEvent(PRKEVENT Event, KPRIORITY Increment, + BOOLEAN Wait); +LONG KeSetEvent(PRKEVENT Event, KPRIORITY Increment, BOOLEAN Wait) { + LONG l = __VERIFIER_nondet_long(); + + { + setEventCalled = 1; + return (l); + } +} +NTSTATUS KeWaitForSingleObject(PVOID Object, KWAIT_REASON WaitReason, + KPROCESSOR_MODE WaitMode, + BOOLEAN Alertable, + PLARGE_INTEGER Timeout); +NTSTATUS KeWaitForSingleObject(PVOID Object, KWAIT_REASON WaitReason, KPROCESSOR_MODE WaitMode, + BOOLEAN Alertable, PLARGE_INTEGER Timeout) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + + { + if (s == MPR3) { + if (setEventCalled == 1) { + s = NP; + setEventCalled = 0; + } else { + goto _L; + } + } else { + _L: /* CIL Label */ + if (customIrp == 1) { + s = NP; + customIrp = 0; + } else { + if (s == MPR3) { + { + errorFn(); + } + } else { + } + } + } + if (__BLAST_NONDET == 0) { + goto switch_17_0; + } else { + { + goto switch_17_default; + if (0) { + switch_17_0: /* CIL Label */; + return (0L); + switch_17_default: /* CIL Label */; + return (-1073741823L); + } else { + switch_17_break: /* CIL Label */; + } + } + } + } +} +PVOID MmAllocateContiguousMemory(SIZE_T NumberOfBytes, + PHYSICAL_ADDRESS HighestAcceptableAddress); +PVOID MmAllocateContiguousMemory(SIZE_T NumberOfBytes, PHYSICAL_ADDRESS HighestAcceptableAddress) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + char *tmp; + + { + if (__BLAST_NONDET == 0) { + goto switch_18_0; + } else { + if (__BLAST_NONDET == 1) { + goto switch_18_1; + } else { + if (0) { + switch_18_0 : /* CIL Label */ + { + tmp = malloc(NumberOfBytes); + } + return (tmp); + switch_18_1: /* CIL Label */; + return ((void *)0); + } else { + switch_18_break: /* CIL Label */; + } + } + } + return ((void *)0); + } +} +void MmFreeContiguousMemory(PVOID BaseAddress); +void MmFreeContiguousMemory(PVOID BaseAddress) { + + { + return; + } +} +PVOID MmMapLockedPagesSpecifyCache(PMDL MemoryDescriptorList, + KPROCESSOR_MODE AccessMode, + MEMORY_CACHING_TYPE CacheType, + PVOID BaseAddress, + ULONG BugCheckOnFailure, + MM_PAGE_PRIORITY Priority); +PVOID MmMapLockedPagesSpecifyCache(PMDL MemoryDescriptorList, KPROCESSOR_MODE AccessMode, + MEMORY_CACHING_TYPE CacheType, PVOID BaseAddress, + ULONG BugCheckOnFailure, MM_PAGE_PRIORITY Priority) { + + { + return ((void *)0); + } +} +PVOID MmPageEntireDriver(PVOID AddressWithinSection); +PVOID MmPageEntireDriver(PVOID AddressWithinSection) { + + { + return ((void *)0); + } +} +void MmResetDriverPaging(PVOID AddressWithinSection); +void MmResetDriverPaging(PVOID AddressWithinSection) { + + { + return; + } +} +void MmUnlockPages(PMDL MemoryDescriptorList); +void MmUnlockPages(PMDL MemoryDescriptorList) { + + { + return; + } +} +NTSTATUS ObReferenceObjectByHandle(HANDLE Handle, + ACCESS_MASK DesiredAccess, + POBJECT_TYPE ObjectType, + KPROCESSOR_MODE AccessMode, + PVOID *Object, + POBJECT_HANDLE_INFORMATION HandleInformation); +NTSTATUS ObReferenceObjectByHandle(HANDLE Handle, ACCESS_MASK DesiredAccess, POBJECT_TYPE ObjectType, + KPROCESSOR_MODE AccessMode, PVOID *Object, POBJECT_HANDLE_INFORMATION HandleInformation) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + + { + if (__BLAST_NONDET == 0) { + goto switch_19_0; + } else { + { + goto switch_19_default; + if (0) { + switch_19_0: /* CIL Label */; + return (0L); + switch_19_default: /* CIL Label */; + return (-1073741823L); + } else { + switch_19_break: /* CIL Label */; + } + } + } + } +} +void ObfDereferenceObject(PVOID Object); +void ObfDereferenceObject(PVOID Object) { + + { + return; + } +} +NTSTATUS PoCallDriver(PDEVICE_OBJECT DeviceObject, + PIRP Irp); +NTSTATUS PoCallDriver(PDEVICE_OBJECT DeviceObject, PIRP Irp) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + int compRetStatus; + NTSTATUS returnVal; + PVOID lcontext = 0; + NTSTATUS tmp; + + { + if (compRegistered) { + { + tmp = KbFilter_Complete(DeviceObject, Irp, lcontext); + compRetStatus = tmp; + } + if ((long)compRetStatus == -1073741802L) { + { + stubMoreProcessingRequired(); + } + } else { + } + } else { + } + if (__BLAST_NONDET == 0) { + goto switch_20_0; + } else { + if (__BLAST_NONDET == 1) { + goto switch_20_1; + } else { + { + goto switch_20_default; + if (0) { + switch_20_0: /* CIL Label */ + returnVal = 0L; + goto switch_20_break; + switch_20_1: /* CIL Label */ + returnVal = -1073741823L; + goto switch_20_break; + switch_20_default: /* CIL Label */ + returnVal = 259L; + goto switch_20_break; + } else { + switch_20_break: /* CIL Label */; + } + } + } + } + if (s == NP) { + s = IPC; + lowerDriverReturn = returnVal; + } else { + if (s == MPR1) { + if (returnVal == 259L) { + s = MPR3; + lowerDriverReturn = returnVal; + } else { + s = NP; + lowerDriverReturn = returnVal; + } + } else { + if (s == SKIP1) { + s = SKIP2; + lowerDriverReturn = returnVal; + } else { + { + errorFn(); + } + } + } + } + return (returnVal); + } +} +void PoStartNextPowerIrp(PIRP Irp); +void PoStartNextPowerIrp(PIRP Irp) { + + { + return; + } +} +NTSTATUS PsCreateSystemThread(PHANDLE ThreadHandle, + ULONG DesiredAccess, + POBJECT_ATTRIBUTES ObjectAttributes, + HANDLE ProcessHandle, + PCLIENT_ID ClientId, + void (*StartRoutine)(PVOID StartContext), + PVOID StartContext); +NTSTATUS PsCreateSystemThread(PHANDLE ThreadHandle, ULONG DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, + HANDLE ProcessHandle, PCLIENT_ID ClientId, void (*StartRoutine)(PVOID StartContext), + PVOID StartContext) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + + { + if (__BLAST_NONDET == 0) { + goto switch_21_0; + } else { + { + goto switch_21_default; + if (0) { + switch_21_0: /* CIL Label */; + return (0L); + switch_21_default: /* CIL Label */; + return (-1073741823L); + } else { + switch_21_break: /* CIL Label */; + } + } + } + } +} +NTSTATUS PsTerminateSystemThread(NTSTATUS ExitStatus); +NTSTATUS PsTerminateSystemThread(NTSTATUS ExitStatus) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + + { + if (__BLAST_NONDET == 0) { + goto switch_22_0; + } else { + { + goto switch_22_default; + if (0) { + switch_22_0: /* CIL Label */; + return (0L); + switch_22_default: /* CIL Label */; + return (-1073741823L); + } else { + switch_22_break: /* CIL Label */; + } + } + } + } +} +NTSTATUS RtlAnsiStringToUnicodeString(PUNICODE_STRING DestinationString, + PANSI_STRING SourceString, + BOOLEAN AllocateDestinationString); +NTSTATUS RtlAnsiStringToUnicodeString(PUNICODE_STRING DestinationString, + PANSI_STRING SourceString, + BOOLEAN AllocateDestinationString) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + + { + if (__BLAST_NONDET == 0) { + goto switch_23_0; + } else { + { + goto switch_23_default; + if (0) { + switch_23_0: /* CIL Label */; + return (0L); + switch_23_default: /* CIL Label */; + return (-1073741823L); + } else { + switch_23_break: /* CIL Label */; + } + } + } + } +} +SIZE_T RtlCompareMemory(void const *Source1, + void const *Source2, + SIZE_T Length); +SIZE_T RtlCompareMemory(void const *Source1, void const *Source2, + SIZE_T Length) { + SIZE_T r = __VERIFIER_nondet_long(); + + { + return (r); + } +} +void RtlCopyUnicodeString(PUNICODE_STRING DestinationString, + PUNICODE_STRING SourceString); +void RtlCopyUnicodeString(PUNICODE_STRING DestinationString, + PUNICODE_STRING SourceString) { + + { + return; + } +} +NTSTATUS RtlDeleteRegistryValue(ULONG RelativeTo, + PCWSTR Path, + PCWSTR ValueName); +NTSTATUS RtlDeleteRegistryValue(ULONG RelativeTo, + PCWSTR Path, PCWSTR ValueName) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + + { + if (__BLAST_NONDET == 0) { + goto switch_24_0; + } else { + { + goto switch_24_default; + if (0) { + switch_24_0: /* CIL Label */; + return (0L); + switch_24_default: /* CIL Label */; + return (-1073741823L); + } else { + switch_24_break: /* CIL Label */; + } + } + } + } +} +void RtlFreeUnicodeString(PUNICODE_STRING UnicodeString); +void RtlFreeUnicodeString(PUNICODE_STRING UnicodeString) { + + { + return; + } +} +void RtlInitString(PSTRING DestinationString, + PCSZ SourceString); +void RtlInitString(PSTRING DestinationString, PCSZ SourceString) { + + { + return; + } +} +void RtlInitUnicodeString(PUNICODE_STRING DestinationString, + PCWSTR SourceString); +void RtlInitUnicodeString(PUNICODE_STRING DestinationString, + PCWSTR SourceString) { + + { + return; + } +} +NTSTATUS RtlQueryRegistryValues(ULONG RelativeTo, + PCWSTR Path, + PRTL_QUERY_REGISTRY_TABLE QueryTable, + PVOID Context, + PVOID Environment); +NTSTATUS RtlQueryRegistryValues(ULONG RelativeTo, + PCWSTR Path, PRTL_QUERY_REGISTRY_TABLE QueryTable, + PVOID Context, PVOID Environment) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + + { + if (__BLAST_NONDET == 0) { + goto switch_25_0; + } else { + { + goto switch_25_default; + if (0) { + switch_25_0: /* CIL Label */; + return (0L); + switch_25_default: /* CIL Label */; + return (-1073741823L); + } else { + switch_25_break: /* CIL Label */; + } + } + } + } +} +NTSTATUS ZwClose(HANDLE Handle); +NTSTATUS ZwClose(HANDLE Handle) { + int __BLAST_NONDET = __VERIFIER_nondet_int(); + + { + if (__BLAST_NONDET == 0) { + goto switch_26_0; + } else { + { + goto switch_26_default; + if (0) { + switch_26_0: /* CIL Label */; + return (0L); + switch_26_default: /* CIL Label */; + return (-1073741823L); + } else { + switch_26_break: /* CIL Label */; + } + } + } + } +} + +// CHECK: generated tests = 3 diff --git a/test/regression/2023-10-13-uninitialized-memory.c b/test/regression/2023-10-13-uninitialized-memory.c new file mode 100644 index 0000000000..bf13fd0986 --- /dev/null +++ b/test/regression/2023-10-13-uninitialized-memory.c @@ -0,0 +1,21 @@ +// RUN: %clang %s -emit-llvm %O0opt -c -g -o %t.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --use-sym-size-alloc --skip-not-symbolic-objects --use-merged-pointer-dereference=true %t.bc 2>&1 | FileCheck %s +#include "klee/klee.h" + +#include +#include +#include + +int main() { + char *s1 = (char *)malloc(1); + char *s2 = (char *)malloc(1); + if (s1[0] == s2[0]) { + printf("1) eq\n"); + } else { + printf("1) not eq\n"); + } + + // CHECK-DAG: 1) eq + // CHECK-DAG: 1) not eq +} diff --git a/tools/klee/main.cpp b/tools/klee/main.cpp index e9bb118371..0e509a9c00 100644 --- a/tools/klee/main.cpp +++ b/tools/klee/main.cpp @@ -408,14 +408,16 @@ class KleeHandler : public InterpreterHandler { void processTestCase(const ExecutionState &state, const char *message, const char *suffix, bool isError = false); - void writeTestCaseXML(bool isError, const KTest &out, unsigned id); + void writeTestCaseXML(bool isError, const KTest &out, unsigned id, + unsigned version = 0); std::string getOutputFilename(const std::string &filename); std::unique_ptr openOutputFile(const std::string &filename); - std::string getTestFilename(const std::string &suffix, unsigned id); - std::unique_ptr openTestFile(const std::string &suffix, - unsigned id); + std::string getTestFilename(const std::string &suffix, unsigned id, + unsigned version = 0); + std::unique_ptr + openTestFile(const std::string &suffix, unsigned id, unsigned version = 0); // load a .path file static void loadPathFile(std::string name, std::vector &buffer); @@ -556,11 +558,14 @@ KleeHandler::openOutputFile(const std::string &filename) { return f; } -std::string KleeHandler::getTestFilename(const std::string &suffix, - unsigned id) { +std::string KleeHandler::getTestFilename(const std::string &suffix, unsigned id, + unsigned version) { std::stringstream filename; - filename << "test" << std::setfill('0') << std::setw(6) << id << '.' - << suffix; + filename << "test" << std::setfill('0') << std::setw(6) << id; + if (version) { + filename << '_' << version; + } + filename << '.' << suffix; return filename.str(); } @@ -569,8 +574,9 @@ SmallString<128> KleeHandler::getOutputDirectory() const { } std::unique_ptr -KleeHandler::openTestFile(const std::string &suffix, unsigned id) { - return openOutputFile(getTestFilename(suffix, id)); +KleeHandler::openTestFile(const std::string &suffix, unsigned id, + unsigned version) { + return openOutputFile(getTestFilename(suffix, id, version)); } /* Outputs all files (.ktest, .kquery, .cov etc.) describing a test case */ @@ -598,12 +604,14 @@ void KleeHandler::processTestCase(const ExecutionState &state, if (WriteKTests) { if (success) { - if (!kTest_toFile( - &ktest, - getOutputFilename(getTestFilename("ktest", id)).c_str())) { - klee_warning("unable to write output test case, losing it"); - } else { - atLeastOneGenerated = true; + for (unsigned i = 0; i < ktest.uninitCoeff + 1; ++i) { + if (!kTest_toFile( + &ktest, + getOutputFilename(getTestFilename("ktest", id, i)).c_str())) { + klee_warning("unable to write output test case, losing it"); + } else { + atLeastOneGenerated = true; + } } if (WriteStates) { @@ -691,8 +699,10 @@ void KleeHandler::processTestCase(const ExecutionState &state, } if (WriteXMLTests) { - writeTestCaseXML(message != nullptr, ktest, id); - atLeastOneGenerated = true; + for (unsigned i = 0; i < ktest.uninitCoeff + 1; ++i) { + writeTestCaseXML(message != nullptr, ktest, id, i); + atLeastOneGenerated = true; + } } if (atLeastOneGenerated) { @@ -723,11 +733,11 @@ void KleeHandler::processTestCase(const ExecutionState &state, } void KleeHandler::writeTestCaseXML(bool isError, const KTest &assignments, - unsigned id) { + unsigned id, unsigned version) { // TODO: This is super specific to test-comp and assumes that the name is the // type information - auto file = openTestFile("xml", id); + auto file = openTestFile("xml", id, version); if (!file) return; diff --git a/unittests/Expr/ArrayExprTest.cpp b/unittests/Expr/ArrayExprTest.cpp index 68b6948612..c2c522007d 100644 --- a/unittests/Expr/ArrayExprTest.cpp +++ b/unittests/Expr/ArrayExprTest.cpp @@ -41,8 +41,8 @@ static ArrayCache ac; TEST(ArrayExprTest, HashCollisions) { klee::OptimizeArray = ALL; - std::vector> constVals(256, - ConstantExpr::create(5, Expr::Int8)); + SparseStorage> constVals( + ConstantExpr::create(5, Expr::Int8)); const Array *array = ac.CreateArray( ConstantExpr::create(256, sizeof(uint64_t) * CHAR_BIT), SourceBuilder::constant(constVals), Expr::Int32, Expr::Int8); diff --git a/unittests/Expr/ExprTest.cpp b/unittests/Expr/ExprTest.cpp index 2a34463d9f..f6d79683e7 100644 --- a/unittests/Expr/ExprTest.cpp +++ b/unittests/Expr/ExprTest.cpp @@ -128,9 +128,10 @@ TEST(ExprTest, ReadExprFoldingBasic) { unsigned size = 5; // Constant array - std::vector> Contents(size); + SparseStorage> Contents( + ConstantExpr::create(0, Expr::Int8)); for (unsigned i = 0; i < size; ++i) - Contents[i] = ConstantExpr::create(i + 1, Expr::Int8); + Contents.store(i, ConstantExpr::create(i + 1, Expr::Int8)); ArrayCache ac; const Array *array = @@ -148,7 +149,7 @@ TEST(ExprTest, ReadExprFoldingBasic) { // Read - should be constant folded to Contents[i] // Check that constant folding worked ConstantExpr *c = static_cast(read.get()); - EXPECT_EQ(Contents[i]->getZExtValue(), c->getZExtValue()); + EXPECT_EQ(Contents.load(i)->getZExtValue(), c->getZExtValue()); } } @@ -156,9 +157,10 @@ TEST(ExprTest, ReadExprFoldingIndexOutOfBound) { unsigned size = 5; // Constant array - std::vector> Contents(size); + SparseStorage> Contents( + ConstantExpr::create(0, Expr::Int8)); for (unsigned i = 0; i < size; ++i) - Contents[i] = ConstantExpr::create(i + 1, Expr::Int8); + Contents.store(i, ConstantExpr::create(i + 1, Expr::Int8)); ArrayCache ac; const Array *array = ac.CreateArray(ConstantExpr::create(size, sizeof(uint64_t) * CHAR_BIT), @@ -178,9 +180,10 @@ TEST(ExprTest, ReadExprFoldingConstantUpdate) { unsigned size = 5; // Constant array - std::vector> Contents(size); + SparseStorage> Contents( + ConstantExpr::create(0, Expr::Int8)); for (unsigned i = 0; i < size; ++i) - Contents[i] = ConstantExpr::create(i + 1, Expr::Int8); + Contents.store(i, ConstantExpr::create(i + 1, Expr::Int8)); ArrayCache ac; const Array *array = @@ -205,9 +208,10 @@ TEST(ExprTest, ReadExprFoldingConstantMultipleUpdate) { unsigned size = 5; // Constant array - std::vector> Contents(size); + SparseStorage> Contents( + ConstantExpr::create(0, Expr::Int8)); for (unsigned i = 0; i < size; ++i) - Contents[i] = ConstantExpr::create(i + 1, Expr::Int8); + Contents.store(i, ConstantExpr::create(i + 1, Expr::Int8)); ArrayCache ac; const Array *array = @@ -234,9 +238,10 @@ TEST(ExprTest, ReadExprFoldingSymbolicValueUpdate) { unsigned size = 5; // Constant array - std::vector> Contents(size); + SparseStorage> Contents( + ConstantExpr::create(0, Expr::Int8)); for (unsigned i = 0; i < size; ++i) - Contents[i] = ConstantExpr::create(i + 1, Expr::Int8); + Contents.store(i, ConstantExpr::create(i + 1, Expr::Int8)); ArrayCache ac; const Array *array = @@ -263,9 +268,10 @@ TEST(ExprTest, ReadExprFoldingSymbolicIndexUpdate) { unsigned size = 5; // Constant array - std::vector> Contents(size); + SparseStorage> Contents( + ConstantExpr::create(0, Expr::Int8)); for (unsigned i = 0; i < size; ++i) - Contents[i] = ConstantExpr::create(i + 1, Expr::Int8); + Contents.store(i, ConstantExpr::create(i + 1, Expr::Int8)); ArrayCache ac; const Array *array = diff --git a/unittests/Solver/Z3SolverTest.cpp b/unittests/Solver/Z3SolverTest.cpp index d10a7b853c..a9a2581d89 100644 --- a/unittests/Solver/Z3SolverTest.cpp +++ b/unittests/Solver/Z3SolverTest.cpp @@ -14,6 +14,7 @@ #include "gtest/gtest.h" +#include "klee/ADT/SparseStorage.h" #include "klee/Expr/ArrayCache.h" #include "klee/Expr/Constraints.h" #include "klee/Expr/Expr.h" @@ -40,14 +41,13 @@ TEST_F(Z3SolverTest, GetConstraintLog) { constraints_ty Constraints; const std::vector ConstantValues{1, 2, 3, 4}; - std::vector> ConstantExpressions; + SparseStorage> ConstantExpressions( + ConstantExpr::create(0, Expr::Int8)); - std::transform( - ConstantValues.begin(), ConstantValues.end(), - std::back_inserter(ConstantExpressions), [](const uint64_t Value) { - ref ConstantExpr(ConstantExpr::alloc(Value, Expr::Int8)); - return ConstantExpr; - }); + for (unsigned i = 0; i < ConstantValues.size(); ++i) { + ConstantExpressions.store( + i, ConstantExpr::alloc(ConstantValues[i], Expr::Int8)); + } const Array *ConstantArray = AC.CreateArray(ConstantExpr::create(4, sizeof(uint64_t) * CHAR_BIT), From 6408e41d69603592ead258be02e33e70ba281e86 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Sat, 21 Oct 2023 20:38:36 +0400 Subject: [PATCH 049/103] [chore] Disable test --- test/Feature/SymbolicSizes/IntArray.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/Feature/SymbolicSizes/IntArray.c b/test/Feature/SymbolicSizes/IntArray.c index ddad754c44..46edaeb836 100644 --- a/test/Feature/SymbolicSizes/IntArray.c +++ b/test/Feature/SymbolicSizes/IntArray.c @@ -1,4 +1,5 @@ -// REQUIRES: not-metasmt +// REQUIRES: not-darwin +// Disabling darwin because it overflows stack on CI // RUN: %clang %s -g -emit-llvm %O0opt -c -o %t1.bc // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --use-sym-size-alloc --use-sym-size-li --min-number-elements-li=1 --skip-not-lazy-initialized %t1.bc 2>&1 | FileCheck %s From c70df432a671d4c893ed72800356efe3d70ccefa Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Sun, 22 Oct 2023 12:17:50 +0400 Subject: [PATCH 050/103] [fix] Fix performance bugs --- include/klee/ADT/SparseStorage.h | 3 ++- lib/Core/Memory.cpp | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/include/klee/ADT/SparseStorage.h b/include/klee/ADT/SparseStorage.h index 307f8b671e..638119ee79 100644 --- a/include/klee/ADT/SparseStorage.h +++ b/include/klee/ADT/SparseStorage.h @@ -66,7 +66,8 @@ class SparseStorage { } ValueType load(size_t idx) const { - return contains(idx) ? internalStorage.at(idx) : defaultValue; + auto it = internalStorage.find(idx); + return it != internalStorage.end() ? it->second : defaultValue; } size_t sizeOfSetRange() const { diff --git a/lib/Core/Memory.cpp b/lib/Core/Memory.cpp index dd8496baba..4e364ef27d 100644 --- a/lib/Core/Memory.cpp +++ b/lib/Core/Memory.cpp @@ -138,9 +138,9 @@ const UpdateList &ObjectState::getUpdates() const { void ObjectState::flushForRead() const { for (const auto &unflushed : unflushedMask.storage()) { auto offset = unflushed.first; - assert(knownSymbolics.load(offset)); - updates.extend(ConstantExpr::create(offset, Expr::Int32), - knownSymbolics.load(offset)); + auto value = knownSymbolics.load(offset); + assert(value); + updates.extend(ConstantExpr::create(offset, Expr::Int32), value); } unflushedMask.reset(false); } From 341510c8fd0a3816014ba3f202d43b25821b0bfe Mon Sep 17 00:00:00 2001 From: dim8art Date: Sat, 21 Oct 2023 18:28:40 +0300 Subject: [PATCH 051/103] [fix] Change satisfies function in InvalidReponse --- include/klee/Solver/SolverUtil.h | 16 +++++++++++++++- lib/Solver/CexCachingSolver.cpp | 19 ++++--------------- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/include/klee/Solver/SolverUtil.h b/include/klee/Solver/SolverUtil.h index d68d3ea77e..ffd3849c62 100644 --- a/include/klee/Solver/SolverUtil.h +++ b/include/klee/Solver/SolverUtil.h @@ -299,7 +299,21 @@ class InvalidResponse : public SolverResponse { } bool satisfies(const std::set> &key, bool allowFreeValues = true) { - return result.satisfies(key.begin(), key.end(), allowFreeValues); + std::set> booleanKey; + std::set> nonBooleanKey; + + for (auto i : key) { + if (i->getWidth() == Expr::Bool) { + booleanKey.insert(i); + } else { + nonBooleanKey.insert(i); + } + } + + return result.satisfies(booleanKey.begin(), booleanKey.end(), + allowFreeValues) && + result.satisfiesNonBoolean(nonBooleanKey.begin(), + nonBooleanKey.end(), allowFreeValues); } bool satisfiesNonBoolean(const std::set> &key, diff --git a/lib/Solver/CexCachingSolver.cpp b/lib/Solver/CexCachingSolver.cpp index 20d35f8bd6..ddb5861c88 100644 --- a/lib/Solver/CexCachingSolver.cpp +++ b/lib/Solver/CexCachingSolver.cpp @@ -128,23 +128,12 @@ struct isInvalidResponse { }; struct isValidOrSatisfyingResponse { - KeyType booleanKey; - KeyType nonBooleanKey; - isValidOrSatisfyingResponse(KeyType &_key) { - for (auto i : _key) { - if (i->getWidth() == Expr::Bool) { - booleanKey.insert(i); - } else { - nonBooleanKey.insert(i); - } - } - } + KeyType key; + isValidOrSatisfyingResponse(KeyType &_key) : key(_key) {} bool operator()(ref a) const { - return isa(a) || - (isa(a) && - cast(a)->satisfies(booleanKey) && - cast(a)->satisfiesNonBoolean(nonBooleanKey)); + return isa(a) || (isa(a) && + cast(a)->satisfies(key)); } }; From c4f7c5c16ea644261254e06f388c8f7b90a90da3 Mon Sep 17 00:00:00 2001 From: dim8art Date: Sat, 21 Oct 2023 18:28:40 +0300 Subject: [PATCH 052/103] Change CacheEntry to store constraints_ty --- lib/Solver/CachingSolver.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/Solver/CachingSolver.cpp b/lib/Solver/CachingSolver.cpp index 75dbe1dfec..f01d760d32 100644 --- a/lib/Solver/CachingSolver.cpp +++ b/lib/Solver/CachingSolver.cpp @@ -36,12 +36,12 @@ class CachingSolver : public SolverImpl { struct CacheEntry { CacheEntry(const ConstraintSet &c, ref q) - : constraints(c), query(q) {} + : constraints(c.cs()), query(q) {} CacheEntry(const CacheEntry &ce) : constraints(ce.constraints), query(ce.query) {} - ConstraintSet constraints; + constraints_ty constraints; ref query; bool operator==(const CacheEntry &b) const { @@ -53,7 +53,7 @@ class CachingSolver : public SolverImpl { unsigned operator()(const CacheEntry &ce) const { unsigned result = ce.query->hash(); - for (auto const &constraint : ce.constraints.cs()) { + for (auto const &constraint : ce.constraints) { result ^= constraint->hash(); } From 001f9efe3d997729957000d61998e9d74f78e0f4 Mon Sep 17 00:00:00 2001 From: dim8art Date: Sat, 21 Oct 2023 18:57:16 +0300 Subject: [PATCH 053/103] Create AlphaEquvalenceSolver --- include/klee/Expr/AlphaBuilder.h | 41 +++++ include/klee/Expr/Parser/Parser.h | 2 + include/klee/Expr/SourceBuilder.h | 1 + include/klee/Expr/SymbolicSource.h | 34 +++- include/klee/Solver/Common.h | 2 +- include/klee/Solver/Solver.h | 8 + include/klee/Solver/SolverCmdLine.h | 2 + lib/Core/Executor.cpp | 2 +- lib/Expr/AlphaBuilder.cpp | 85 ++++++++++ lib/Expr/CMakeLists.txt | 1 + lib/Expr/ExprPPrinter.cpp | 2 + lib/Expr/Parser.cpp | 11 ++ lib/Expr/SourceBuilder.cpp | 6 + lib/Solver/AlphaEquivalenceSolver.cpp | 235 ++++++++++++++++++++++++++ lib/Solver/CMakeLists.txt | 1 + lib/Solver/ConstructSolverChain.cpp | 5 +- lib/Solver/SolverCmdLine.cpp | 5 + test/Feature/ExprLogging.c | 2 +- test/Solver/AlphaEquivalenceCheck.c | 19 +++ tools/kleaver/main.cpp | 4 +- 20 files changed, 462 insertions(+), 6 deletions(-) create mode 100644 include/klee/Expr/AlphaBuilder.h create mode 100644 lib/Expr/AlphaBuilder.cpp create mode 100644 lib/Solver/AlphaEquivalenceSolver.cpp create mode 100644 test/Solver/AlphaEquivalenceCheck.c diff --git a/include/klee/Expr/AlphaBuilder.h b/include/klee/Expr/AlphaBuilder.h new file mode 100644 index 0000000000..f00b324ae7 --- /dev/null +++ b/include/klee/Expr/AlphaBuilder.h @@ -0,0 +1,41 @@ +//===-- AlphaBuilder.h -----------------------------------*- C++ -*-===// +// +// The KLEE Symbolic Virtual Machine +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef KLEE_ALPHA_BUILDER_H +#define KLEE_ALPHA_BUILDER_H + +#include "klee/Expr/ArrayCache.h" +#include "klee/Expr/ExprHashMap.h" +#include "klee/Expr/ExprVisitor.h" + +namespace klee { + +class AlphaBuilder : public ExprVisitor { +public: + ExprHashMap> reverseExprMap; + ArrayCache::ArrayHashMap reverseAlphaArrayMap; + ArrayCache::ArrayHashMap alphaArrayMap; + +private: + ArrayCache &arrayCache; + unsigned index = 0; + + const Array *visitArray(const Array *arr); + UpdateList visitUpdateList(UpdateList u); + Action visitRead(const ReadExpr &re); + +public: + AlphaBuilder(ArrayCache &_arrayCache); + constraints_ty visitConstraints(constraints_ty cs); + ref visitExpr(ref v); +}; + +} // namespace klee + +#endif /*KLEE_ALPHA_VERSION_BUILDER_H*/ diff --git a/include/klee/Expr/Parser/Parser.h b/include/klee/Expr/Parser/Parser.h index 0f6ec291c0..5009125c85 100644 --- a/include/klee/Expr/Parser/Parser.h +++ b/include/klee/Expr/Parser/Parser.h @@ -220,6 +220,8 @@ class Parser { static Parser *Create(const std::string Name, const llvm::MemoryBuffer *MB, ExprBuilder *Builder, ArrayCache *TheArrayCache, KModule *km, bool ClearArrayAfterQuery); + + virtual ArrayCache &getArrayCache() = 0; }; } // namespace expr } // namespace klee diff --git a/include/klee/Expr/SourceBuilder.h b/include/klee/Expr/SourceBuilder.h index 1747fab458..6869ad0753 100644 --- a/include/klee/Expr/SourceBuilder.h +++ b/include/klee/Expr/SourceBuilder.h @@ -32,6 +32,7 @@ class SourceBuilder { static ref value(const llvm::Value &_allocSite, int _index, KModule *km); static ref irreproducible(const std::string &name); + static ref alpha(int _index); }; }; // namespace klee diff --git a/include/klee/Expr/SymbolicSource.h b/include/klee/Expr/SymbolicSource.h index ded381bb00..5829855543 100644 --- a/include/klee/Expr/SymbolicSource.h +++ b/include/klee/Expr/SymbolicSource.h @@ -45,7 +45,8 @@ class SymbolicSource { LazyInitializationSize, Instruction, Argument, - Irreproducible + Irreproducible, + Alpha }; public: @@ -349,6 +350,37 @@ class IrreproducibleSource : public SymbolicSource { } }; +class AlphaSource : public SymbolicSource { +public: + const unsigned index; + + AlphaSource(unsigned _index) : index(_index) {} + Kind getKind() const override { return Kind::Alpha; } + virtual std::string getName() const override { return "alpha"; } + + static bool classof(const SymbolicSource *S) { + return S->getKind() == Kind::Alpha; + } + static bool classof(const AlphaSource *) { return true; } + + virtual unsigned computeHash() override { + unsigned res = getKind(); + hashValue = res ^ (index * SymbolicSource::MAGIC_HASH_CONSTANT); + return hashValue; + } + + virtual int internalCompare(const SymbolicSource &b) const override { + if (getKind() != b.getKind()) { + return getKind() < b.getKind() ? -1 : 1; + } + const AlphaSource &amb = static_cast(b); + if (index != amb.index) { + return index < amb.index ? -1 : 1; + } + return 0; + } +}; + } // namespace klee #endif /* KLEE_SYMBOLICSOURCE_H */ diff --git a/include/klee/Solver/Common.h b/include/klee/Solver/Common.h index 57ebad547d..2a43b9eb67 100644 --- a/include/klee/Solver/Common.h +++ b/include/klee/Solver/Common.h @@ -29,7 +29,7 @@ std::unique_ptr constructSolverChain( std::unique_ptr coreSolver, std::string querySMT2LogPath, std::string baseSolverQuerySMT2LogPath, std::string queryKQueryLogPath, std::string baseSolverQueryKQueryLogPath, - AddressGenerator *addressGenerator); + AddressGenerator *addressGenerator, ArrayCache &arrayCache); } // namespace klee #endif /* KLEE_COMMON_H */ diff --git a/include/klee/Solver/Solver.h b/include/klee/Solver/Solver.h index c39d8a2ae3..93fad34f54 100644 --- a/include/klee/Solver/Solver.h +++ b/include/klee/Solver/Solver.h @@ -244,6 +244,14 @@ std::unique_ptr createFastCexSolver(std::unique_ptr s); /// \param s - The underlying solver to use. std::unique_ptr createIndependentSolver(std::unique_ptr s); +/// createAlphaEquivalenceSolver - Create a solver which will change +/// independent queries to their alpha-equvalent version +/// +/// \param s - The underlying solver to use. +/// \param arrayCache - Class to create new arrays. +std::unique_ptr createAlphaEquivalenceSolver(std::unique_ptr s, + ArrayCache &arrayCache); + /// createKQueryLoggingSolver - Create a solver which will forward all queries /// after writing them to the given path in .kquery format. std::unique_ptr createKQueryLoggingSolver(std::unique_ptr s, diff --git a/include/klee/Solver/SolverCmdLine.h b/include/klee/Solver/SolverCmdLine.h index 6bd0c285bb..692f741734 100644 --- a/include/klee/Solver/SolverCmdLine.h +++ b/include/klee/Solver/SolverCmdLine.h @@ -32,6 +32,8 @@ extern llvm::cl::opt UseCexCache; extern llvm::cl::opt UseBranchCache; +extern llvm::cl::opt UseAlphaEquivalence; + extern llvm::cl::opt UseConcretizingSolver; extern llvm::cl::opt UseIndependentSolver; diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index dd34b18d5d..3217f33f92 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -515,7 +515,7 @@ Executor::Executor(LLVMContext &ctx, const InterpreterOptions &opts, interpreterHandler->getOutputFilename(SOLVER_QUERIES_SMT2_FILE_NAME), interpreterHandler->getOutputFilename(ALL_QUERIES_KQUERY_FILE_NAME), interpreterHandler->getOutputFilename(SOLVER_QUERIES_KQUERY_FILE_NAME), - addressManager.get()); + addressManager.get(), arrayCache); this->solver = std::make_unique(std::move(solver), optimizer, EqualitySubstitution); diff --git a/lib/Expr/AlphaBuilder.cpp b/lib/Expr/AlphaBuilder.cpp new file mode 100644 index 0000000000..fa52783660 --- /dev/null +++ b/lib/Expr/AlphaBuilder.cpp @@ -0,0 +1,85 @@ +//===-- AlphaBuilder.cpp ---------------------------------*- C++ -*-===// +// +// The KLEE Symbolic Virtual Machine +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "klee/Expr/AlphaBuilder.h" +#include "klee/Expr/ArrayCache.h" +#include "klee/Expr/SourceBuilder.h" + +#include + +namespace klee { + +const Array *AlphaBuilder::visitArray(const Array *arr) { + if (alphaArrayMap.find(arr) == alphaArrayMap.end()) { + ref source = arr->source; + ref size = visit(arr->getSize()); + + if (!arr->isConstantArray()) { + source = SourceBuilder::alpha(index); + index++; + alphaArrayMap[arr] = arrayCache.CreateArray( + size, source, arr->getDomain(), arr->getRange()); + reverseAlphaArrayMap[alphaArrayMap[arr]] = arr; + } else if (size != arr->getSize()) { + alphaArrayMap[arr] = arrayCache.CreateArray( + size, source, arr->getDomain(), arr->getRange()); + reverseAlphaArrayMap[alphaArrayMap[arr]] = arr; + } else { + alphaArrayMap[arr] = arr; + reverseAlphaArrayMap[arr] = arr; + } + } + return alphaArrayMap[arr]; +} + +UpdateList AlphaBuilder::visitUpdateList(UpdateList u) { + const Array *root = visitArray(u.root); + std::vector> updates; + + for (auto un = u.head; un; un = un->next) { + updates.push_back(un); + } + + updates.push_back(nullptr); + + for (int i = updates.size() - 2; i >= 0; i--) { + ref index = visit(updates[i]->index); + ref value = visit(updates[i]->value); + updates[i] = new UpdateNode(updates[i + 1], index, value); + } + return UpdateList(root, updates[0]); +} + +ExprVisitor::Action AlphaBuilder::visitRead(const ReadExpr &re) { + ref v = visit(re.index); + UpdateList u = visitUpdateList(re.updates); + ref e = ReadExpr::create(u, v); + return Action::changeTo(e); +} + +AlphaBuilder::AlphaBuilder(ArrayCache &_arrayCache) : arrayCache(_arrayCache) {} + +constraints_ty AlphaBuilder::visitConstraints(constraints_ty cs) { + constraints_ty result; + for (auto arg : cs) { + ref v = visit(arg); + reverseExprMap[v] = arg; + reverseExprMap[Expr::createIsZero(v)] = Expr::createIsZero(arg); + result.insert(v); + } + return result; +} +ref AlphaBuilder::visitExpr(ref v) { + ref e = visit(v); + reverseExprMap[e] = v; + reverseExprMap[Expr::createIsZero(e)] = Expr::createIsZero(v); + return e; +} + +} // namespace klee diff --git a/lib/Expr/CMakeLists.txt b/lib/Expr/CMakeLists.txt index 03137ef820..6167bbf721 100644 --- a/lib/Expr/CMakeLists.txt +++ b/lib/Expr/CMakeLists.txt @@ -7,6 +7,7 @@ # #===------------------------------------------------------------------------===# add_library(kleaverExpr + AlphaBuilder.cpp APFloatEval.cpp ArrayCache.cpp ArrayExprOptimizer.cpp diff --git a/lib/Expr/ExprPPrinter.cpp b/lib/Expr/ExprPPrinter.cpp index 46d4a1072b..5ffba87725 100644 --- a/lib/Expr/ExprPPrinter.cpp +++ b/lib/Expr/ExprPPrinter.cpp @@ -410,6 +410,8 @@ class PPrinter : public ExprPPrinter { << kf->getName().str() << " " << s->index; } else if (auto s = dyn_cast(source)) { PC << s->name; + } else if (auto s = dyn_cast(source)) { + PC << s->index; } else { assert(0 && "Not implemented"); } diff --git a/lib/Expr/Parser.cpp b/lib/Expr/Parser.cpp index 19b72f7321..a144437fd8 100644 --- a/lib/Expr/Parser.cpp +++ b/lib/Expr/Parser.cpp @@ -280,6 +280,8 @@ class ParserImpl : public Parser { } } + ArrayCache &getArrayCache() { return *TheArrayCache; } + /*** Grammar productions ****/ /* Top level decls */ @@ -329,6 +331,7 @@ class ParserImpl : public Parser { SourceResult ParseLazyInitializationSizeSource(); SourceResult ParseInstructionSource(); SourceResult ParseArgumentSource(); + SourceResult ParseAlphaSource(); /*** Diagnostics ***/ @@ -498,6 +501,8 @@ SourceResult ParserImpl::ParseSource() { } else if (type == "argument") { assert(km); source = ParseArgumentSource(); + } else if (type == "alpha") { + source = ParseAlphaSource(); } else { assert(0); } @@ -626,6 +631,12 @@ SourceResult ParserImpl::ParseInstructionSource() { return SourceBuilder::instruction(*KI->inst, index, km); } +SourceResult ParserImpl::ParseAlphaSource() { + auto indexExpr = ParseNumber(64).get(); + auto index = dyn_cast(indexExpr)->getZExtValue(); + return SourceBuilder::alpha(index); +} + /// ParseCommandDecl - Parse a command declaration. The lexer should /// be positioned at the opening '('. /// diff --git a/lib/Expr/SourceBuilder.cpp b/lib/Expr/SourceBuilder.cpp index 2a3a09908d..866f89da6d 100644 --- a/lib/Expr/SourceBuilder.cpp +++ b/lib/Expr/SourceBuilder.cpp @@ -88,3 +88,9 @@ ref SourceBuilder::irreproducible(const std::string &name) { r->computeHash(); return r; } + +ref SourceBuilder::alpha(int _index) { + ref r(new AlphaSource(_index)); + r->computeHash(); + return r; +} diff --git a/lib/Solver/AlphaEquivalenceSolver.cpp b/lib/Solver/AlphaEquivalenceSolver.cpp new file mode 100644 index 0000000000..4f29759cc3 --- /dev/null +++ b/lib/Solver/AlphaEquivalenceSolver.cpp @@ -0,0 +1,235 @@ +//===-- AlphaEquivalenceSolver.cpp-----------------------------------------===// +// +// The KLEE Symbolic Virtual Machine +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "klee/Expr/SymbolicSource.h" +#include "klee/Solver/SolverUtil.h" + +#include "klee/Solver/Solver.h" + +#include "klee/Expr/AlphaBuilder.h" +#include "klee/Expr/Assignment.h" +#include "klee/Expr/Constraints.h" +#include "klee/Expr/ExprHashMap.h" +#include "klee/Solver/SolverImpl.h" +#include "klee/Support/Debug.h" + +#include "klee/Support/CompilerWarning.h" +DISABLE_WARNING_PUSH +DISABLE_WARNING_DEPRECATED_DECLARATIONS +#include "llvm/Support/Casting.h" +#include "llvm/Support/raw_ostream.h" +DISABLE_WARNING_POP + +using namespace klee; +using namespace llvm; + +class AlphaEquivalenceSolver : public SolverImpl { +private: + std::unique_ptr solver; + ArrayCache &arrayCache; + +public: + AlphaEquivalenceSolver(std::unique_ptr solver, + ArrayCache &_arrayCache) + : solver(std::move(solver)), arrayCache(_arrayCache) {} + + bool computeTruth(const Query &, bool &isValid); + bool computeValidity(const Query &, PartialValidity &result); + bool computeValue(const Query &, ref &result); + bool computeInitialValues(const Query &query, + const std::vector &objects, + std::vector> &values, + bool &hasSolution); + bool check(const Query &query, ref &result); + bool computeValidityCore(const Query &query, ValidityCore &validityCore, + bool &isValid); + SolverRunStatus getOperationStatusCode(); + char *getConstraintLog(const Query &); + void setCoreSolverTimeout(time::Span timeout); + void notifyStateTermination(std::uint32_t id); + ValidityCore changeVersion(const ValidityCore &validityCore, + const ExprHashMap> &reverse); + const std::vector + changeVersion(const std::vector &objects, + const ArrayCache::ArrayHashMap &reverse); + Assignment + changeVersion(const Assignment &a, + const ArrayCache::ArrayHashMap &reverse); + ref changeVersion(ref res, + const AlphaBuilder &builder); + ref createAlphaVersion(ref res, + const AlphaBuilder &builder); +}; + +ValidityCore +AlphaEquivalenceSolver::changeVersion(const ValidityCore &validityCore, + const ExprHashMap> &reverse) { + ValidityCore reverseValidityCore; + assert(reverse.find(validityCore.expr) != reverse.end()); + reverseValidityCore.expr = reverse.at(validityCore.expr); + for (auto e : validityCore.constraints) { + assert(reverse.find(e) != reverse.end()); + reverseValidityCore.constraints.insert(reverse.at(e)); + } + return reverseValidityCore; +} + +const std::vector AlphaEquivalenceSolver::changeVersion( + const std::vector &objects, + const ArrayCache::ArrayHashMap &reverse) { + std::vector reverseObjects; + for (auto it : objects) { + reverseObjects.push_back(reverse.at(it)); + } + return reverseObjects; +} + +Assignment AlphaEquivalenceSolver::changeVersion( + const Assignment &a, + const ArrayCache::ArrayHashMap &reverse) { + std::vector objects = a.keys(); + std::vector> values = a.values(); + objects = changeVersion(objects, reverse); + return Assignment(objects, values); +} + +ref +AlphaEquivalenceSolver::changeVersion(ref res, + const AlphaBuilder &builder) { + ref reverseRes; + if (!isa(res) && !isa(res)) { + return res; + } + + if (isa(res)) { + Assignment a = cast(res)->initialValues(); + a = changeVersion(a, builder.reverseAlphaArrayMap); + reverseRes = new InvalidResponse(a.bindings); + } else { + ValidityCore validityCore; + res->tryGetValidityCore(validityCore); + validityCore = changeVersion(validityCore, builder.reverseExprMap); + reverseRes = new ValidResponse(validityCore); + } + return reverseRes; +} + +ref +AlphaEquivalenceSolver::createAlphaVersion(ref res, + const AlphaBuilder &builder) { + if (!res || !isa(res)) { + return res; + } + + Assignment a = cast(res)->initialValues(); + changeVersion(a, builder.alphaArrayMap); + return new InvalidResponse(a.bindings); +} + +bool AlphaEquivalenceSolver::computeValidity(const Query &query, + PartialValidity &result) { + AlphaBuilder builder(arrayCache); + constraints_ty alphaQuery = builder.visitConstraints(query.constraints.cs()); + ref alphaQueryExpr = builder.visitExpr(query.expr); + return solver->impl->computeValidity( + Query(ConstraintSet(alphaQuery, {}, {}), alphaQueryExpr, query.id), + result); +} + +bool AlphaEquivalenceSolver::computeTruth(const Query &query, bool &isValid) { + AlphaBuilder builder(arrayCache); + constraints_ty alphaQuery = builder.visitConstraints(query.constraints.cs()); + ref alphaQueryExpr = builder.visitExpr(query.expr); + return solver->impl->computeTruth( + Query(ConstraintSet(alphaQuery, {}, {}), alphaQueryExpr, query.id), + isValid); +} + +bool AlphaEquivalenceSolver::computeValue(const Query &query, + ref &result) { + AlphaBuilder builder(arrayCache); + constraints_ty alphaQuery = builder.visitConstraints(query.constraints.cs()); + ref alphaQueryExpr = builder.visitExpr(query.expr); + return solver->impl->computeValue( + Query(ConstraintSet(alphaQuery, {}, {}), alphaQueryExpr, query.id), + result); +} + +bool AlphaEquivalenceSolver::computeInitialValues( + const Query &query, const std::vector &objects, + std::vector> &values, bool &hasSolution) { + AlphaBuilder builder(arrayCache); + constraints_ty alphaQuery = builder.visitConstraints(query.constraints.cs()); + ref alphaQueryExpr = builder.visitExpr(query.expr); + const std::vector newObjects = + changeVersion(objects, builder.alphaArrayMap); + + if (!solver->impl->computeInitialValues( + Query(ConstraintSet(alphaQuery, {}, {}), alphaQueryExpr, query.id), + newObjects, values, hasSolution)) { + return false; + } + return true; +} + +bool AlphaEquivalenceSolver::check(const Query &query, + ref &result) { + AlphaBuilder builder(arrayCache); + + constraints_ty alphaQuery = builder.visitConstraints(query.constraints.cs()); + ref alphaQueryExpr = builder.visitExpr(query.expr); + result = createAlphaVersion(result, builder); + if (!solver->impl->check( + Query(ConstraintSet(alphaQuery, {}, {}), alphaQueryExpr, query.id), + result)) { + return false; + } + + result = changeVersion(result, builder); + return true; +} + +bool AlphaEquivalenceSolver::computeValidityCore(const Query &query, + ValidityCore &validityCore, + bool &isValid) { + AlphaBuilder builder(arrayCache); + + constraints_ty alphaQuery = builder.visitConstraints(query.constraints.cs()); + ref alphaQueryExpr = builder.visitExpr(query.expr); + if (!solver->impl->computeValidityCore( + Query(ConstraintSet(alphaQuery, {}, {}), alphaQueryExpr, query.id), + validityCore, isValid)) { + return false; + } + validityCore = changeVersion(validityCore, builder.reverseExprMap); + return true; +} + +SolverImpl::SolverRunStatus AlphaEquivalenceSolver::getOperationStatusCode() { + return solver->impl->getOperationStatusCode(); +} + +char *AlphaEquivalenceSolver::getConstraintLog(const Query &query) { + return solver->impl->getConstraintLog(query); +} + +void AlphaEquivalenceSolver::setCoreSolverTimeout(time::Span timeout) { + solver->impl->setCoreSolverTimeout(timeout); +} + +void AlphaEquivalenceSolver::notifyStateTermination(std::uint32_t id) { + solver->impl->notifyStateTermination(id); +} + +std::unique_ptr +klee::createAlphaEquivalenceSolver(std::unique_ptr s, + ArrayCache &arrayCache) { + return std::make_unique( + std::make_unique(std::move(s), arrayCache)); +} diff --git a/lib/Solver/CMakeLists.txt b/lib/Solver/CMakeLists.txt index a1b15052bc..9ee7805b64 100644 --- a/lib/Solver/CMakeLists.txt +++ b/lib/Solver/CMakeLists.txt @@ -7,6 +7,7 @@ # #===------------------------------------------------------------------------===# add_library(kleaverSolver + AlphaEquivalenceSolver.cpp AssignmentValidatingSolver.cpp CachingSolver.cpp CexCachingSolver.cpp diff --git a/lib/Solver/ConstructSolverChain.cpp b/lib/Solver/ConstructSolverChain.cpp index f8c9c8d522..c734db9c64 100644 --- a/lib/Solver/ConstructSolverChain.cpp +++ b/lib/Solver/ConstructSolverChain.cpp @@ -34,7 +34,7 @@ std::unique_ptr constructSolverChain( std::unique_ptr coreSolver, std::string querySMT2LogPath, std::string baseSolverQuerySMT2LogPath, std::string queryKQueryLogPath, std::string baseSolverQueryKQueryLogPath, - AddressGenerator *addressGenerator) { + AddressGenerator *addressGenerator, ArrayCache &arrayCache) { Solver *rawCoreSolver = coreSolver.get(); std::unique_ptr solver = std::move(coreSolver); const time::Span minQueryTimeToLog(MinQueryTimeToLog); @@ -67,6 +67,9 @@ std::unique_ptr constructSolverChain( if (UseBranchCache) solver = createCachingSolver(std::move(solver)); + if (UseAlphaEquivalence) + solver = createAlphaEquivalenceSolver(std::move(solver), arrayCache); + if (UseIndependentSolver) solver = createIndependentSolver(std::move(solver)); diff --git a/lib/Solver/SolverCmdLine.cpp b/lib/Solver/SolverCmdLine.cpp index 0f51525d53..4974abe1f8 100644 --- a/lib/Solver/SolverCmdLine.cpp +++ b/lib/Solver/SolverCmdLine.cpp @@ -56,6 +56,11 @@ cl::opt UseBranchCache("use-branch-cache", cl::init(true), cl::desc("Use the branch cache (default=true)"), cl::cat(SolvingCat)); +cl::opt + UseAlphaEquivalence("use-alpha-equivalence", cl::init(true), + cl::desc("Use the alpha version builder(default=true)"), + cl::cat(SolvingCat)); + cl::opt UseConcretizingSolver("use-concretizing-solver", cl::init(true), cl::desc("Use concretization manager(default=true)"), diff --git a/test/Feature/ExprLogging.c b/test/Feature/ExprLogging.c index 8109647a57..ca8d7a7913 100644 --- a/test/Feature/ExprLogging.c +++ b/test/Feature/ExprLogging.c @@ -1,7 +1,7 @@ // RUN: %clang %s -emit-llvm -g %O0opt -c -o %t1.bc // We disable the cex-cache to eliminate nondeterminism across different solvers, in particular when counting the number of queries in the last two commands // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --use-cex-cache=false --use-query-log=all:kquery,all:smt2,solver:kquery,solver:smt2 --write-kqueries --write-cvcs --write-smt2s %t1.bc 2> %t2.log +// RUN: %klee --output-dir=%t.klee-out --use-cex-cache=false --use-alpha-equivalence=false --use-query-log=all:kquery,all:smt2,solver:kquery,solver:smt2 --write-kqueries --write-cvcs --write-smt2s %t1.bc 2> %t2.log // RUN: %kleaver -print-ast %t.klee-out/all-queries.kquery > %t3.log // RUN: %kleaver -print-ast %t3.log > %t4.log // RUN: diff %t3.log %t4.log diff --git a/test/Solver/AlphaEquivalenceCheck.c b/test/Solver/AlphaEquivalenceCheck.c new file mode 100644 index 0000000000..160fdee515 --- /dev/null +++ b/test/Solver/AlphaEquivalenceCheck.c @@ -0,0 +1,19 @@ +// RUN: %clang %s -emit-llvm -g %O0opt -c -o %t1.bc +// RUN: rm -rf %t1.klee-out +// RUN: %klee --output-dir=%t1.klee-out --use-alpha-equivalence=false --use-cex-cache=true --use-query-log=solver:kquery,solver:smt2 --write-kqueries --write-cvcs --write-smt2s %t1.bc 2> %t2.log +// RUN: rm -rf %t2.klee-out +// RUN: %klee --output-dir=%t2.klee-out --use-alpha-equivalence=true --use-cex-cache=true --use-query-log=solver:kquery,solver:smt2 --write-kqueries --write-cvcs --write-smt2s %t1.bc 2> %t2.log +// RUN: grep "^; Query" %t1.klee-out/solver-queries.smt2 | wc -l | grep -q 2 +// RUN: grep "^; Query" %t2.klee-out/solver-queries.smt2 | wc -l | grep -q 1 + +#include "klee/klee.h" + +int main(int argc, char **argv) { + int a, b, c, d; + klee_make_symbolic(&a, sizeof(a), "a"); + klee_make_symbolic(&b, sizeof(b), "b"); + klee_make_symbolic(&c, sizeof(c), "c"); + klee_make_symbolic(&d, sizeof(d), "d"); + klee_assume(a + b == 0); + klee_assume(c + d == 0); +} diff --git a/tools/kleaver/main.cpp b/tools/kleaver/main.cpp index 5488055bd2..2deedb3c0b 100644 --- a/tools/kleaver/main.cpp +++ b/tools/kleaver/main.cpp @@ -9,6 +9,7 @@ #include "klee/ADT/SparseStorage.h" #include "klee/Config/Version.h" +#include "klee/Expr/ArrayCache.h" #include "klee/Expr/Constraints.h" #include "klee/Expr/Expr.h" #include "klee/Expr/ExprBuilder.h" @@ -212,7 +213,8 @@ static bool EvaluateInputAST(const char *Filename, const llvm::MemoryBuffer *MB, std::move(coreSolver), getQueryLogPath(ALL_QUERIES_SMT2_FILE_NAME), getQueryLogPath(SOLVER_QUERIES_SMT2_FILE_NAME), getQueryLogPath(ALL_QUERIES_KQUERY_FILE_NAME), - getQueryLogPath(SOLVER_QUERIES_KQUERY_FILE_NAME), nullptr); + getQueryLogPath(SOLVER_QUERIES_KQUERY_FILE_NAME), nullptr, + P->getArrayCache()); unsigned Index = 0; for (std::vector::iterator it = Decls.begin(), ie = Decls.end(); From 85299803b629591ebad055c77f193094801b079d Mon Sep 17 00:00:00 2001 From: Yurii Kostyukov Date: Mon, 23 Oct 2023 14:14:33 +0300 Subject: [PATCH 054/103] [fix] Propagation of without filter --- lib/Core/TargetManager.h | 6 +- test/Industry/egcd3-ll_valuebound10.c | 85 +++++++++++++++++++++++++++ 2 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 test/Industry/egcd3-ll_valuebound10.c diff --git a/lib/Core/TargetManager.h b/lib/Core/TargetManager.h index c135f354dd..ba2dea9ab3 100644 --- a/lib/Core/TargetManager.h +++ b/lib/Core/TargetManager.h @@ -136,7 +136,11 @@ class TargetHistoryTargetPairToStatesMap final { inline map_it begin() noexcept { return self.begin(); } inline map_it end() noexcept { return self.end(); } - inline const cv at(const k &__k) const { return self.at(__k); } + inline const cv at(const k &__k) const { + cv result = self.at(__k); + result.setWithout(without); + return result; + } inline it begin() const noexcept { return it(self.begin(), without); }; inline it end() const noexcept { return it(self.end(), without); }; diff --git a/test/Industry/egcd3-ll_valuebound10.c b/test/Industry/egcd3-ll_valuebound10.c new file mode 100644 index 0000000000..5fd1bc76d1 --- /dev/null +++ b/test/Industry/egcd3-ll_valuebound10.c @@ -0,0 +1,85 @@ +// RUN: %clang %s -emit-llvm %O0opt -g -c -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --delete-dead-loops=false --emit-all-errors --mock-all-externals --use-forked-solver=false --max-memory=6008 --optimize --skip-not-lazy-initialized --output-source=false --output-stats=true --output-istats=true -istats-write-interval=90s --use-sym-size-alloc=true --cex-cache-validity-cores --symbolic-allocation-threshold=8192 --max-solver-time=5s --track-coverage=branches --use-iterative-deepening-search=max-cycles --cover-on-the-fly=false --delay-cover-on-the-fly=400000 --only-output-states-covering-new --dump-states-on-halt=true --search=dfs --search=random-state %t1.bc +// RUN: %klee-stats --print-columns 'BCov(%)' --table-format=csv %t.klee-out > %t.stats +// RUN: FileCheck -input-file=%t.stats %s +// CHECK: BCov(%) +// CHECK-NEXT: {{(8[5-9]|9[0-9]|100)\.}} + +#include "klee-test-comp.c" +/* extended Euclid's algorithm */ +extern void abort(void); +extern void __assert_fail(const char *, const char *, unsigned int, const char *) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__noreturn__)); +void reach_error() { __assert_fail("0", "egcd3-ll.c", 4, "reach_error"); } +extern int __VERIFIER_nondet_int(void); +extern void abort(void); +void assume_abort_if_not(int cond) { + if(!cond) {abort();} +} +void __VERIFIER_assert(int cond) { + if (!(cond)) { + ERROR: + {reach_error();} + } + return; +} + +int main() { + int x, y; + long long a, b, p, q, r, s; + x = __VERIFIER_nondet_int(); + assume_abort_if_not(x>=0 && x<=10); + y = __VERIFIER_nondet_int(); + assume_abort_if_not(y>=0 && y<=10); + assume_abort_if_not(x >= 1); + assume_abort_if_not(y >= 1); + + a = x; + b = y; + p = 1; + q = 0; + r = 0; + s = 1; + + while (1) { + if (!(b != 0)) + break; + long long c, k; + c = a; + k = 0; + + while (1) { + if (!(c >= b)) + break; + long long d, v; + d = 1; + v = b; + + while (1) { + __VERIFIER_assert(a == y * r + x * p); + __VERIFIER_assert(b == x * q + y * s); + __VERIFIER_assert(a == k * b + c); + __VERIFIER_assert(v == b * d); + + if (!(c >= 2 * v)) + break; + d = 2 * d; + v = 2 * v; + } + c = c - v; + k = k + d; + } + + a = b; + b = c; + long long temp; + temp = p; + p = q; + q = temp - q * k; + temp = r; + r = s; + s = temp - s * k; + } + __VERIFIER_assert(p*x - q*x + r*y - s*y == a); + return 0; +} From ecfca388195ef61364f88096c3be5af0d4bd5980 Mon Sep 17 00:00:00 2001 From: Yurii Kostyukov Date: Mon, 23 Oct 2023 17:57:17 +0300 Subject: [PATCH 055/103] [fix] Small fixes --- lib/Core/Executor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index 3217f33f92..cda2c31aaf 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -6021,13 +6021,13 @@ void Executor::executeMemoryOperation( bool success = solver->getResponse(state->constraints.cs(), inBounds, response, state->queryMetaData); solver->setTimeout(time::Span()); - bool mustBeInBounds = !isa(response); if (!success) { state->pc = state->prevPC; terminateStateOnSolverError(*state, "Query timed out (bounds check)."); return; } + bool mustBeInBounds = !isa(response); if (mustBeInBounds) { if (isa(response)) { addConstraint(*state, inBounds); From 8991cbcaae0b8ec85af9bf7529ca42674188f47d Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Tue, 24 Oct 2023 18:34:36 +0400 Subject: [PATCH 056/103] [fix] Generate test only for successful solution found --- lib/Core/Executor.cpp | 1 - tools/klee/main.cpp | 147 +++++++++++++++++++++--------------------- 2 files changed, 73 insertions(+), 75 deletions(-) diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index cda2c31aaf..103c9d3880 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -7180,7 +7180,6 @@ bool Executor::getSymbolicSolution(const ExecutionState &state, KTest &res) { } bool success = solver->getInitialValues(extendedConstraints.cs(), objects, values, state.queryMetaData); - Assignment assignment(objects, values); solver->setTimeout(time::Span()); if (!success) { klee_warning("unable to compute initial values (invalid constraints?)!"); diff --git a/tools/klee/main.cpp b/tools/klee/main.cpp index 0e509a9c00..71e7f8623a 100644 --- a/tools/klee/main.cpp +++ b/tools/klee/main.cpp @@ -34,6 +34,7 @@ DISABLE_WARNING_DEPRECATED_DECLARATIONS #include "llvm/Bitcode/BitcodeReader.h" #include "llvm/IR/Constants.h" #include "llvm/IR/IRBuilder.h" +#include "llvm/IR/InstIterator.h" #include "llvm/IR/Instruction.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Type.h" @@ -62,7 +63,6 @@ DISABLE_WARNING_POP #include #include #include -#include #include using json = nlohmann::json; @@ -601,9 +601,8 @@ void KleeHandler::processTestCase(const ExecutionState &state, const auto start_time = time::getWallTime(); bool atLeastOneGenerated = false; - if (WriteKTests) { - - if (success) { + if (success) { + if (WriteKTests) { for (unsigned i = 0; i < ktest.uninitCoeff + 1; ++i) { if (!kTest_toFile( &ktest, @@ -620,49 +619,36 @@ void KleeHandler::processTestCase(const ExecutionState &state, } } - if (message) { - auto f = openTestFile(suffix, id); - if (f) - *f << message; - } - - if (m_pathWriter) { - std::vector concreteBranches; - m_pathWriter->readStream(m_interpreter->getPathStreamID(state), - concreteBranches); - auto f = openTestFile("path", id); - if (f) { - for (const auto &branch : concreteBranches) { - *f << branch << '\n'; - } + if (WriteXMLTests) { + for (unsigned i = 0; i < ktest.uninitCoeff + 1; ++i) { + writeTestCaseXML(message != nullptr, ktest, id, i); + atLeastOneGenerated = true; } } - } - if (message || WriteKQueries) { - std::string constraints; - m_interpreter->getConstraintLog(state, constraints, Interpreter::KQUERY); - auto f = openTestFile("kquery", id); - if (f) - *f << constraints; + for (unsigned i = 0; i < ktest.numObjects; i++) { + delete[] ktest.objects[i].bytes; + delete[] ktest.objects[i].pointers; + } + delete[] ktest.objects; } - if (WriteCVCs) { - // FIXME: If using Z3 as the core solver the emitted file is actually - // SMT-LIBv2 not CVC which is a bit confusing - std::string constraints; - m_interpreter->getConstraintLog(state, constraints, Interpreter::STP); - auto f = openTestFile("cvc", id); + if (message) { + auto f = openTestFile(suffix, id); if (f) - *f << constraints; + *f << message; } - if (WriteSMT2s) { - std::string constraints; - m_interpreter->getConstraintLog(state, constraints, Interpreter::SMTLIB2); - auto f = openTestFile("smt2", id); - if (f) - *f << constraints; + if (m_pathWriter) { + std::vector concreteBranches; + m_pathWriter->readStream(m_interpreter->getPathStreamID(state), + concreteBranches); + auto f = openTestFile("path", id); + if (f) { + for (const auto &branch : concreteBranches) { + *f << branch << '\n'; + } + } } if (m_symPathWriter) { @@ -677,48 +663,14 @@ void KleeHandler::processTestCase(const ExecutionState &state, } } - if (WriteKPaths) { - std::string blockPath; - m_interpreter->getBlockPath(state, blockPath); - auto f = openTestFile("kpath", id); - if (f) - *f << blockPath; - } - - if (WriteCov) { - std::map> cov; - m_interpreter->getCoveredLines(state, cov); - auto f = openTestFile("cov", id); - if (f) { - for (const auto &entry : cov) { - for (const auto &line : entry.second) { - *f << entry.first << ':' << line << '\n'; - } - } - } - } - - if (WriteXMLTests) { - for (unsigned i = 0; i < ktest.uninitCoeff + 1; ++i) { - writeTestCaseXML(message != nullptr, ktest, id, i); - atLeastOneGenerated = true; - } - } - if (atLeastOneGenerated) { ++m_numGeneratedTests; } - for (unsigned i = 0; i < ktest.numObjects; i++) { - delete[] ktest.objects[i].bytes; - delete[] ktest.objects[i].pointers; - } - delete[] ktest.objects; - if (m_numGeneratedTests == MaxTests) m_interpreter->setHaltExecution(HaltExecution::MaxTests); - if (!WriteXMLTests && WriteTestInfo) { + if (WriteTestInfo) { time::Span elapsed_time(time::getWallTime() - start_time); auto f = openTestFile("info", id); if (f) @@ -726,6 +678,53 @@ void KleeHandler::processTestCase(const ExecutionState &state, } } // if (!WriteNone) + if (WriteKQueries) { + std::string constraints; + m_interpreter->getConstraintLog(state, constraints, Interpreter::KQUERY); + auto f = openTestFile("kquery", id); + if (f) + *f << constraints; + } + + if (WriteCVCs) { + // FIXME: If using Z3 as the core solver the emitted file is actually + // SMT-LIBv2 not CVC which is a bit confusing + std::string constraints; + m_interpreter->getConstraintLog(state, constraints, Interpreter::STP); + auto f = openTestFile("cvc", id); + if (f) + *f << constraints; + } + + if (WriteSMT2s) { + std::string constraints; + m_interpreter->getConstraintLog(state, constraints, Interpreter::SMTLIB2); + auto f = openTestFile("smt2", id); + if (f) + *f << constraints; + } + + if (WriteKPaths) { + std::string blockPath; + m_interpreter->getBlockPath(state, blockPath); + auto f = openTestFile("kpath", id); + if (f) + *f << blockPath; + } + + if (WriteCov) { + std::map> cov; + m_interpreter->getCoveredLines(state, cov); + auto f = openTestFile("cov", id); + if (f) { + for (const auto &entry : cov) { + for (const auto &line : entry.second) { + *f << entry.first << ':' << line << '\n'; + } + } + } + } + if (isError && OptExitOnError) { m_interpreter->prepareForEarlyExit(); klee_error("EXITING ON ERROR:\n%s\n", message); From 058365753f692e2e5ad277b1e17f76bd2886b530 Mon Sep 17 00:00:00 2001 From: Yurii Kostyukov Date: Tue, 24 Oct 2023 11:19:41 +0300 Subject: [PATCH 057/103] [chore] Deal with compiler warnings --- include/klee/Expr/AlphaBuilder.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/klee/Expr/AlphaBuilder.h b/include/klee/Expr/AlphaBuilder.h index f00b324ae7..b56e9563cf 100644 --- a/include/klee/Expr/AlphaBuilder.h +++ b/include/klee/Expr/AlphaBuilder.h @@ -16,7 +16,7 @@ namespace klee { -class AlphaBuilder : public ExprVisitor { +class AlphaBuilder final : public ExprVisitor { public: ExprHashMap> reverseExprMap; ArrayCache::ArrayHashMap reverseAlphaArrayMap; @@ -28,7 +28,8 @@ class AlphaBuilder : public ExprVisitor { const Array *visitArray(const Array *arr); UpdateList visitUpdateList(UpdateList u); - Action visitRead(const ReadExpr &re); + Action visitRead(const ReadExpr &re) override; + using ExprVisitor::visitExpr; public: AlphaBuilder(ArrayCache &_arrayCache); From d8ff87b06f26163c9eee83984664f2f6935fcb87 Mon Sep 17 00:00:00 2001 From: Yurii Kostyukov Date: Tue, 24 Oct 2023 13:27:04 +0300 Subject: [PATCH 058/103] [feat] Cover on the fly based on time --- lib/Core/Executor.cpp | 24 ++++++++++++++++-------- lib/Core/Executor.h | 3 +++ test/Feature/CoverOnTheFly.c | 6 ++---- 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index 103c9d3880..49df803c89 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -249,10 +249,10 @@ cl::opt CoverOnTheFly( "(default=false, i.e. one per (error,instruction) pair)"), cl::cat(TestGenCat)); -cl::opt DelayCoverOnTheFly( - "delay-cover-on-the-fly", cl::init(10000), - cl::desc("Start on the fly tests generation after this many instructions " - "(default=10000)"), +cl::opt DelayCoverOnTheFly( + "delay-cover-on-the-fly", cl::init("0s"), + cl::desc("Start on the fly tests generation after the specified duration. " + "Set to 0s to disable (default=0s)"), cl::cat(TestGenCat)); cl::opt UninitMemoryTestMultiplier( @@ -487,8 +487,9 @@ Executor::Executor(LLVMContext &ctx, const InterpreterOptions &opts, targetedExecutionManager( new TargetedExecutionManager(*codeGraphInfo, *targetManager)), replayKTest(0), replayPath(0), usingSeeds(0), atMemoryLimit(false), - inhibitForking(false), haltExecution(HaltExecution::NotHalt), - ivcEnabled(false), debugLogBuffer(debugBufferString) { + inhibitForking(false), coverOnTheFly(false), + haltExecution(HaltExecution::NotHalt), ivcEnabled(false), + debugLogBuffer(debugBufferString) { const time::Span maxTime{MaxTime}; if (maxTime) timers.add(std::make_unique(maxTime, [&] { @@ -496,6 +497,13 @@ Executor::Executor(LLVMContext &ctx, const InterpreterOptions &opts, setHaltExecution(HaltExecution::MaxTime); })); + if (CoverOnTheFly && guidanceKind != GuidanceKind::ErrorGuidance) { + const time::Span delayTime{DelayCoverOnTheFly}; + if (delayTime) + timers.add( + std::make_unique(delayTime, [&] { coverOnTheFly = true; })); + } + coreSolverTimeout = time::Span{MaxCoreSolverTime}; if (coreSolverTimeout) UseForkedCoreSolver = true; @@ -4381,8 +4389,8 @@ static std::string terminationTypeFileExtension(StateTerminationType type) { void Executor::executeStep(ExecutionState &state) { KFunction *initKF = state.initPC->parent->parent; - if (CoverOnTheFly && guidanceKind != GuidanceKind::ErrorGuidance && - stats::instructions > DelayCoverOnTheFly && shouldWriteTest(state)) { + + if (coverOnTheFly && shouldWriteTest(state)) { state.clearCoveredNew(); interpreterHandler->processTestCase( state, nullptr, diff --git a/lib/Core/Executor.h b/lib/Core/Executor.h index 5a4f8bc554..a1a1e3c380 100644 --- a/lib/Core/Executor.h +++ b/lib/Core/Executor.h @@ -208,6 +208,9 @@ class Executor : public Interpreter { /// Disables forking, set by client. \see setInhibitForking() bool inhibitForking; + /// Should it generate test cases for each new covered block or branch + bool coverOnTheFly; + /// Signals the executor to halt execution at the next instruction /// step. HaltExecution::Reason haltExecution = HaltExecution::NotHalt; diff --git a/test/Feature/CoverOnTheFly.c b/test/Feature/CoverOnTheFly.c index 85c0ead78c..37e4381614 100644 --- a/test/Feature/CoverOnTheFly.c +++ b/test/Feature/CoverOnTheFly.c @@ -2,11 +2,10 @@ // REQUIRES: not-asan // RUN: %clang %s -emit-llvm %O0opt -c -o %t.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --only-output-states-covering-new --max-instructions=2000 --delay-cover-on-the-fly=500 --dump-states-on-halt=false --cover-on-the-fly --search=bfs --use-guided-search=none --output-dir=%t.klee-out %t.bc 2>&1 | FileCheck %s +// RUN: %klee --only-output-states-covering-new --max-instructions=2000 --timer-interval=1ms --delay-cover-on-the-fly=1ms --dump-states-on-halt=false --cover-on-the-fly --search=bfs --use-guided-search=none --output-dir=%t.klee-out %t.bc 2>&1 | FileCheck %s #include "klee/klee.h" -#define a (2) int main() { int res = 0; for (;;) { @@ -31,5 +30,4 @@ int main() { } } -// CHECK: KLEE: done: completed paths = 0 -// CHECK: KLEE: done: generated tests = 5 +// CHECK-NOT: KLEE: done: generated tests = 0 From d74463ab0b379c2cb16498ad434e2090d26650ca Mon Sep 17 00:00:00 2001 From: Yurii Kostyukov Date: Tue, 24 Oct 2023 13:28:09 +0300 Subject: [PATCH 059/103] [fix] rewriting ordering for terms with equal height --- include/klee/Expr/Expr.h | 4 ++-- lib/Expr/Constraints.cpp | 32 ++++++++++++++------------------ lib/Expr/Expr.cpp | 10 ++++++---- 3 files changed, 22 insertions(+), 24 deletions(-) diff --git a/include/klee/Expr/Expr.h b/include/klee/Expr/Expr.h index df98d892f9..4646b1a3c8 100644 --- a/include/klee/Expr/Expr.h +++ b/include/klee/Expr/Expr.h @@ -304,8 +304,8 @@ class Expr { std::string toString() const; /// Returns the pre-computed hash of the current expression - virtual unsigned hash() const { return hashValue; } - virtual unsigned height() const { return heightValue; } + unsigned hash() const { return hashValue; } + unsigned height() const { return heightValue; } /// (Re)computes the hash of the current expression. /// Returns the hash value. diff --git a/lib/Expr/Constraints.cpp b/lib/Expr/Constraints.cpp index 241c1a329b..ae00a3303c 100644 --- a/lib/Expr/Constraints.cpp +++ b/lib/Expr/Constraints.cpp @@ -423,27 +423,23 @@ Simplificator::simplifyExpr(const constraints_ty &constraints, for (auto &constraint : constraints) { if (const EqExpr *ee = dyn_cast(constraint)) { - ref left = ee->left; - ref right = ee->right; - if (right->height() < left->height()) { - left = ee->right; - right = ee->left; - } - if (isa(ee->left)) { - equalities.insert(std::make_pair(ee->right, ee->left)); - equalitiesParents.insert({ee->right, constraint}); - } else { - equalities.insert(std::make_pair(constraint, Expr::createTrue())); - equalities.insert(std::make_pair(right, left)); - equalitiesParents.insert({constraint, constraint}); - equalitiesParents.insert({right, constraint}); + ref small = ee->left; + ref big = ee->right; + if (!isa(small)) { + auto hr = big->height(), hl = small->height(); + if (hr < hl || (hr == hl && big < small)) + std::swap(small, big); + equalities.emplace(constraint, Expr::createTrue()); + equalitiesParents.emplace(constraint, constraint); } + equalities.emplace(big, small); + equalitiesParents.emplace(big, constraint); } else { - equalities.insert(std::make_pair(constraint, Expr::createTrue())); - equalitiesParents.insert({constraint, constraint}); + equalities.emplace(constraint, Expr::createTrue()); + equalitiesParents.emplace(constraint, constraint); if (const NotExpr *ne = dyn_cast(constraint)) { - equalities.insert(std::make_pair(ne->expr, Expr::createFalse())); - equalitiesParents.insert({ne->expr, constraint}); + equalities.emplace(ne->expr, Expr::createFalse()); + equalitiesParents.emplace(ne->expr, constraint); } } } diff --git a/lib/Expr/Expr.cpp b/lib/Expr/Expr.cpp index c889af5ed4..4f26cb1aaa 100644 --- a/lib/Expr/Expr.cpp +++ b/lib/Expr/Expr.cpp @@ -153,11 +153,13 @@ int Expr::compare(const Expr &b, ExprEquivSet &equivs) const { return 0; Kind ak = getKind(), bk = b.getKind(); - if (ak != bk) - return (ak < bk) ? -1 : 1; + int kc = (ak > bk) - (ak < bk); + if (kc) + return kc; - if (hashValue != b.hashValue) - return (hashValue < b.hashValue) ? -1 : 1; + int hc = (hashValue > b.hashValue) - (hashValue < b.hashValue); + if (hc) + return hc; if (int res = compareContents(b)) return res; From b4fbe6d7fa1deb7e32e0b24c0755f24e0af8bd2c Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Wed, 25 Oct 2023 02:03:49 +0400 Subject: [PATCH 060/103] [fix] Update test --- test/Feature/SymbolicSizes/IntArray.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Feature/SymbolicSizes/IntArray.c b/test/Feature/SymbolicSizes/IntArray.c index 46edaeb836..48ea30e48e 100644 --- a/test/Feature/SymbolicSizes/IntArray.c +++ b/test/Feature/SymbolicSizes/IntArray.c @@ -1,5 +1,5 @@ -// REQUIRES: not-darwin -// Disabling darwin because it overflows stack on CI +// REQUIRES: not-darwin, not-metasmt +// Disabling darwin and metasmt because test has flaky behaviour on CI // RUN: %clang %s -g -emit-llvm %O0opt -c -o %t1.bc // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --use-sym-size-alloc --use-sym-size-li --min-number-elements-li=1 --skip-not-lazy-initialized %t1.bc 2>&1 | FileCheck %s From 65691196c5fddcf22f26d8f24a40d40fda79a3f5 Mon Sep 17 00:00:00 2001 From: Yurii Kostyukov Date: Wed, 25 Oct 2023 11:10:49 +0300 Subject: [PATCH 061/103] [feat] Removed unwanted calls pass --- lib/Module/CMakeLists.txt | 1 + lib/Module/CallRemover.cpp | 36 ++++++++++++++++++++++++++++++++++++ lib/Module/CallSplitter.cpp | 8 ++++---- lib/Module/KModule.cpp | 7 +++++++ lib/Module/Optimize.cpp | 7 ------- lib/Module/Passes.h | 8 ++++++++ 6 files changed, 56 insertions(+), 11 deletions(-) create mode 100644 lib/Module/CallRemover.cpp diff --git a/lib/Module/CMakeLists.txt b/lib/Module/CMakeLists.txt index 42ef35556b..bca27a10ea 100644 --- a/lib/Module/CMakeLists.txt +++ b/lib/Module/CMakeLists.txt @@ -8,6 +8,7 @@ #===------------------------------------------------------------------------===# set(KLEE_MODULE_COMPONENT_SRCS CallSplitter.cpp + CallRemover.cpp Checks.cpp CodeGraphInfo.cpp FunctionAlias.cpp diff --git a/lib/Module/CallRemover.cpp b/lib/Module/CallRemover.cpp new file mode 100644 index 0000000000..d2854ebd47 --- /dev/null +++ b/lib/Module/CallRemover.cpp @@ -0,0 +1,36 @@ +//===-- CallRemover.cpp----------------------------------------------------===// +// +// The KLEE Symbolic Virtual Machine +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "Passes.h" +#include + +namespace klee { + +using namespace llvm; + +char CallRemover::ID; + +bool CallRemover::runOnModule(llvm::Module &M) { + std::vector badFuncs = {"llvm.dbg.declare", "llvm.dbg.label"}; + + for (const auto &f : badFuncs) { + auto Declare = M.getFunction(f); + if (!Declare) + continue; + while (!Declare->use_empty()) { + auto CI = cast(Declare->user_back()); + assert(CI->use_empty() && "deleted function must have void result"); + CI->eraseFromParent(); + } + Declare->eraseFromParent(); + } + + return true; +} +} // namespace klee diff --git a/lib/Module/CallSplitter.cpp b/lib/Module/CallSplitter.cpp index 4c4a71c4f3..a90e17516d 100644 --- a/lib/Module/CallSplitter.cpp +++ b/lib/Module/CallSplitter.cpp @@ -1,5 +1,4 @@ -//===-- CallSplitter.cpp -//-------------------------------------------------------===// +//===-- CallSplitter.cpp --------------------------------------------------===// // // The KLEE Symbolic Virtual Machine // @@ -46,8 +45,9 @@ bool CallSplitter::runOnFunction(Function &F) { if (callInst != firstInst) { fbb = fbb->splitBasicBlock(callInst); } - if (isa(afterCallInst) && - cast(afterCallInst)->isUnconditional()) { + if ((isa(afterCallInst) && + cast(afterCallInst)->isUnconditional()) || + isa(afterCallInst)) { break; } fbb = fbb->splitBasicBlock(afterCallInst); diff --git a/lib/Module/KModule.cpp b/lib/Module/KModule.cpp index 343974b472..ce09edfcc2 100644 --- a/lib/Module/KModule.cpp +++ b/lib/Module/KModule.cpp @@ -117,6 +117,11 @@ cl::opt cl::desc("Split each call in own basic block (default=true)"), cl::init(true), cl::cat(klee::ModuleCat)); +static cl::opt + StripUnwantedCalls("strip-unwanted-calls", + cl::desc("Strip all unwanted calls (llvm.dbg.* stuff)"), + cl::init(false), cl::cat(klee::ModuleCat)); + cl::opt SplitReturns( "split-returns", cl::desc("Split each return in own basic block (default=true)"), @@ -332,6 +337,8 @@ void KModule::optimiseAndPrepare( pm3.add(createScalarizerPass()); pm3.add(new PhiCleanerPass()); pm3.add(new FunctionAliasPass()); + if (StripUnwantedCalls) + pm3.add(new CallRemover()); if (SplitCalls) { pm3.add(new CallSplitter()); } diff --git a/lib/Module/Optimize.cpp b/lib/Module/Optimize.cpp index 77e11b2e2d..cda430bd96 100644 --- a/lib/Module/Optimize.cpp +++ b/lib/Module/Optimize.cpp @@ -72,11 +72,6 @@ static cl::opt cl::desc("Strip debugger symbol info from executable"), cl::init(false), cl::cat(klee::ModuleCat)); -static cl::opt - StripDebugDeclare("strip-debug-declare", - cl::desc("Strip all llvm.dbg.declare intrinsics"), - cl::init(true), cl::cat(klee::ModuleCat)); - static cl::alias A1("S", cl::desc("Alias for --strip-debug"), cl::aliasopt(StripDebug)); @@ -103,8 +98,6 @@ static void AddStandardCompilePasses(legacy::PassManager &PM) { // If the -strip-debug command line option was specified, do it. if (StripDebug) addPass(PM, createStripSymbolsPass(true)); - if (StripDebugDeclare) - addPass(PM, createStripDebugDeclarePass()); addPass(PM, createCFGSimplificationPass()); // Clean up disgusting code addPass(PM, createPromoteMemoryToRegisterPass()); // Kill useless allocas diff --git a/lib/Module/Passes.h b/lib/Module/Passes.h index 76499428df..01983e0b85 100644 --- a/lib/Module/Passes.h +++ b/lib/Module/Passes.h @@ -206,6 +206,14 @@ class CallSplitter : public llvm::FunctionPass { bool runOnFunction(llvm::Function &F) override; }; +/// Remove unwanted calls +class CallRemover : public llvm::ModulePass { +public: + static char ID; + CallRemover() : llvm::ModulePass(ID) {} + bool runOnModule(llvm::Module &M) override; +}; + class ReturnSplitter : public llvm::FunctionPass { public: static char ID; From 1e08227d676aae15c6499b026723fee537a29211 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Wed, 25 Oct 2023 18:09:39 +0400 Subject: [PATCH 062/103] [fix] Filter objects and values in `changeVersion` --- include/klee/Expr/AlphaBuilder.h | 2 +- lib/Expr/AlphaBuilder.cpp | 2 +- lib/Solver/AlphaEquivalenceSolver.cpp | 44 +++++++++++++++++++-------- 3 files changed, 34 insertions(+), 14 deletions(-) diff --git a/include/klee/Expr/AlphaBuilder.h b/include/klee/Expr/AlphaBuilder.h index b56e9563cf..79c09bf457 100644 --- a/include/klee/Expr/AlphaBuilder.h +++ b/include/klee/Expr/AlphaBuilder.h @@ -34,7 +34,7 @@ class AlphaBuilder final : public ExprVisitor { public: AlphaBuilder(ArrayCache &_arrayCache); constraints_ty visitConstraints(constraints_ty cs); - ref visitExpr(ref v); + ref build(ref v); }; } // namespace klee diff --git a/lib/Expr/AlphaBuilder.cpp b/lib/Expr/AlphaBuilder.cpp index fa52783660..b3b98723c9 100644 --- a/lib/Expr/AlphaBuilder.cpp +++ b/lib/Expr/AlphaBuilder.cpp @@ -75,7 +75,7 @@ constraints_ty AlphaBuilder::visitConstraints(constraints_ty cs) { } return result; } -ref AlphaBuilder::visitExpr(ref v) { +ref AlphaBuilder::build(ref v) { ref e = visit(v); reverseExprMap[e] = v; reverseExprMap[Expr::createIsZero(e)] = Expr::createIsZero(v); diff --git a/lib/Solver/AlphaEquivalenceSolver.cpp b/lib/Solver/AlphaEquivalenceSolver.cpp index 4f29759cc3..b8e5e1f8b7 100644 --- a/lib/Solver/AlphaEquivalenceSolver.cpp +++ b/lib/Solver/AlphaEquivalenceSolver.cpp @@ -55,10 +55,14 @@ class AlphaEquivalenceSolver : public SolverImpl { void notifyStateTermination(std::uint32_t id); ValidityCore changeVersion(const ValidityCore &validityCore, const ExprHashMap> &reverse); - const std::vector + std::vector changeVersion(const std::vector &objects, const ArrayCache::ArrayHashMap &reverse); Assignment + changeVersion(const std::vector &objects, + const std::vector> &values, + const ArrayCache::ArrayHashMap &reverse); + Assignment changeVersion(const Assignment &a, const ArrayCache::ArrayHashMap &reverse); ref changeVersion(ref res, @@ -80,12 +84,29 @@ AlphaEquivalenceSolver::changeVersion(const ValidityCore &validityCore, return reverseValidityCore; } -const std::vector AlphaEquivalenceSolver::changeVersion( +Assignment AlphaEquivalenceSolver::changeVersion( + const std::vector &objects, + const std::vector> &values, + const ArrayCache::ArrayHashMap &reverse) { + std::vector reverseObjects; + std::vector> reverseValues; + for (size_t i = 0; i < objects.size(); i++) { + if (reverse.count(objects.at(i)) != 0) { + reverseObjects.push_back(reverse.at(objects.at(i))); + reverseValues.push_back(values.at(i)); + } + } + return Assignment(reverseObjects, reverseValues); +} + +std::vector AlphaEquivalenceSolver::changeVersion( const std::vector &objects, const ArrayCache::ArrayHashMap &reverse) { std::vector reverseObjects; - for (auto it : objects) { - reverseObjects.push_back(reverse.at(it)); + for (size_t i = 0; i < objects.size(); i++) { + if (reverse.count(objects.at(i)) != 0) { + reverseObjects.push_back(reverse.at(objects.at(i))); + } } return reverseObjects; } @@ -95,8 +116,7 @@ Assignment AlphaEquivalenceSolver::changeVersion( const ArrayCache::ArrayHashMap &reverse) { std::vector objects = a.keys(); std::vector> values = a.values(); - objects = changeVersion(objects, reverse); - return Assignment(objects, values); + return changeVersion(objects, values, reverse); } ref @@ -136,7 +156,7 @@ bool AlphaEquivalenceSolver::computeValidity(const Query &query, PartialValidity &result) { AlphaBuilder builder(arrayCache); constraints_ty alphaQuery = builder.visitConstraints(query.constraints.cs()); - ref alphaQueryExpr = builder.visitExpr(query.expr); + ref alphaQueryExpr = builder.build(query.expr); return solver->impl->computeValidity( Query(ConstraintSet(alphaQuery, {}, {}), alphaQueryExpr, query.id), result); @@ -145,7 +165,7 @@ bool AlphaEquivalenceSolver::computeValidity(const Query &query, bool AlphaEquivalenceSolver::computeTruth(const Query &query, bool &isValid) { AlphaBuilder builder(arrayCache); constraints_ty alphaQuery = builder.visitConstraints(query.constraints.cs()); - ref alphaQueryExpr = builder.visitExpr(query.expr); + ref alphaQueryExpr = builder.build(query.expr); return solver->impl->computeTruth( Query(ConstraintSet(alphaQuery, {}, {}), alphaQueryExpr, query.id), isValid); @@ -155,7 +175,7 @@ bool AlphaEquivalenceSolver::computeValue(const Query &query, ref &result) { AlphaBuilder builder(arrayCache); constraints_ty alphaQuery = builder.visitConstraints(query.constraints.cs()); - ref alphaQueryExpr = builder.visitExpr(query.expr); + ref alphaQueryExpr = builder.build(query.expr); return solver->impl->computeValue( Query(ConstraintSet(alphaQuery, {}, {}), alphaQueryExpr, query.id), result); @@ -166,7 +186,7 @@ bool AlphaEquivalenceSolver::computeInitialValues( std::vector> &values, bool &hasSolution) { AlphaBuilder builder(arrayCache); constraints_ty alphaQuery = builder.visitConstraints(query.constraints.cs()); - ref alphaQueryExpr = builder.visitExpr(query.expr); + ref alphaQueryExpr = builder.build(query.expr); const std::vector newObjects = changeVersion(objects, builder.alphaArrayMap); @@ -183,7 +203,7 @@ bool AlphaEquivalenceSolver::check(const Query &query, AlphaBuilder builder(arrayCache); constraints_ty alphaQuery = builder.visitConstraints(query.constraints.cs()); - ref alphaQueryExpr = builder.visitExpr(query.expr); + ref alphaQueryExpr = builder.build(query.expr); result = createAlphaVersion(result, builder); if (!solver->impl->check( Query(ConstraintSet(alphaQuery, {}, {}), alphaQueryExpr, query.id), @@ -201,7 +221,7 @@ bool AlphaEquivalenceSolver::computeValidityCore(const Query &query, AlphaBuilder builder(arrayCache); constraints_ty alphaQuery = builder.visitConstraints(query.constraints.cs()); - ref alphaQueryExpr = builder.visitExpr(query.expr); + ref alphaQueryExpr = builder.build(query.expr); if (!solver->impl->computeValidityCore( Query(ConstraintSet(alphaQuery, {}, {}), alphaQueryExpr, query.id), validityCore, isValid)) { From 200db1d16c756388460311452ce7567087bd59ec Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Thu, 26 Oct 2023 20:19:14 +0400 Subject: [PATCH 063/103] [fix] Clean memory operations --- include/klee/ADT/SparseStorage.h | 4 ++-- lib/Core/Memory.cpp | 11 ----------- lib/Solver/Z3Builder.cpp | 2 +- 3 files changed, 3 insertions(+), 14 deletions(-) diff --git a/include/klee/ADT/SparseStorage.h b/include/klee/ADT/SparseStorage.h index 638119ee79..a06f63391f 100644 --- a/include/klee/ADT/SparseStorage.h +++ b/include/klee/ADT/SparseStorage.h @@ -79,7 +79,7 @@ class SparseStorage { } bool operator==(const SparseStorage &another) const { - return defaultValue == another.defaultValue && compare(another) == 0; + return eq(defaultValue, another.defaultValue) && compare(another) == 0; } bool operator!=(const SparseStorage &another) const { @@ -131,7 +131,7 @@ class SparseStorage { void reset(ValueType newDefault) { defaultValue = newDefault; - internalStorage.clear(); + reset(); } void print(llvm::raw_ostream &os, Density) const; diff --git a/lib/Core/Memory.cpp b/lib/Core/Memory.cpp index 4e364ef27d..16a49c6938 100644 --- a/lib/Core/Memory.cpp +++ b/lib/Core/Memory.cpp @@ -183,13 +183,6 @@ ref ObjectState::read8(ref offset) const { } void ObjectState::write8(unsigned offset, uint8_t value) { - auto byte = knownSymbolics.load(offset); - if (byte) { - auto ce = dyn_cast(byte); - if (ce && ce->getZExtValue(8) == value) { - return; - } - } knownSymbolics.store(offset, ConstantExpr::create(value, Expr::Int8)); unflushedMask.store(offset, true); } @@ -199,10 +192,6 @@ void ObjectState::write8(unsigned offset, ref value) { if (ConstantExpr *CE = dyn_cast(value)) { write8(offset, (uint8_t)CE->getZExtValue(8)); } else { - auto byte = knownSymbolics.load(offset); - if (byte && byte == value) { - return; - } knownSymbolics.store(offset, value); unflushedMask.store(offset, true); } diff --git a/lib/Solver/Z3Builder.cpp b/lib/Solver/Z3Builder.cpp index c26d8fb372..b26ec1e75c 100644 --- a/lib/Solver/Z3Builder.cpp +++ b/lib/Solver/Z3Builder.cpp @@ -284,7 +284,7 @@ Z3ASTHandle Z3Builder::getInitialArray(const Array *root) { } constant_array_assertions[root] = std::move(array_assertions); } else { - for (auto [index, value] : source->constantValues.storage()) { + for (auto &[index, value] : source->constantValues.storage()) { int width_out; Z3ASTHandle array_value = construct(value, &width_out); assert(width_out == (int)root->getRange() && From 0cb981da5b9de4ddf57c37f8d772629bf3fc1310 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Fri, 27 Oct 2023 15:58:08 +0400 Subject: [PATCH 064/103] [fix] Fix `AlphaEquivalenceSolver` --- include/klee/Expr/AlphaBuilder.h | 1 + lib/Solver/AlphaEquivalenceSolver.cpp | 15 ++++++------- test/regression/2023-27-10-SimpleComparison.c | 21 +++++++++++++++++++ 3 files changed, 28 insertions(+), 9 deletions(-) create mode 100644 test/regression/2023-27-10-SimpleComparison.c diff --git a/include/klee/Expr/AlphaBuilder.h b/include/klee/Expr/AlphaBuilder.h index 79c09bf457..9095c489e2 100644 --- a/include/klee/Expr/AlphaBuilder.h +++ b/include/klee/Expr/AlphaBuilder.h @@ -35,6 +35,7 @@ class AlphaBuilder final : public ExprVisitor { AlphaBuilder(ArrayCache &_arrayCache); constraints_ty visitConstraints(constraints_ty cs); ref build(ref v); + const Array *buildArray(const Array *arr) { return visitArray(arr); } }; } // namespace klee diff --git a/lib/Solver/AlphaEquivalenceSolver.cpp b/lib/Solver/AlphaEquivalenceSolver.cpp index b8e5e1f8b7..2c5df35fdb 100644 --- a/lib/Solver/AlphaEquivalenceSolver.cpp +++ b/lib/Solver/AlphaEquivalenceSolver.cpp @@ -57,7 +57,7 @@ class AlphaEquivalenceSolver : public SolverImpl { const ExprHashMap> &reverse); std::vector changeVersion(const std::vector &objects, - const ArrayCache::ArrayHashMap &reverse); + AlphaBuilder &builder); Assignment changeVersion(const std::vector &objects, const std::vector> &values, @@ -99,14 +99,12 @@ Assignment AlphaEquivalenceSolver::changeVersion( return Assignment(reverseObjects, reverseValues); } -std::vector AlphaEquivalenceSolver::changeVersion( - const std::vector &objects, - const ArrayCache::ArrayHashMap &reverse) { +std::vector +AlphaEquivalenceSolver::changeVersion(const std::vector &objects, + AlphaBuilder &builder) { std::vector reverseObjects; for (size_t i = 0; i < objects.size(); i++) { - if (reverse.count(objects.at(i)) != 0) { - reverseObjects.push_back(reverse.at(objects.at(i))); - } + reverseObjects.push_back(builder.buildArray(objects.at(i))); } return reverseObjects; } @@ -187,8 +185,7 @@ bool AlphaEquivalenceSolver::computeInitialValues( AlphaBuilder builder(arrayCache); constraints_ty alphaQuery = builder.visitConstraints(query.constraints.cs()); ref alphaQueryExpr = builder.build(query.expr); - const std::vector newObjects = - changeVersion(objects, builder.alphaArrayMap); + const std::vector newObjects = changeVersion(objects, builder); if (!solver->impl->computeInitialValues( Query(ConstraintSet(alphaQuery, {}, {}), alphaQueryExpr, query.id), diff --git a/test/regression/2023-27-10-SimpleComparison.c b/test/regression/2023-27-10-SimpleComparison.c new file mode 100644 index 0000000000..def7647d8c --- /dev/null +++ b/test/regression/2023-27-10-SimpleComparison.c @@ -0,0 +1,21 @@ +// RUN: %clang %s -emit-llvm %O0opt -c -o %t.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --debug-assignment-validating-solver=false --use-fast-cex-solver=false --use-cex-cache=false --use-branch-cache=false --use-alpha-equivalence=true --use-independent-solver=false --use-concretizing-solver=false --output-dir=%t.klee-out --skip-not-symbolic-objects --use-timestamps=false --use-guided-search=none %t.bc + +#include + +struct Node { + int *x; +}; + +int main() { + struct Node *nodeA; + struct Node *nodeB; + klee_make_symbolic(&nodeA, sizeof(nodeA), "nodeA"); + klee_make_symbolic(&nodeB, sizeof(nodeB), "nodeB"); + + if (nodeA && nodeB && nodeA == nodeB && (*nodeA->x * 2) != (*nodeA->x + *nodeB->x)) { + assert(0); + } + return 0; +} From 0a8018515934c1b3833880ee43005e8bab8c76e9 Mon Sep 17 00:00:00 2001 From: Yurii Kostyukov Date: Fri, 27 Oct 2023 13:00:44 +0300 Subject: [PATCH 065/103] [fix] Halt when LLVM passes already proved unreachability --- lib/Core/Executor.cpp | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index 49df803c89..0cc740787b 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -6672,14 +6672,19 @@ void Executor::runFunctionAsMain(Function *f, int argc, char **argv, } else { /* Find all calls to function specified in .prp file * and combine them to single target forest */ - KFunction *kEntryFunction = kmodule->functionMap.at(f); - ref forest = new TargetForest(kEntryFunction); - auto kfunction = kmodule->functionNameMap.at(FunctionCallReproduce); - KBlock *kCallBlock = kfunction->entryKBlock; - forest->add(ReproduceErrorTarget::create( - {ReachWithError::Reachable}, "", - ErrorLocation(kCallBlock->getFirstInstruction()), kCallBlock)); - prepTargets.emplace(kEntryFunction, forest); + auto kfIt = kmodule->functionNameMap.find(FunctionCallReproduce); + if (kfIt == kmodule->functionNameMap.end()) { + klee_warning("%s was eliminated by LLVM passes, so it is unreachable", + FunctionCallReproduce.c_str()); + } else { + auto kCallBlock = kfIt->second->entryKBlock; + KFunction *kEntryFunction = kmodule->functionMap.at(f); + ref forest = new TargetForest(kEntryFunction); + forest->add(ReproduceErrorTarget::create( + {ReachWithError::Reachable}, "", + ErrorLocation(kCallBlock->getFirstInstruction()), kCallBlock)); + prepTargets.emplace(kEntryFunction, forest); + } } if (prepTargets.empty()) { From 803fabc14d369f38de1dde37aba595d711249e7f Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Mon, 30 Oct 2023 19:08:46 +0400 Subject: [PATCH 066/103] [chore] Update version and `README.md` --- CMakeLists.txt | 8 ++++---- README.md | 28 +++++----------------------- 2 files changed, 9 insertions(+), 27 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 18d853e189..7f6bcf2697 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,16 +17,16 @@ project(KLEE CXX C) # Project version ############################################################################### set(KLEE_VERSION_MAJOR 3) -set(KLEE_VERSION_MINOR 0-utbot) +set(KLEE_VERSION_MINOR 0) set(KLEE_VERSION "${KLEE_VERSION_MAJOR}.${KLEE_VERSION_MINOR}") # If a patch is needed, we can add KLEE_VERSION_PATCH # set(KLEE_VERSION_PATCH 0) # set(KLEE_VERSION "${KLEE_VERSION_MAJOR}.${KLEE_VERSION_MINOR}.${KLEE_VERSION_PATCH}") -message(STATUS "KLEE version ${KLEE_VERSION}") -set(PACKAGE_STRING "\"KLEE ${KLEE_VERSION}\"") -set(PACKAGE_URL "\"https://klee.github.io\"") +message(STATUS "KLEEF version ${KLEE_VERSION}") +set(PACKAGE_STRING "\"KLEEF ${KLEE_VERSION}\"") +set(PACKAGE_URL "\"https://toolchain-labs.com/projects/kleef.html\"") ################################################################################ # Sanity check - Disallow building in source. diff --git a/README.md b/README.md index 9aefd2c9bf..7038b9a745 100644 --- a/README.md +++ b/README.md @@ -1,27 +1,9 @@ -KLEE Symbolic Virtual Machine +KLEEF Symbolic Virtual Machine ============================= -[![Build Status](https://github.com/klee/klee/workflows/CI/badge.svg)](https://github.com/klee/klee/actions?query=workflow%3ACI) -[![Build Status](https://api.cirrus-ci.com/github/klee/klee.svg)](https://cirrus-ci.com/github/klee/klee) -[![Coverage](https://codecov.io/gh/klee/klee/branch/master/graph/badge.svg)](https://codecov.io/gh/klee/klee) +[![Build Status](https://github.com/UnitTestBot/klee/workflows/CI/badge.svg)](https://github.com/UnitTestBot/klee/actions?query=workflow%3ACI) +[![Coverage](https://codecov.io/gh/UnitTestBot/klee/branch/main/graph/badge.svg)](https://codecov.io/gh/UnitTestBot/klee) -`KLEE` is a symbolic virtual machine built on top of the LLVM compiler -infrastructure. Currently, there are two primary components: - 1. The core symbolic virtual machine engine; this is responsible for - executing LLVM bitcode modules with support for symbolic - values. This is comprised of the code in lib/. - - 2. A POSIX/Linux emulation layer oriented towards supporting uClibc, - with additional support for making parts of the operating system - environment symbolic. - -Additionally, there is a simple library for replaying computed inputs -on native code (for closed programs). There is also a more complicated -infrastructure for replaying the inputs generated for the POSIX/Linux -emulation layer, which handles running native programs in an -environment that matches a computed test input, including setting up -files, pipes, environment variables, and passing command line -arguments. - -For further information, see the [webpage](http://klee.github.io/). +`KLEEF`` is a complete overhaul of the KLEE symbolic execution engine for LLVM, fine-tuned for a robust analysis of industrial C/C++ code. +For further information, see the [webpage](https://toolchain-labs.com/projects/kleef.html). From 8865af3581b52ec0660953ee70e63d3cb3f657d7 Mon Sep 17 00:00:00 2001 From: Yurii Kostyukov Date: Tue, 31 Oct 2023 12:31:24 +0300 Subject: [PATCH 067/103] [fix] Improved call remover --- lib/Module/CallRemover.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/Module/CallRemover.cpp b/lib/Module/CallRemover.cpp index d2854ebd47..7c94f6d26e 100644 --- a/lib/Module/CallRemover.cpp +++ b/lib/Module/CallRemover.cpp @@ -17,7 +17,8 @@ using namespace llvm; char CallRemover::ID; bool CallRemover::runOnModule(llvm::Module &M) { - std::vector badFuncs = {"llvm.dbg.declare", "llvm.dbg.label"}; + std::vector badFuncs = {"llvm.dbg.declare", "llvm.dbg.label", + "llvm.dbg.value"}; for (const auto &f : badFuncs) { auto Declare = M.getFunction(f); From 06bfbc03049fe16440e5a5cc9ad39e107c6b1b3a Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Wed, 1 Nov 2023 19:17:41 +0400 Subject: [PATCH 068/103] [feat] Add `OptimizeAggressive` option --- lib/Module/Optimize.cpp | 75 +++++++++++-------- ...r.3.ufo.UNBOUNDED.pals+Problem12_label00.c | 2 +- .../pals_floodmax.5.2.ufo.BOUNDED-10.pals.c | 2 +- .../2023-10-04-email_spec0_product16.cil.c | 2 +- ...ChenFlurMukhopadhyay-2012SAS-Fig1-alloca.c | 2 +- test/regression/2023-10-06-Dubois-015.c | 2 +- test/regression/2023-10-13-kbfiltr.i.cil-2.c | 2 +- test/regression/2023-10-16-CostasArray-17.c | 21 ++++-- 8 files changed, 64 insertions(+), 44 deletions(-) diff --git a/lib/Module/Optimize.cpp b/lib/Module/Optimize.cpp index cda430bd96..e087ed2208 100644 --- a/lib/Module/Optimize.cpp +++ b/lib/Module/Optimize.cpp @@ -79,6 +79,11 @@ static cl::opt DeleteDeadLoops("delete-dead-loops", cl::desc("Use LoopDeletionPass"), cl::init(true), cl::cat(klee::ModuleCat)); +static cl::opt + OptimizeAggressive("optimize-aggressive", + cl::desc("Use aggressive optimization passes"), + cl::init(true), cl::cat(klee::ModuleCat)); + // A utility function that adds a pass to the pass manager but will also add // a verifier pass after if we're supposed to verify. static inline void addPass(legacy::PassManager &PM, Pass *P) { @@ -149,43 +154,12 @@ static void AddStandardCompilePasses(legacy::PassManager &PM) { addPass(PM, createInstructionCombiningPass()); addPass(PM, createDeadStoreEliminationPass()); // Delete dead stores - addPass(PM, createAggressiveDCEPass()); // Delete dead instructions addPass(PM, createCFGSimplificationPass()); // Merge & remove BBs addPass(PM, createStripDeadPrototypesPass()); // Get rid of dead prototypes addPass(PM, createConstantMergePass()); // Merge dup global constants } -/// Optimize - Perform link time optimizations. This will run the scalar -/// optimizations, any loaded plugin-optimization modules, and then the -/// inter-procedural optimizations if applicable. -void Optimize(Module *M, llvm::ArrayRef preservedFunctions) { - - // Instantiate the pass manager to organize the passes. - legacy::PassManager Passes; - - // If we're verifying, start off with a verification pass. - if (VerifyEach) - Passes.add(createVerifierPass()); - - // DWD - Run the opt standard pass list as well. - AddStandardCompilePasses(Passes); - - // Now that composite has been compiled, scan through the module, looking - // for a main function. If main is defined, mark all other functions - // internal. - if (!DisableInternalize) { - auto PreserveFunctions = [=](const GlobalValue &GV) { - StringRef GVName = GV.getName(); - - for (const char *fun : preservedFunctions) - if (GVName.equals(fun)) - return true; - - return false; - }; - ModulePass *pass = createInternalizePass(PreserveFunctions); - addPass(Passes, pass); - } +static void AddNonStandardCompilePasses(legacy::PassManager &Passes) { // Propagate constants at call sites into the functions they call. This // opens opportunities for globalopt (and inlining) by substituting function @@ -257,6 +231,43 @@ void Optimize(Module *M, llvm::ArrayRef preservedFunctions) { addPass(Passes, createCFGSimplificationPass()); addPass(Passes, createAggressiveDCEPass()); addPass(Passes, createGlobalDCEPass()); +} + +/// Optimize - Perform link time optimizations. This will run the scalar +/// optimizations, any loaded plugin-optimization modules, and then the +/// inter-procedural optimizations if applicable. +void Optimize(Module *M, llvm::ArrayRef preservedFunctions) { + + // Instantiate the pass manager to organize the passes. + legacy::PassManager Passes; + + // If we're verifying, start off with a verification pass. + if (VerifyEach) + Passes.add(createVerifierPass()); + + // DWD - Run the opt standard pass list as well. + AddStandardCompilePasses(Passes); + + // Now that composite has been compiled, scan through the module, looking + // for a main function. If main is defined, mark all other functions + // internal. + if (!DisableInternalize) { + auto PreserveFunctions = [=](const GlobalValue &GV) { + StringRef GVName = GV.getName(); + + for (const char *fun : preservedFunctions) + if (GVName.equals(fun)) + return true; + + return false; + }; + ModulePass *pass = createInternalizePass(PreserveFunctions); + addPass(Passes, pass); + } + + if (OptimizeAggressive) { + AddNonStandardCompilePasses(Passes); + } // Run our queue of passes all at once now, efficiently. Passes.run(*M); diff --git a/test/Industry/pals_lcr.3.ufo.UNBOUNDED.pals+Problem12_label00.c b/test/Industry/pals_lcr.3.ufo.UNBOUNDED.pals+Problem12_label00.c index 7b90ea5b2d..0c49afc42e 100644 --- a/test/Industry/pals_lcr.3.ufo.UNBOUNDED.pals+Problem12_label00.c +++ b/test/Industry/pals_lcr.3.ufo.UNBOUNDED.pals+Problem12_label00.c @@ -1,7 +1,7 @@ // REQUIRES: geq-llvm-14.0 // RUN: %clang %s -emit-llvm %O0opt -g -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --track-coverage=branches --delete-dead-loops=false --emit-all-errors --mock-all-externals --use-forked-solver=false --optimize --skip-not-lazy-initialized --output-source=false --output-stats=true --output-istats=true -istats-write-interval=3s --use-sym-size-alloc=true --cex-cache-validity-cores --symbolic-allocation-threshold=8192 --cover-on-the-fly=false --delay-cover-on-the-fly=400000 --only-output-states-covering-new --dump-states-on-halt=true --search=dfs --search=random-state --use-iterative-deepening-search=max-cycles --max-cycles=4 %t1.bc +// RUN: %klee --output-dir=%t.klee-out --optimize-aggressive=false --track-coverage=branches --delete-dead-loops=false --emit-all-errors --mock-all-externals --use-forked-solver=false --optimize --skip-not-lazy-initialized --output-source=false --output-stats=true --output-istats=true -istats-write-interval=3s --use-sym-size-alloc=true --cex-cache-validity-cores --symbolic-allocation-threshold=8192 --cover-on-the-fly=false --delay-cover-on-the-fly=400000 --only-output-states-covering-new --dump-states-on-halt=true --search=dfs --search=random-state --use-iterative-deepening-search=max-cycles --max-cycles=4 %t1.bc // RUN: %klee-stats --print-columns 'BCov(%)' --table-format=csv %t.klee-out > %t.stats // RUN: FileCheck -input-file=%t.stats %s diff --git a/test/Solver/pals_floodmax.5.2.ufo.BOUNDED-10.pals.c b/test/Solver/pals_floodmax.5.2.ufo.BOUNDED-10.pals.c index 4dd74f1d3c..4341173c1d 100644 --- a/test/Solver/pals_floodmax.5.2.ufo.BOUNDED-10.pals.c +++ b/test/Solver/pals_floodmax.5.2.ufo.BOUNDED-10.pals.c @@ -1,7 +1,7 @@ // REQUIRES: z3 // RUN: %clang %s -emit-llvm %O0opt -g -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --use-forked-solver=false --solver-backend=z3-tree --max-solvers-approx-tree-inc=16 -max-memory=6008 --optimize --skip-not-lazy-initialized -output-source=false --output-stats=false --use-sym-size-alloc=true --cex-cache-validity-cores --symbolic-allocation-threshold=8192 --function-call-reproduce=reach_error -dump-states-on-halt=true -exit-on-error-type=Assert --search=dfs -max-instructions=6000 --debug-crosscheck-core-solver=z3 --debug-z3-validate-models --debug-assignment-validating-solver --use-cex-cache=false %t1.bc 2>&1 | FileCheck -check-prefix=CHECK-VERDICT %s +// RUN: %klee --output-dir=%t.klee-out --use-forked-solver=false --solver-backend=z3-tree --max-solvers-approx-tree-inc=16 --optimize-aggressive=false --track-coverage=branches -max-memory=6008 --optimize --skip-not-lazy-initialized -output-source=false --output-stats=false --use-sym-size-alloc=true --cex-cache-validity-cores --symbolic-allocation-threshold=8192 --function-call-reproduce=reach_error -dump-states-on-halt=true -exit-on-error-type=Assert --search=dfs -max-instructions=6000 --debug-crosscheck-core-solver=z3 --debug-z3-validate-models --debug-assignment-validating-solver --use-cex-cache=false %t1.bc 2>&1 | FileCheck -check-prefix=CHECK-VERDICT %s // CHECK-VERDICT: KLEE: done: total instructions = 6000 #include "klee-test-comp.c" diff --git a/test/regression/2023-10-04-email_spec0_product16.cil.c b/test/regression/2023-10-04-email_spec0_product16.cil.c index e407b7bbb2..291d48229c 100644 --- a/test/regression/2023-10-04-email_spec0_product16.cil.c +++ b/test/regression/2023-10-04-email_spec0_product16.cil.c @@ -1,6 +1,6 @@ // RUN: %clang -Wno-everything %s -emit-llvm %O0opt -g -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --use-forked-solver=false --max-memory=6008 --optimize --skip-not-lazy-initialized --istats-write-interval=90s --exit-on-error-type=Assert --search=dfs --max-time=10s %t1.bc 2>&1 | FileCheck -check-prefix=CHECK %s +// RUN: %klee --output-dir=%t.klee-out --use-forked-solver=false --optimize-aggressive=false --track-coverage=branches --max-memory=6008 --optimize --skip-not-lazy-initialized --istats-write-interval=90s --exit-on-error-type=Assert --search=dfs --max-time=10s %t1.bc 2>&1 | FileCheck -check-prefix=CHECK %s // RUN find %t.klee-out -type f -name "*.assert.err" | sed 's/assert\.err/ktest/' | xargs %ktest-tool | FileCheck -check-prefix=CHECK-TEST %s // CHECK-TEST-NOT: object 20 diff --git a/test/regression/2023-10-06-ChenFlurMukhopadhyay-2012SAS-Fig1-alloca.c b/test/regression/2023-10-06-ChenFlurMukhopadhyay-2012SAS-Fig1-alloca.c index d08c61d74a..25d674dcb7 100644 --- a/test/regression/2023-10-06-ChenFlurMukhopadhyay-2012SAS-Fig1-alloca.c +++ b/test/regression/2023-10-06-ChenFlurMukhopadhyay-2012SAS-Fig1-alloca.c @@ -1,6 +1,6 @@ // RUN: %clang -Wno-everything %s -emit-llvm %O0opt -g -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --optimize=true --delete-dead-loops=false --use-forked-solver=false -max-memory=6008 --cex-cache-validity-cores --only-output-states-covering-new=true --dump-states-on-halt=true %t1.bc 2>&1 | FileCheck -check-prefix=CHECK %s +// RUN: %klee --output-dir=%t.klee-out --optimize-aggressive=false --track-coverage=branches --optimize=true --delete-dead-loops=false --use-forked-solver=false -max-memory=6008 --cex-cache-validity-cores --only-output-states-covering-new=true --dump-states-on-halt=true %t1.bc 2>&1 | FileCheck -check-prefix=CHECK %s #include "klee-test-comp.c" diff --git a/test/regression/2023-10-06-Dubois-015.c b/test/regression/2023-10-06-Dubois-015.c index fccb9acd93..c782d694b5 100644 --- a/test/regression/2023-10-06-Dubois-015.c +++ b/test/regression/2023-10-06-Dubois-015.c @@ -1,6 +1,6 @@ // RUN: %clang -Wno-everything %s -emit-llvm %O0opt -g -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --optimize=true --emit-all-errors --only-output-states-covering-new=true --dump-states-on-halt=true --search=dfs %t1.bc 2>&1 | FileCheck -check-prefix=CHECK %s +// RUN: %klee --output-dir=%t.klee-out --optimize-aggressive=false --track-coverage=branches --optimize=true --emit-all-errors --only-output-states-covering-new=true --dump-states-on-halt=true --search=dfs %t1.bc 2>&1 | FileCheck -check-prefix=CHECK %s #include "klee-test-comp.c" diff --git a/test/regression/2023-10-13-kbfiltr.i.cil-2.c b/test/regression/2023-10-13-kbfiltr.i.cil-2.c index 8a3d658124..d46b853526 100644 --- a/test/regression/2023-10-13-kbfiltr.i.cil-2.c +++ b/test/regression/2023-10-13-kbfiltr.i.cil-2.c @@ -1,7 +1,7 @@ // REQUIRES: geq-llvm-14.0 // RUN: %clang -Wno-everything %s -emit-llvm %O0opt -g -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --optimize=true --mock-all-externals --external-calls=all --use-forked-solver=false --max-memory=6008 --skip-not-lazy-initialized --istats-write-interval=90s --use-sym-size-alloc=true --cex-cache-validity-cores --symbolic-allocation-threshold=8192 --write-kqueries --write-xml-tests --only-output-states-covering-new=true --dump-states-on-halt=true --emit-all-errors=true --search=bfs %t1.bc +// RUN: %klee --output-dir=%t.klee-out --optimize-aggressive=false --track-coverage=branches --optimize=true --mock-all-externals --external-calls=all --use-forked-solver=false --max-memory=6008 --skip-not-lazy-initialized --istats-write-interval=90s --use-sym-size-alloc=true --cex-cache-validity-cores --symbolic-allocation-threshold=8192 --write-kqueries --write-xml-tests --only-output-states-covering-new=true --dump-states-on-halt=true --emit-all-errors=true --search=bfs %t1.bc // RUN: test -f %t.klee-out/test000023_1.xml #include "klee-test-comp.c" diff --git a/test/regression/2023-10-16-CostasArray-17.c b/test/regression/2023-10-16-CostasArray-17.c index 0321c71828..ed1651a15d 100644 --- a/test/regression/2023-10-16-CostasArray-17.c +++ b/test/regression/2023-10-16-CostasArray-17.c @@ -1,12 +1,21 @@ // RUN: %clang -Wno-everything %s -emit-llvm %O0opt -g -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --track-coverage=branches --optimize=true --emit-all-errors --only-output-states-covering-new=true --dump-states-on-halt=true --search=dfs %t1.bc -// RUN: %klee-stats --print-columns 'ICov(%),BCov(%)' --table-format=csv %t.klee-out > %t.stats -// RUN: FileCheck -input-file=%t.stats %s +// RUN: %klee --output-dir=%t.klee-out --optimize-aggressive --track-coverage=branches --optimize=true --emit-all-errors --only-output-states-covering-new=true --dump-states-on-halt=true --search=dfs %t1.bc +// RUN: %klee-stats --print-columns ' Branches,ICov(%),BCov(%)' --table-format=csv %t.klee-out > %t.stats +// RUN: FileCheck --input-file=%t.stats --check-prefix=CHECK-AGGRESSIVE %s -// Branch coverage 100%, and instruction coverage is very small: -// CHECK: ICov(%),BCov(%) -// CHECK-NEXT: {{(0\.[0-9][0-9])}},100.00 +// Branch coverage 100%, the number of branches is 1: +// CHECK-AGGRESSIVE: Branches,ICov(%),BCov(%) +// CHECK-AGGRESSIVE-NEXT: 1,{{(0\.[0-9][0-9])}},100.00 + +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --optimize-aggressive=false --track-coverage=branches --optimize=true --emit-all-errors --only-output-states-covering-new=true --dump-states-on-halt=true --search=dfs %t1.bc +// RUN: %klee-stats --print-columns ' Branches,ICov(%),BCov(%)' --table-format=csv %t.klee-out > %t.stats +// RUN: FileCheck --input-file=%t.stats --check-prefix=CHECK-NOT-AGGRESSIVE %s + +// Branch coverage 50%, but the number of branches is 2: +// CHECK-NOT-AGGRESSIVE: Branches,ICov(%),BCov(%) +// CHECK-NOT-AGGRESSIVE-NEXT: 2,{{(0\.[0-9][0-9])}},50.00 #include "klee-test-comp.c" From 1a472d97c55eb504481fb9ecc47e8c82d6d47c85 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Thu, 2 Nov 2023 05:15:39 +0400 Subject: [PATCH 069/103] [feat] Getting the performance/memory consumption balance in `DisjointSetUnion` --- include/klee/ADT/DisjointSetUnion.h | 48 ++++++++++--------- include/klee/ADT/Either.h | 23 ++++++++- .../klee/Expr/IndependentConstraintSetUnion.h | 4 +- include/klee/Expr/IndependentSet.h | 16 ++++++- include/klee/Expr/Symcrete.h | 2 + lib/Expr/IndependentConstraintSetUnion.cpp | 14 +++--- 6 files changed, 73 insertions(+), 34 deletions(-) diff --git a/include/klee/ADT/DisjointSetUnion.h b/include/klee/ADT/DisjointSetUnion.h index b479ca0765..41c1a0296b 100644 --- a/include/klee/ADT/DisjointSetUnion.h +++ b/include/klee/ADT/DisjointSetUnion.h @@ -24,21 +24,29 @@ namespace klee { using ExprEitherSymcrete = either; template , + typename PRED = std::equal_to, typename CMP = std::less> class DisjointSetUnion { +public: + using internal_storage_ty = std::unordered_set; + using disjoint_sets_ty = + std::unordered_map, HASH, PRED>; + using iterator = typename internal_storage_ty::iterator; + protected: - PersistentMap parent; - PersistentSet roots; - PersistentMap rank; + std::unordered_map parent; + std::set roots; + std::unordered_map rank; - PersistentSet internalStorage; - PersistentMap, CMP> disjointSets; + std::unordered_set internalStorage; + std::unordered_map, HASH, PRED> disjointSets; ValueType find(const ValueType &v) { // findparent assert(parent.find(v) != parent.end()); if (v == parent.at(v)) return v; - parent.replace({v, find(parent.at(v))}); + parent.insert_or_assign(v, find(parent.at(v))); return parent.at(v); } @@ -60,15 +68,15 @@ class DisjointSetUnion { if (rank.at(a) < rank.at(b)) { std::swap(a, b); } - parent.replace({b, a}); + parent.insert_or_assign(b, a); if (rank.at(a) == rank.at(b)) { - rank.replace({a, rank.at(a) + 1}); + rank.insert_or_assign(a, rank.at(a) + 1); } - roots.remove(b); - disjointSets.replace( - {a, SetType::merge(disjointSets.at(a), disjointSets.at(b))}); - disjointSets.remove(b); + roots.erase(b); + disjointSets.insert_or_assign( + a, SetType::merge(disjointSets.at(a), disjointSets.at(b))); + disjointSets.erase(b); } bool areJoined(const ValueType &i, const ValueType &j) const { @@ -76,10 +84,6 @@ class DisjointSetUnion { } public: - using internalStorage_ty = PersistentSet; - using disjointSets_ty = ImmutableMap, CMP>; - using iterator = typename internalStorage_ty::iterator; - iterator begin() const { return internalStorage.begin(); } iterator end() const { return internalStorage.end(); } @@ -107,7 +111,7 @@ class DisjointSetUnion { disjointSets.insert({value, new SetType(value)}); internalStorage.insert(value); - internalStorage_ty oldRoots = roots; + std::set oldRoots = roots; for (ValueType v : oldRoots) { if (!areJoined(v, value) && SetType::intersects(disjointSets.at(find(v)), @@ -122,8 +126,8 @@ class DisjointSetUnion { } void add(const DisjointSetUnion &b) { - internalStorage_ty oldRoots = roots; - internalStorage_ty newRoots = b.roots; + std::set oldRoots = roots; + std::set newRoots = b.roots; for (auto it : b.parent) { parent.insert(it); } @@ -152,16 +156,16 @@ class DisjointSetUnion { DisjointSetUnion() {} - DisjointSetUnion(const internalStorage_ty &is) { + DisjointSetUnion(const internal_storage_ty &is) { for (ValueType v : is) { addValue(v); } } public: - internalStorage_ty is() const { return internalStorage; } + internal_storage_ty is() const { return internalStorage; } - disjointSets_ty ds() const { return disjointSets; } + disjoint_sets_ty ds() const { return disjointSets; } }; } // namespace klee diff --git a/include/klee/ADT/Either.h b/include/klee/ADT/Either.h index cc01bf761e..81b2d8e51c 100644 --- a/include/klee/ADT/Either.h +++ b/include/klee/ADT/Either.h @@ -32,6 +32,9 @@ template class either { /// @brief Required by klee::ref-managed objects class ReferenceCounter _refCount; + unsigned hashValue; + + static const unsigned MAGIC_HASH_CONSTANT = 39; public: using left = either_left; @@ -46,6 +49,8 @@ template class either { // virtual unsigned hash() = 0; virtual int compare(const either &b) = 0; virtual bool equals(const either &b) = 0; + + unsigned hash() const { return hashValue; } }; template class either_left : public either { @@ -56,8 +61,15 @@ template class either_left : public either { private: ref value_; + unsigned computeHash() { + unsigned res = (unsigned)getKind(); + res = (res * either::MAGIC_HASH_CONSTANT) + value_->hash(); + either::hashValue = res; + return either::hashValue; + } + public: - either_left(ref leftValue) : value_(leftValue){}; + either_left(ref leftValue) : value_(leftValue) { computeHash(); }; ref value() const { return value_; } operator ref const() { return value_; } @@ -100,8 +112,15 @@ template class either_right : public either { private: ref value_; + unsigned computeHash() { + unsigned res = (unsigned)getKind(); + res = (res * either::MAGIC_HASH_CONSTANT) + value_->hash(); + either::hashValue = res; + return either::hashValue; + } + public: - either_right(ref rightValue) : value_(rightValue){}; + either_right(ref rightValue) : value_(rightValue) { computeHash(); }; ref value() const { return value_; } operator ref const() { return value_; } diff --git a/include/klee/Expr/IndependentConstraintSetUnion.h b/include/klee/Expr/IndependentConstraintSetUnion.h index 4ec9e11c5a..3d6eb0f14c 100644 --- a/include/klee/Expr/IndependentConstraintSetUnion.h +++ b/include/klee/Expr/IndependentConstraintSetUnion.h @@ -8,8 +8,8 @@ namespace klee { class IndependentConstraintSetUnion - : public DisjointSetUnion, - IndependentConstraintSet> { + : public DisjointSetUnion, IndependentConstraintSet, + ExprEitherSymcreteHash, ExprEitherSymcreteCmp> { public: Assignment concretization; diff --git a/include/klee/Expr/IndependentSet.h b/include/klee/Expr/IndependentSet.h index a0878ea6c2..c1c69f2f72 100644 --- a/include/klee/Expr/IndependentSet.h +++ b/include/klee/Expr/IndependentSet.h @@ -24,6 +24,19 @@ DISABLE_WARNING_POP namespace klee { using ExprEitherSymcrete = either; +struct ExprEitherSymcreteHash { + unsigned operator()(const ref &e) const { + return e->hash(); + } +}; + +struct ExprEitherSymcreteCmp { + bool operator()(const ref &a, + const ref &b) const { + return a == b; + } +}; + template class DenseSet { typedef std::set set_ty; set_ty s; @@ -87,7 +100,8 @@ inline llvm::raw_ostream &operator<<(llvm::raw_ostream &os, class IndependentConstraintSet { private: using InnerSetUnion = - DisjointSetUnion, IndependentConstraintSet>; + DisjointSetUnion, IndependentConstraintSet, + ExprEitherSymcreteHash, ExprEitherSymcreteCmp>; void initIndependentConstraintSet(ref e); void initIndependentConstraintSet(ref s); diff --git a/include/klee/Expr/Symcrete.h b/include/klee/Expr/Symcrete.h index 6646c4cf16..65b70b20f7 100644 --- a/include/klee/Expr/Symcrete.h +++ b/include/klee/Expr/Symcrete.h @@ -75,6 +75,8 @@ class Symcrete { return id < rhs.id ? -1 : 1; } + unsigned hash() { return id; } + bool operator<(const Symcrete &rhs) const { return compare(rhs) < 0; }; }; diff --git a/lib/Expr/IndependentConstraintSetUnion.cpp b/lib/Expr/IndependentConstraintSetUnion.cpp index 01358e2623..0dcbf7154b 100644 --- a/lib/Expr/IndependentConstraintSetUnion.cpp +++ b/lib/Expr/IndependentConstraintSetUnion.cpp @@ -21,13 +21,13 @@ IndependentConstraintSetUnion::IndependentConstraintSetUnion( auto exprs = ics->exprs; for (ref e : exprs) { auto v = ref(new ExprEitherSymcrete::left(e)); - rank.replace({v, 0}); + rank.insert_or_assign(v, 0); internalStorage.insert(v); } for (ref s : ics->symcretes) { auto v = ref(new ExprEitherSymcrete::right(s)); - rank.replace({v, 0}); + rank.insert_or_assign(v, 0); internalStorage.insert(v); } @@ -37,11 +37,11 @@ IndependentConstraintSetUnion::IndependentConstraintSetUnion( auto &first = *(internalStorage.begin()); for (auto &e : internalStorage) { - parent.replace({e, first}); + parent.insert_or_assign(e, first); } - rank.replace({first, 1}); + rank.insert_or_assign(first, 1); roots.insert(first); - disjointSets.replace({first, ics}); + disjointSets.insert_or_assign(first, ics); concretization = ics->concretization; } @@ -57,7 +57,7 @@ void IndependentConstraintSetUnion::updateConcretization( ref ics = disjointSets.at(e); Assignment part = delta.part(ics->getSymcretes()); ics = ics->updateConcretization(part, concretizedExprs); - disjointSets.replace({e, ics}); + disjointSets.insert_or_assign(e, ics); } for (auto &it : delta.bindings) { concretization.bindings.replace({it.first, it.second}); @@ -70,7 +70,7 @@ void IndependentConstraintSetUnion::removeConcretization( ref ics = disjointSets.at(e); Assignment part = remove.part(ics->getSymcretes()); ics = ics->removeConcretization(part, concretizedExprs); - disjointSets.replace({e, ics}); + disjointSets.insert_or_assign(e, ics); } for (auto &it : remove.bindings) { concretization.bindings.remove(it.first); From f14b8ac292d041e683058c7d0327acb956de239f Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Thu, 2 Nov 2023 05:17:59 +0400 Subject: [PATCH 070/103] [fix] Fix performance for unbalanced expressions --- include/klee/Expr/Expr.h | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/include/klee/Expr/Expr.h b/include/klee/Expr/Expr.h index 4646b1a3c8..9937999e2e 100644 --- a/include/klee/Expr/Expr.h +++ b/include/klee/Expr/Expr.h @@ -753,7 +753,14 @@ class SelectExpr : public NonConstantExpr { static ref create(ref c, ref t, ref f); - Width getWidth() const { return trueExpr->getWidth(); } + Width getWidth() const { + if (trueExpr->height() < falseExpr->height()) { + return trueExpr->getWidth(); + } else { + return falseExpr->getWidth(); + } + } + Kind getKind() const { return Select; } unsigned getNumKids() const { return numKids; } @@ -1093,7 +1100,6 @@ FP_CAST_EXPR_CLASS(SIToFP) return createCachedExpr(res); \ } \ static ref create(const ref &l, const ref &r); \ - Width getWidth() const { return left->getWidth(); } \ Kind getKind() const { return _class_kind; } \ virtual ref rebuild(ref kids[]) const { \ return create(kids[0], kids[1]); \ @@ -1103,6 +1109,13 @@ FP_CAST_EXPR_CLASS(SIToFP) return E->getKind() == Expr::_class_kind; \ } \ static bool classof(const _class_kind##Expr *) { return true; } \ + Width getWidth() const { \ + if (left->height() < right->height()) { \ + return left->getWidth(); \ + } else { \ + return right->getWidth(); \ + } \ + } \ \ protected: \ virtual int compareContents(const Expr &b) const { \ @@ -1145,7 +1158,14 @@ ARITHMETIC_EXPR_CLASS(AShr) } \ static ref create(const ref &l, const ref &r, \ llvm::APFloat::roundingMode rm); \ - Width getWidth() const { return left->getWidth(); } \ + Width getWidth() const { \ + if (left->height() < right->height()) { \ + return left->getWidth(); \ + } else { \ + return right->getWidth(); \ + } \ + } \ + \ Kind getKind() const { return _class_kind; } \ virtual ref rebuild(ref kids[]) const { \ return create(kids[0], kids[1], roundingMode); \ From 1689ececddc6ec3dba38e326efa8220c06ba6c37 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Thu, 2 Nov 2023 05:27:08 +0400 Subject: [PATCH 071/103] [refactor] Separate `isStuck` and `isCycled`, `isStuck` is smarter now --- .../klee/{util => Utilities}/APFloatEval.h | 0 include/klee/Utilities/Math.h | 32 +++++++++++++++++++ lib/Core/ExecutionState.h | 9 +++++- lib/Core/Searcher.cpp | 21 +++--------- lib/Core/TargetManager.cpp | 2 +- lib/Expr/APFloatEval.cpp | 2 +- lib/Expr/Expr.cpp | 2 +- 7 files changed, 47 insertions(+), 21 deletions(-) rename include/klee/{util => Utilities}/APFloatEval.h (100%) create mode 100644 include/klee/Utilities/Math.h diff --git a/include/klee/util/APFloatEval.h b/include/klee/Utilities/APFloatEval.h similarity index 100% rename from include/klee/util/APFloatEval.h rename to include/klee/Utilities/APFloatEval.h diff --git a/include/klee/Utilities/Math.h b/include/klee/Utilities/Math.h new file mode 100644 index 0000000000..a7739cadc6 --- /dev/null +++ b/include/klee/Utilities/Math.h @@ -0,0 +1,32 @@ +//===-- Math.h --------------------------------------------------*- C++ -*-===// +// +// The KLEE Symbolic Virtual Machine +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef KLEE_MATH_H +#define KLEE_MATH_H + +#include + +namespace klee { +namespace util { +static unsigned int ulog2(unsigned int val) { + if (val == 0) + return UINT_MAX; + if (val == 1) + return 0; + unsigned int ret = 0; + while (val > 1) { + val >>= 1; + ret++; + } + return ret; +} +} // namespace util +} // namespace klee + +#endif /* KLEE_MATH_H */ diff --git a/lib/Core/ExecutionState.h b/lib/Core/ExecutionState.h index d10afb7072..58fb0f7881 100644 --- a/lib/Core/ExecutionState.h +++ b/lib/Core/ExecutionState.h @@ -29,6 +29,7 @@ #include "klee/Module/TargetHash.h" #include "klee/Solver/Solver.h" #include "klee/System/Time.h" +#include "klee/Utilities/Math.h" #include "klee/Support/CompilerWarning.h" DISABLE_WARNING_PUSH @@ -492,7 +493,7 @@ class ExecutionState { bool reachedTarget(ref target) const; static std::uint32_t getLastID() { return nextID - 1; }; - inline bool isStuck(unsigned long long bound) const { + inline bool isCycled(unsigned long long bound) const { if (bound == 0) return false; if (prevPC->inst->isTerminator() && stack.size() > 0) { @@ -508,6 +509,12 @@ class ExecutionState { return false; } + inline bool isStuck(unsigned long long bound) const { + if (depth == 1) + return false; + return isCycled(bound) && depth > klee::util::ulog2(bound); + } + bool isCoveredNew() const { return !coveredNew.empty() && coveredNew.back()->value; } diff --git a/lib/Core/Searcher.cpp b/lib/Core/Searcher.cpp index ad73527320..7611b14c45 100644 --- a/lib/Core/Searcher.cpp +++ b/lib/Core/Searcher.cpp @@ -25,6 +25,7 @@ #include "klee/Statistics/Statistics.h" #include "klee/Support/ErrorHandling.h" #include "klee/System/Time.h" +#include "klee/Utilities/Math.h" #include "klee/Support/CompilerWarning.h" DISABLE_WARNING_PUSH @@ -136,21 +137,6 @@ void RandomSearcher::printName(llvm::raw_ostream &os) { /// -static unsigned int ulog2(unsigned int val) { - if (val == 0) - return UINT_MAX; - if (val == 1) - return 0; - unsigned int ret = 0; - while (val > 1) { - val >>= 1; - ret++; - } - return ret; -} - -/// - TargetedSearcher::~TargetedSearcher() {} bool TargetedSearcher::empty() { return states->empty(); } @@ -195,7 +181,8 @@ weight_type TargetedSearcher::getWeight(ExecutionState *es) { return weight; } auto distRes = distanceCalculator.getDistance(*es, target->getBlock()); - weight = ulog2(distRes.weight + es->steppedMemoryInstructions + 1); // [0, 32) + weight = klee::util::ulog2(distRes.weight + es->steppedMemoryInstructions + + 1); // [0, 32) if (!distRes.isInsideFunction) { weight += 32; // [32, 64) } @@ -667,7 +654,7 @@ class MaxCyclesMetric final : public IterativeDeepeningSearcher::Metric { explicit MaxCyclesMetric() : MaxCyclesMetric(1ULL){}; bool exceeds(const ExecutionState &state) const final { - return state.isStuck(maxCycles); + return state.isCycled(maxCycles); } void increaseLimit() final { maxCycles *= 2ULL; diff --git a/lib/Core/TargetManager.cpp b/lib/Core/TargetManager.cpp index 9dcaedcd86..23ad1347e8 100644 --- a/lib/Core/TargetManager.cpp +++ b/lib/Core/TargetManager.cpp @@ -135,7 +135,7 @@ void TargetManager::updateReached(ExecutionState &state) { void TargetManager::updateTargets(ExecutionState &state) { if (guidance == Interpreter::GuidanceKind::CoverageGuidance) { - if (targets(state).empty() && state.isStuck(MaxCyclesBeforeStuck)) { + if (targets(state).empty() && state.isCycled(MaxCyclesBeforeStuck)) { state.setTargeted(true); } if (isTargeted(state) && targets(state).empty()) { diff --git a/lib/Expr/APFloatEval.cpp b/lib/Expr/APFloatEval.cpp index a1f49b28f9..49ae758d1c 100644 --- a/lib/Expr/APFloatEval.cpp +++ b/lib/Expr/APFloatEval.cpp @@ -6,7 +6,7 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -#include "klee/util/APFloatEval.h" +#include "klee/Utilities/APFloatEval.h" #include "klee/Config/Version.h" #include "klee/Support/CompilerWarning.h" diff --git a/lib/Expr/Expr.cpp b/lib/Expr/Expr.cpp index 4f26cb1aaa..ec1ecd9235 100644 --- a/lib/Expr/Expr.cpp +++ b/lib/Expr/Expr.cpp @@ -16,7 +16,7 @@ #include "klee/Support/ErrorHandling.h" #include "klee/Support/OptionCategories.h" #include "klee/Support/RoundingModeUtil.h" -#include "klee/util/APFloatEval.h" +#include "klee/Utilities/APFloatEval.h" #include "klee/Support/CompilerWarning.h" DISABLE_WARNING_PUSH From ab185fedd5fdaf15e95f0f274ac2059b38355eaa Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Thu, 2 Nov 2023 05:53:46 +0400 Subject: [PATCH 072/103] [fix] Limit the cexPreferences size --- lib/Core/Executor.cpp | 46 ++++++++++++++++++++++++------------------- lib/Core/Searcher.cpp | 2 +- 2 files changed, 27 insertions(+), 21 deletions(-) diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index 0cc740787b..46462e235b 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -7151,26 +7151,32 @@ bool Executor::getSymbolicSolution(const ExecutionState &state, KTest &res) { // the preferred constraints. See test/Features/PreferCex.c for // an example) While this process can be very expensive, it can // also make understanding individual test cases much easier. - for (auto &pi : state.cexPreferences) { - bool mustBeTrue; - // Attempt to bound byte to constraints held in cexPreferences - bool success = - solver->mustBeTrue(extendedConstraints.cs(), Expr::createIsZero(pi), - mustBeTrue, state.queryMetaData); - // If it isn't possible to add the condition without making the entire - // list UNSAT, then just continue to the next condition - if (!success) - break; - // If the particular constraint operated on in this iteration through - // the loop isn't implied then add it to the list of constraints. - if (!mustBeTrue) { - Assignment concretization = computeConcretization( - extendedConstraints.cs(), pi, state.queryMetaData); - - if (!concretization.isEmpty()) { - extendedConstraints.addConstraint(pi, concretization); - } else { - extendedConstraints.addConstraint(pi, {}); + const size_t cexPreferencesBound = 16; + if (state.cexPreferences.size() > cexPreferencesBound) { + klee_warning_once(0, "skipping cex preffering (size of restrictons > %d).", + cexPreferencesBound); + } else { + for (auto &pi : state.cexPreferences) { + bool mustBeTrue; + // Attempt to bound byte to constraints held in cexPreferences + bool success = + solver->mustBeTrue(extendedConstraints.cs(), Expr::createIsZero(pi), + mustBeTrue, state.queryMetaData); + // If it isn't possible to add the condition without making the entire + // list UNSAT, then just continue to the next condition + if (!success) + break; + // If the particular constraint operated on in this iteration through + // the loop isn't implied then add it to the list of constraints. + if (!mustBeTrue) { + Assignment concretization = computeConcretization( + extendedConstraints.cs(), pi, state.queryMetaData); + + if (!concretization.isEmpty()) { + extendedConstraints.addConstraint(pi, concretization); + } else { + extendedConstraints.addConstraint(pi, {}); + } } } } diff --git a/lib/Core/Searcher.cpp b/lib/Core/Searcher.cpp index 7611b14c45..f2d91cfd79 100644 --- a/lib/Core/Searcher.cpp +++ b/lib/Core/Searcher.cpp @@ -714,7 +714,7 @@ void IterativeDeepeningSearcher::update(ExecutionState *current, } // no states left in underlying searcher: fill with paused states - if (baseSearcher->empty()) { + if (baseSearcher->empty() && !pausedStates.empty()) { metric->increaseLimit(); baseSearcher->update(nullptr, pausedStates, {}); pausedStates.clear(); From fa0c7b698ab9f39f6dad1406159ab025fe5b48ca Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Thu, 2 Nov 2023 05:57:38 +0400 Subject: [PATCH 073/103] [fix] Remove unused field --- include/klee/Module/TargetHash.h | 5 ----- lib/Core/ExecutionState.cpp | 13 +++++-------- lib/Core/ExecutionState.h | 1 - lib/Core/TargetCalculator.h | 2 -- lib/Module/TargetHash.cpp | 5 ----- 5 files changed, 5 insertions(+), 21 deletions(-) diff --git a/include/klee/Module/TargetHash.h b/include/klee/Module/TargetHash.h index 2c2c2f81bd..1962ba906c 100644 --- a/include/klee/Module/TargetHash.h +++ b/include/klee/Module/TargetHash.h @@ -31,13 +31,8 @@ struct TargetCmp { bool operator()(const ref &a, const ref &b) const; }; -typedef std::pair Transition; typedef std::pair Branch; -struct TransitionHash { - std::size_t operator()(const Transition &p) const; -}; - struct BranchHash { std::size_t operator()(const Branch &p) const; }; diff --git a/lib/Core/ExecutionState.cpp b/lib/Core/ExecutionState.cpp index 9b7667ee62..31d60372dd 100644 --- a/lib/Core/ExecutionState.cpp +++ b/lib/Core/ExecutionState.cpp @@ -160,11 +160,11 @@ ExecutionState::ExecutionState(const ExecutionState &state) : initPC(state.initPC), pc(state.pc), prevPC(state.prevPC), stack(state.stack), stackBalance(state.stackBalance), incomingBBIndex(state.incomingBBIndex), depth(state.depth), - level(state.level), transitionLevel(state.transitionLevel), - addressSpace(state.addressSpace), constraints(state.constraints), - targetForest(state.targetForest), pathOS(state.pathOS), - symPathOS(state.symPathOS), coveredLines(state.coveredLines), - symbolics(state.symbolics), resolvedPointers(state.resolvedPointers), + level(state.level), addressSpace(state.addressSpace), + constraints(state.constraints), targetForest(state.targetForest), + pathOS(state.pathOS), symPathOS(state.symPathOS), + coveredLines(state.coveredLines), symbolics(state.symbolics), + resolvedPointers(state.resolvedPointers), cexPreferences(state.cexPreferences), arrayNames(state.arrayNames), steppedInstructions(state.steppedInstructions), steppedMemoryInstructions(state.steppedMemoryInstructions), @@ -448,9 +448,6 @@ void ExecutionState::increaseLevel() { stack.infoStack().back().multilevel.replace({srcbb, srcLevel + 1}); level.insert(prevPC->parent); } - if (srcbb != dstbb) { - transitionLevel.insert(std::make_pair(srcbb, dstbb)); - } } bool ExecutionState::isGEPExpr(ref expr) const { diff --git a/lib/Core/ExecutionState.h b/lib/Core/ExecutionState.h index 58fb0f7881..5ebcf17a74 100644 --- a/lib/Core/ExecutionState.h +++ b/lib/Core/ExecutionState.h @@ -291,7 +291,6 @@ class ExecutionState { /// @brief Exploration level, i.e., number of times KLEE cycled for this state std::set level; - std::unordered_set transitionLevel; /// @brief Address space used by this state (e.g. Global and Heap) AddressSpace addressSpace; diff --git a/lib/Core/TargetCalculator.h b/lib/Core/TargetCalculator.h index cd96306524..f337b879fd 100644 --- a/lib/Core/TargetCalculator.h +++ b/lib/Core/TargetCalculator.h @@ -34,7 +34,6 @@ DISABLE_WARNING_POP namespace klee { class CodeGraphInfo; class ExecutionState; -struct TransitionHash; enum class TrackCoverageBy { None, Blocks, Branches, All }; @@ -44,7 +43,6 @@ class TargetCalculator { using StatesSet = std::unordered_set; typedef std::unordered_set VisitedBlocks; - typedef std::unordered_set VisitedTransitions; typedef std::unordered_set VisitedBranches; enum HistoryKind { Blocks, Transitions }; diff --git a/lib/Module/TargetHash.cpp b/lib/Module/TargetHash.cpp index 7f5b9be2eb..f7c3010689 100644 --- a/lib/Module/TargetHash.cpp +++ b/lib/Module/TargetHash.cpp @@ -22,11 +22,6 @@ bool TargetCmp::operator()(const ref &a, const ref &b) const { return a == b; } -std::size_t TransitionHash::operator()(const Transition &p) const { - return reinterpret_cast(p.first) * 31 + - reinterpret_cast(p.second); -} - std::size_t BranchHash::operator()(const Branch &p) const { return reinterpret_cast(p.first) * 31 + p.second; } From 7c002e7c891d431bcf6f3087c8667d275a7c67ef Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Thu, 2 Nov 2023 05:58:52 +0400 Subject: [PATCH 074/103] [fix] Fix memory consumption `using path_ty = std::vector` -> `using path_ty = ImmutableList` --- include/klee/ADT/ImmutableList.h | 17 ++++++++ include/klee/Expr/Constraints.h | 3 +- include/klee/Expr/Path.h | 24 ++--------- lib/Core/ExecutionState.h | 2 +- lib/Expr/Constraints.cpp | 31 ++------------ lib/Expr/Path.cpp | 72 ++++---------------------------- 6 files changed, 35 insertions(+), 114 deletions(-) diff --git a/include/klee/ADT/ImmutableList.h b/include/klee/ADT/ImmutableList.h index 20cb225fd8..425036979e 100644 --- a/include/klee/ADT/ImmutableList.h +++ b/include/klee/ADT/ImmutableList.h @@ -10,6 +10,7 @@ #ifndef KLEE_IMMUTABLELIST_H #define KLEE_IMMUTABLELIST_H +#include #include #include @@ -96,6 +97,22 @@ template class ImmutableList { node->values.push_back(std::move(value)); } + void push_back(const T &value) { + if (!node) { + node = std::make_shared(); + } + node->values.push_back(value); + } + + bool empty() { return size() == 0; } + + const T &back() { + assert(node && "requiers not empty list"); + auto it = iterator(node.get()); + it.get = size() - 1; + return *it; + } + ImmutableList() : node(){}; ImmutableList(const ImmutableList &il) : node(std::make_shared(il)) {} diff --git a/include/klee/Expr/Constraints.h b/include/klee/Expr/Constraints.h index d6f47e3d94..75769b3fb4 100644 --- a/include/klee/Expr/Constraints.h +++ b/include/klee/Expr/Constraints.h @@ -12,6 +12,7 @@ #include "klee/ADT/Ref.h" +#include "klee/ADT/PersistentMap.h" #include "klee/Expr/Assignment.h" #include "klee/Expr/Expr.h" #include "klee/Expr/ExprHashMap.h" @@ -91,7 +92,7 @@ class ConstraintSet { class PathConstraints { public: using ordered_constraints_ty = - std::map; + PersistentMap; void advancePath(KInstruction *ki); void advancePath(const Path &path); diff --git a/include/klee/Expr/Path.h b/include/klee/Expr/Path.h index 48bb63ec47..a556a00213 100644 --- a/include/klee/Expr/Path.h +++ b/include/klee/Expr/Path.h @@ -1,6 +1,8 @@ #ifndef KLEE_PATH_H #define KLEE_PATH_H +#include "klee/ADT/ImmutableList.h" + #include #include #include @@ -16,7 +18,7 @@ using stackframe_ty = std::pair; class Path { public: - using path_ty = std::vector; + using path_ty = ImmutableList; enum class TransitionKind { StepInto, StepOut, None }; struct PathIndex { @@ -38,23 +40,6 @@ class Path { void advance(KInstruction *ki); - friend bool operator==(const Path &lhs, const Path &rhs) { - return lhs.KBlocks == rhs.KBlocks && - lhs.firstInstruction == rhs.firstInstruction && - lhs.lastInstruction == rhs.lastInstruction; - } - friend bool operator!=(const Path &lhs, const Path &rhs) { - return !(lhs == rhs); - } - - friend bool operator<(const Path &lhs, const Path &rhs) { - return lhs.KBlocks < rhs.KBlocks || - (lhs.KBlocks == rhs.KBlocks && - (lhs.firstInstruction < rhs.firstInstruction || - (lhs.firstInstruction == rhs.firstInstruction && - lhs.lastInstruction < rhs.lastInstruction))); - } - unsigned KBlockSize() const; const path_ty &getBlocks() const; unsigned getFirstIndex() const; @@ -64,7 +49,6 @@ class Path { std::vector getStack(bool reversed) const; - std::vector> asFunctionRanges() const; std::string toString() const; static Path concat(const Path &l, const Path &r); @@ -73,7 +57,7 @@ class Path { Path() = default; - Path(unsigned firstInstruction, std::vector kblocks, + Path(unsigned firstInstruction, const path_ty &kblocks, unsigned lastInstruction) : KBlocks(kblocks), firstInstruction(firstInstruction), lastInstruction(lastInstruction) {} diff --git a/lib/Core/ExecutionState.h b/lib/Core/ExecutionState.h index 5ebcf17a74..7ae7d692cb 100644 --- a/lib/Core/ExecutionState.h +++ b/lib/Core/ExecutionState.h @@ -290,7 +290,7 @@ class ExecutionState { std::uint32_t depth = 0; /// @brief Exploration level, i.e., number of times KLEE cycled for this state - std::set level; + PersistentSet level; /// @brief Address space used by this state (e.g. Global and Heap) AddressSpace addressSpace; diff --git a/lib/Expr/Constraints.cpp b/lib/Expr/Constraints.cpp index ae00a3303c..d349c9d0b2 100644 --- a/lib/Expr/Constraints.cpp +++ b/lib/Expr/Constraints.cpp @@ -330,10 +330,6 @@ PathConstraints::orderedCS() const { void PathConstraints::advancePath(KInstruction *ki) { _path.advance(ki); } -void PathConstraints::advancePath(const Path &path) { - _path = Path::concat(_path, path); -} - ExprHashSet PathConstraints::addConstraint(ref e, const Assignment &delta, Path::PathIndex currIndex) { auto expr = Simplificator::simplifyExpr(constraints, e); @@ -352,7 +348,9 @@ ExprHashSet PathConstraints::addConstraint(ref e, const Assignment &delta, added.insert(expr); pathIndexes.insert({expr, currIndex}); _simplificationMap[expr].insert(expr); - orderedConstraints[currIndex].insert(expr); + auto indexConstraints = orderedConstraints[currIndex].second; + indexConstraints.insert(expr); + orderedConstraints.replace({currIndex, indexConstraints}); constraints.addConstraint(expr, delta); } } @@ -389,29 +387,6 @@ void PathConstraints::rewriteConcretization(const Assignment &a) { constraints.rewriteConcretization(a); } -PathConstraints PathConstraints::concat(const PathConstraints &l, - const PathConstraints &r) { - // TODO : How to handle symcretes and concretization? - PathConstraints path = l; - path._path = Path::concat(l._path, r._path); - auto offset = l._path.KBlockSize(); - for (const auto &i : r._original) { - path._original.insert(i); - auto index = r.pathIndexes.at(i); - index.block += offset; - path.pathIndexes.insert({i, index}); - path.orderedConstraints[index].insert(i); - } - for (const auto &i : r.constraints.cs()) { - path.constraints.addConstraint(i, {}); - if (r._simplificationMap.count(i)) { - path._simplificationMap.insert({i, r._simplificationMap.at(i)}); - } - } - // Run the simplificator on the newly constructed set? - return path; -} - Simplificator::ExprResult Simplificator::simplifyExpr(const constraints_ty &constraints, const ref &expr) { diff --git a/lib/Expr/Path.cpp b/lib/Expr/Path.cpp index e67abd51b4..829e73b374 100644 --- a/lib/Expr/Path.cpp +++ b/lib/Expr/Path.cpp @@ -39,67 +39,6 @@ Path::PathIndex Path::getCurrentIndex() const { return {KBlocks.size() - 1, lastInstruction}; } -std::vector Path::getStack(bool reversed) const { - std::vector stack; - for (unsigned i = 0; i < KBlocks.size(); i++) { - auto current = reversed ? KBlocks[KBlocks.size() - 1 - i] : KBlocks[i]; - // Previous for reversed is the next - KBlock *prev = nullptr; - if (i != 0) { - prev = reversed ? KBlocks[KBlocks.size() - i] : KBlocks[i - 1]; - } - if (i == 0) { - stack.push_back({nullptr, current->parent}); - continue; - } - if (reversed) { - auto kind = getTransitionKind(current, prev); - if (kind == TransitionKind::StepInto) { - if (!stack.empty()) { - stack.pop_back(); - } - } else if (kind == TransitionKind::StepOut) { - assert(isa(prev)); - stack.push_back({prev->getFirstInstruction(), current->parent}); - } - } else { - auto kind = getTransitionKind(prev, current); - if (kind == TransitionKind::StepInto) { - stack.push_back({prev->getFirstInstruction(), current->parent}); - } else if (kind == TransitionKind::StepOut) { - if (!stack.empty()) { - stack.pop_back(); - } - } - } - } - return stack; -} - -std::vector> -Path::asFunctionRanges() const { - assert(!KBlocks.empty()); - std::vector> ranges; - BlockRange range{0, 0}; - KFunction *function = KBlocks[0]->parent; - for (unsigned i = 1; i < KBlocks.size(); i++) { - if (getTransitionKind(KBlocks[i - 1], KBlocks[i]) == TransitionKind::None) { - if (i == KBlocks.size() - 1) { - range.last = i; - ranges.push_back({function, range}); - return ranges; - } else { - continue; - } - } - range.last = i - 1; - ranges.push_back({function, range}); - range.first = i; - function = KBlocks[i]->parent; - } - llvm_unreachable("asFunctionRanges reached the end of the for!"); -} - Path Path::concat(const Path &l, const Path &r) { Path path = l; for (auto block : r.KBlocks) { @@ -112,11 +51,16 @@ Path Path::concat(const Path &l, const Path &r) { std::string Path::toString() const { std::string blocks = ""; unsigned depth = 0; - for (unsigned i = 0; i < KBlocks.size(); i++) { - auto current = KBlocks[i]; + std::vector KBlocksVector; + KBlocksVector.reserve(KBlocks.size()); + for (auto kblock : KBlocks) { + KBlocksVector.push_back(kblock); + } + for (size_t i = 0; i < KBlocksVector.size(); i++) { + auto current = KBlocksVector[i]; KBlock *prev = nullptr; if (i != 0) { - prev = KBlocks[i - 1]; + prev = KBlocksVector[i - 1]; } auto kind = i == 0 ? TransitionKind::StepInto : getTransitionKind(prev, current); From 1b1e7892019aad5f8335f63f98d5b5bd09816223 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Thu, 2 Nov 2023 12:49:58 +0400 Subject: [PATCH 075/103] [feat] Enable `coverOnTheFly` after approaching memory cup --- lib/Core/Executor.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index 46462e235b..f7b5fe697f 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -246,7 +246,13 @@ cl::opt EmitAllErrors( cl::opt CoverOnTheFly( "cover-on-the-fly", cl::init(false), cl::desc("Generate tests cases for each new covered block or branch " - "(default=false, i.e. one per (error,instruction) pair)"), + "(default=false)"), + cl::cat(TestGenCat)); + +cl::opt MemoryTriggerCoverOnTheFly( + "mem-trigger-cof", cl::init(false), + cl::desc("Start on the fly tests generation after approaching memory cup" + "(default=false)"), cl::cat(TestGenCat)); cl::opt DelayCoverOnTheFly( @@ -4082,6 +4088,14 @@ bool Executor::checkMemoryUsage() { const auto mallocUsage = util::GetTotalMallocUsage() >> 20U; const auto mmapUsage = memory->getUsedDeterministicSize() >> 20U; const auto totalUsage = mallocUsage + mmapUsage; + + if (MemoryTriggerCoverOnTheFly && 3 * totalUsage <= 2 * MaxMemory) { + klee_warning_once(0, + "enabling cover-on-the-fly (close to memory cap: %luMB)", + totalUsage); + coverOnTheFly = true; + } + atMemoryLimit = totalUsage > MaxMemory; // inhibit forking if (!atMemoryLimit) return true; From 287258649dcd52e1b8222d37afa2ea478be1f2d6 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Fri, 3 Nov 2023 02:11:13 +0400 Subject: [PATCH 076/103] [style] --- lib/Core/Executor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index f7b5fe697f..fd4d9333be 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -7167,7 +7167,7 @@ bool Executor::getSymbolicSolution(const ExecutionState &state, KTest &res) { // also make understanding individual test cases much easier. const size_t cexPreferencesBound = 16; if (state.cexPreferences.size() > cexPreferencesBound) { - klee_warning_once(0, "skipping cex preffering (size of restrictons > %d).", + klee_warning_once(0, "skipping cex preffering (size of restrictons > %zu).", cexPreferencesBound); } else { for (auto &pi : state.cexPreferences) { From 8b91d6a2b4715049e81b424b1e9fc910709f9578 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Fri, 3 Nov 2023 15:37:56 +0400 Subject: [PATCH 077/103] [fix] Consider all not empty and not fully covered functions --- lib/Core/TargetCalculator.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/Core/TargetCalculator.cpp b/lib/Core/TargetCalculator.cpp index 94953d51b8..36c23a9026 100644 --- a/lib/Core/TargetCalculator.cpp +++ b/lib/Core/TargetCalculator.cpp @@ -92,8 +92,7 @@ void TargetCalculator::update(const ExecutionState &state) { } if (!fnsTaken.count(calledKFunction) && fullyCoveredFunctions.count(calledKFunction) == 0 && - calledKFunction->numInstructions != 0 && - !getCoverageTargets(calledKFunction).empty()) { + calledKFunction->numInstructions != 0) { fns.push_back(calledKFunction); } } From 01ddb65ce8abe83fbf1543ea56d6bb521f723662 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Fri, 3 Nov 2023 15:38:17 +0400 Subject: [PATCH 078/103] [fix] Fix perfomance bug --- include/klee/Expr/Assignment.h | 39 ++++++++++++++++++++++++-------- include/klee/Solver/SolverUtil.h | 20 +++------------- lib/Solver/CexCachingSolver.cpp | 25 ++------------------ 3 files changed, 34 insertions(+), 50 deletions(-) diff --git a/include/klee/Expr/Assignment.h b/include/klee/Expr/Assignment.h index f72bb581b7..bb86172a60 100644 --- a/include/klee/Expr/Assignment.h +++ b/include/klee/Expr/Assignment.h @@ -25,6 +25,7 @@ class ConstraintSet; typedef std::set, SymcreteLess> SymcreteOrderedSet; using symcretes_ty = SymcreteOrderedSet; +typedef std::function)> ExprPredicate; class Assignment { public: @@ -57,11 +58,14 @@ class Assignment { ref evaluate(ref e, bool allowFreeValues = true) const; constraints_ty createConstraintsFromAssignment() const; + template + bool satisfies(InputIterator begin, InputIterator end, + ExprPredicate predicate, bool allowFreeValues = true); template bool satisfies(InputIterator begin, InputIterator end, bool allowFreeValues = true); template - bool satisfiesNonBoolean(InputIterator begin, InputIterator end, + bool satisfiesOrConstant(InputIterator begin, InputIterator end, bool allowFreeValues = true); void dump() const; @@ -115,28 +119,43 @@ inline ref Assignment::evaluate(ref e, bool allowFreeValues) const { return v.visit(e); } +struct isTrueBoolean { + bool operator()(ref e) const { + return e->getWidth() == Expr::Bool && e->isTrue(); + } +}; + +struct isTrueBooleanOrConstantNotBoolean { + bool operator()(ref e) const { + return (e->getWidth() == Expr::Bool && e->isTrue()) || + ((isa(e) && e->getWidth() != Expr::Bool)); + } +}; + template inline bool Assignment::satisfies(InputIterator begin, InputIterator end, + ExprPredicate predicate, bool allowFreeValues) { AssignmentEvaluator v(*this, allowFreeValues); for (; begin != end; ++begin) { - assert((*begin)->getWidth() == Expr::Bool && "constraints must be boolean"); - if (!v.visit(*begin)->isTrue()) + if (!predicate(v.visit(*begin))) return false; } return true; } template -inline bool Assignment::satisfiesNonBoolean(InputIterator begin, +inline bool Assignment::satisfies(InputIterator begin, InputIterator end, + bool allowFreeValues) { + return satisfies(begin, end, isTrueBoolean(), allowFreeValues); +} + +template +inline bool Assignment::satisfiesOrConstant(InputIterator begin, InputIterator end, bool allowFreeValues) { - AssignmentEvaluator v(*this, allowFreeValues); - for (; begin != end; ++begin) { - if (!isa(v.visit(*begin))) - return false; - } - return true; + return satisfies(begin, end, isTrueBooleanOrConstantNotBoolean(), + allowFreeValues); } } // namespace klee diff --git a/include/klee/Solver/SolverUtil.h b/include/klee/Solver/SolverUtil.h index ffd3849c62..9be7d0f2d2 100644 --- a/include/klee/Solver/SolverUtil.h +++ b/include/klee/Solver/SolverUtil.h @@ -299,26 +299,12 @@ class InvalidResponse : public SolverResponse { } bool satisfies(const std::set> &key, bool allowFreeValues = true) { - std::set> booleanKey; - std::set> nonBooleanKey; - - for (auto i : key) { - if (i->getWidth() == Expr::Bool) { - booleanKey.insert(i); - } else { - nonBooleanKey.insert(i); - } - } - - return result.satisfies(booleanKey.begin(), booleanKey.end(), - allowFreeValues) && - result.satisfiesNonBoolean(nonBooleanKey.begin(), - nonBooleanKey.end(), allowFreeValues); + return result.satisfies(key.begin(), key.end(), allowFreeValues); } - bool satisfiesNonBoolean(const std::set> &key, + bool satisfiesOrConstant(const std::set> &key, bool allowFreeValues = true) { - return result.satisfiesNonBoolean(key.begin(), key.end(), allowFreeValues); + return result.satisfiesOrConstant(key.begin(), key.end(), allowFreeValues); } void dump() { result.dump(); } diff --git a/lib/Solver/CexCachingSolver.cpp b/lib/Solver/CexCachingSolver.cpp index ddb5861c88..74144a0697 100644 --- a/lib/Solver/CexCachingSolver.cpp +++ b/lib/Solver/CexCachingSolver.cpp @@ -169,16 +169,6 @@ bool CexCachingSolver::searchForResponse(KeyType &key, return true; } - KeyType booleanKey; - KeyType nonBooleanKey; - for (auto i : key) { - if (i->getWidth() == Expr::Bool) { - booleanKey.insert(i); - } else { - nonBooleanKey.insert(i); - } - } - // Otherwise, iterate through the set of current solver responses to see if // one of them satisfies the query. for (responseTable_ty::iterator it = responseTable.begin(), @@ -186,8 +176,7 @@ bool CexCachingSolver::searchForResponse(KeyType &key, it != ie; ++it) { ref a = *it; if (isa(a) && - cast(a)->satisfies(booleanKey) && - cast(a)->satisfiesNonBoolean(nonBooleanKey)) { + cast(a)->satisfiesOrConstant(key)) { result = a; return true; } @@ -272,17 +261,7 @@ bool CexCachingSolver::getResponse(const Query &query, } if (DebugCexCacheCheckBinding) { - KeyType booleanKey; - KeyType nonBooleanKey; - for (auto i : key) { - if (i->getWidth() == Expr::Bool) { - booleanKey.insert(i); - } else { - nonBooleanKey.insert(i); - } - } - if (!cast(result)->satisfies(booleanKey) || - !cast(result)->satisfiesNonBoolean(nonBooleanKey)) { + if (!cast(result)->satisfiesOrConstant(key)) { query.dump(); result->dump(); klee_error("Generated assignment doesn't match query"); From 9f054a924d8cc76a54c7a039f8949b0b77ed402e Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Fri, 3 Nov 2023 16:48:59 +0400 Subject: [PATCH 079/103] [fix] Fix `isStuck` --- lib/Core/ExecutionState.h | 4 ++-- lib/Core/Executor.cpp | 2 +- lib/Core/TargetManager.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/Core/ExecutionState.h b/lib/Core/ExecutionState.h index 7ae7d692cb..9e74c4ef37 100644 --- a/lib/Core/ExecutionState.h +++ b/lib/Core/ExecutionState.h @@ -509,9 +509,9 @@ class ExecutionState { } inline bool isStuck(unsigned long long bound) const { - if (depth == 1) + if (depth == 0) return false; - return isCycled(bound) && depth > klee::util::ulog2(bound); + return isCycled(bound) && klee::util::ulog2(depth) > bound; } bool isCoveredNew() const { diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index fd4d9333be..b4e17bf9e6 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -4415,7 +4415,7 @@ void Executor::executeStep(ExecutionState &state) { if (targetManager->isTargeted(state) && state.targets().empty()) { terminateStateEarlyAlgorithm(state, "State missed all it's targets.", StateTerminationType::MissedAllTargets); - } else if (state.isStuck(MaxCycles)) { + } else if (state.isCycled(MaxCycles)) { terminateStateEarly(state, "max-cycles exceeded.", StateTerminationType::MaxCycles); } else { diff --git a/lib/Core/TargetManager.cpp b/lib/Core/TargetManager.cpp index 23ad1347e8..9dcaedcd86 100644 --- a/lib/Core/TargetManager.cpp +++ b/lib/Core/TargetManager.cpp @@ -135,7 +135,7 @@ void TargetManager::updateReached(ExecutionState &state) { void TargetManager::updateTargets(ExecutionState &state) { if (guidance == Interpreter::GuidanceKind::CoverageGuidance) { - if (targets(state).empty() && state.isCycled(MaxCyclesBeforeStuck)) { + if (targets(state).empty() && state.isStuck(MaxCyclesBeforeStuck)) { state.setTargeted(true); } if (isTargeted(state) && targets(state).empty()) { From 2477ed7cb013a974c15abba9991d9618c77ba6fe Mon Sep 17 00:00:00 2001 From: Yurii Kostyukov Date: Fri, 3 Nov 2023 12:10:50 +0300 Subject: [PATCH 080/103] [fix] klee-test-comp.c --- CMakeLists.txt | 6 ++++++ include/klee-test-comp.c | 5 ++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7f6bcf2697..cad45136e7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -643,6 +643,12 @@ unset(_flags) configure_file(${CMAKE_SOURCE_DIR}/include/klee/Config/config.h.cmin ${CMAKE_BINARY_DIR}/include/klee/Config/config.h) +################################################################################ +# Generate `klee/klee.h` and `klee-test-comp.c` +################################################################################ +configure_file(${CMAKE_SOURCE_DIR}/include/klee/klee.h ${CMAKE_BINARY_DIR}/include/klee/klee.h COPYONLY) +configure_file(${CMAKE_SOURCE_DIR}/include/klee-test-comp.c ${CMAKE_BINARY_DIR}/include/klee-test-comp.c COPYONLY) + ################################################################################ # Generate `CompileTimeInfo.h` ################################################################################ diff --git a/include/klee-test-comp.c b/include/klee-test-comp.c index 90774aa2b2..413011abea 100644 --- a/include/klee-test-comp.c +++ b/include/klee-test-comp.c @@ -7,11 +7,11 @@ // //===----------------------------------------------------------------------===// +#include #ifdef EXTERNAL #include "klee.h" #include #include -#include #include #else void klee_make_symbolic(void *addr, unsigned int nbytes, const char *name); @@ -19,6 +19,7 @@ void klee_assume(_Bool condition); __attribute__((noreturn)) void klee_silent_exit(int status); void __assert_fail(const char *assertion, const char *file, unsigned int line, const char *function); +void klee_prefer_cex(void *, uintptr_t); #endif int __VERIFIER_nondet_int(void) { @@ -35,11 +36,13 @@ unsigned int __VERIFIER_nondet_uint(void) { return x; } +#ifdef __x86_64__ unsigned __int128 __VERIFIER_nondet_uint128(void) { unsigned __int128 x; klee_make_symbolic(&x, sizeof(x), "unsigned __int128"); return x; } +#endif unsigned __VERIFIER_nondet_unsigned(void) { unsigned x; From 0cf7c49369f8a6107cddcd2e6f083c752284c265 Mon Sep 17 00:00:00 2001 From: Yurii Kostyukov Date: Fri, 3 Nov 2023 13:50:09 +0300 Subject: [PATCH 081/103] [feat] Single-file run script --- scripts/kleef | 432 ++++++++++++++++++++++++++ test/Industry/btor2c-lazyMod.mul6.c | 260 ++++++++++++++++ test/Industry/coverage-error-call.prp | 2 + tools/klee/CMakeLists.txt | 3 + 4 files changed, 697 insertions(+) create mode 100755 scripts/kleef create mode 100644 test/Industry/btor2c-lazyMod.mul6.c create mode 100644 test/Industry/coverage-error-call.prp diff --git a/scripts/kleef b/scripts/kleef new file mode 100755 index 0000000000..be47bde285 --- /dev/null +++ b/scripts/kleef @@ -0,0 +1,432 @@ +#!/usr/bin/env python3 +import argparse +import os +import subprocess +import shutil +import tempfile +import hashlib +from functools import partial +from pathlib import Path + + +def klee_options( + max_memory, + test_output_dir, + source, + hexhash, + max_time, + compiled_file, + is32, + f_err, + f_cov, +): + if max_time and int(max_time) > 30: + MAX_SOLVER_TIME = 10 + else: + MAX_SOLVER_TIME = 5 + cmd = [ + "--strip-unwanted-calls", # removes llvm.dbg.* instructions, exponentially reduces time on some benchmarks + "--delete-dead-loops=false", # without this optimizer removes some code, which decreases coverage + "--emit-all-errors", # without this we generate only one test for assertion failures, which decreases coverage + "--mock-all-externals", # this helps for some linux benchmarks, which have unused extern globals. without this flag we will not even start on them. + "--use-forked-solver=false", + # "--solver-backend=stp", + "--solver-backend=z3-tree", + "--max-solvers-approx-tree-inc=16", + f"--max-memory={int(max_memory * 0.9)}", # Just use half of the memory in case we have to fork + "--optimize", + "--skip-not-lazy-initialized", + f"--output-dir={test_output_dir}", # Output files into specific directory + "--output-source=false", # Do not output assembly.ll - it can be too large + "--output-stats=false", + "--output-istats=false", + # "--istats-write-interval=90s", # Istats file can be large as well + "--write-xml-tests", # Write tests in XML format + f"--xml-metadata-programfile={source.name}", # Provide the name of the original source file + f"--xml-metadata-programhash={hexhash}", # Provide sha256 hash of source file + # "--use-guided-search=none", + "--use-sym-size-alloc=true", + "--cex-cache-validity-cores", + # "--libc=uclibc", + # "--posix-runtime", + # "--fp-runtime", + # "--max-sym-array-size=4096", + "--symbolic-allocation-threshold=8192", + # "--dump-all-states=false", + # "--search=nurs:covnew", + # "--search=nurs:md2u", "--search=random-path", + # "-const-array-opt", + ] + + if is32: + cmd += [ + "--allocate-determ", + f"--allocate-determ-size={min(int(max_memory * 0.6), 3 * 1024)}", + "--allocate-determ-start-address=0x00030000000", + ] + + if f_err: + cmd += [ + "--use-alpha-equivalence=false", + "--function-call-reproduce=reach_error", + # "--max-cycles=0", + # "--tc-type=bug", + "--dump-states-on-halt=false", # Explicitly do not dump states + "--exit-on-error-type=Assert", # Only generate test cases of type assert + # "--dump-test-case-type=Assert", # Only dump test cases of type assert + "--search=dfs", + # "--search=nurs:covnew", "--search=random-path","--search=dfs", "--use-batching-search", + # "--search=distance","--search=random-path","--use-batching-search", + # "--target-assert", # Target + ] + if max_time: + cmd += [ + f"--max-time={int(max_time)}", # Use the whole time + ] + + if f_cov: + cmd += [ + "--mem-trigger-cof", # Start on the fly tests generation after approaching memory cup + "--use-alpha-equivalence=true", + "--track-coverage=all", # Only branches and only instructions are wrong in real life. E.g., ternary operators are sometimes counted as different branches, while we stick to look at them as a single instruction from a single branch + "--use-iterative-deepening-search=max-cycles", + f"--max-solver-time={MAX_SOLVER_TIME}s", + # "--tc-type=cov", + "--only-output-states-covering-new", # Don't generate all test cases + "--dump-states-on-halt=true", # Check in case we missed some oncovered instructions + "--search=dfs", + "--search=random-state", + ] + if max_time: + max_time = float(max_time) + late_time = int(max_time * 0.9) + last_time = int(max_time * 0.97) + cmd += [ + "--cover-on-the-fly=true", + f"--delay-cover-on-the-fly={late_time}", + f"--max-time={last_time}", + ] + + cmd += [compiled_file] # Finally add the file to be tested + return cmd + + +def normalize_command(cmd, shell=False): + if shell: + out = cmd + else: + cmd2 = [x.as_posix() if isinstance(x, Path) else x for x in cmd] + out = " ".join(cmd2) + print("Running:", out) + return out + + +def check_call(cmd, shell=False): + normalize_command(cmd, shell) + subprocess.check_call(cmd, shell=shell) + # p = subprocess.Popen(cmd, stdout=subprocess.PIPE) + # p.communicate() + # print(p.returncode) + + +def locateBinaryOrFail(binary, err_mess=""): + output = shutil.which(binary) + if output is not None: + return Path(output) + print(f"Command '{binary}' not found{err_mess}") + exit(1) + + +def tryFind(folder, binary): + output = folder / binary + if output.exists(): + return output + return locateBinaryOrFail(binary) + + +def printNotNone(s): + if s is not None: + print(s.decode("utf-8")) + + +class KLEEF(object): + """ + Wrapper to run KLEEF within BenchExec + Compiles source and executes KLEEF + """ + + def __init__( + self, + source=None, + is32=False, + f_cov=False, + f_err=False, + max_memory=0, + max_time=0, + use_perf=False, + use_valgrind=False, + ): + self.source = Path(source) if source else None + self.is32 = is32 + self.tempdir = None + self.compiled_file = None + self.f_cov = f_cov + self.f_err = f_err + self.max_memory = max_memory / 1024 / 1024 # Convert to MB + self.max_time = max_time + self.use_perf = use_perf + self.use_valgrind = use_valgrind + + # This file is inside the bin directory - use the root as base + self.bin_directory = Path(__file__).parent + self.base_directory = self.bin_directory.parent + self.klee_path = self.bin_directory / "klee" + self.compiler_path = tryFind(self.bin_directory, "clang") + self.linker_path = tryFind(self.bin_directory, "llvm-link") + self.library_path = self.base_directory / "libraries" + self.runtime_library_path = self.base_directory / "runtime/lib" + self.test_results_path = Path.cwd() / "test-suite" + self.test_results_path.mkdir(exist_ok=True) + + self.callEnv = os.environ.copy() + self.callEnv["LD_LIBRARY_PATH"] = self.library_path + self.callEnv["KLEE_RUNTIME_LIBRARY_PATH"] = self.runtime_library_path + + def compile(self): + self.tempdir = Path(tempfile.mkdtemp()) + + # Compile file for testing + self.compiled_file = self.tempdir / (self.source.name + ".bc") + + compiler_options = [ + self.compiler_path, + "-O0", + "-Xclang", + "-disable-O0-optnone", + "-fbracket-depth=1024", + "-c", + "-g", + "-emit-llvm", + ] + if self.is32: + compiler_options += ["-m32"] + if self.use_perf: + compiler_options += ["-gdwarf-4"] + cmd = compiler_options + [ + "-Wno-everything", # do not print any error statements - we are not allowed to change the code + "-fno-default-inline", + "-o", + self.compiled_file, + self.source, + ] + check_call(cmd) + + # Compile library + compiled_library = self.tempdir / "library.bc" + include_path = self.base_directory / "include/klee-test-comp.c" + cmd = compiler_options + [ + "-o", + compiled_library, + include_path, + ] + check_call(cmd) + + # Link both together to final + cmd = [ + self.linker_path, + "-o", + self.compiled_file, + compiled_library, + self.compiled_file, + ] + check_call(cmd) + + def isModifyingUlimitPermitted(self): + out = subprocess.run( + "ulimit -s unlimited", + shell=True, + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL, + ).returncode + return not out + + def run(self): + test_output_dir = self.test_results_path / self.source.name + # Clean-up from previous runs if needed + shutil.rmtree(test_output_dir, ignore_errors=True) + + # Calculate hashsum of original source file + with open(self.source, mode="rb") as f: + h = hashlib.sha256() + for buf in iter(partial(f.read, 128), b""): + h.update(buf) + + cmd = [self.klee_path] + if self.use_perf: + cmd = ["perf", "record", "-g", "--call-graph", "dwarf"] + cmd + elif self.use_valgrind: + cmd = ["valgrind", "--tool=massif"] + cmd + + # Add common arguments + cmd += klee_options( + self.max_memory, + test_output_dir, + self.source, + h.hexdigest(), + self.max_time, + self.compiled_file, + self.is32, + self.f_err, + self.f_cov, + ) + if self.isModifyingUlimitPermitted(): + cmd = ["ulimit -s unlimited", "&&"] + cmd + cmd = normalize_command(cmd) + + p = subprocess.Popen( + cmd, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + shell=True, + env=self.callEnv, + ) + s_out, s_err = p.communicate() + if not self.use_perf: + printNotNone(s_out) + printNotNone(s_err) + + if self.use_perf: + cmd = "perf script | c++filt | gprof2dot -f perf -s | dot -Tpdf -o output.pdf" + check_call(cmd, shell=True) + + return test_output_dir + + def version(self): + cmd = [self.klee_path, "--version"] + p = subprocess.Popen( + cmd, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + env=self.callEnv, + ) + s_out, s_err = p.communicate() + printNotNone(s_out) + + +def run(args): + if args.version: + wrapper = KLEEF() + wrapper.version() + exit(0) + + # Validation of arguments + if not args.source or not os.path.isfile(args.source): + print("File does not exist", args.source) + exit(1) + + if args.property_file: + with open(args.property_file, "r") as f: + for line in f: + if "@DECISIONEDGE" in line: + args.coverage_only = True + if "@CALL(reach_error)" in line: + args.error_only = True + # Generate wrapper + time = 0 + if args.max_cputime_soft: # Use soft timeout if available + time = args.max_cputime_soft + elif args.max_cputime_hard: + time = args.max_cputime_hard + elif args.max_walltime: + time = args.max_walltime + elif args.max_time: + time = args.max_time + + is32 = None + if vars(args).get("32"): + is32 = True + if vars(args).get("64"): + if is32: + print("Cannot set --64 and --32 simultanously") + exit(1) + is32 = False + + if is32 is None: + print("No architecture set. Assume 64bit") + is32 = False + optAndUsed = [ + (args.perf, "perf", ["perf", "c++filt", "gprof2dot", "dot"]), + (args.valgrind, "valgrind", ["valgrind"]), + ] + for opt, name, used_by_opt in optAndUsed: + if not opt: + continue + for tool in used_by_opt: + locateBinaryOrFail(tool, err_mess=f", so cannot run with option --{name}") + + if args.perf and args.valgrind: + print("Cannot use perf and valgrind at the same time") + exit(1) + wrapper = KLEEF( + source=args.source, + is32=is32, + f_cov=args.coverage_only, + f_err=args.error_only, + max_memory=args.max_memory, + max_time=time, + use_perf=args.perf, + use_valgrind=args.valgrind, + ) + wrapper.compile() + return wrapper.run() + + +def main(): + # Initialize argparse + parser = argparse.ArgumentParser(description="KLEEF single-file runner") + parser.add_argument( + "source", help="klee-out directory to parse", nargs="?", default=None + ) + parser.add_argument("--version", help="print version of klee", action="store_true") + parser.add_argument("--32", help="Compile 32bit binaries", action="store_true") + parser.add_argument("--64", help="Compile 64bit binaries", action="store_true") + parser.add_argument( + "--error-only", help="Focus on searching errors", action="store_true" + ) + parser.add_argument( + "--perf", help="Measure speed with perf", action="store_true", default=False + ) + parser.add_argument( + "--valgrind", + help="Measure memory with valgrind", + action="store_true", + default=False, + ) + parser.add_argument( + "--coverage-only", help="Focus on coverage", action="store_true" + ) + parser.add_argument( + "--max-memory", help="Maximum memory in byte ", type=int, default=2000 + ) + parser.add_argument("--max-time", help="Maximum time in s", type=int, default=0) + parser.add_argument( + "--max-walltime", help="Maximum walltime in s", type=int, default=0 + ) + parser.add_argument( + "--max-cputime-soft", help="Maximum cputime in s (soft)", type=int, default=0 + ) + parser.add_argument( + "--max-cputime-hard", help="Maximum cputime in s (hard)", type=int, default=0 + ) + parser.add_argument( + "--property-file", + help="Property file for test goal description", + type=str, + default=None, + ) + args = parser.parse_args() + run(args) + + +if __name__ == "__main__": + main() diff --git a/test/Industry/btor2c-lazyMod.mul6.c b/test/Industry/btor2c-lazyMod.mul6.c new file mode 100644 index 0000000000..0a1b1dcd5e --- /dev/null +++ b/test/Industry/btor2c-lazyMod.mul6.c @@ -0,0 +1,260 @@ +// It requires Z3 because the script currently runs with Z3 solver backend +//REQUIRES: z3 +//RUN: %kleef --property-file=%S/coverage-error-call.prp --max-memory=7000000000 --max-cputime-soft=30 --64 %s 2>&1 | FileCheck %s +//CHECK: KLEE: WARNING: 100.00% Reachable Reachable + +// This file is part of the SV-Benchmarks collection of verification tasks: +// https://gitlab.com/sosy-lab/benchmarking/sv-benchmarks +// +// SPDX-FileCopyrightText: 2020 Aman Goel +// SPDX-FileCopyrightText: 2022 The SV-Benchmarks Community +// +// SPDX-License-Identifier: GPL-3.0-or-later + +// This C program is converted from Btor2 by Btor2C version bfcfb8b +// with arguments: { architecture=64, lazy_modulo=true, use_memmove=false, unroll_inner_loops=false, shortest_type=true, diff_type=true, decimal_constant=true, zero_init=false, sra_extend_sign=true } +// Comments from the original Btor2 file: +// ; source: https://github.com/aman-goel/avr/tree/92362931700b66684418a991d018c9fbdbebc06f/tests +// ; BTOR description generated by Yosys 0.9+431 (git sha1 4a3b5437, clang 4.0.1-6 -fPIC -Os) for module main. +extern void abort(void); +void reach_error() {} +extern unsigned char __VERIFIER_nondet_uchar(); +extern unsigned short __VERIFIER_nondet_ushort(); +extern unsigned int __VERIFIER_nondet_uint(); +extern unsigned long __VERIFIER_nondet_ulong(); +extern unsigned __int128 __VERIFIER_nondet_uint128(); +void __VERIFIER_assert(int cond) { if (!(cond)) { ERROR: { reach_error(); abort(); } } } +void assume_abort_if_not(int cond) { if (!cond) { abort(); } } +int main() { + // Defining sorts ... + typedef unsigned char SORT_1; // BV with 1 bits + const SORT_1 mask_SORT_1 = (SORT_1)-1 >> (sizeof(SORT_1) * 8 - 1); + const SORT_1 msb_SORT_1 = (SORT_1)1 << (1 - 1); + typedef unsigned long SORT_5; // BV with 64 bits + const SORT_5 mask_SORT_5 = (SORT_5)-1 >> (sizeof(SORT_5) * 8 - 64); + const SORT_5 msb_SORT_5 = (SORT_5)1 << (64 - 1); + typedef unsigned short SORT_8; // BV with 10 bits + const SORT_8 mask_SORT_8 = (SORT_8)-1 >> (sizeof(SORT_8) * 8 - 10); + const SORT_8 msb_SORT_8 = (SORT_8)1 << (10 - 1); + typedef unsigned __int128 SORT_14; // BV with 128 bits + const SORT_14 mask_SORT_14 = (SORT_14)-1 >> (sizeof(SORT_14) * 8 - 128); + const SORT_14 msb_SORT_14 = (SORT_14)1 << (128 - 1); + typedef unsigned int SORT_57; // BV with 32 bits + const SORT_57 mask_SORT_57 = (SORT_57)-1 >> (sizeof(SORT_57) * 8 - 32); + const SORT_57 msb_SORT_57 = (SORT_57)1 << (32 - 1); + // Initializing constants ... + const SORT_1 var_10 = 0; + const SORT_14 var_15 = 0; + const SORT_1 var_24 = 1; + const SORT_5 var_28 = 0; + const SORT_8 var_35 = 0; + const SORT_57 var_58 = 1; + const SORT_57 var_62 = 1000; + const SORT_5 var_64 = 9223372036854775807; + const SORT_5 var_67 = 12245771; + // Collecting input declarations ... + SORT_1 input_2; + SORT_1 input_3; + SORT_1 input_4; + SORT_5 input_6; + SORT_5 input_7; + SORT_8 input_9; + // Collecting state declarations ... + SORT_1 state_11 = __VERIFIER_nondet_uchar() & mask_SORT_1; + SORT_14 state_16 = __VERIFIER_nondet_uint128() & mask_SORT_14; + SORT_14 state_18 = __VERIFIER_nondet_uint128() & mask_SORT_14; + SORT_5 state_29 = __VERIFIER_nondet_ulong() & mask_SORT_5; + SORT_5 state_31 = __VERIFIER_nondet_ulong() & mask_SORT_5; + SORT_8 state_36 = __VERIFIER_nondet_ushort() & mask_SORT_8; + SORT_1 state_38 = __VERIFIER_nondet_uchar() & mask_SORT_1; + SORT_1 state_40 = __VERIFIER_nondet_uchar() & mask_SORT_1; + SORT_5 state_42 = __VERIFIER_nondet_ulong() & mask_SORT_5; + SORT_5 state_44 = __VERIFIER_nondet_ulong() & mask_SORT_5; + // Initializing states ... + SORT_1 init_12_arg_1 = var_10; + state_11 = init_12_arg_1; + SORT_14 init_17_arg_1 = var_15; + state_16 = init_17_arg_1; + SORT_14 init_19_arg_1 = var_15; + state_18 = init_19_arg_1; + SORT_5 init_30_arg_1 = var_28; + state_29 = init_30_arg_1; + SORT_5 init_32_arg_1 = var_28; + state_31 = init_32_arg_1; + SORT_8 init_37_arg_1 = var_35; + state_36 = init_37_arg_1; + SORT_1 init_39_arg_1 = var_24; + state_38 = init_39_arg_1; + SORT_1 init_41_arg_1 = var_24; + state_40 = init_41_arg_1; + SORT_5 init_43_arg_1 = var_28; + state_42 = init_43_arg_1; + SORT_5 init_45_arg_1 = var_28; + state_44 = init_45_arg_1; + for (;;) { + // Getting external input values ... + input_2 = __VERIFIER_nondet_uchar(); + input_3 = __VERIFIER_nondet_uchar(); + input_3 = input_3 & mask_SORT_1; + input_4 = __VERIFIER_nondet_uchar(); + input_4 = input_4 & mask_SORT_1; + input_6 = __VERIFIER_nondet_ulong(); + input_6 = input_6 & mask_SORT_5; + input_7 = __VERIFIER_nondet_ulong(); + input_7 = input_7 & mask_SORT_5; + input_9 = __VERIFIER_nondet_ushort(); + // Assuming invariants ... + // Asserting properties ... + SORT_1 var_13_arg_0 = state_11; + SORT_1 var_13 = ~var_13_arg_0; + SORT_14 var_20_arg_0 = state_16; + SORT_14 var_20_arg_1 = state_18; + SORT_1 var_20 = var_20_arg_0 == var_20_arg_1; + SORT_1 var_21_arg_0 = var_13; + SORT_1 var_21_arg_1 = var_20; + SORT_1 var_21 = var_21_arg_0 | var_21_arg_1; + SORT_1 var_25_arg_0 = var_21; + SORT_1 var_25 = ~var_25_arg_0; + SORT_1 var_26_arg_0 = var_24; + SORT_1 var_26_arg_1 = var_25; + SORT_1 var_26 = var_26_arg_0 & var_26_arg_1; + var_26 = var_26 & mask_SORT_1; + SORT_1 bad_27_arg_0 = var_26; + __VERIFIER_assert(!(bad_27_arg_0)); + // Computing next states ... + SORT_1 next_51_arg_1 = var_24; + SORT_1 var_33_arg_0 = state_11; + SORT_1 var_33 = ~var_33_arg_0; + var_33 = var_33 & mask_SORT_1; + SORT_5 var_52_arg_0 = state_29; + var_52_arg_0 = var_52_arg_0 & mask_SORT_5; + SORT_14 var_52 = var_52_arg_0; + SORT_5 var_53_arg_0 = state_31; + var_53_arg_0 = var_53_arg_0 & mask_SORT_5; + SORT_14 var_53 = var_53_arg_0; + SORT_14 var_54_arg_0 = var_52; + SORT_14 var_54_arg_1 = var_53; + SORT_14 var_54 = var_54_arg_0 * var_54_arg_1; + SORT_1 var_55_arg_0 = var_33; + SORT_14 var_55_arg_1 = var_15; + SORT_14 var_55_arg_2 = var_54; + SORT_14 var_55 = var_55_arg_0 ? var_55_arg_1 : var_55_arg_2; + var_55 = var_55 & mask_SORT_14; + SORT_14 next_56_arg_1 = var_55; + SORT_1 var_71_arg_0 = state_38; + SORT_1 var_71_arg_1 = state_40; + SORT_1 var_71 = var_71_arg_0 | var_71_arg_1; + var_71 = var_71 & mask_SORT_1; + SORT_8 var_61_arg_0 = state_36; + var_61_arg_0 = var_61_arg_0 & mask_SORT_8; + SORT_57 var_61 = var_61_arg_0; + SORT_57 var_63_arg_0 = var_61; + SORT_57 var_63_arg_1 = var_62; + SORT_1 var_63 = var_63_arg_0 > var_63_arg_1; + SORT_5 var_65_arg_0 = input_6; + SORT_5 var_65_arg_1 = var_64; + SORT_1 var_65 = var_65_arg_0 == var_65_arg_1; + SORT_1 var_66_arg_0 = var_63; + SORT_1 var_66_arg_1 = var_65; + SORT_1 var_66 = var_66_arg_0 & var_66_arg_1; + SORT_5 var_68_arg_0 = input_7; + SORT_5 var_68_arg_1 = var_67; + SORT_1 var_68 = var_68_arg_0 == var_68_arg_1; + SORT_1 var_69_arg_0 = var_66; + SORT_1 var_69_arg_1 = var_68; + SORT_1 var_69 = var_69_arg_0 & var_69_arg_1; + var_69 = var_69 & mask_SORT_1; + SORT_5 var_46_arg_0 = state_42; + var_46_arg_0 = var_46_arg_0 & mask_SORT_5; + SORT_14 var_46 = var_46_arg_0; + SORT_5 var_47_arg_0 = state_44; + var_47_arg_0 = var_47_arg_0 & mask_SORT_5; + SORT_14 var_47 = var_47_arg_0; + SORT_14 var_48_arg_0 = var_46; + SORT_14 var_48_arg_1 = var_47; + SORT_14 var_48 = var_48_arg_0 * var_48_arg_1; + SORT_57 var_59_arg_0 = var_58; + var_59_arg_0 = var_59_arg_0 & mask_SORT_57; + SORT_14 var_59 = var_59_arg_0; + SORT_14 var_60_arg_0 = var_48; + SORT_14 var_60_arg_1 = var_59; + SORT_14 var_60 = var_60_arg_0 + var_60_arg_1; + SORT_1 var_70_arg_0 = var_69; + SORT_14 var_70_arg_1 = var_60; + SORT_14 var_70_arg_2 = var_48; + SORT_14 var_70 = var_70_arg_0 ? var_70_arg_1 : var_70_arg_2; + SORT_1 var_72_arg_0 = var_71; + SORT_14 var_72_arg_1 = var_70; + SORT_14 var_72_arg_2 = state_18; + SORT_14 var_72 = var_72_arg_0 ? var_72_arg_1 : var_72_arg_2; + SORT_1 var_73_arg_0 = var_33; + SORT_14 var_73_arg_1 = var_15; + SORT_14 var_73_arg_2 = var_72; + SORT_14 var_73 = var_73_arg_0 ? var_73_arg_1 : var_73_arg_2; + var_73 = var_73 & mask_SORT_14; + SORT_14 next_74_arg_1 = var_73; + SORT_1 var_75_arg_0 = input_3; + SORT_5 var_75_arg_1 = input_6; + SORT_5 var_75_arg_2 = state_29; + SORT_5 var_75 = var_75_arg_0 ? var_75_arg_1 : var_75_arg_2; + SORT_1 var_76_arg_0 = var_33; + SORT_5 var_76_arg_1 = var_28; + SORT_5 var_76_arg_2 = var_75; + SORT_5 var_76 = var_76_arg_0 ? var_76_arg_1 : var_76_arg_2; + SORT_5 next_77_arg_1 = var_76; + SORT_1 var_78_arg_0 = input_4; + SORT_5 var_78_arg_1 = input_7; + SORT_5 var_78_arg_2 = state_31; + SORT_5 var_78 = var_78_arg_0 ? var_78_arg_1 : var_78_arg_2; + SORT_1 var_79_arg_0 = var_33; + SORT_5 var_79_arg_1 = var_28; + SORT_5 var_79_arg_2 = var_78; + SORT_5 var_79 = var_79_arg_0 ? var_79_arg_1 : var_79_arg_2; + SORT_5 next_80_arg_1 = var_79; + SORT_1 var_81_arg_0 = var_33; + SORT_8 var_81_arg_1 = input_9; + SORT_8 var_81_arg_2 = state_36; + SORT_8 var_81 = var_81_arg_0 ? var_81_arg_1 : var_81_arg_2; + SORT_8 next_82_arg_1 = var_81; + SORT_1 var_83_arg_0 = var_33; + SORT_1 var_83_arg_1 = var_24; + SORT_1 var_83_arg_2 = input_3; + SORT_1 var_83 = var_83_arg_0 ? var_83_arg_1 : var_83_arg_2; + SORT_1 next_84_arg_1 = var_83; + SORT_1 var_85_arg_0 = var_33; + SORT_1 var_85_arg_1 = var_24; + SORT_1 var_85_arg_2 = input_4; + SORT_1 var_85 = var_85_arg_0 ? var_85_arg_1 : var_85_arg_2; + SORT_1 next_86_arg_1 = var_85; + SORT_1 var_87_arg_0 = input_3; + SORT_5 var_87_arg_1 = input_6; + SORT_5 var_87_arg_2 = state_42; + SORT_5 var_87 = var_87_arg_0 ? var_87_arg_1 : var_87_arg_2; + SORT_1 var_88_arg_0 = var_33; + SORT_5 var_88_arg_1 = var_28; + SORT_5 var_88_arg_2 = var_87; + SORT_5 var_88 = var_88_arg_0 ? var_88_arg_1 : var_88_arg_2; + SORT_5 next_89_arg_1 = var_88; + SORT_1 var_90_arg_0 = input_4; + SORT_5 var_90_arg_1 = input_7; + SORT_5 var_90_arg_2 = state_44; + SORT_5 var_90 = var_90_arg_0 ? var_90_arg_1 : var_90_arg_2; + SORT_1 var_91_arg_0 = var_33; + SORT_5 var_91_arg_1 = var_28; + SORT_5 var_91_arg_2 = var_90; + SORT_5 var_91 = var_91_arg_0 ? var_91_arg_1 : var_91_arg_2; + SORT_5 next_92_arg_1 = var_91; + // Assigning next states ... + state_11 = next_51_arg_1; + state_16 = next_56_arg_1; + state_18 = next_74_arg_1; + state_29 = next_77_arg_1; + state_31 = next_80_arg_1; + state_36 = next_82_arg_1; + state_38 = next_84_arg_1; + state_40 = next_86_arg_1; + state_42 = next_89_arg_1; + state_44 = next_92_arg_1; + } + return 0; +} diff --git a/test/Industry/coverage-error-call.prp b/test/Industry/coverage-error-call.prp new file mode 100644 index 0000000000..496ed998fa --- /dev/null +++ b/test/Industry/coverage-error-call.prp @@ -0,0 +1,2 @@ +COVER( init(main()), FQL(COVER EDGES(@CALL(reach_error))) ) + diff --git a/tools/klee/CMakeLists.txt b/tools/klee/CMakeLists.txt index cabdfdfcbd..5d63f93901 100644 --- a/tools/klee/CMakeLists.txt +++ b/tools/klee/CMakeLists.txt @@ -20,6 +20,9 @@ target_compile_options(klee PRIVATE ${KLEE_COMPONENT_CXX_FLAGS}) target_compile_definitions(klee PRIVATE ${KLEE_COMPONENT_CXX_DEFINES}) +# Copy run script +configure_file(${CMAKE_SOURCE_DIR}/scripts/kleef ${CMAKE_BINARY_DIR}/bin/kleef COPYONLY) + install(TARGETS klee RUNTIME DESTINATION bin) # The KLEE binary depends on the runtimes From 3b81fd8d1cd337702285bd625a33ed3beba717b7 Mon Sep 17 00:00:00 2001 From: Yurii Kostyukov Date: Tue, 7 Nov 2023 11:08:58 +0300 Subject: [PATCH 082/103] [chore] Updated README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7038b9a745..b1577b18b3 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,6 @@ KLEEF Symbolic Virtual Machine [![Build Status](https://github.com/UnitTestBot/klee/workflows/CI/badge.svg)](https://github.com/UnitTestBot/klee/actions?query=workflow%3ACI) [![Coverage](https://codecov.io/gh/UnitTestBot/klee/branch/main/graph/badge.svg)](https://codecov.io/gh/UnitTestBot/klee) +`KLEEF` is a complete overhaul of the KLEE symbolic execution engine for LLVM, fine-tuned for a robust analysis of industrial C/C++ code. -`KLEEF`` is a complete overhaul of the KLEE symbolic execution engine for LLVM, fine-tuned for a robust analysis of industrial C/C++ code. For further information, see the [webpage](https://toolchain-labs.com/projects/kleef.html). From 984f5e646825e36dc0915b4033bf8d922851d376 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Sun, 5 Nov 2023 19:08:40 +0400 Subject: [PATCH 083/103] [feat] Improve coverage branches tests --- runtime/Runtest/intrinsics.c | 5 +- scripts/replay.sh | 14 +++ ...henFlurMukhopadhyay-2012SAS-Fig1-alloca.c} | 14 ++- .../CoverageBranches/CostasArray-17.c} | 45 +++++-- .../CoverageBranches/egcd3-ll_valuebound10.c | 111 ++++++++++++++++++ test/Industry/CoverageBranches/lit.local.cfg | 8 ++ ...r.3.ufo.UNBOUNDED.pals+Problem12_label00.c | 41 +++++-- test/Industry/egcd3-ll_valuebound10.c | 39 +++++- test/Industry/ll_create_rec-alloca-2.c | 4 +- .../replay_invalid_klee_assume.c | 2 +- .../replay_invalid_klee_choose.c | 2 +- .../replay_invalid_klee_range.c | 2 +- .../replay_invalid_num_objects.c | 2 +- .../replay_invalid_object_names.c | 2 +- .../replay_invalid_object_size.c | 2 +- test/lit.cfg | 13 ++ ...eplay-test-with-lazy-initialized-objects.c | 11 +- test/regression/2023-10-13-kbfiltr.i.cil-2.c | 5 +- 18 files changed, 273 insertions(+), 49 deletions(-) create mode 100755 scripts/replay.sh rename test/{regression/2023-10-06-ChenFlurMukhopadhyay-2012SAS-Fig1-alloca.c => Industry/CoverageBranches/ChenFlurMukhopadhyay-2012SAS-Fig1-alloca.c} (56%) rename test/{regression/2023-10-16-CostasArray-17.c => Industry/CoverageBranches/CostasArray-17.c} (97%) create mode 100644 test/Industry/CoverageBranches/egcd3-ll_valuebound10.c create mode 100644 test/Industry/CoverageBranches/lit.local.cfg rename test/Industry/{ => CoverageBranches}/pals_lcr.3.ufo.UNBOUNDED.pals+Problem12_label00.c (99%) diff --git a/runtime/Runtest/intrinsics.c b/runtime/Runtest/intrinsics.c index 34a9e9d2c8..7372549b93 100644 --- a/runtime/Runtest/intrinsics.c +++ b/runtime/Runtest/intrinsics.c @@ -43,7 +43,10 @@ static void report_internal_error(const char *msg, ...) { va_end(ap); fprintf(stderr, "\n"); char *testErrorsNonFatal = getenv("KLEE_RUN_TEST_ERRORS_NON_FATAL"); - if (testErrorsNonFatal) { + if (testErrorsNonFatal && !strcmp(testErrorsNonFatal, "STOP")) { + fprintf(stderr, "KLEE_RUN_TEST_ERROR: Stop execution without an error\n"); + exit(0); + } else if (testErrorsNonFatal && !strcmp(testErrorsNonFatal, "FORCE")) { fprintf(stderr, "KLEE_RUN_TEST_ERROR: Forcing execution to continue\n"); } else { exit(1); diff --git a/scripts/replay.sh b/scripts/replay.sh new file mode 100755 index 0000000000..2673c91e4a --- /dev/null +++ b/scripts/replay.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash + +# ===-- replay.sh --------------------------------------------------------===## +# +# The KLEE Symbolic Virtual Machine +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +# ===----------------------------------------------------------------------===## + +for f in `find $1 -name "*.ktest" -type f`; do + KLEE_RUN_TEST_ERRORS_NON_FATAL=STOP KTEST_FILE=$f timeout 1 $2 +done diff --git a/test/regression/2023-10-06-ChenFlurMukhopadhyay-2012SAS-Fig1-alloca.c b/test/Industry/CoverageBranches/ChenFlurMukhopadhyay-2012SAS-Fig1-alloca.c similarity index 56% rename from test/regression/2023-10-06-ChenFlurMukhopadhyay-2012SAS-Fig1-alloca.c rename to test/Industry/CoverageBranches/ChenFlurMukhopadhyay-2012SAS-Fig1-alloca.c index 25d674dcb7..b0efaf937e 100644 --- a/test/regression/2023-10-06-ChenFlurMukhopadhyay-2012SAS-Fig1-alloca.c +++ b/test/Industry/CoverageBranches/ChenFlurMukhopadhyay-2012SAS-Fig1-alloca.c @@ -1,7 +1,19 @@ -// RUN: %clang -Wno-everything %s -emit-llvm %O0opt -g -c -o %t1.bc +// RUN: %clang -Wno-everything %s -emit-llvm %O0opt -g -c -o %t1.bc // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --optimize-aggressive=false --track-coverage=branches --optimize=true --delete-dead-loops=false --use-forked-solver=false -max-memory=6008 --cex-cache-validity-cores --only-output-states-covering-new=true --dump-states-on-halt=true %t1.bc 2>&1 | FileCheck -check-prefix=CHECK %s +// RUN: rm -f %t*.gcda %t*.gcno %t*.gcov +// RUN: %cc -DGCOV %s %libkleeruntest -Wl,-rpath %libkleeruntestdir -o %t_runner --coverage +// RUN: %replay %t.klee-out %t_runner +// RUN: gcov -b %t_runner-%basename_t > %t.cov.log + +// RUN: FileCheck --input-file=%t.cov.log --check-prefix=CHECK-COV %s + +// Branch coverage 100%, the number of branches is 1: +// CHECK-COV: Lines executed:100.00% of 11 +// CHECK-COV-NEXT: Branches executed:100.00% of 2 +// CHECK-COV-NEXT: Taken at least once:100.00% of 2 + #include "klee-test-comp.c" extern int __VERIFIER_nondet_int(void); diff --git a/test/regression/2023-10-16-CostasArray-17.c b/test/Industry/CoverageBranches/CostasArray-17.c similarity index 97% rename from test/regression/2023-10-16-CostasArray-17.c rename to test/Industry/CoverageBranches/CostasArray-17.c index ed1651a15d..6f326016af 100644 --- a/test/regression/2023-10-16-CostasArray-17.c +++ b/test/Industry/CoverageBranches/CostasArray-17.c @@ -1,21 +1,28 @@ -// RUN: %clang -Wno-everything %s -emit-llvm %O0opt -g -c -o %t1.bc +// RUN: %clang -Wno-everything %s -emit-llvm %O0opt -g -c -o %t1.bc // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --optimize-aggressive --track-coverage=branches --optimize=true --emit-all-errors --only-output-states-covering-new=true --dump-states-on-halt=true --search=dfs %t1.bc -// RUN: %klee-stats --print-columns ' Branches,ICov(%),BCov(%)' --table-format=csv %t.klee-out > %t.stats -// RUN: FileCheck --input-file=%t.stats --check-prefix=CHECK-AGGRESSIVE %s -// Branch coverage 100%, the number of branches is 1: -// CHECK-AGGRESSIVE: Branches,ICov(%),BCov(%) -// CHECK-AGGRESSIVE-NEXT: 1,{{(0\.[0-9][0-9])}},100.00 +// RUN: rm -f %t*.gcda %t*.gcno %t*.gcov +// RUN: %cc -DGCOV %s %libkleeruntest -Wl,-rpath %libkleeruntestdir -o %t_runner --coverage +// RUN: %replay %t.klee-out %t_runner +// RUN: gcov -b %t_runner-%basename_t > %t.cov.log + +// RUN: FileCheck --input-file=%t.cov.log --check-prefix=CHECK %s // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --optimize-aggressive=false --track-coverage=branches --optimize=true --emit-all-errors --only-output-states-covering-new=true --dump-states-on-halt=true --search=dfs %t1.bc -// RUN: %klee-stats --print-columns ' Branches,ICov(%),BCov(%)' --table-format=csv %t.klee-out > %t.stats -// RUN: FileCheck --input-file=%t.stats --check-prefix=CHECK-NOT-AGGRESSIVE %s -// Branch coverage 50%, but the number of branches is 2: -// CHECK-NOT-AGGRESSIVE: Branches,ICov(%),BCov(%) -// CHECK-NOT-AGGRESSIVE-NEXT: 2,{{(0\.[0-9][0-9])}},50.00 +// RUN: rm -f %t*.gcda %t*.gcno %t*.gcov +// RUN: %cc -DGCOV %s %libkleeruntest -Wl,-rpath %libkleeruntestdir -o %t_runner --coverage +// RUN: %replay %t.klee-out %t_runner +// RUN: gcov -b %t_runner-%basename_t > %t.cov.log + +// RUN: FileCheck --input-file=%t.cov.log --check-prefix=CHECK %s + +// Branch coverage 100%, the number of branches is 1: +// CHECK: Lines executed:{{(0\.7[0-9])}}% of 1545 +// CHECK-NEXT: Branches executed:100.00% of 2 +// CHECK-NEXT: Taken at least once:100.00% of 2 #include "klee-test-comp.c" @@ -34,10 +41,24 @@ extern void __assert_fail(const char *, const char *, unsigned int, const char *) __attribute__((__nothrow__, __leaf__)) __attribute__((__noreturn__)); int __VERIFIER_nondet_int(); + +#ifdef GCOV +extern void __gcov_dump(void); +#endif + +void abort_prog() { +#ifdef GCOV + __gcov_dump(); + exit(0); +#else + abort(); +#endif +} + void reach_error() { __assert_fail("0", "CostasArray-17.c", 5, "reach_error"); } void assume(int cond) { if (!cond) - abort(); + abort_prog(); } int main() { int cond0; diff --git a/test/Industry/CoverageBranches/egcd3-ll_valuebound10.c b/test/Industry/CoverageBranches/egcd3-ll_valuebound10.c new file mode 100644 index 0000000000..72396f861a --- /dev/null +++ b/test/Industry/CoverageBranches/egcd3-ll_valuebound10.c @@ -0,0 +1,111 @@ +// RUN: %clang %s -emit-llvm %O0opt -g -c -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --delete-dead-loops=false --emit-all-errors --mock-all-externals --use-forked-solver=false --max-memory=6008 --optimize --skip-not-lazy-initialized --output-source=false --output-stats=true --output-istats=true -istats-write-interval=90s --use-sym-size-alloc=true --cex-cache-validity-cores --symbolic-allocation-threshold=8192 --max-solver-time=5s --track-coverage=branches --use-iterative-deepening-search=max-cycles --cover-on-the-fly=false --delay-cover-on-the-fly=400000 --only-output-states-covering-new --dump-states-on-halt=true --search=dfs --search=random-state %t1.bc + +// RUN: rm -f %t*.gcda %t*.gcno %t*.gcov +// RUN: %cc -DGCOV %s %libkleeruntest -Wl,-rpath %libkleeruntestdir -o %t_runner --coverage +// RUN: %replay %t.klee-out %t_runner +// RUN: gcov -b %t_runner-%basename_t > %t.cov.log + +// RUN: FileCheck --input-file=%t.cov.log --check-prefix=CHECK %s + +// Branch coverage 100%, the number of branches is 1: +// CHECK: Lines executed:87.93% of 58 +// CHECK-NEXT: Branches executed:100.00% of 18 +// CHECK-NEXT: Taken at least once:83.33% of 18 + +#include "klee-test-comp.c" +/* extended Euclid's algorithm */ +extern void abort(void); +#ifdef GCOV +extern void __gcov_dump(void); +#endif + +void dump() { +#ifdef GCOV + __gcov_dump(); +#endif +} + +void abort_prog() { +#ifdef GCOV + __gcov_dump(); + exit(0); +#else + abort(); +#endif +} +extern void __assert_fail(const char *, const char *, unsigned int, const char *) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__noreturn__)); +void reach_error() { dump(); __assert_fail("0", "egcd3-ll.c", 4, "reach_error"); } +extern int __VERIFIER_nondet_int(void); +extern void abort(void); +void assume_abort_if_not(int cond) { + if(!cond) {abort_prog();} +} +void __VERIFIER_assert(int cond) { + if (!(cond)) { + ERROR: + {reach_error();} + } + return; +} + +int main() { + int x, y; + long long a, b, p, q, r, s; + x = __VERIFIER_nondet_int(); + assume_abort_if_not(x>=0 && x<=10); + y = __VERIFIER_nondet_int(); + assume_abort_if_not(y>=0 && y<=10); + assume_abort_if_not(x >= 1); + assume_abort_if_not(y >= 1); + + a = x; + b = y; + p = 1; + q = 0; + r = 0; + s = 1; + + while (1) { + if (!(b != 0)) + break; + long long c, k; + c = a; + k = 0; + + while (1) { + if (!(c >= b)) + break; + long long d, v; + d = 1; + v = b; + + while (1) { + __VERIFIER_assert(a == y * r + x * p); + __VERIFIER_assert(b == x * q + y * s); + __VERIFIER_assert(a == k * b + c); + __VERIFIER_assert(v == b * d); + + if (!(c >= 2 * v)) + break; + d = 2 * d; + v = 2 * v; + } + c = c - v; + k = k + d; + } + + a = b; + b = c; + long long temp; + temp = p; + p = q; + q = temp - q * k; + temp = r; + r = s; + s = temp - s * k; + } + __VERIFIER_assert(p*x - q*x + r*y - s*y == a); + return 0; +} diff --git a/test/Industry/CoverageBranches/lit.local.cfg b/test/Industry/CoverageBranches/lit.local.cfg new file mode 100644 index 0000000000..ad131f8f64 --- /dev/null +++ b/test/Industry/CoverageBranches/lit.local.cfg @@ -0,0 +1,8 @@ +def getRoot(config): + if not config.parent: + return config + return getRoot(config.parent) + +rootConfig = getRoot(config) +if config.have_asan or config.have_ubsan or config.have_msan or config.target_triple.find("darwin") != -1: + config.unsupported = True diff --git a/test/Industry/pals_lcr.3.ufo.UNBOUNDED.pals+Problem12_label00.c b/test/Industry/CoverageBranches/pals_lcr.3.ufo.UNBOUNDED.pals+Problem12_label00.c similarity index 99% rename from test/Industry/pals_lcr.3.ufo.UNBOUNDED.pals+Problem12_label00.c rename to test/Industry/CoverageBranches/pals_lcr.3.ufo.UNBOUNDED.pals+Problem12_label00.c index 0c49afc42e..adb6d27c74 100644 --- a/test/Industry/pals_lcr.3.ufo.UNBOUNDED.pals+Problem12_label00.c +++ b/test/Industry/CoverageBranches/pals_lcr.3.ufo.UNBOUNDED.pals+Problem12_label00.c @@ -1,13 +1,19 @@ -// REQUIRES: geq-llvm-14.0 +// REQUIRES: z3 // RUN: %clang %s -emit-llvm %O0opt -g -c -o %t1.bc // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --optimize-aggressive=false --track-coverage=branches --delete-dead-loops=false --emit-all-errors --mock-all-externals --use-forked-solver=false --optimize --skip-not-lazy-initialized --output-source=false --output-stats=true --output-istats=true -istats-write-interval=3s --use-sym-size-alloc=true --cex-cache-validity-cores --symbolic-allocation-threshold=8192 --cover-on-the-fly=false --delay-cover-on-the-fly=400000 --only-output-states-covering-new --dump-states-on-halt=true --search=dfs --search=random-state --use-iterative-deepening-search=max-cycles --max-cycles=4 %t1.bc -// RUN: %klee-stats --print-columns 'BCov(%)' --table-format=csv %t.klee-out > %t.stats -// RUN: FileCheck -input-file=%t.stats %s -// Branch coverage at least 94%: -// CHECK: BCov(%) -// CHECK-NEXT: {{(9[4-9]|100)\.}} +// RUN: rm -f %t*.gcda %t*.gcno %t*.gcov +// RUN: %cc -DGCOV %s %libkleeruntest -Wl,-rpath %libkleeruntestdir -o %t_runner --coverage +// RUN: %replay %t.klee-out %t_runner +// RUN: gcov -b %t_runner-%basename_t > %t.cov.log + +// RUN: FileCheck --input-file=%t.cov.log --check-prefix=CHECK %s + +// Branch coverage 89.29% +// CHECK: Lines executed:{{(9[0-9]\.[0-9][0-9])}}% of 4114 +// CHECK-NEXT: Branches executed:{{(9[0-9]\.[0-9][0-9])}}% of 13404 +// CHECK-NEXT: Taken at least once:{{(8[0-9]\.[0-9][0-9])}}% of 13404 // This file is part of the SV-Benchmarks collection of verification tasks: // https://gitlab.com/sosy-lab/benchmarking/sv-benchmarks @@ -28,8 +34,27 @@ extern unsigned long __VERIFIER_nondet_ulong(); extern float __VERIFIER_nondet_float(); extern void exit(int); extern void abort(void); +#ifdef GCOV +extern void __gcov_dump(void); +#endif + +void dump() { +#ifdef GCOV + __gcov_dump(); + exit(0); +#endif +} + +void abort_prog() { +#ifdef GCOV + __gcov_dump(); + exit(0); +#else + abort(); +#endif +} extern void __assert_fail(const char *, const char *, unsigned int, const char *) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__noreturn__)); -void reach_error() { __assert_fail("0", "pals_lcr.3.ufo.UNBOUNDED.pals.c", 3, "reach_error"); } +void reach_error() { dump(); __assert_fail("0", "pals_lcr.3.ufo.UNBOUNDED.pals.c", 3, "reach_error"); } /* Generated by CIL v. 1.6.0 */ @@ -41,7 +66,7 @@ unsigned char __VERIFIER_nondet_uchar(void) ; void assert(_Bool arg ) ; void abort(void); void assume_abort_if_not(int cond) { - if(!cond) {abort();} + if(!cond) {abort_prog();} } typedef char msg_t; typedef int port_t; diff --git a/test/Industry/egcd3-ll_valuebound10.c b/test/Industry/egcd3-ll_valuebound10.c index 5fd1bc76d1..cf89ea4af7 100644 --- a/test/Industry/egcd3-ll_valuebound10.c +++ b/test/Industry/egcd3-ll_valuebound10.c @@ -1,20 +1,47 @@ +// REQUIRES: not-darwin, not-san // RUN: %clang %s -emit-llvm %O0opt -g -c -o %t1.bc // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --delete-dead-loops=false --emit-all-errors --mock-all-externals --use-forked-solver=false --max-memory=6008 --optimize --skip-not-lazy-initialized --output-source=false --output-stats=true --output-istats=true -istats-write-interval=90s --use-sym-size-alloc=true --cex-cache-validity-cores --symbolic-allocation-threshold=8192 --max-solver-time=5s --track-coverage=branches --use-iterative-deepening-search=max-cycles --cover-on-the-fly=false --delay-cover-on-the-fly=400000 --only-output-states-covering-new --dump-states-on-halt=true --search=dfs --search=random-state %t1.bc -// RUN: %klee-stats --print-columns 'BCov(%)' --table-format=csv %t.klee-out > %t.stats -// RUN: FileCheck -input-file=%t.stats %s -// CHECK: BCov(%) -// CHECK-NEXT: {{(8[5-9]|9[0-9]|100)\.}} + +// RUN: rm -f %t*.gcda %t*.gcno %t*.gcov +// RUN: %cc -DGCOV %s %libkleeruntest -Wl,-rpath %libkleeruntestdir -o %t_runner --coverage +// RUN: %replay %t.klee-out %t_runner +// RUN: gcov -b %t_runner-%basename_t > %t.cov.log + +// RUN: FileCheck --input-file=%t.cov.log --check-prefix=CHECK %s + +// Branch coverage 100%, the number of branches is 1: +// CHECK: Lines executed:87.93% of 58 +// CHECK-NEXT: Branches executed:100.00% of 18 +// CHECK-NEXT: Taken at least once:83.33% of 18 #include "klee-test-comp.c" /* extended Euclid's algorithm */ extern void abort(void); +#ifdef GCOV +extern void __gcov_dump(void); +#endif + +void dump() { +#ifdef GCOV + __gcov_dump(); +#endif +} + +void abort_prog() { +#ifdef GCOV + __gcov_dump(); + exit(0); +#else + abort(); +#endif +} extern void __assert_fail(const char *, const char *, unsigned int, const char *) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__noreturn__)); -void reach_error() { __assert_fail("0", "egcd3-ll.c", 4, "reach_error"); } +void reach_error() { dump(); __assert_fail("0", "egcd3-ll.c", 4, "reach_error"); } extern int __VERIFIER_nondet_int(void); extern void abort(void); void assume_abort_if_not(int cond) { - if(!cond) {abort();} + if(!cond) {abort_prog();} } void __VERIFIER_assert(int cond) { if (!(cond)) { diff --git a/test/Industry/ll_create_rec-alloca-2.c b/test/Industry/ll_create_rec-alloca-2.c index 127a38df5f..a91b65235c 100644 --- a/test/Industry/ll_create_rec-alloca-2.c +++ b/test/Industry/ll_create_rec-alloca-2.c @@ -4,7 +4,7 @@ // RUN: %klee-stats --print-columns 'ICov(%),BCov(%)' --table-format=csv %t.klee-out > %t.stats // RUN: FileCheck -check-prefix=CHECK-BRANCH -input-file=%t.stats %s -// Branch coverage 100%, and instruction coverage is very small: +// Branch coverage 100%, and instruction coverage may vary: // CHECK-BRANCH: ICov(%),BCov(%) // CHECK-BRANCH-NEXT: {{([1-9][0-9]\.[0-9][0-9])}},100.00 @@ -13,7 +13,7 @@ // RUN: %klee-stats --print-columns 'ICov(%),BCov(%)' --table-format=csv %t.klee-out > %t.stats // RUN: FileCheck -check-prefix=CHECK-BLOCK -input-file=%t.stats %s -// Branch coverage 100%, and instruction coverage is very small: +// Branch coverage 100%, and instruction 100%: // CHECK-BLOCK: ICov(%),BCov(%) // CHECK-BLOCK-NEXT: 100.00,100.00 diff --git a/test/Replay/libkleeruntest/replay_invalid_klee_assume.c b/test/Replay/libkleeruntest/replay_invalid_klee_assume.c index 89584d6a29..b83cce79e6 100644 --- a/test/Replay/libkleeruntest/replay_invalid_klee_assume.c +++ b/test/Replay/libkleeruntest/replay_invalid_klee_assume.c @@ -13,7 +13,7 @@ // Check that setting `KLEE_RUN_TEST_ERRORS_NON_FATAL` will not exit with an error // and will continue executing. -// RUN: env KTEST_FILE=%t.klee-out/test000001.ktest KLEE_RUN_TEST_ERRORS_NON_FATAL=1 %t_runner 2>&1 | FileCheck %s +// RUN: env KTEST_FILE=%t.klee-out/test000001.ktest KLEE_RUN_TEST_ERRORS_NON_FATAL=FORCE %t_runner 2>&1 | FileCheck %s #include "klee/klee.h" #include diff --git a/test/Replay/libkleeruntest/replay_invalid_klee_choose.c b/test/Replay/libkleeruntest/replay_invalid_klee_choose.c index 32cd136489..9f114d74d9 100644 --- a/test/Replay/libkleeruntest/replay_invalid_klee_choose.c +++ b/test/Replay/libkleeruntest/replay_invalid_klee_choose.c @@ -13,7 +13,7 @@ // Check that setting `KLEE_RUN_TEST_ERRORS_NON_FATAL` will not exit with an error // and will continue executing. -// RUN: env KTEST_FILE=%t.klee-out/test000001.ktest KLEE_RUN_TEST_ERRORS_NON_FATAL=1 %t_runner 2>&1 | FileCheck %s +// RUN: env KTEST_FILE=%t.klee-out/test000001.ktest KLEE_RUN_TEST_ERRORS_NON_FATAL=FORCE %t_runner 2>&1 | FileCheck %s #include "klee/klee.h" #include diff --git a/test/Replay/libkleeruntest/replay_invalid_klee_range.c b/test/Replay/libkleeruntest/replay_invalid_klee_range.c index f342a56aca..7cb016dd28 100644 --- a/test/Replay/libkleeruntest/replay_invalid_klee_range.c +++ b/test/Replay/libkleeruntest/replay_invalid_klee_range.c @@ -13,7 +13,7 @@ // Check that setting `KLEE_RUN_TEST_ERRORS_NON_FATAL` will not exit with an error // and will continue executing. -// RUN: env KTEST_FILE=%t.klee-out/test000001.ktest KLEE_RUN_TEST_ERRORS_NON_FATAL=1 %t_runner 2>&1 | FileCheck %s +// RUN: env KTEST_FILE=%t.klee-out/test000001.ktest KLEE_RUN_TEST_ERRORS_NON_FATAL=FORCE %t_runner 2>&1 | FileCheck %s #include "klee/klee.h" #include diff --git a/test/Replay/libkleeruntest/replay_invalid_num_objects.c b/test/Replay/libkleeruntest/replay_invalid_num_objects.c index ca5615ccc0..8bc5d08d1b 100644 --- a/test/Replay/libkleeruntest/replay_invalid_num_objects.c +++ b/test/Replay/libkleeruntest/replay_invalid_num_objects.c @@ -13,7 +13,7 @@ // Check that setting `KLEE_RUN_TEST_ERRORS_NON_FATAL` will not exit with an error // and will continue executing. -// RUN: env KTEST_FILE=%t.klee-out/test000001.ktest KLEE_RUN_TEST_ERRORS_NON_FATAL=1 %t_runner 2>&1 | FileCheck %s +// RUN: env KTEST_FILE=%t.klee-out/test000001.ktest KLEE_RUN_TEST_ERRORS_NON_FATAL=FORCE %t_runner 2>&1 | FileCheck %s #include "klee/klee.h" #include diff --git a/test/Replay/libkleeruntest/replay_invalid_object_names.c b/test/Replay/libkleeruntest/replay_invalid_object_names.c index 88e81e1bd8..4111da54d5 100644 --- a/test/Replay/libkleeruntest/replay_invalid_object_names.c +++ b/test/Replay/libkleeruntest/replay_invalid_object_names.c @@ -12,7 +12,7 @@ // Check that setting `KLEE_RUN_TEST_ERRORS_NON_FATAL` will not exit with an error // and will continue executing. -// RUN: env KTEST_FILE=%t.klee-out/test000001.ktest KLEE_RUN_TEST_ERRORS_NON_FATAL=1 %t_runner 2>&1 | FileCheck %s +// RUN: env KTEST_FILE=%t.klee-out/test000001.ktest KLEE_RUN_TEST_ERRORS_NON_FATAL=FORCE %t_runner 2>&1 | FileCheck %s #include "klee/klee.h" #include diff --git a/test/Replay/libkleeruntest/replay_invalid_object_size.c b/test/Replay/libkleeruntest/replay_invalid_object_size.c index 4de37bbf7a..6a1e50e28f 100644 --- a/test/Replay/libkleeruntest/replay_invalid_object_size.c +++ b/test/Replay/libkleeruntest/replay_invalid_object_size.c @@ -13,7 +13,7 @@ // Check that setting `KLEE_RUN_TEST_ERRORS_NON_FATAL` will not exit with an error // and will continue executing. -// RUN: env KTEST_FILE=%t.klee-out/test000001.ktest KLEE_RUN_TEST_ERRORS_NON_FATAL=1 %t_runner 2>&1 | FileCheck %s +// RUN: env KTEST_FILE=%t.klee-out/test000001.ktest KLEE_RUN_TEST_ERRORS_NON_FATAL=FORCE %t_runner 2>&1 | FileCheck %s #include "klee/klee.h" #include #include diff --git a/test/lit.cfg b/test/lit.cfg index 8c01d8fc36..11308ae424 100644 --- a/test/lit.cfg +++ b/test/lit.cfg @@ -113,6 +113,10 @@ config.substitutions.append( config.substitutions.append( ('%llvmlink', os.path.join(llvm_tools_dir, 'llvm-link')) ) +# Add a substitution for llvm-link +config.substitutions.append( + ('%llvmcov', os.path.join(llvm_tools_dir, 'llvm-cov')) +) # Add a substition for libkleeruntest config.substitutions.append( @@ -162,6 +166,10 @@ config.substitutions.append( ('%gentmp', os.path.join(klee_src_root, 'scripts/genTempFiles.sh')) ) +config.substitutions.append( + ('%replay', os.path.join(klee_src_root, 'scripts/replay.sh')) +) + config.substitutions.append( ('%libcxx_include', getattr(config, 'libcxx_include_dir', None))) @@ -255,3 +263,8 @@ config.available_features.add('{}32bit-support'.format('' if config.have_32bit_s config.available_features.add('{}asan'.format('' if config.have_asan else 'not-')) config.available_features.add('{}ubsan'.format('' if config.have_ubsan else 'not-')) config.available_features.add('{}msan'.format('' if config.have_msan else 'not-')) + +if config.have_asan or config.have_ubsan or config.have_msan: + config.available_features.add('san') +else: + config.available_features.add('not-san') diff --git a/test/regression/2023-02-01-replay-test-with-lazy-initialized-objects.c b/test/regression/2023-02-01-replay-test-with-lazy-initialized-objects.c index 66edca58dc..6befbf686c 100644 --- a/test/regression/2023-02-01-replay-test-with-lazy-initialized-objects.c +++ b/test/regression/2023-02-01-replay-test-with-lazy-initialized-objects.c @@ -3,17 +3,10 @@ // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --libc=klee --posix-runtime --skip-not-lazy-initialized --skip-not-symbolic-objects %t.bc > %t.log -// RUN: test -f %t.klee-out/test000006.ktest - // RUN: %cc %s %libkleeruntest -Wl,-rpath %libkleeruntestdir -o %t_runner -// RUN: env KTEST_FILE=%t.klee-out/test000001.ktest %t_runner >> %t_runner.log -// RUN: env KTEST_FILE=%t.klee-out/test000002.ktest %t_runner >> %t_runner.log -// RUN: env KTEST_FILE=%t.klee-out/test000003.ktest %t_runner >> %t_runner.log -// RUN: env KTEST_FILE=%t.klee-out/test000004.ktest %t_runner >> %t_runner.log -// RUN: env KTEST_FILE=%t.klee-out/test000005.ktest %t_runner >> %t_runner.log -// RUN: env KTEST_FILE=%t.klee-out/test000006.ktest %t_runner >> %t_runner.log - +// RUN: rm -f %t_runner.log +// RUN: %replay %t.klee-out %t_runner > %t_runner.log // RUN: FileCheck -input-file=%t_runner.log %s #include diff --git a/test/regression/2023-10-13-kbfiltr.i.cil-2.c b/test/regression/2023-10-13-kbfiltr.i.cil-2.c index d46b853526..57a75af0b9 100644 --- a/test/regression/2023-10-13-kbfiltr.i.cil-2.c +++ b/test/regression/2023-10-13-kbfiltr.i.cil-2.c @@ -1,9 +1,8 @@ -// REQUIRES: geq-llvm-14.0 // RUN: %clang -Wno-everything %s -emit-llvm %O0opt -g -c -o %t1.bc // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --optimize-aggressive=false --track-coverage=branches --optimize=true --mock-all-externals --external-calls=all --use-forked-solver=false --max-memory=6008 --skip-not-lazy-initialized --istats-write-interval=90s --use-sym-size-alloc=true --cex-cache-validity-cores --symbolic-allocation-threshold=8192 --write-kqueries --write-xml-tests --only-output-states-covering-new=true --dump-states-on-halt=true --emit-all-errors=true --search=bfs %t1.bc +// RUN: ls %t.klee-out | grep _1.xml | wc -l | grep 8 -// RUN: test -f %t.klee-out/test000023_1.xml #include "klee-test-comp.c" extern void abort(void); @@ -3645,5 +3644,3 @@ NTSTATUS ZwClose(HANDLE Handle) { } } } - -// CHECK: generated tests = 3 From c57d898c753773955c258c0871ac354e5ac9e1d6 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Mon, 6 Nov 2023 19:53:51 +0400 Subject: [PATCH 084/103] [fix] `CexCachingSolver` --- lib/Solver/CexCachingSolver.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Solver/CexCachingSolver.cpp b/lib/Solver/CexCachingSolver.cpp index 74144a0697..2c4b83d4c8 100644 --- a/lib/Solver/CexCachingSolver.cpp +++ b/lib/Solver/CexCachingSolver.cpp @@ -274,7 +274,7 @@ bool CexCachingSolver::getResponse(const Query &query, result->tryGetValidityCore(resultCore); KeyType resultCoreConstarints(resultCore.constraints.begin(), resultCore.constraints.end()); - ref neg = Expr::createIsZero(query.expr); + ref neg = Expr::createIsZero(resultCore.expr); resultCoreConstarints.insert(neg); cache.insert(resultCoreConstarints, result); } From 16d8098b11ae8cf3859dc89fc678ebea36e7cb60 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Sun, 5 Nov 2023 21:18:12 +0400 Subject: [PATCH 085/103] [fix] Slightly improve performance --- lib/Core/AddressSpace.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/Core/AddressSpace.cpp b/lib/Core/AddressSpace.cpp index 553b588bd3..2e1b9593bc 100644 --- a/lib/Core/AddressSpace.cpp +++ b/lib/Core/AddressSpace.cpp @@ -378,9 +378,10 @@ void AddressSpace::copyOutConcrete(const MemoryObject *mo, const ObjectState *os, const Assignment &assignment) const { auto address = reinterpret_cast(mo->address); + AssignmentEvaluator ae(assignment, false); std::vector concreteStore(mo->size); for (size_t i = 0; i < mo->size; i++) { - auto byte = assignment.evaluate(os->read8(i), false); + auto byte = ae.visit(os->read8(i)); concreteStore[i] = cast(byte)->getZExtValue(8); } std::memcpy(address, concreteStore.data(), mo->size); @@ -405,9 +406,10 @@ bool AddressSpace::copyInConcrete(const MemoryObject *mo, const ObjectState *os, uint64_t src_address, const Assignment &assignment) { auto address = reinterpret_cast(src_address); + AssignmentEvaluator ae(assignment, false); std::vector concreteStore(mo->size); for (size_t i = 0; i < mo->size; i++) { - auto byte = assignment.evaluate(os->read8(i), false); + auto byte = ae.visit(os->read8(i)); concreteStore[i] = cast(byte)->getZExtValue(8); } if (memcmp(address, concreteStore.data(), mo->size) != 0) { From b394cb3e53168352fc458dc090c88efb6d2e6ccf Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Wed, 8 Nov 2023 00:53:53 +0400 Subject: [PATCH 086/103] [fix] `AlphaEquivalenceSolver` --- lib/Solver/AlphaEquivalenceSolver.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/Solver/AlphaEquivalenceSolver.cpp b/lib/Solver/AlphaEquivalenceSolver.cpp index 2c5df35fdb..4c0cc81fa3 100644 --- a/lib/Solver/AlphaEquivalenceSolver.cpp +++ b/lib/Solver/AlphaEquivalenceSolver.cpp @@ -75,8 +75,12 @@ ValidityCore AlphaEquivalenceSolver::changeVersion(const ValidityCore &validityCore, const ExprHashMap> &reverse) { ValidityCore reverseValidityCore; - assert(reverse.find(validityCore.expr) != reverse.end()); - reverseValidityCore.expr = reverse.at(validityCore.expr); + if (isa(validityCore.expr)) { + reverseValidityCore.expr = validityCore.expr; + } else { + assert(reverse.find(validityCore.expr) != reverse.end()); + reverseValidityCore.expr = reverse.at(validityCore.expr); + } for (auto e : validityCore.constraints) { assert(reverse.find(e) != reverse.end()); reverseValidityCore.constraints.insert(reverse.at(e)); From 14b89d40822006e8c69e0bb7bd9eff95472bb328 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Wed, 8 Nov 2023 02:02:48 +0400 Subject: [PATCH 087/103] [feat] Add `X86FPAsX87FP80` --- lib/Core/Executor.cpp | 82 ++++++++++++++++++++++++++++++++++++++- lib/Core/ExecutorUtil.cpp | 25 +++++++++++- 2 files changed, 104 insertions(+), 3 deletions(-) diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index b4e17bf9e6..d1003d7942 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -221,6 +221,12 @@ cl::opt FunctionCallReproduce( "function-call-reproduce", cl::init(""), cl::desc("Marks mentioned function as target for error-guided mode."), cl::cat(ExecCat)); + +llvm::cl::opt X86FPAsX87FP80( + "x86FP-as-x87FP80", cl::init(false), + cl::desc("Convert X86 fp values to X87FP80 during computation according to " + "GCC behavior (default=false)"), + cl::cat(ExecCat)); } // namespace klee namespace { @@ -1972,6 +1978,7 @@ void Executor::executeCall(ExecutionState &state, KInstruction *ki, Function *f, #endif break; } +#ifdef ENABLE_FP case Intrinsic::sqrt: { ref op = eval(ki, 1, state).value; ref result = FSqrtExpr::create(op, state.roundingMode); @@ -2014,6 +2021,7 @@ void Executor::executeCall(ExecutionState &state, KInstruction *ki, Function *f, bindLocal(ki, state, result); break; } +#endif case Intrinsic::fma: case Intrinsic::fmuladd: { @@ -2448,6 +2456,40 @@ void Executor::checkNullCheckAfterDeref(ref cond, ExecutionState &state, } } +ref X87FP80ToFPTrunc(ref arg, Expr::Width type, + llvm::APFloat::roundingMode rm) { + ref result = arg; +#ifdef ENABLE_FP + Expr::Width resultType = type; + if (Context::get().getPointerWidth() == 32 && arg->getWidth() == Expr::Fl80) { + result = FPTruncExpr::create(arg, resultType, rm); + } +#else + klee_message( + "You may enable x86-as-x87FP80 behaviour by passing the following options" + " to cmake:\n" + "\"-DENABLE_FLOATING_POINT=ON\"\n"); +#endif + return result; +} + +ref FPToX87FP80Ext(ref arg) { + ref result = arg; +#ifdef ENABLE_FP + Expr::Width resultType = Expr::Fl80; + if (Context::get().getPointerWidth() == 32 && + arg->getWidth() == Expr::Int64) { + result = FPExtExpr::create(arg, resultType); + } +#else + klee_message( + "You may enable x86-as-x87FP80 behaviour by passing the following options" + " to cmake:\n" + "\"-DENABLE_FLOATING_POINT=ON\"\n"); +#endif + return result; +} + void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) { Instruction *i = ki->inst; @@ -2540,6 +2582,11 @@ void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) { Expr::Width from = result->getWidth(); Expr::Width to = getWidthForLLVMType(t); + if (X86FPAsX87FP80 && t->isFloatingPointTy() && + Context::get().getPointerWidth() == 32) { + to = Expr::Fl80; + } + if (from != to) { const CallBase &cb = cast(*caller); @@ -3660,7 +3707,7 @@ void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) { ref arg = eval(ki, 0, state).value; if (!fpWidthToSemantics(arg->getWidth()) || !fpWidthToSemantics(resultType)) return terminateStateOnExecError(state, "Unsupported FPTrunc operation"); - if (arg->getWidth() <= resultType) + if (arg->getWidth() < resultType) return terminateStateOnExecError(state, "Invalid FPTrunc"); ref result = FPTruncExpr::create(arg, resultType, state.roundingMode); bindLocal(ki, state, result); @@ -3673,7 +3720,7 @@ void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) { ref arg = eval(ki, 0, state).value; if (!fpWidthToSemantics(arg->getWidth()) || !fpWidthToSemantics(resultType)) return terminateStateOnExecError(state, "Unsupported FPExt operation"); - if (arg->getWidth() >= resultType) + if (arg->getWidth() > resultType) return terminateStateOnExecError(state, "Invalid FPExt"); ref result = FPExtExpr::create(arg, resultType); bindLocal(ki, state, result); @@ -3709,6 +3756,9 @@ void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) { case Instruction::UIToFP: { UIToFPInst *fi = cast(i); Expr::Width resultType = getWidthForLLVMType(fi->getType()); + if (X86FPAsX87FP80 && Context::get().getPointerWidth() == 32) { + resultType = Expr::Fl80; + } ref arg = eval(ki, 0, state).value; const llvm::fltSemantics *semantics = fpWidthToSemantics(resultType); if (!semantics) @@ -3721,6 +3771,9 @@ void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) { case Instruction::SIToFP: { SIToFPInst *fi = cast(i); Expr::Width resultType = getWidthForLLVMType(fi->getType()); + if (Context::get().getPointerWidth() == 32) { + resultType = Expr::Fl80; + } ref arg = eval(ki, 0, state).value; const llvm::fltSemantics *semantics = fpWidthToSemantics(resultType); if (!semantics) @@ -5917,6 +5970,11 @@ void Executor::collectReads( ref result = os->read(mo->getOffsetExpr(address), type); + if (X86FPAsX87FP80 && state.prevPC->inst->getType()->isFloatingPointTy() && + Context::get().getPointerWidth() == 32) { + result = FPToX87FP80Ext(result); + } + if (MockMutableGlobals == MockMutableGlobalsPolicy::PrimitiveFields && mo->isGlobal && !os->readOnly && isa(result) && !targetType->getRawType()->isPointerTy()) { @@ -5933,6 +5991,16 @@ void Executor::executeMemoryOperation( ExecutionState &estate, bool isWrite, KType *targetType, ref address, ref value /* undef if read */, KInstruction *target /* undef if write */) { + KInstruction *ki = estate.prevPC; + if (X86FPAsX87FP80 && isWrite) { + auto valueOperand = cast(ki->inst)->getValueOperand(); + if (valueOperand->getType()->isFloatingPointTy() && + Context::get().getPointerWidth() == 32) { + value = + X87FP80ToFPTrunc(value, getWidthForLLVMType(valueOperand->getType()), + estate.roundingMode); + } + } Expr::Width type = (isWrite ? value->getWidth() : getWidthForLLVMType(target->inst->getType())); unsigned bytes = Expr::getMinBytesForWidth(type); @@ -6073,6 +6141,11 @@ void Executor::executeMemoryOperation( } else { result = os->read(mo->getOffsetExpr(address), type); + if (X86FPAsX87FP80 && ki->inst->getType()->isFloatingPointTy() && + Context::get().getPointerWidth() == 32) { + result = FPToX87FP80Ext(result); + } + if (interpreterOpts.MakeConcreteSymbolic) result = replaceReadWithSymbolic(*state, result); @@ -6257,6 +6330,11 @@ void Executor::executeMemoryOperation( } else { ref result = os->read(mo->getOffsetExpr(address), type); + if (X86FPAsX87FP80 && ki->inst->getType()->isFloatingPointTy() && + Context::get().getPointerWidth() == 32) { + result = FPToX87FP80Ext(result); + } + if (MockMutableGlobals == MockMutableGlobalsPolicy::PrimitiveFields && mo->isGlobal && !os->readOnly && isa(result) && !targetType->getRawType()->isPointerTy()) { diff --git a/lib/Core/ExecutorUtil.cpp b/lib/Core/ExecutorUtil.cpp index 9a4c6054a0..ef3a100f0e 100644 --- a/lib/Core/ExecutorUtil.cpp +++ b/lib/Core/ExecutorUtil.cpp @@ -35,6 +35,24 @@ DISABLE_WARNING_POP using namespace llvm; namespace klee { +extern llvm::cl::opt X86FPAsX87FP80; + +ref FPToX87FP80Ext(ref arg) { + ref result = arg; +#ifdef ENABLE_FP + Expr::Width resultType = Expr::Fl80; + if (Context::get().getPointerWidth() == 32 && + arg->getWidth() == Expr::Int64) { + result = FPExtExpr::create(arg, resultType); + } +#else + klee_message( + "You may enable x86-as-x87FP80 behaviour by passing the following options" + " to cmake:\n" + "\"-DENABLE_FLOATING_POINT=ON\"\n"); +#endif // ENABLE_FP + return result; +} ref Executor::evalConstant(const Constant *c, llvm::APFloat::roundingMode rm, @@ -51,7 +69,12 @@ ref Executor::evalConstant(const Constant *c, if (const ConstantInt *ci = dyn_cast(c)) { return ConstantExpr::alloc(ci->getValue()); } else if (const ConstantFP *cf = dyn_cast(c)) { - return ConstantExpr::alloc(cf->getValueAPF()); + ref result = ConstantExpr::alloc(cf->getValueAPF()); + if (X86FPAsX87FP80 && c->getType()->isFloatingPointTy() && + Context::get().getPointerWidth() == 32) { + result = cast(FPToX87FP80Ext(result)); + } + return result; } else if (const GlobalValue *gv = dyn_cast(c)) { auto it = globalAddresses.find(gv); assert(it != globalAddresses.end()); From ee3b20068b78e3b35c295e460c5a694c42ff73b4 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Wed, 8 Nov 2023 02:06:05 +0400 Subject: [PATCH 088/103] [chore] Update `scripts/kleef` --- lib/Core/Executor.cpp | 2 +- scripts/kleef | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index d1003d7942..6185e98e5e 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -3771,7 +3771,7 @@ void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) { case Instruction::SIToFP: { SIToFPInst *fi = cast(i); Expr::Width resultType = getWidthForLLVMType(fi->getType()); - if (Context::get().getPointerWidth() == 32) { + if (X86FPAsX87FP80 && Context::get().getPointerWidth() == 32) { resultType = Expr::Fl80; } ref arg = eval(ki, 0, state).value; diff --git a/scripts/kleef b/scripts/kleef index be47bde285..86a250c171 100755 --- a/scripts/kleef +++ b/scripts/kleef @@ -49,7 +49,8 @@ def klee_options( "--cex-cache-validity-cores", # "--libc=uclibc", # "--posix-runtime", - # "--fp-runtime", + "--fp-runtime", + "--x86FP-as-x87FP80", # "--max-sym-array-size=4096", "--symbolic-allocation-threshold=8192", # "--dump-all-states=false", From ccf75c6e30c7c4bf546bb8ff59e03b8c31056714 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Wed, 8 Nov 2023 14:29:31 +0400 Subject: [PATCH 089/103] [chore] Disable `libc++` tests on msan run because they time out on CI --- test/CXX/symex/libc++/can_catch_test.cpp | 2 ++ test/CXX/symex/libc++/exception_inheritance.cpp | 2 ++ test/CXX/symex/libc++/landingpad.cpp | 2 ++ test/CXX/symex/libc++/rethrow.cpp | 2 ++ test/CXX/symex/libc++/throw_specifiers.cpp | 2 ++ test/CXX/symex/libc++/throwing_exception_destructor.cpp | 2 ++ 6 files changed, 12 insertions(+) diff --git a/test/CXX/symex/libc++/can_catch_test.cpp b/test/CXX/symex/libc++/can_catch_test.cpp index c70d14a2aa..7515ef33d8 100644 --- a/test/CXX/symex/libc++/can_catch_test.cpp +++ b/test/CXX/symex/libc++/can_catch_test.cpp @@ -1,3 +1,5 @@ +// REQUIRES: not-msan +// Disabling msan because it times out on CI // REQUIRES: uclibc // REQUIRES: libcxx // REQUIRES: eh-cxx diff --git a/test/CXX/symex/libc++/exception_inheritance.cpp b/test/CXX/symex/libc++/exception_inheritance.cpp index ca207eb4be..e24be60da2 100644 --- a/test/CXX/symex/libc++/exception_inheritance.cpp +++ b/test/CXX/symex/libc++/exception_inheritance.cpp @@ -1,3 +1,5 @@ +// REQUIRES: not-msan +// Disabling msan because it times out on CI // REQUIRES: uclibc // REQUIRES: libcxx // REQUIRES: eh-cxx diff --git a/test/CXX/symex/libc++/landingpad.cpp b/test/CXX/symex/libc++/landingpad.cpp index 13dd6bc47a..6e8b13bcd6 100644 --- a/test/CXX/symex/libc++/landingpad.cpp +++ b/test/CXX/symex/libc++/landingpad.cpp @@ -1,3 +1,5 @@ +// REQUIRES: not-msan +// Disabling msan because it times out on CI // Testcase for proper handling of // c++ type, constructors and destructors. // Based on: https://gcc.gnu.org/wiki/Dwarf2EHNewbiesHowto diff --git a/test/CXX/symex/libc++/rethrow.cpp b/test/CXX/symex/libc++/rethrow.cpp index 149fe693d5..febdf0b3e9 100644 --- a/test/CXX/symex/libc++/rethrow.cpp +++ b/test/CXX/symex/libc++/rethrow.cpp @@ -1,3 +1,5 @@ +// REQUIRES: not-msan +// Disabling msan because it times out on CI // REQUIRES: uclibc // REQUIRES: libcxx // REQUIRES: eh-cxx diff --git a/test/CXX/symex/libc++/throw_specifiers.cpp b/test/CXX/symex/libc++/throw_specifiers.cpp index 96195cd498..6eae7f3abd 100644 --- a/test/CXX/symex/libc++/throw_specifiers.cpp +++ b/test/CXX/symex/libc++/throw_specifiers.cpp @@ -1,3 +1,5 @@ +// REQUIRES: not-msan +// Disabling msan because it times out on CI // Testcase for proper handling of // throw specifications on functions // REQUIRES: uclibc diff --git a/test/CXX/symex/libc++/throwing_exception_destructor.cpp b/test/CXX/symex/libc++/throwing_exception_destructor.cpp index 02d7cdb920..f1e0e5d447 100644 --- a/test/CXX/symex/libc++/throwing_exception_destructor.cpp +++ b/test/CXX/symex/libc++/throwing_exception_destructor.cpp @@ -1,3 +1,5 @@ +// REQUIRES: not-msan +// Disabling msan because it times out on CI // Testcase for proper handling of exception destructors that throw. // REQUIRES: uclibc // REQUIRES: libcxx From 08d24ad5e9c896f7915d9da04e38c6c090a91534 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Wed, 8 Nov 2023 18:11:06 +0400 Subject: [PATCH 090/103] [fix] Must consider the whole concretization --- lib/Core/Executor.cpp | 4 ++-- lib/Expr/Constraints.cpp | 2 +- lib/Expr/IndependentSet.cpp | 31 +++++++++++++++++++++++++++++-- 3 files changed, 32 insertions(+), 5 deletions(-) diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index 6185e98e5e..c5dc81f2f5 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -1460,9 +1460,9 @@ void Executor::addConstraint(ExecutionState &state, ref condition) { if (!concretization.isEmpty()) { // Update memory objects if arrays have affected them. + updateStateWithSymcretes(state, concretization); Assignment delta = state.constraints.cs().concretization().diffWith(concretization); - updateStateWithSymcretes(state, delta); state.addConstraint(condition, delta); } else { state.addConstraint(condition, {}); @@ -6490,7 +6490,7 @@ void Executor::updateStateWithSymcretes(ExecutionState &state, * assign. We want to update only objects, whose size were changed. */ std::vector> updatedSizeSymcretes; - const Assignment &diffAssignment = + Assignment diffAssignment = state.constraints.cs().concretization().diffWith(assignment); for (const ref &symcrete : state.constraints.cs().symcretes()) { diff --git a/lib/Expr/Constraints.cpp b/lib/Expr/Constraints.cpp index d349c9d0b2..17ae8e50bc 100644 --- a/lib/Expr/Constraints.cpp +++ b/lib/Expr/Constraints.cpp @@ -209,7 +209,7 @@ ConstraintSet::ConstraintSet() {} void ConstraintSet::addConstraint(ref e, const Assignment &delta) { _constraints.insert(e); // Update bindings - for (auto i : delta.bindings) { + for (auto &i : delta.bindings) { _concretization.bindings.replace({i.first, i.second}); } _independentElements.updateConcretization(delta); diff --git a/lib/Expr/IndependentSet.cpp b/lib/Expr/IndependentSet.cpp index feb3d26583..d01b234f17 100644 --- a/lib/Expr/IndependentSet.cpp +++ b/lib/Expr/IndependentSet.cpp @@ -23,7 +23,7 @@ IndependentConstraintSet::updateConcretization( if (delta.bindings.size() == 0) { return ics; } - for (auto i : delta.bindings) { + for (auto &i : delta.bindings) { ics->concretization.bindings.replace({i.first, i.second}); } InnerSetUnion DSU; @@ -45,6 +45,15 @@ IndependentConstraintSet::updateConcretization( } DSU.addValue(new ExprEitherSymcrete::left(e)); } + auto concretizationConstraints = + ics->concretization.createConstraintsFromAssignment(); + for (ref e : concretizationConstraints) { + if (auto ce = dyn_cast(e)) { + assert(ce->isTrue() && "Attempt to add invalid constraint"); + continue; + } + DSU.addValue(new ExprEitherSymcrete::left(e)); + } ics->concretizedSets = DSU; return ics; } @@ -56,7 +65,7 @@ IndependentConstraintSet::removeConcretization( if (delta.bindings.size() == 0) { return ics; } - for (auto i : delta.bindings) { + for (auto &i : delta.bindings) { ics->concretization.bindings.remove(i.first); } InnerSetUnion DSU; @@ -78,6 +87,15 @@ IndependentConstraintSet::removeConcretization( } DSU.addValue(new ExprEitherSymcrete::left(e)); } + auto concretizationConstraints = + ics->concretization.createConstraintsFromAssignment(); + for (ref e : concretizationConstraints) { + if (auto ce = dyn_cast(e)) { + assert(ce->isTrue() && "Attempt to add invalid constraint"); + continue; + } + DSU.addValue(new ExprEitherSymcrete::left(e)); + } ics->concretizedSets = DSU; return ics; @@ -343,6 +361,15 @@ IndependentConstraintSet::merge(ref A, } DSU.addValue(new ExprEitherSymcrete::left(e)); } + auto concretizationConstraints = + a->concretization.createConstraintsFromAssignment(); + for (ref e : concretizationConstraints) { + if (auto ce = dyn_cast(e)) { + assert(ce->isTrue() && "Attempt to add invalid constraint"); + continue; + } + DSU.addValue(new ExprEitherSymcrete::left(e)); + } a->concretizedSets = DSU; } From 2677745bf8e1374a0bf16824b828ee98b14a5491 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Fri, 10 Nov 2023 04:33:01 +0400 Subject: [PATCH 091/103] [chore] Update `kleef` script --- scripts/kleef | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/kleef b/scripts/kleef index 86a250c171..c98a94114a 100755 --- a/scripts/kleef +++ b/scripts/kleef @@ -92,6 +92,7 @@ def klee_options( "--track-coverage=all", # Only branches and only instructions are wrong in real life. E.g., ternary operators are sometimes counted as different branches, while we stick to look at them as a single instruction from a single branch "--use-iterative-deepening-search=max-cycles", f"--max-solver-time={MAX_SOLVER_TIME}s", + "--max-cycles-before-stuck=15", # "--tc-type=cov", "--only-output-states-covering-new", # Don't generate all test cases "--dump-states-on-halt=true", # Check in case we missed some oncovered instructions From 82b0cfd60099568804a2f736a010e664b283e494 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Fri, 10 Nov 2023 04:33:17 +0400 Subject: [PATCH 092/103] [chore] Update tests --- ...ChenFlurMukhopadhyay-2012SAS-Fig1-alloca.c | 2 +- .../CoverageBranches/CostasArray-17.c | 2 +- .../CoverageBranches/egcd3-ll_valuebound10.c | 1 - test/Industry/CoverageBranches/matrix-2-2.c | 68 +++++++++++++++++++ ...r.3.ufo.UNBOUNDED.pals+Problem12_label00.c | 1 - .../btor2c-lazyMod.mul6.c | 0 .../coverage-error-call.prp | 0 7 files changed, 70 insertions(+), 4 deletions(-) create mode 100644 test/Industry/CoverageBranches/matrix-2-2.c rename test/Industry/{ => CoverageErrorCall}/btor2c-lazyMod.mul6.c (100%) rename test/Industry/{ => CoverageErrorCall}/coverage-error-call.prp (100%) diff --git a/test/Industry/CoverageBranches/ChenFlurMukhopadhyay-2012SAS-Fig1-alloca.c b/test/Industry/CoverageBranches/ChenFlurMukhopadhyay-2012SAS-Fig1-alloca.c index b0efaf937e..99f638327a 100644 --- a/test/Industry/CoverageBranches/ChenFlurMukhopadhyay-2012SAS-Fig1-alloca.c +++ b/test/Industry/CoverageBranches/ChenFlurMukhopadhyay-2012SAS-Fig1-alloca.c @@ -9,7 +9,7 @@ // RUN: FileCheck --input-file=%t.cov.log --check-prefix=CHECK-COV %s -// Branch coverage 100%, the number of branches is 1: +// Branch coverage 100%, the number of branches is 2: // CHECK-COV: Lines executed:100.00% of 11 // CHECK-COV-NEXT: Branches executed:100.00% of 2 // CHECK-COV-NEXT: Taken at least once:100.00% of 2 diff --git a/test/Industry/CoverageBranches/CostasArray-17.c b/test/Industry/CoverageBranches/CostasArray-17.c index 6f326016af..088a33fbb0 100644 --- a/test/Industry/CoverageBranches/CostasArray-17.c +++ b/test/Industry/CoverageBranches/CostasArray-17.c @@ -19,7 +19,7 @@ // RUN: FileCheck --input-file=%t.cov.log --check-prefix=CHECK %s -// Branch coverage 100%, the number of branches is 1: +// Branch coverage 100%, the number of branches is 2: // CHECK: Lines executed:{{(0\.7[0-9])}}% of 1545 // CHECK-NEXT: Branches executed:100.00% of 2 // CHECK-NEXT: Taken at least once:100.00% of 2 diff --git a/test/Industry/CoverageBranches/egcd3-ll_valuebound10.c b/test/Industry/CoverageBranches/egcd3-ll_valuebound10.c index 72396f861a..d5405512d8 100644 --- a/test/Industry/CoverageBranches/egcd3-ll_valuebound10.c +++ b/test/Industry/CoverageBranches/egcd3-ll_valuebound10.c @@ -9,7 +9,6 @@ // RUN: FileCheck --input-file=%t.cov.log --check-prefix=CHECK %s -// Branch coverage 100%, the number of branches is 1: // CHECK: Lines executed:87.93% of 58 // CHECK-NEXT: Branches executed:100.00% of 18 // CHECK-NEXT: Taken at least once:83.33% of 18 diff --git a/test/Industry/CoverageBranches/matrix-2-2.c b/test/Industry/CoverageBranches/matrix-2-2.c new file mode 100644 index 0000000000..d25bd92255 --- /dev/null +++ b/test/Industry/CoverageBranches/matrix-2-2.c @@ -0,0 +1,68 @@ +// RUN: %clang -Wno-everything %s -emit-llvm %O0opt -g -c -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --optimize-aggressive=false --track-coverage=all --max-cycles=2 --optimize=true --emit-all-errors --delete-dead-loops=false --use-forked-solver=false -max-memory=6008 --cex-cache-validity-cores --only-output-states-covering-new=true --dump-states-on-halt=true --use-sym-size-alloc=true --symbolic-allocation-threshold=8192 %t1.bc 2>&1 + +// RUN: rm -f %t*.gcda %t*.gcno %t*.gcov +// RUN: %cc -DGCOV %s %libkleeruntest -Wl,-rpath %libkleeruntestdir -o %t_runner --coverage +// RUN: %replay %t.klee-out %t_runner +// RUN: gcov -b %t_runner-%basename_t > %t.cov.log + +// RUN: FileCheck --input-file=%t.cov.log --check-prefix=CHECK-COV %s + +// Branch coverage is greater 80%: +// CHECK-COV: Lines executed:9{{([0-9]\.[0-9][0-9])}}% of 24 +// CHECK-COV-NEXT: Branches executed:100.00% of 16 +// CHECK-COV-NEXT: Taken at least once:{{([8-9][0-9]\.[0-9][0-9])}}% of 16 + +#include "klee-test-comp.c" + +extern void exit(int); +extern void abort(void); +#ifdef GCOV +extern void __gcov_dump(void); +#endif + +void dump() { +#ifdef GCOV + __gcov_dump(); + exit(0); +#endif +} + +extern void __assert_fail(const char *, const char *, unsigned int, const char *) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__noreturn__)); +void reach_error() { dump(); __assert_fail("0", "matrix-2-2.c", 3, "reach_error"); } + +void __VERIFIER_assert(int cond) { + if (!(cond)) { + ERROR: {reach_error();abort();} + } + return; +} +extern unsigned int __VERIFIER_nondet_uint(); +extern int __VERIFIER_nondet_int(); + +int main() +{ + unsigned int N_LIN=__VERIFIER_nondet_uint(); + unsigned int N_COL=__VERIFIER_nondet_uint(); + if (N_LIN >= 4000000000 / sizeof(int) || N_COL >= 4000000000 / sizeof(int)) { + return 0; + } + unsigned int j,k; + int matriz[N_COL][N_LIN], maior; + + maior = __VERIFIER_nondet_int(); + for(j=0;jmaior) + maior = matriz[j][k]; + } + + for(j=0;j Date: Sun, 12 Nov 2023 15:26:51 +0400 Subject: [PATCH 093/103] [fix] `MemoryTriggerCoverOnTheFly` --- lib/Core/Executor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index c5dc81f2f5..f0a919e514 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -4142,7 +4142,7 @@ bool Executor::checkMemoryUsage() { const auto mmapUsage = memory->getUsedDeterministicSize() >> 20U; const auto totalUsage = mallocUsage + mmapUsage; - if (MemoryTriggerCoverOnTheFly && 3 * totalUsage <= 2 * MaxMemory) { + if (MemoryTriggerCoverOnTheFly && totalUsage > MaxMemory * 0.75) { klee_warning_once(0, "enabling cover-on-the-fly (close to memory cap: %luMB)", totalUsage); From 22dadeb8944a0dcaa0def5463a2ad34b0de554a3 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Sun, 12 Nov 2023 17:11:37 +0400 Subject: [PATCH 094/103] [chore] Update `kleef` --- scripts/kleef | 21 +++++++++++++++++-- .../CoverageErrorCall/btor2c-lazyMod.mul6.c | 6 +++--- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/scripts/kleef b/scripts/kleef index c98a94114a..3994601fe9 100755 --- a/scripts/kleef +++ b/scripts/kleef @@ -19,6 +19,7 @@ def klee_options( is32, f_err, f_cov, + write_ktests, ): if max_time and int(max_time) > 30: MAX_SOLVER_TIME = 10 @@ -29,6 +30,7 @@ def klee_options( "--delete-dead-loops=false", # without this optimizer removes some code, which decreases coverage "--emit-all-errors", # without this we generate only one test for assertion failures, which decreases coverage "--mock-all-externals", # this helps for some linux benchmarks, which have unused extern globals. without this flag we will not even start on them. + "--external-calls=all", "--use-forked-solver=false", # "--solver-backend=stp", "--solver-backend=z3-tree", @@ -42,6 +44,7 @@ def klee_options( "--output-istats=false", # "--istats-write-interval=90s", # Istats file can be large as well "--write-xml-tests", # Write tests in XML format + f"--write-ktests={write_ktests}", # Write tests in KTest format f"--xml-metadata-programfile={source.name}", # Provide the name of the original source file f"--xml-metadata-programhash={hexhash}", # Provide sha256 hash of source file # "--use-guided-search=none", @@ -101,8 +104,12 @@ def klee_options( ] if max_time: max_time = float(max_time) - late_time = int(max_time * 0.9) - last_time = int(max_time * 0.97) + if max_time and int(max_time) > 30: + late_time = int(max_time * 0.9) + last_time = int(max_time * 0.97) + else: + late_time = int(max_time * 0.8) + last_time = int(max_time * 0.9) cmd += [ "--cover-on-the-fly=true", f"--delay-cover-on-the-fly={late_time}", @@ -167,6 +174,7 @@ class KLEEF(object): max_time=0, use_perf=False, use_valgrind=False, + write_ktests=False, ): self.source = Path(source) if source else None self.is32 = is32 @@ -178,6 +186,10 @@ class KLEEF(object): self.max_time = max_time self.use_perf = use_perf self.use_valgrind = use_valgrind + if write_ktests: + self.write_ktests = "true" + else: + self.write_ktests = "false" # This file is inside the bin directory - use the root as base self.bin_directory = Path(__file__).parent @@ -280,6 +292,7 @@ class KLEEF(object): self.is32, self.f_err, self.f_cov, + self.write_ktests, ) if self.isModifyingUlimitPermitted(): cmd = ["ulimit -s unlimited", "&&"] + cmd @@ -378,6 +391,7 @@ def run(args): max_time=time, use_perf=args.perf, use_valgrind=args.valgrind, + write_ktests=args.write_ktests, ) wrapper.compile() return wrapper.run() @@ -426,6 +440,9 @@ def main(): type=str, default=None, ) + parser.add_argument( + "--write-ktests", help="Write tests in KTest format", action="store_true" + ) args = parser.parse_args() run(args) diff --git a/test/Industry/CoverageErrorCall/btor2c-lazyMod.mul6.c b/test/Industry/CoverageErrorCall/btor2c-lazyMod.mul6.c index 0a1b1dcd5e..f11474a141 100644 --- a/test/Industry/CoverageErrorCall/btor2c-lazyMod.mul6.c +++ b/test/Industry/CoverageErrorCall/btor2c-lazyMod.mul6.c @@ -1,7 +1,7 @@ // It requires Z3 because the script currently runs with Z3 solver backend -//REQUIRES: z3 -//RUN: %kleef --property-file=%S/coverage-error-call.prp --max-memory=7000000000 --max-cputime-soft=30 --64 %s 2>&1 | FileCheck %s -//CHECK: KLEE: WARNING: 100.00% Reachable Reachable +// REQUIRES: z3 +// RUN: %kleef --property-file=%S/coverage-error-call.prp --max-memory=7000000000 --max-cputime-soft=30 --64 --write-ktests %s 2>&1 | FileCheck %s +// CHECK: KLEE: WARNING: 100.00% Reachable Reachable // This file is part of the SV-Benchmarks collection of verification tasks: // https://gitlab.com/sosy-lab/benchmarking/sv-benchmarks From 5f27906edb27e5362ed8df7bdb2b2e0b3a138317 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Tue, 14 Nov 2023 02:03:06 +0400 Subject: [PATCH 095/103] [fix] Optimized free-standing functions are broken --- lib/Core/Executor.cpp | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index f0a919e514..e97704699f 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -575,7 +575,7 @@ llvm::Module *Executor::setModule( kmodule = std::make_unique(); // 1.) Link the modules together && 2.) Apply different instrumentation - kmodule->link(userModules, 0); + kmodule->link(userModules, 1); kmodule->instrument(opts); kmodule->link(libsModules, 2); @@ -603,8 +603,6 @@ llvm::Module *Executor::setModule( specialFunctionHandler = new SpecialFunctionHandler(*this); specialFunctionHandler->prepare(preservedFunctions); - preservedFunctions.push_back(opts.EntryPoint.c_str()); - // Preserve the free-standing library calls preservedFunctions.push_back("memset"); preservedFunctions.push_back("memcpy"); @@ -612,12 +610,21 @@ llvm::Module *Executor::setModule( preservedFunctions.push_back("memmove"); if (FunctionCallReproduce != "") { - // prevent elimination of the function - auto f = kmodule->module->getFunction(FunctionCallReproduce); - if (f) + preservedFunctions.push_back(FunctionCallReproduce.c_str()); + } + + // prevent elimination of the preservedFunctions functions + for (auto pf : preservedFunctions) { + auto f = kmodule->module->getFunction(pf); + if (f) { f->addFnAttr(Attribute::OptimizeNone); + f->addFnAttr(Attribute::NoInline); + } } + // except the entry point + preservedFunctions.push_back(opts.EntryPoint.c_str()); + kmodule->optimiseAndPrepare(opts, preservedFunctions); kmodule->checkModule(); From a8bbfb50ab5cf546b758f57a16d4e10b194efcbc Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Fri, 10 Nov 2023 04:33:01 +0400 Subject: [PATCH 096/103] [chore] Update `kleef` script --- scripts/kleef | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/kleef b/scripts/kleef index 3994601fe9..35f0e4ac65 100755 --- a/scripts/kleef +++ b/scripts/kleef @@ -53,9 +53,10 @@ def klee_options( # "--libc=uclibc", # "--posix-runtime", "--fp-runtime", - "--x86FP-as-x87FP80", + "--x86FP-as-x87FP80=false", # "--max-sym-array-size=4096", "--symbolic-allocation-threshold=8192", + "--uninit-memory-test-multiplier=10", # "--dump-all-states=false", # "--search=nurs:covnew", # "--search=nurs:md2u", "--search=random-path", From b2d233cd0d0b4ff170a5a4831269aa86b452870e Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Wed, 15 Nov 2023 00:57:59 +0400 Subject: [PATCH 097/103] [fix] Address may be symbolic but unique, try resolve firstly --- lib/Core/Executor.cpp | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index e97704699f..48a2b4ae09 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -2949,18 +2949,19 @@ void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) { } else { ref v = eval(ki, 0, state).value; - if (!isa(v) && MockExternalCalls) { - if (ki->inst->getType()->isSized()) { - prepareMockValue(state, "mockExternResult", ki); - } - } else { - ExecutionState *free = &state; - bool hasInvalid = false, first = true; - - /* XXX This is wasteful, no need to do a full evaluate since we - have already got a value. But in the end the caches should - handle it for us, albeit with some overhead. */ - do { + ExecutionState *free = &state; + bool hasInvalid = false, first = true; + + /* XXX This is wasteful, no need to do a full evaluate since we + have already got a value. But in the end the caches should + handle it for us, albeit with some overhead. */ + do { + if (!first && MockExternalCalls) { + free = nullptr; + if (ki->inst->getType()->isSized()) { + prepareMockValue(state, "mockExternResult", ki); + } + } else { v = optimizer.optimizeExpr(v, true); ref value; bool success = solver->getValue(free->constraints.cs(), v, value, @@ -2993,8 +2994,8 @@ void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) { first = false; free = res.second; timers.invoke(); - } while (free && !haltExecution); - } + } + } while (free && !haltExecution); } break; } From 2b513ac10b344b24ea6aa1b494e7577901b9f4cb Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Wed, 15 Nov 2023 01:00:34 +0400 Subject: [PATCH 098/103] [fix] Put in order `fp-runtime` functions --- include/klee/Support/ModuleUtil.h | 35 ++++--------------- lib/Module/KModule.cpp | 19 ++-------- lib/Module/ModuleUtil.cpp | 16 +++++++++ runtime/klee-fp/CMakeLists.txt | 12 +++---- runtime/klee-fp/ceil.c | 16 ++++----- .../klee-fp/{klee_copysign.c => copysign.c} | 4 +-- .../klee-fp/{klee_copysign.h => copysign.h} | 2 +- runtime/klee-fp/fabs.c | 8 ++--- runtime/klee-fp/{klee_fenv.c => fenv.c} | 8 ++--- runtime/klee-fp/{klee_fenv.h => fenv.h} | 4 +-- runtime/klee-fp/{klee_floor.c => floor.c} | 11 +++--- runtime/klee-fp/{klee_floor.h => floor.h} | 8 ++--- runtime/klee-fp/fpclassify.c | 27 +++++++++----- .../{klee_internal_isinf.ll => isinf.ll} | 28 +++++++++++---- runtime/klee-fp/log.c | 3 +- runtime/klee-fp/{klee_rint.c => rint.c} | 10 +++--- runtime/klee-fp/{klee_rint.h => rint.h} | 8 ++--- runtime/klee-fp/round.c | 6 ++++ .../klee-fp/{klee_signbit.ll => signbit.ll} | 6 ++-- runtime/klee-fp/sqrt.c | 8 ++--- tools/klee/main.cpp | 16 --------- 21 files changed, 124 insertions(+), 131 deletions(-) rename runtime/klee-fp/{klee_copysign.c => copysign.c} (97%) rename runtime/klee-fp/{klee_copysign.h => copysign.h} (88%) rename runtime/klee-fp/{klee_fenv.c => fenv.c} (92%) rename runtime/klee-fp/{klee_fenv.h => fenv.h} (85%) rename runtime/klee-fp/{klee_floor.c => floor.c} (79%) rename runtime/klee-fp/{klee_floor.h => floor.h} (68%) rename runtime/klee-fp/{klee_internal_isinf.ll => isinf.ll} (78%) rename runtime/klee-fp/{klee_rint.c => rint.c} (62%) rename runtime/klee-fp/{klee_rint.h => rint.h} (69%) rename runtime/klee-fp/{klee_signbit.ll => signbit.ll} (89%) diff --git a/include/klee/Support/ModuleUtil.h b/include/klee/Support/ModuleUtil.h index 4d385c4c42..7ff0e36bd2 100644 --- a/include/klee/Support/ModuleUtil.h +++ b/include/klee/Support/ModuleUtil.h @@ -39,19 +39,16 @@ bool linkModules(llvm::Module *composite, std::vector> &modules, const unsigned Flags, std::string &errorMsg); -#if defined(__x86_64__) || defined(__i386__) -#define addFunctionReplacement(from, to) \ - {#from "f", #to "f"}, {#from "", #to ""}, { "" #from "l", #to "l" } +void replaceOrRenameFunction(llvm::Module *module, const char *old_name, + const char *new_name); +#if defined(__x86_64__) || defined(__i386__) #define addIntrinsicReplacement(from, to) \ {"llvm." #from ".f32", #to "f"}, {"llvm." #from ".f64", #to}, { \ "llvm." #from ".f80", #to "l" \ } #else -#define addFunctionReplacement(from, to) \ - {#from "f", #to "f"}, { "" #from, "" #to } - #define addIntrinsicReplacement(from, to) \ {"llvm." #from ".f32", #to "f"}, { "llvm." #from ".f64", #to } @@ -62,33 +59,15 @@ bool linkModules(llvm::Module *composite, /// implementations in runtime/klee-fp, but not explicitly replaced here. Should /// we rename them and complete the list? const std::vector> floatReplacements = { - addFunctionReplacement(__isnan, klee_internal_isnan), - addFunctionReplacement(isnan, klee_internal_isnan), - addFunctionReplacement(__isinf, klee_internal_isinf), - addFunctionReplacement(isinf, klee_internal_isinf), - addFunctionReplacement(__fpclassify, klee_internal_fpclassify), - addFunctionReplacement(fpclassify, klee_internal_fpclassify), - addFunctionReplacement(__finite, klee_internal_finite), - addFunctionReplacement(finite, klee_internal_finite), - addFunctionReplacement(sqrt, klee_internal_sqrt), - addFunctionReplacement(fabs, klee_internal_fabs), - addFunctionReplacement(rint, klee_internal_rint), - addFunctionReplacement(round, klee_internal_rint), - addFunctionReplacement(__signbit, klee_internal_signbit), - addIntrinsicReplacement(sqrt, klee_internal_sqrt), - addIntrinsicReplacement(rint, klee_internal_rint), - addIntrinsicReplacement(round, klee_internal_rint), + addIntrinsicReplacement(sqrt, sqrt), + addIntrinsicReplacement(rint, rint), + addIntrinsicReplacement(round, rint), addIntrinsicReplacement(nearbyint, nearbyint), addIntrinsicReplacement(copysign, copysign), - addIntrinsicReplacement(floor, klee_floor), + addIntrinsicReplacement(floor, floor), addIntrinsicReplacement(ceil, ceil)}; -#undef addFunctionReplacement #undef addIntrinsicReplacement -const std::vector> feRoundReplacements{ - {"fegetround", "klee_internal_fegetround"}, - {"fesetround", "klee_internal_fesetround"}}; - /// Return the Function* target of a Call or Invoke instruction, or /// null if it cannot be determined (should be only for indirect /// calls, although complicated constant expressions might be diff --git a/lib/Module/KModule.cpp b/lib/Module/KModule.cpp index ce09edfcc2..64e1d3037c 100644 --- a/lib/Module/KModule.cpp +++ b/lib/Module/KModule.cpp @@ -235,19 +235,6 @@ bool KModule::link(std::vector> &modules, return true; } -void KModule::replaceFunction(const std::unique_ptr &m, - const char *original, const char *replacement) { - llvm::Function *originalFunc = m->getFunction(original); - llvm::Function *replacementFunc = m->getFunction(replacement); - if (!originalFunc) - return; - klee_message("Replacing function \"%s\" with \"%s\"", original, replacement); - assert(replacementFunc && "Replacement function not found"); - assert(!(replacementFunc->isDeclaration()) && "replacement must have body"); - originalFunc->replaceAllUsesWith(replacementFunc); - originalFunc->eraseFromParent(); -} - void KModule::instrument(const Interpreter::ModuleOptions &opts) { // Inject checks prior to optimization... we also perform the // invariant transformations that we will end up doing later so that @@ -301,12 +288,10 @@ void KModule::optimiseAndPrepare( if (opts.WithFPRuntime) { if (UseKleeFloatInternals) { for (const auto &p : klee::floatReplacements) { - replaceFunction(module, p.first.c_str(), p.second.c_str()); + replaceOrRenameFunction(module.get(), p.first.c_str(), + p.second.c_str()); } } - for (const auto &p : klee::feRoundReplacements) { - replaceFunction(module, p.first.c_str(), p.second.c_str()); - } } // Needs to happen after linking (since ctors/dtors can be modified) diff --git a/lib/Module/ModuleUtil.cpp b/lib/Module/ModuleUtil.cpp index e64d628e71..d23e41a607 100644 --- a/lib/Module/ModuleUtil.cpp +++ b/lib/Module/ModuleUtil.cpp @@ -367,3 +367,19 @@ bool klee::loadFileAsOneModule( } return res; } + +void klee::replaceOrRenameFunction(llvm::Module *module, const char *old_name, + const char *new_name) { + Function *new_function, *old_function; + new_function = module->getFunction(new_name); + old_function = module->getFunction(old_name); + if (old_function) { + if (new_function) { + old_function->replaceAllUsesWith(new_function); + old_function->eraseFromParent(); + } else { + old_function->setName(new_name); + assert(old_function->getName() == new_name); + } + } +} \ No newline at end of file diff --git a/runtime/klee-fp/CMakeLists.txt b/runtime/klee-fp/CMakeLists.txt index 0314ca9c50..42b2829004 100644 --- a/runtime/klee-fp/CMakeLists.txt +++ b/runtime/klee-fp/CMakeLists.txt @@ -10,18 +10,18 @@ set(LIB_PREFIX "RuntimeFp") set(SRC_FILES ceil.c - klee_copysign.c + copysign.c exp.c fabs.c - klee_fenv.c - klee_floor.c + fenv.c + floor.c fpclassify.c - klee_internal_isinf.ll - klee_rint.c + isinf.ll klee_set_rounding_mode.c - klee_signbit.ll log.c + rint.c round.c + signbit.ll sqrt.c trigonometry.c ) diff --git a/runtime/klee-fp/ceil.c b/runtime/klee-fp/ceil.c index 9d112a16a3..d185cb7cb1 100644 --- a/runtime/klee-fp/ceil.c +++ b/runtime/klee-fp/ceil.c @@ -8,26 +8,26 @@ //===----------------------------------------------------------------------===*/ #include "float.h" -#include "klee_floor.h" -#include "klee_rint.h" +#include "floor.h" +#include "rint.h" float ceilf(float f) { - if (f == klee_internal_rintf(f)) { + if (f == rintf(f)) { return f; } - return ((f < 0.0f) ? -1 : 1) + klee_floorf(f); + return ((f < 0.0f) ? -1 : 1) + floorf(f); } double ceil(double f) { - if (f == klee_internal_rint(f)) { + if (f == rint(f)) { return f; } - return ((f < 0.0f) ? -1 : 1) + klee_floor(f); + return ((f < 0.0f) ? -1 : 1) + floor(f); } long double ceill(long double f) { - if (f == klee_internal_rintl(f)) { + if (f == rintl(f)) { return f; } - return ((f < 0.0f) ? -1 : 1) + klee_floorl(f); + return ((f < 0.0f) ? -1 : 1) + floorl(f); } diff --git a/runtime/klee-fp/klee_copysign.c b/runtime/klee-fp/copysign.c similarity index 97% rename from runtime/klee-fp/klee_copysign.c rename to runtime/klee-fp/copysign.c index ddd72fdc53..7505b51ffb 100644 --- a/runtime/klee-fp/klee_copysign.c +++ b/runtime/klee-fp/copysign.c @@ -1,4 +1,4 @@ -/*===-- klee_copysign.c ---------------------------------------------------===// +/*===-- copysign.c --------------------------------------------------------===// // // The KLEE Symbolic Virtual Machine // @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===*/ -#include "klee_copysign.h" +#include "copysign.h" #include "ansidecl.h" #include "klee/klee.h" diff --git a/runtime/klee-fp/klee_copysign.h b/runtime/klee-fp/copysign.h similarity index 88% rename from runtime/klee-fp/klee_copysign.h rename to runtime/klee-fp/copysign.h index 444e0ab264..4384a216cb 100644 --- a/runtime/klee-fp/klee_copysign.h +++ b/runtime/klee-fp/copysign.h @@ -1,4 +1,4 @@ -/*===-- klee_copysign.h ---------------------------------------------------===// +/*===-- copysign.h --------------------------------------------------------===// // // The KLEE Symbolic Virtual Machine // diff --git a/runtime/klee-fp/fabs.c b/runtime/klee-fp/fabs.c index c3c4c88a6a..236cc38658 100644 --- a/runtime/klee-fp/fabs.c +++ b/runtime/klee-fp/fabs.c @@ -8,12 +8,10 @@ //===----------------------------------------------------------------------===*/ #include "klee/klee.h" -double klee_internal_fabs(double d) { return klee_abs_double(d); } +double fabs(double d) { return klee_abs_double(d); } -float klee_internal_fabsf(float f) { return klee_abs_float(f); } +float fabsf(float f) { return klee_abs_float(f); } #if defined(__x86_64__) || defined(__i386__) -long double klee_internal_fabsl(long double f) { - return klee_abs_long_double(f); -} +long double fabsl(long double f) { return klee_abs_long_double(f); } #endif diff --git a/runtime/klee-fp/klee_fenv.c b/runtime/klee-fp/fenv.c similarity index 92% rename from runtime/klee-fp/klee_fenv.c rename to runtime/klee-fp/fenv.c index d6b52e3820..0a70f90f34 100644 --- a/runtime/klee-fp/klee_fenv.c +++ b/runtime/klee-fp/fenv.c @@ -1,4 +1,4 @@ -/*===-- klee_fenv.c -------------------------------------------------------===// +/*===-- fenv.c ------------------------------------------------------------===// // // The KLEE Symbolic Virtual Machine // @@ -6,7 +6,7 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===*/ -#include "klee_fenv.h" +#include "fenv.h" #include "klee/klee.h" // Define the constants. Don't include `fenv.h` here to avoid @@ -28,7 +28,7 @@ enum { #error Architecture not supported #endif -int klee_internal_fegetround(void) { +int fegetround(void) { enum KleeRoundingMode rm = klee_get_rounding_mode(); switch (rm) { case KLEE_FP_RNE: @@ -52,7 +52,7 @@ int klee_internal_fegetround(void) { } } -int klee_internal_fesetround(int rm) { +int fesetround(int rm) { switch (rm) { case FE_TONEAREST: klee_set_rounding_mode(KLEE_FP_RNE); diff --git a/runtime/klee-fp/klee_fenv.h b/runtime/klee-fp/fenv.h similarity index 85% rename from runtime/klee-fp/klee_fenv.h rename to runtime/klee-fp/fenv.h index af75c5591b..3cb7728f20 100644 --- a/runtime/klee-fp/klee_fenv.h +++ b/runtime/klee-fp/fenv.h @@ -11,7 +11,7 @@ #define KLEE_FENV_H #include "klee/klee.h" -int klee_internal_fegetround(void); -int klee_internal_fesetround(int rm); +int fegetround(void); +int fesetround(int rm); #endif // KLEE_FENV_H diff --git a/runtime/klee-fp/klee_floor.c b/runtime/klee-fp/floor.c similarity index 79% rename from runtime/klee-fp/klee_floor.c rename to runtime/klee-fp/floor.c index 51a3785fe7..3b79738fe2 100644 --- a/runtime/klee-fp/klee_floor.c +++ b/runtime/klee-fp/floor.c @@ -1,4 +1,5 @@ -/*===-- klee_floor.c ------------------------------------------------------===// +/*===-- floor.c +------------------------------------------------------------===// // // The KLEE Symbolic Virtual Machine // @@ -7,11 +8,11 @@ // //===----------------------------------------------------------------------===*/ -#include "klee_floor.h" +#include "floor.h" #include "klee/klee.h" #include "math.h" -float klee_floorf(float x) { +float floorf(float x) { int sign = signbit(x); x = klee_abs_float(x); if (klee_rintf(x) > x) { @@ -21,7 +22,7 @@ float klee_floorf(float x) { } } -double klee_floor(double x) { +double floor(double x) { int sign = signbit(x); x = klee_abs_double(x); if (klee_rint(x) > x) { @@ -31,7 +32,7 @@ double klee_floor(double x) { } } -long double klee_floorl(long double x) { +long double floorl(long double x) { int sign = signbit(x); x = klee_abs_long_double(x); if (klee_rintl(x) > x) { diff --git a/runtime/klee-fp/klee_floor.h b/runtime/klee-fp/floor.h similarity index 68% rename from runtime/klee-fp/klee_floor.h rename to runtime/klee-fp/floor.h index 03e1c1c8da..4cdbc93981 100644 --- a/runtime/klee-fp/klee_floor.h +++ b/runtime/klee-fp/floor.h @@ -1,4 +1,4 @@ -/*===-- klee_floor.h ------------------------------------------------------===// +/*===-- floor.h -----------------------------------------------------------===// // // The KLEE Symbolic Virtual Machine // @@ -10,8 +10,8 @@ #ifndef KLEE_FLOOR_H #define KLEE_FLOOR_H -float klee_floorf(float x); -double klee_floor(double x); -long double klee_floorl(long double x); +float floorf(float x); +double floor(double x); +long double floorl(long double x); #endif // KLEE_FLOOR_H diff --git a/runtime/klee-fp/fpclassify.c b/runtime/klee-fp/fpclassify.c index 06f9d001f9..0e0b1b179d 100644 --- a/runtime/klee-fp/fpclassify.c +++ b/runtime/klee-fp/fpclassify.c @@ -13,16 +13,19 @@ // during linking. // __isnanf -int klee_internal_isnanf(float f) { return klee_is_nan_float(f); } +int __isnanf(float f) { return klee_is_nan_float(f); } +int isnanf(float f) { return __isnanf(f); } // __isnan -int klee_internal_isnan(double d) { return klee_is_nan_double(d); } +int __isnan(double d) { return klee_is_nan_double(d); } +int isnan(double d) { return __isnan(d); } // __isnanl -int klee_internal_isnanl(long double d) { return klee_is_nan_long_double(d); } +int __isnanl(long double d) { return klee_is_nan_long_double(d); } +int isnanl(long double d) { return __isnanl(d); } // __fpclassifyf -int klee_internal_fpclassifyf(float f) { +int __fpclassifyf(float f) { /* * This version acts like a switch case which returns correct * float type from the enum, but itself does not fork @@ -33,38 +36,44 @@ int klee_internal_fpclassifyf(float f) { int x = klee_is_normal_float(f); return ((x << 2) | ((c | d) << 1) | (b | d)); } +int fpclassifyf(float f) { return __fpclassifyf(f); } // __fpclassify -int klee_internal_fpclassify(double f) { +int __fpclassify(double f) { int b = klee_is_infinite_double(f); int c = (f == 0.0f); int d = klee_is_subnormal_double(f); int x = klee_is_normal_double(f); return ((x << 2) | ((c | d) << 1) | (b | d)); } +int fpclassify(double f) { return __fpclassify(f); } // __fpclassifyl #if defined(__x86_64__) || defined(__i386__) -int klee_internal_fpclassifyl(long double f) { +int __fpclassifyl(long double f) { int b = klee_is_infinite_long_double(f); int c = (f == 0.0f); int d = klee_is_subnormal_long_double(f); int x = klee_is_normal_long_double(f); return ((x << 2) | ((c | d) << 1) | (b | d)); } +int fpclassifyl(long double f) { return __fpclassifyl(f); } #endif // __finitef -int klee_internal_finitef(float f) { +int __finitef(float f) { return (!klee_is_nan_float(f)) & (!klee_is_infinite_float(f)); } +int finitef(float f) { return __finitef(f); } // __finite -int klee_internal_finite(double f) { +int __finite(double f) { return (!klee_is_nan_double(f)) & (!klee_is_infinite_double(f)); } +int finite(double f) { return __finite(f); } // __finitel -int klee_internal_finitel(long double f) { +int __finitel(long double f) { return (!klee_is_nan_long_double(f)) & (!klee_is_infinite_long_double(f)); } +int finitel(long double f) { return finitel(f); } diff --git a/runtime/klee-fp/klee_internal_isinf.ll b/runtime/klee-fp/isinf.ll similarity index 78% rename from runtime/klee-fp/klee_internal_isinf.ll rename to runtime/klee-fp/isinf.ll index 8a50b15134..f22bee07ce 100644 --- a/runtime/klee-fp/klee_internal_isinf.ll +++ b/runtime/klee-fp/isinf.ll @@ -1,4 +1,4 @@ -;;===-- klee_internal_isinff.ll --------------------------------------------===;; +;;===-- isinff.ll ---------------------------------------------------------===;; ;; ;; The KLEE Symbolic Virtual Machine ;; @@ -6,8 +6,6 @@ ;; License. See LICENSE.TXT for details. ;; ;;===----------------------------------------------------------------------===;; -;target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" -;target triple = "x86_64-unknown-linux-gnu" ;; These are implementations of internal functions found in libm for classifying ;; floating point numbers. They have different names to avoid name collisions @@ -19,7 +17,7 @@ declare zeroext i1 @klee_is_infinite_float(float) #2 declare zeroext i1 @klee_is_infinite_double(double) #2 declare zeroext i1 @klee_is_infinite_long_double(x86_fp80) #2 -define i32 @klee_internal_isinff(float %f) #1 #0 { +define i32 @__isinff(float %f) #1 #0 { entry: %isinf = tail call zeroext i1 @klee_is_infinite_float(float %f) #3 %cmp = fcmp ogt float %f, 0.000000e+00 @@ -28,7 +26,13 @@ entry: ret i32 %result } -define i32 @klee_internal_isinf(double %d) #1 #0 { +define i32 @isinff(float %f) #1 #0 { +entry: + %result = tail call zeroext i32 @__isinff(float %f) #3 + ret i32 %result +} + +define i32 @__isinf(double %d) #1 #0 { entry: %isinf = tail call zeroext i1 @klee_is_infinite_double(double %d) #3 %cmp = fcmp ogt double %d, 0.000000e+00 @@ -37,7 +41,13 @@ entry: ret i32 %result } -define i32 @klee_internal_isinfl(x86_fp80 %d) #0 { +define i32 @isinf(double %d) #1 #0 { +entry: + %result = tail call zeroext i32 @__isinf(double %d) #3 + ret i32 %result +} + +define i32 @__isinfl(x86_fp80 %d) #0 { entry: %isinf = tail call zeroext i1 @klee_is_infinite_long_double(x86_fp80 %d) #3 %cmp = fcmp ogt x86_fp80 %d, 0xK00000000000000000000 @@ -46,6 +56,12 @@ entry: ret i32 %result } +define i32 @isinfl(x86_fp80 %d) #0 { +entry: + %result = tail call zeroext i32 @__isinfl(x86_fp80 %d) #3 + ret i32 %result +} + ; NOTE: Use of optnone and noinline here are important so that the KLEE diff --git a/runtime/klee-fp/log.c b/runtime/klee-fp/log.c index 25b797ace4..77f3d3a12f 100644 --- a/runtime/klee-fp/log.c +++ b/runtime/klee-fp/log.c @@ -8,9 +8,10 @@ //===----------------------------------------------------------------------===*/ #include "fenv.h" -#include "klee_fenv.h" #include "math.h" +#include + #define LOG_CORNER_CASE(suffix, type, isnan_function) \ int log_corner_case_##suffix(type *x) { \ if (isinf(*x) || isnan_function(*x)) { \ diff --git a/runtime/klee-fp/klee_rint.c b/runtime/klee-fp/rint.c similarity index 62% rename from runtime/klee-fp/klee_rint.c rename to runtime/klee-fp/rint.c index 9dc7701991..a15096a01c 100644 --- a/runtime/klee-fp/klee_rint.c +++ b/runtime/klee-fp/rint.c @@ -1,4 +1,4 @@ -/*===-- klee_rint.c -------------------------------------------------------===// +/*===-- rint.c ------------------------------------------------------------===// // // The KLEE Symbolic Virtual Machine // @@ -7,14 +7,14 @@ // //===----------------------------------------------------------------------===*/ -#include "klee_rint.h" +#include "rint.h" #include "klee/klee.h" -float klee_internal_rintf(float arg) { return klee_rintf(arg); } +float rintf(float arg) { return klee_rintf(arg); } -double klee_internal_rint(double arg) { return klee_rint(arg); } +double rint(double arg) { return klee_rint(arg); } -long double klee_internal_rintl(long double arg) { return klee_rintl(arg); } +long double rintl(long double arg) { return klee_rintl(arg); } float nearbyintf(float arg) { return klee_rintf(arg); } diff --git a/runtime/klee-fp/klee_rint.h b/runtime/klee-fp/rint.h similarity index 69% rename from runtime/klee-fp/klee_rint.h rename to runtime/klee-fp/rint.h index b1be763080..4fb35f4382 100644 --- a/runtime/klee-fp/klee_rint.h +++ b/runtime/klee-fp/rint.h @@ -1,4 +1,4 @@ -/*===-- klee_rint.h -------------------------------------------------------===// +/*===-- rint.h ------------------------------------------------------------===// // // The KLEE Symbolic Virtual Machine // @@ -10,9 +10,9 @@ #ifndef KLEE_RINT_H #define KLEE_RINT_H -float klee_internal_rintf(float arg); -double klee_internal_rint(double arg); -long double klee_internal_rintl(long double arg); +float rintf(float arg); +double rint(double arg); +long double rintl(long double arg); float nearbyintf(float arg); double nearbyint(double arg); long double nearbyintl(long double arg); diff --git a/runtime/klee-fp/round.c b/runtime/klee-fp/round.c index 490cc4849e..d5a6ad9f51 100644 --- a/runtime/klee-fp/round.c +++ b/runtime/klee-fp/round.c @@ -9,6 +9,12 @@ #include "klee/klee.h" +float roundf(float x) { return klee_rintf(x); } + +double round(double x) { return klee_rint(x); } + +long double roundl(long double x) { return klee_rintl(x); } + long lroundf(float x) { return klee_rintf(x); } long lround(double x) { return klee_rint(x); } diff --git a/runtime/klee-fp/klee_signbit.ll b/runtime/klee-fp/signbit.ll similarity index 89% rename from runtime/klee-fp/klee_signbit.ll rename to runtime/klee-fp/signbit.ll index a7c504f856..8ee4768ed9 100644 --- a/runtime/klee-fp/klee_signbit.ll +++ b/runtime/klee-fp/signbit.ll @@ -9,7 +9,7 @@ ;target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" ;target triple = "x86_64-unknown-linux-gnu" -define i32 @klee_internal_signbitf(float %f) #1 #0 { +define i32 @__signbitf(float %f) #1 #0 { entry: %0 = bitcast float %f to i32 %1 = icmp slt i32 %0, 0 @@ -17,7 +17,7 @@ entry: ret i32 %2 } -define i32 @klee_internal_signbit(double %d) #1 #0 { +define i32 @__signbit(double %d) #1 #0 { entry: %0 = bitcast double %d to i64 %1 = icmp slt i64 %0, 0 @@ -25,7 +25,7 @@ entry: ret i32 %2 } -define i32 @klee_internal_signbitl(x86_fp80 %d) #0 { +define i32 @__signbitl(x86_fp80 %d) #0 { entry: %0 = bitcast x86_fp80 %d to i80 %1 = icmp slt i80 %0, 0 diff --git a/runtime/klee-fp/sqrt.c b/runtime/klee-fp/sqrt.c index ba1b928340..26fbe2cc9f 100644 --- a/runtime/klee-fp/sqrt.c +++ b/runtime/klee-fp/sqrt.c @@ -8,12 +8,10 @@ //===----------------------------------------------------------------------===*/ #include "klee/klee.h" -double klee_internal_sqrt(double d) { return klee_sqrt_double(d); } +double sqrt(double d) { return klee_sqrt_double(d); } -float klee_internal_sqrtf(float f) { return klee_sqrt_float(f); } +float sqrtf(float f) { return klee_sqrt_float(f); } #if defined(__x86_64__) || defined(__i386__) -long double klee_internal_sqrtl(long double f) { - return klee_sqrt_long_double(f); -} +long double sqrtl(long double f) { return klee_sqrt_long_double(f); } #endif diff --git a/tools/klee/main.cpp b/tools/klee/main.cpp index 71e7f8623a..766013544b 100644 --- a/tools/klee/main.cpp +++ b/tools/klee/main.cpp @@ -1222,22 +1222,6 @@ static void halt_via_gdb(int pid) { perror("system"); } -static void replaceOrRenameFunction(llvm::Module *module, const char *old_name, - const char *new_name) { - Function *new_function, *old_function; - new_function = module->getFunction(new_name); - old_function = module->getFunction(old_name); - if (old_function) { - if (new_function) { - old_function->replaceAllUsesWith(new_function); - old_function->eraseFromParent(); - } else { - old_function->setName(new_name); - assert(old_function->getName() == new_name); - } - } -} - static void createLibCWrapper(std::vector> &userModules, std::vector> &libsModules, From c1648ab8753741eb98d15f2fcae3789a40daedae Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Wed, 15 Nov 2023 06:08:44 +0400 Subject: [PATCH 099/103] [fix] Bring calls to `SparseStorage` constructor up to date --- lib/Solver/CexCachingSolver.cpp | 5 +++-- lib/Solver/ConcretizingSolver.cpp | 2 +- lib/Solver/IndependentSolver.cpp | 2 +- unittests/Assignment/AssignmentTest.cpp | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/Solver/CexCachingSolver.cpp b/lib/Solver/CexCachingSolver.cpp index 2c4b83d4c8..3cd4947c9f 100644 --- a/lib/Solver/CexCachingSolver.cpp +++ b/lib/Solver/CexCachingSolver.cpp @@ -382,10 +382,11 @@ bool CexCachingSolver::computeInitialValues( // FIXME: We should use smarter assignment for result so we don't // need redundant copy. values = std::vector>(objects.size()); + Assignment::bindings_ty aBindings; + a->tryGetInitialValues(aBindings); + for (unsigned i = 0; i < objects.size(); ++i) { const Array *os = objects[i]; - Assignment::bindings_ty aBindings; - a->tryGetInitialValues(aBindings); Assignment::bindings_ty::iterator it = aBindings.find(os); if (it == aBindings.end()) { diff --git a/lib/Solver/ConcretizingSolver.cpp b/lib/Solver/ConcretizingSolver.cpp index c2d717ceed..6f0327a226 100644 --- a/lib/Solver/ConcretizingSolver.cpp +++ b/lib/Solver/ConcretizingSolver.cpp @@ -378,7 +378,7 @@ bool ConcretizingSolver::relaxSymcreteConstraints(const Query &query, sizeSymcrete->addressSymcrete.symcretized, newSize); unsigned char *charAddressIterator = reinterpret_cast(&address); - SparseStorage storage(sizeof(address)); + SparseStorage storage(0); storage.store(0, charAddressIterator, charAddressIterator + sizeof(address)); diff --git a/lib/Solver/IndependentSolver.cpp b/lib/Solver/IndependentSolver.cpp index 67c0309335..56cf4d043c 100644 --- a/lib/Solver/IndependentSolver.cpp +++ b/lib/Solver/IndependentSolver.cpp @@ -225,7 +225,7 @@ bool IndependentSolver::computeInitialValues( dyn_cast(retMap.evaluate(arr->size)); assert(arrayConstantSize && "Array of symbolic size had not receive value for size!"); - SparseStorage ret(arrayConstantSize->getZExtValue()); + SparseStorage ret(0); values.push_back(ret); } else { values.push_back(retMap.bindings.at(arr)); diff --git a/unittests/Assignment/AssignmentTest.cpp b/unittests/Assignment/AssignmentTest.cpp index 410a4ce357..419a4d0956 100644 --- a/unittests/Assignment/AssignmentTest.cpp +++ b/unittests/Assignment/AssignmentTest.cpp @@ -19,7 +19,7 @@ TEST(AssignmentTest, FoldNotOptimized) { SourceBuilder::makeSymbolic("simple_array", 0)); // Create a simple assignment std::vector objects; - SparseStorage value(1); + SparseStorage value(0); std::vector> values; objects.push_back(array); From 44f64ed8a604ceb3057511ec07f46e8e87d96c36 Mon Sep 17 00:00:00 2001 From: Aleksei Babushkin Date: Tue, 21 Nov 2023 14:20:13 +0300 Subject: [PATCH 100/103] [experiment] SparseStorage persistent on threshold --- include/klee/ADT/PersistentMap.h | 1 + include/klee/ADT/SparseStorage.h | 282 ++++++++++++++++++++++++++++--- lib/Core/Memory.cpp | 21 ++- lib/Expr/Assignment.cpp | 2 +- lib/Solver/MetaSMTBuilder.h | 28 ++- lib/Solver/STPBuilder.cpp | 24 ++- lib/Solver/Z3Builder.cpp | 31 +++- 7 files changed, 342 insertions(+), 47 deletions(-) diff --git a/include/klee/ADT/PersistentMap.h b/include/klee/ADT/PersistentMap.h index dabc5495db..b0c8679777 100644 --- a/include/klee/ADT/PersistentMap.h +++ b/include/klee/ADT/PersistentMap.h @@ -57,6 +57,7 @@ template > class PersistentMap { void remove(const key_type &key) { elts = elts.remove(key); } void popMin(const value_type &valueOut) { elts = elts.popMin(valueOut); } void popMax(const value_type &valueOut) { elts = elts.popMax(valueOut); } + void clear() { elts = Map(); } iterator begin() const { return elts.begin(); } iterator end() const { return elts.end(); } diff --git a/include/klee/ADT/SparseStorage.h b/include/klee/ADT/SparseStorage.h index a06f63391f..1b9f3cd8de 100644 --- a/include/klee/ADT/SparseStorage.h +++ b/include/klee/ADT/SparseStorage.h @@ -1,11 +1,15 @@ #ifndef KLEE_SPARSESTORAGE_H #define KLEE_SPARSESTORAGE_H +#include "klee/ADT/PersistentMap.h" +#include "llvm/Support/Casting.h" #include #include #include #include #include +#include +#include #include #include @@ -20,22 +24,227 @@ enum class Density { Dense, }; +enum class MapKind { + Regular, + Persistent, +}; + +// template +// class SparseStorageIterator { +// using RegularIterator = typename std::unordered_map::const_iterator; +// using PersistentIterator = typename PersistentMap::iterator; +// public: + +// // SparseStorageIterator() : kind(MapKind::Regular), regIt(std::nullopt), perIt(std::nullopt) {} +// SparseStorageIterator(RegularIterator it) : kind(MapKind::Regular), regIt(it), perIt(std::nullopt) {} +// SparseStorageIterator(PersistentIterator it) : kind(MapKind::Persistent), regIt(std::nullopt), perIt(it) {} + +// SparseStorageIterator& operator++() { +// if (kind == MapKind::Regular) { +// ++(*regIt); +// } else { +// ++(*perIt); +// } +// return *this; +// } + +// bool operator==(const SparseStorageIterator &other) const { +// if (kind != other.kind) { +// return false; +// } + +// if (kind == MapKind::Regular) { +// return (*regIt) == (*other.regIt); +// } else { +// return (*perIt) == (*other.perIt); +// } +// } + +// bool operator!=(const SparseStorageIterator &other) const { +// return !(*this == other); +// } + +// std::pair operator*() const { +// if (kind == MapKind::Regular) { +// return *(*regIt); +// } else { +// return (*perIt); +// } +// } + +// private: +// MapKind kind; +// std::optional regIt; +// std::optional perIt; +// }; + +template +class SparseStorage_Map { +public: + SparseStorage_Map(MapKind kind) : kind(kind) {} + virtual ~SparseStorage_Map() = default; + + virtual bool contains(size_t key) const = 0; + virtual void erase(size_t key) = 0; + virtual void set(size_t key, ValueType value) = 0; + virtual std::optional find(size_t key) const = 0; + virtual size_t sizeOfSetRange() const = 0; + virtual size_t mapSize() const = 0; + virtual void clear() = 0; + + // virtual SparseStorageIterator begin() const = 0; + // virtual SparseStorageIterator end() const = 0; + + MapKind getKind() const { + return kind; + } + +private: + MapKind kind; +}; + +template +class SparseStorage_RegularMap : public SparseStorage_Map { +public: + SparseStorage_RegularMap() : SparseStorage_Map(MapKind::Regular) {} + ~SparseStorage_RegularMap() override = default; + + bool contains(size_t key) const override { + return map.count(key); + } + + void erase(size_t key) override { + map.erase(key); + } + void set(size_t key, ValueType value) override { + map[key] = value; + } + + std::optional find(size_t key) const override { + auto it = map.find(key); + if (it != map.end()) { + return it->second; + } else { + return std::nullopt; + } + } + + size_t sizeOfSetRange() const override { + size_t sizeOfRange = 0; + for (auto i : map) { + sizeOfRange = std::max(i.first, sizeOfRange); + } + return map.empty() ? 0 : sizeOfRange + 1; + } + + size_t mapSize() const override { + return map.size(); + } + + void clear() override { + map.clear(); + } + + static bool classof(const SparseStorage_Map *map) { + return map->getKind() == MapKind::Regular; + } + + const std::unordered_map &getMap() const { + return map; + } + + // SparseStorageIterator begin() const override { + // return map.cbegin(); + // } + + // SparseStorageIterator end() const override { + // return map.cend(); + // } + +private: + std::unordered_map map; +}; + +template +class SparseStorage_PersistentMap : public SparseStorage_Map { +public: + SparseStorage_PersistentMap() : SparseStorage_Map(MapKind::Persistent) {} + ~SparseStorage_PersistentMap() override = default; + + bool contains(size_t key) const override { + return map.count(key); + } + + void erase(size_t key) override { + map.remove(key); + } + void set(size_t key, ValueType value) override { + map.replace({key, value}); + } + + std::optional find(size_t key) const override { + auto it = map.find(key); + if (it != map.end()) { + return it->second; + } else { + return std::nullopt; + } + } + + size_t sizeOfSetRange() const override { + size_t sizeOfRange = 0; + for (auto i : map) { + sizeOfRange = std::max(i.first, sizeOfRange); + } + return map.empty() ? 0 : sizeOfRange + 1; + } + + size_t mapSize() const override { return map.size(); } + + void clear() override { + map.clear(); + } + + static bool classof(const SparseStorage_Map *map) { + return map->getKind() == MapKind::Persistent; + } + + const PersistentMap &getMap() const { + return map; + } + + // SparseStorageIterator begin() const override { + // return map.begin(); + // } + + // SparseStorageIterator end() const override { return map.end(); } + +private: + PersistentMap map; +}; + template > class SparseStorage { private: - std::unordered_map internalStorage; + using RegularMap_t = SparseStorage_RegularMap; + using PersistentMap_t = SparseStorage_PersistentMap; + +private: ValueType defaultValue; + std::unique_ptr> internalStorage; Eq eq; - bool contains(size_t key) const { return internalStorage.count(key) != 0; } + bool contains(size_t key) const { return internalStorage->contains(key) != 0; } public: SparseStorage(const ValueType &defaultValue = ValueType()) - : defaultValue(defaultValue) {} + : defaultValue(defaultValue), + internalStorage(std::make_unique()) {} SparseStorage(const std::unordered_map &internalStorage, const ValueType &defaultValue) - : defaultValue(defaultValue) { + : defaultValue(defaultValue), + internalStorage(std::make_unique()) { for (auto &[index, value] : internalStorage) { store(index, value); } @@ -43,17 +252,49 @@ class SparseStorage { SparseStorage(const std::vector &values, const ValueType &defaultValue = ValueType()) - : defaultValue(defaultValue) { + : defaultValue(defaultValue), + internalStorage(std::make_unique()) { for (size_t idx = 0; idx < values.size(); ++idx) { store(idx, values[idx]); } } + SparseStorage(const SparseStorage &other) : defaultValue(other.defaultValue) { + if (auto regularMap = llvm::dyn_cast(other.internalStorage.get())) { + internalStorage = std::make_unique(*regularMap); + } else if (auto persistentMap = llvm::dyn_cast(other.internalStorage.get())) { + internalStorage = std::make_unique(*persistentMap); + } + } + + SparseStorage& operator=(const SparseStorage &other) { + if (this != &other) { + defaultValue = other.defaultValue; + if (auto regularMap = llvm::dyn_cast(other.internalStorage.get())) { + internalStorage = std::make_unique(*regularMap); + } else if (auto persistentMap = llvm::dyn_cast(other.internalStorage.get())) { + internalStorage = std::make_unique(*persistentMap); + } + } + return *this; + } + void store(size_t idx, const ValueType &value) { if (eq(value, defaultValue)) { - internalStorage.erase(idx); + internalStorage->erase(idx); } else { - internalStorage[idx] = value; + internalStorage->set(idx, value); + } + + if (internalStorage->mapSize() > 100000000) { + if (auto regularMap = + llvm::dyn_cast(internalStorage.get())) { + PersistentMap_t *newStorage = new PersistentMap_t(); + for (const auto &i : regularMap->getMap()) { + newStorage->set(i.first, i.second); + } + internalStorage = std::unique_ptr(newStorage); + } } } @@ -66,16 +307,12 @@ class SparseStorage { } ValueType load(size_t idx) const { - auto it = internalStorage.find(idx); - return it != internalStorage.end() ? it->second : defaultValue; + auto it = internalStorage->find(idx); + return it ? *it : defaultValue; } size_t sizeOfSetRange() const { - size_t sizeOfRange = 0; - for (auto i : internalStorage) { - sizeOfRange = std::max(i.first, sizeOfRange); - } - return sizeOfRange; + return internalStorage->sizeOfSetRange(); } bool operator==(const SparseStorage &another) const { @@ -107,8 +344,15 @@ class SparseStorage { std::map calculateOrderedStorage() const { std::map ordered; - for (const auto &i : internalStorage) { - ordered.insert(i); + if (auto storage = llvm::dyn_cast(internalStorage.get())) { + for (const auto &i : storage->getMap()) { + ordered.insert(i); + } + } else if (auto storage = + llvm::dyn_cast(internalStorage.get())) { + for (const auto &i : storage->getMap()) { + ordered.insert(i); + } } return ordered; } @@ -121,13 +365,13 @@ class SparseStorage { return vectorized; } - const std::unordered_map &storage() const { - return internalStorage; + const SparseStorage_Map *storage() const { + return internalStorage.get(); }; const ValueType &defaultV() const { return defaultValue; }; - void reset() { internalStorage.clear(); } + void reset() { internalStorage->clear(); } void reset(ValueType newDefault) { defaultValue = newDefault; diff --git a/lib/Core/Memory.cpp b/lib/Core/Memory.cpp index 16a49c6938..749b76ba5f 100644 --- a/lib/Core/Memory.cpp +++ b/lib/Core/Memory.cpp @@ -101,7 +101,7 @@ const UpdateList &ObjectState::getUpdates() const { if (auto sizeExpr = dyn_cast(size)) { auto size = sizeExpr->getZExtValue(); - if (knownSymbolics.storage().size() == size) { + if (knownSymbolics.storage()->mapSize() == size) { SparseStorage> values( ConstantExpr::create(0, Expr::Int8)); UpdateList symbolicUpdates = UpdateList(nullptr, nullptr); @@ -136,11 +136,20 @@ const UpdateList &ObjectState::getUpdates() const { } void ObjectState::flushForRead() const { - for (const auto &unflushed : unflushedMask.storage()) { - auto offset = unflushed.first; - auto value = knownSymbolics.load(offset); - assert(value); - updates.extend(ConstantExpr::create(offset, Expr::Int32), value); + if (auto storage = dyn_cast>(unflushedMask.storage())) { + for (const auto &unflushed : storage->getMap()) { + auto offset = unflushed.first; + auto value = knownSymbolics.load(offset); + assert(value); + updates.extend(ConstantExpr::create(offset, Expr::Int32), value); + } + } else if (auto storage = dyn_cast>(unflushedMask.storage())) { + for (const auto &unflushed : storage->getMap()) { + auto offset = unflushed.first; + auto value = knownSymbolics.load(offset); + assert(value); + updates.extend(ConstantExpr::create(offset, Expr::Int32), value); + } } unflushedMask.reset(false); } diff --git a/lib/Expr/Assignment.cpp b/lib/Expr/Assignment.cpp index 860f1a0a50..c58957d36b 100644 --- a/lib/Expr/Assignment.cpp +++ b/lib/Expr/Assignment.cpp @@ -24,7 +24,7 @@ void Assignment::dump() const { ++i) { llvm::errs() << (*i).first->getName() << "\n"; Density d = - ((*i).second.storage().size() * 2 < (*i).second.sizeOfSetRange()) + ((*i).second.storage()->mapSize() * 2 < (*i).second.sizeOfSetRange()) ? Density::Sparse : Density::Dense; (*i).second.print(llvm::errs(), d); diff --git a/lib/Solver/MetaSMTBuilder.h b/lib/Solver/MetaSMTBuilder.h index 6944402788..a033f2c063 100644 --- a/lib/Solver/MetaSMTBuilder.h +++ b/lib/Solver/MetaSMTBuilder.h @@ -711,12 +711,24 @@ MetaSMTBuilder::constructActual(ref e, int *width_out) { dyn_cast(re->updates.root->source)) { if (!isa(re->updates.root->size)) { ref selectExpr = constantSource->constantValues.defaultV(); - for (const auto &[index, value] : - constantSource->constantValues.storage()) { - selectExpr = SelectExpr::create( - EqExpr::create(re->index, ConstantExpr::create( - index, re->index->getWidth())), - value, selectExpr); + if (auto storage = + llvm::dyn_cast>>( + source->constantValues.storage())) { + for (const auto &[index, value] : storage->getMap()) { + selectExpr = SelectExpr::create( + EqExpr::create(re->index, ConstantExpr::create( + index, re->index->getWidth())), + value, selectExpr); + } + } else if (auto storage = llvm::dyn_cast< + SparseStorage_PersistentMap>>( + source->constantValues.storage())) { + for (const auto &[index, value] : storage->getMap()) { + selectExpr = SelectExpr::create( + EqExpr::create(re->index, ConstantExpr::create( + index, re->index->getWidth())), + value, selectExpr); + } } std::vector update_nodes; auto un = re->updates.head.get(); @@ -730,8 +742,8 @@ MetaSMTBuilder::constructActual(ref e, int *width_out) { (*it)->value, selectExpr); } return construct(selectExpr, width_out); - } - } + } + } // FixMe call method of Array res = evaluate(_solver, metaSMT::logic::Array::select( diff --git a/lib/Solver/STPBuilder.cpp b/lib/Solver/STPBuilder.cpp index b766111ed7..91a276bc98 100644 --- a/lib/Solver/STPBuilder.cpp +++ b/lib/Solver/STPBuilder.cpp @@ -575,12 +575,24 @@ ExprHandle STPBuilder::constructActual(ref e, int *width_out) { dyn_cast(re->updates.root->source)) { if (!isa(re->updates.root->size)) { ref selectExpr = constantSource->constantValues.defaultV(); - for (const auto &[index, value] : - constantSource->constantValues.storage()) { - selectExpr = SelectExpr::create( - EqExpr::create(re->index, ConstantExpr::create( - index, re->index->getWidth())), - value, selectExpr); + if (auto storage = + llvm::dyn_cast>>( + source->constantValues.storage())) { + for (const auto &[index, value] : storage->getMap()) { + selectExpr = SelectExpr::create( + EqExpr::create(re->index, ConstantExpr::create( + index, re->index->getWidth())), + value, selectExpr); + } + } else if (auto storage = llvm::dyn_cast< + SparseStorage_PersistentMap>>( + source->constantValues.storage())) { + for (const auto &[index, value] : storage->getMap()) { + selectExpr = SelectExpr::create( + EqExpr::create(re->index, ConstantExpr::create( + index, re->index->getWidth())), + value, selectExpr); + } } std::vector update_nodes; auto un = re->updates.head.get(); diff --git a/lib/Solver/Z3Builder.cpp b/lib/Solver/Z3Builder.cpp index b26ec1e75c..35a91677e3 100644 --- a/lib/Solver/Z3Builder.cpp +++ b/lib/Solver/Z3Builder.cpp @@ -6,7 +6,9 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// +#include "klee/ADT/SparseStorage.h" #include "klee/Config/config.h" +#include "llvm/Support/Casting.h" #ifdef ENABLE_Z3 #include "Z3Builder.h" @@ -284,13 +286,28 @@ Z3ASTHandle Z3Builder::getInitialArray(const Array *root) { } constant_array_assertions[root] = std::move(array_assertions); } else { - for (auto &[index, value] : source->constantValues.storage()) { - int width_out; - Z3ASTHandle array_value = construct(value, &width_out); - assert(width_out == (int)root->getRange() && - "Value doesn't match root range"); - array_expr = writeExpr( - array_expr, bvConst32(root->getDomain(), index), array_value); + if (auto storage = + llvm::dyn_cast>>( + source->constantValues.storage())) { + for (const auto &[index, value] : storage->getMap()) { + int width_out; + Z3ASTHandle array_value = construct(value, &width_out); + assert(width_out == (int)root->getRange() && + "Value doesn't match root range"); + array_expr = writeExpr( + array_expr, bvConst32(root->getDomain(), index), array_value); + } + } else if (auto storage = llvm::dyn_cast< + SparseStorage_PersistentMap>>( + source->constantValues.storage())) { + for (const auto &[index, value] : storage->getMap()) { + int width_out; + Z3ASTHandle array_value = construct(value, &width_out); + assert(width_out == (int)root->getRange() && + "Value doesn't match root range"); + array_expr = writeExpr( + array_expr, bvConst32(root->getDomain(), index), array_value); + } } } } From 6459807854a57e29ffbbbc4e93e2b8cf8ec49e66 Mon Sep 17 00:00:00 2001 From: Aleksei Babushkin Date: Tue, 21 Nov 2023 14:52:31 +0300 Subject: [PATCH 101/103] [] start CI --- .github/workflows/build.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index dc2c95350c..287eab776e 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -3,9 +3,9 @@ name: CI on: pull_request: - branches: [main, utbot-main] + branches: [persistent_object_state] push: - branches: [main, utbot-main] + branches: [persistent_object_state] # Defaults for building KLEE env: From 312ff29d24d4ddc07ea23fb08be16dfe3f450356 Mon Sep 17 00:00:00 2001 From: Aleksei Babushkin Date: Tue, 21 Nov 2023 15:02:06 +0300 Subject: [PATCH 102/103] [fix] --- lib/Solver/MetaSMTBuilder.h | 8 ++++---- lib/Solver/STPBuilder.cpp | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/Solver/MetaSMTBuilder.h b/lib/Solver/MetaSMTBuilder.h index a033f2c063..7039022b31 100644 --- a/lib/Solver/MetaSMTBuilder.h +++ b/lib/Solver/MetaSMTBuilder.h @@ -713,7 +713,7 @@ MetaSMTBuilder::constructActual(ref e, int *width_out) { ref selectExpr = constantSource->constantValues.defaultV(); if (auto storage = llvm::dyn_cast>>( - source->constantValues.storage())) { + constantSource->constantValues.storage())) { for (const auto &[index, value] : storage->getMap()) { selectExpr = SelectExpr::create( EqExpr::create(re->index, ConstantExpr::create( @@ -722,7 +722,7 @@ MetaSMTBuilder::constructActual(ref e, int *width_out) { } } else if (auto storage = llvm::dyn_cast< SparseStorage_PersistentMap>>( - source->constantValues.storage())) { + constantSource->constantValues.storage())) { for (const auto &[index, value] : storage->getMap()) { selectExpr = SelectExpr::create( EqExpr::create(re->index, ConstantExpr::create( @@ -742,8 +742,8 @@ MetaSMTBuilder::constructActual(ref e, int *width_out) { (*it)->value, selectExpr); } return construct(selectExpr, width_out); - } - } + } + } // FixMe call method of Array res = evaluate(_solver, metaSMT::logic::Array::select( diff --git a/lib/Solver/STPBuilder.cpp b/lib/Solver/STPBuilder.cpp index 91a276bc98..77fa091139 100644 --- a/lib/Solver/STPBuilder.cpp +++ b/lib/Solver/STPBuilder.cpp @@ -577,7 +577,7 @@ ExprHandle STPBuilder::constructActual(ref e, int *width_out) { ref selectExpr = constantSource->constantValues.defaultV(); if (auto storage = llvm::dyn_cast>>( - source->constantValues.storage())) { + constantSource->constantValues.storage())) { for (const auto &[index, value] : storage->getMap()) { selectExpr = SelectExpr::create( EqExpr::create(re->index, ConstantExpr::create( @@ -586,7 +586,7 @@ ExprHandle STPBuilder::constructActual(ref e, int *width_out) { } } else if (auto storage = llvm::dyn_cast< SparseStorage_PersistentMap>>( - source->constantValues.storage())) { + constantSource->constantValues.storage())) { for (const auto &[index, value] : storage->getMap()) { selectExpr = SelectExpr::create( EqExpr::create(re->index, ConstantExpr::create( From c91e602b1bca501a101baadaba5e48917f66b0d3 Mon Sep 17 00:00:00 2001 From: Aleksei Babushkin Date: Tue, 21 Nov 2023 16:17:12 +0300 Subject: [PATCH 103/103] [fix] Don't persist constant objects + test always persist --- include/klee/ADT/SparseStorage.h | 14 ++++++++++---- lib/Core/Executor.cpp | 6 ++++++ lib/Core/Memory.h | 4 ++++ 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/include/klee/ADT/SparseStorage.h b/include/klee/ADT/SparseStorage.h index 1b9f3cd8de..4866b90105 100644 --- a/include/klee/ADT/SparseStorage.h +++ b/include/klee/ADT/SparseStorage.h @@ -225,6 +225,7 @@ class SparseStorage_PersistentMap : public SparseStorage_Map { template > class SparseStorage { + friend class ObjectState; private: using RegularMap_t = SparseStorage_RegularMap; using PersistentMap_t = SparseStorage_PersistentMap; @@ -233,6 +234,7 @@ class SparseStorage { ValueType defaultValue; std::unique_ptr> internalStorage; Eq eq; + bool isConstant = false; bool contains(size_t key) const { return internalStorage->contains(key) != 0; } @@ -259,10 +261,13 @@ class SparseStorage { } } - SparseStorage(const SparseStorage &other) : defaultValue(other.defaultValue) { - if (auto regularMap = llvm::dyn_cast(other.internalStorage.get())) { + SparseStorage(const SparseStorage &other) + : defaultValue(other.defaultValue), isConstant(other.isConstant) { + if (auto regularMap = + llvm::dyn_cast(other.internalStorage.get())) { internalStorage = std::make_unique(*regularMap); - } else if (auto persistentMap = llvm::dyn_cast(other.internalStorage.get())) { + } else if (auto persistentMap = llvm::dyn_cast( + other.internalStorage.get())) { internalStorage = std::make_unique(*persistentMap); } } @@ -270,6 +275,7 @@ class SparseStorage { SparseStorage& operator=(const SparseStorage &other) { if (this != &other) { defaultValue = other.defaultValue; + isConstant = other.isConstant; if (auto regularMap = llvm::dyn_cast(other.internalStorage.get())) { internalStorage = std::make_unique(*regularMap); } else if (auto persistentMap = llvm::dyn_cast(other.internalStorage.get())) { @@ -286,7 +292,7 @@ class SparseStorage { internalStorage->set(idx, value); } - if (internalStorage->mapSize() > 100000000) { + if (internalStorage->mapSize() > 0 && !isConstant) { if (auto regularMap = llvm::dyn_cast(internalStorage.get())) { PersistentMap_t *newStorage = new PersistentMap_t(); diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index 48a2b4ae09..55ba079168 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -713,6 +713,9 @@ MemoryObject *Executor::addExternalObject(ExecutionState &state, void *addr, auto mo = memory->allocateFixed(reinterpret_cast(addr), size, nullptr); ObjectState *os = bindObjectInState(state, mo, type, false); + if (isReadOnly) { + os->setConstantSparseStorage(true); + } for (unsigned i = 0; i < size; i++) os->write8(i, ((uint8_t *)addr)[i]); if (isReadOnly) @@ -965,6 +968,9 @@ void Executor::initializeGlobalObjects(ExecutionState &state) { state, mo, typeSystemManager->getWrappedType(v.getType()), SourceBuilder::irreproducible("mockMutableGlobalObject"), false); } else { + if (v.isConstant()) { + os->setConstantSparseStorage(true); + } initializeGlobalObject(state, os, v.getInitializer(), 0); if (v.isConstant()) { os->setReadOnly(true); diff --git a/lib/Core/Memory.h b/lib/Core/Memory.h index 7b072ddcf1..8f80fdfed7 100644 --- a/lib/Core/Memory.h +++ b/lib/Core/Memory.h @@ -245,6 +245,10 @@ class ObjectState { const MemoryObject *getObject() const { return object.get(); } void setReadOnly(bool ro) { readOnly = ro; } + void setConstantSparseStorage(bool constant) { + knownSymbolics.isConstant = constant; + unflushedMask.isConstant = constant; + } void swapObjectHack(MemoryObject *mo) { object = mo; }