From 457911c1c57f03f94b16a9dcfc692844bc3360ae Mon Sep 17 00:00:00 2001 From: Yurii Kostyukov Date: Mon, 2 Oct 2023 17:51:25 +0300 Subject: [PATCH 001/120] [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 002/120] 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 35aad70d0f1d2879615e87551b2e628f29bb4f3d Mon Sep 17 00:00:00 2001 From: Yurii Kostyukov Date: Wed, 4 Oct 2023 13:59:21 +0300 Subject: [PATCH 003/120] [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 23039dc147f52d1b33840c7affb958f21e85b8d0 Mon Sep 17 00:00:00 2001 From: Yurii Kostyukov Date: Thu, 5 Oct 2023 14:38:54 +0300 Subject: [PATCH 004/120] [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 3c0232980b97c7a3e5d4c10b0a77ebc40b67ff40 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Thu, 5 Oct 2023 18:03:24 +0400 Subject: [PATCH 005/120] [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 a7e217da33e28381125975a2c223240043840e81 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Thu, 5 Oct 2023 18:18:07 +0400 Subject: [PATCH 006/120] [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 a967ee033f88148c7d4e156f75b1013ad79feaa8 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Thu, 5 Oct 2023 18:27:47 +0400 Subject: [PATCH 007/120] [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 95023853ef7d4d21a11bea2339f0ded51fada3d4 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Thu, 5 Oct 2023 23:31:23 +0400 Subject: [PATCH 008/120] [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 10d87a699bd0a387a61639df603a0cd81205cccb Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Fri, 6 Oct 2023 01:01:25 +0400 Subject: [PATCH 009/120] [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 924784760cc31a215c0041795a24651e2731c01a Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Fri, 6 Oct 2023 01:01:38 +0400 Subject: [PATCH 010/120] [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 6871b0485e2360f4175016dd07e13d0a2156174b Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Fri, 6 Oct 2023 18:52:19 +0400 Subject: [PATCH 011/120] [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 8bad08fcdc1cfa68eed620903265bee498c73ed4 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Sat, 7 Oct 2023 00:42:55 +0400 Subject: [PATCH 012/120] [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 bef97af64c17849641307ec371243bf9140ea4bd Mon Sep 17 00:00:00 2001 From: Yurii Kostyukov Date: Tue, 10 Oct 2023 16:28:14 +0300 Subject: [PATCH 013/120] [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 87ff7c0881b24edc9c670160eb9377dc22ae8b3a Mon Sep 17 00:00:00 2001 From: Sergey Morozov Date: Thu, 12 Oct 2023 18:10:19 +0400 Subject: [PATCH 014/120] [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 04fb6b51715fdee90ea75376d03780756f3c06ba Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Sat, 23 Sep 2023 00:18:27 +0400 Subject: [PATCH 015/120] [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 e939f09d0e39ae807d2f6c8180a8ae8d46a44722 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Mon, 16 Oct 2023 12:49:15 +0400 Subject: [PATCH 016/120] [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 aede6e41c67af168a51f2c4f8b5d1b140763c5fb Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Tue, 17 Oct 2023 00:08:54 +0400 Subject: [PATCH 017/120] [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 59fdf83597d6a3f957987688c38be6f828241c83 Mon Sep 17 00:00:00 2001 From: Yurii Kostyukov Date: Fri, 20 Oct 2023 14:09:50 +0300 Subject: [PATCH 018/120] [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 a8d246a8e084250b172b8f0c634b557bf8fe30a8 Mon Sep 17 00:00:00 2001 From: Yurii Kostyukov Date: Fri, 20 Oct 2023 14:09:26 +0300 Subject: [PATCH 019/120] [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 5aa5eb8d2ef4ff2db675f51fce3d1ef5c269e2f6 Mon Sep 17 00:00:00 2001 From: Yurii Kostyukov Date: Fri, 20 Oct 2023 13:51:23 +0300 Subject: [PATCH 020/120] [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 9e8bf6431bb5b26fc3b8d96343b5536a8c0b5fbf Mon Sep 17 00:00:00 2001 From: Aleksei Babushkin Date: Fri, 20 Oct 2023 19:27:39 +0300 Subject: [PATCH 021/120] [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 970669034d0a7cfcbbe520d3d14046ae0fc7777c Mon Sep 17 00:00:00 2001 From: Aleksei Babushkin Date: Tue, 17 Oct 2023 13:14:29 +0300 Subject: [PATCH 022/120] [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 f635c8a029ab6ba9f7021feaaccc639d3adc2f0c Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Sat, 21 Oct 2023 20:38:36 +0400 Subject: [PATCH 023/120] [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 8cc4d4bb7d77030feba4ec1eb098cda89ab4e6ac Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Sun, 22 Oct 2023 12:17:50 +0400 Subject: [PATCH 024/120] [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 95c159590a7700f65e5136c722aecb82cd263e2c Mon Sep 17 00:00:00 2001 From: dim8art Date: Sat, 21 Oct 2023 18:28:40 +0300 Subject: [PATCH 025/120] [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 05ee674215f02139c88a97791d16c27736b5f699 Mon Sep 17 00:00:00 2001 From: dim8art Date: Sat, 21 Oct 2023 18:28:40 +0300 Subject: [PATCH 026/120] 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 4c097788ab1da9a45ff2873dba2c242a6217133b Mon Sep 17 00:00:00 2001 From: dim8art Date: Sat, 21 Oct 2023 18:57:16 +0300 Subject: [PATCH 027/120] 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 aa108f2caf0e96fc9c80313fa922b5bf32c90c03 Mon Sep 17 00:00:00 2001 From: Yurii Kostyukov Date: Mon, 23 Oct 2023 14:14:33 +0300 Subject: [PATCH 028/120] [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 4882bbffc98200fdc8a6a006e83f58e6bd5f7608 Mon Sep 17 00:00:00 2001 From: Yurii Kostyukov Date: Mon, 23 Oct 2023 17:57:17 +0300 Subject: [PATCH 029/120] [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 98df581d098523f70bb52b16100644ac04bf3516 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Tue, 24 Oct 2023 18:34:36 +0400 Subject: [PATCH 030/120] [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 a3a4a057e53feee4a693b6d5b9bfdb1b01f8a81f Mon Sep 17 00:00:00 2001 From: Yurii Kostyukov Date: Tue, 24 Oct 2023 11:19:41 +0300 Subject: [PATCH 031/120] [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 943f00376db12a0148db6e30b2e174fd1e950e59 Mon Sep 17 00:00:00 2001 From: Yurii Kostyukov Date: Tue, 24 Oct 2023 13:27:04 +0300 Subject: [PATCH 032/120] [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 6e922860b70c0cd257b14af2d0f08bb938e14e39 Mon Sep 17 00:00:00 2001 From: Yurii Kostyukov Date: Tue, 24 Oct 2023 13:28:09 +0300 Subject: [PATCH 033/120] [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 7229e162686bec2e048398c93e4680a959be03b0 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Wed, 25 Oct 2023 02:03:49 +0400 Subject: [PATCH 034/120] [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 c6b5d1af45ff9c8021d135cef9df5fd87812e86e Mon Sep 17 00:00:00 2001 From: Yurii Kostyukov Date: Wed, 25 Oct 2023 11:10:49 +0300 Subject: [PATCH 035/120] [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 7befcf98d2d088ae7ee9fbd1c39cecf0342f98e7 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Wed, 25 Oct 2023 18:09:39 +0400 Subject: [PATCH 036/120] [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 67480cbcd7c091883f4d3e506b6fa6b88e214ffe Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Thu, 26 Oct 2023 20:19:14 +0400 Subject: [PATCH 037/120] [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 cc224b7907deb4527a9c83b21be6a66503620455 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Fri, 27 Oct 2023 15:58:08 +0400 Subject: [PATCH 038/120] [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 d882995af3f122feb8e6761d1444dec851a54ac4 Mon Sep 17 00:00:00 2001 From: Yurii Kostyukov Date: Fri, 27 Oct 2023 13:00:44 +0300 Subject: [PATCH 039/120] [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 4fd9d16f5b04624c6bd068d0eebe56b07f3cc429 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Mon, 30 Oct 2023 19:08:46 +0400 Subject: [PATCH 040/120] [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 dd6022a2c13fa15473654d4b40a2439e42bf8cb4 Mon Sep 17 00:00:00 2001 From: Yurii Kostyukov Date: Tue, 31 Oct 2023 12:31:24 +0300 Subject: [PATCH 041/120] [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 06cf512cd7794434c24399ff47a895e720ec4d53 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Wed, 1 Nov 2023 19:17:41 +0400 Subject: [PATCH 042/120] [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 21c35237e1ac19228b9ec7718d2f61f41597ba6c Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Thu, 2 Nov 2023 05:15:39 +0400 Subject: [PATCH 043/120] [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 5ab6cd46b7ccd5c085c7524617b0eafcadee1aab Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Thu, 2 Nov 2023 05:17:59 +0400 Subject: [PATCH 044/120] [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 90a9b84cb64de982590ab9e27d222715fc9c3959 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Thu, 2 Nov 2023 05:27:08 +0400 Subject: [PATCH 045/120] [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 f3152613c30bb42e0a5325ce943be18aa1dc621e Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Thu, 2 Nov 2023 05:53:46 +0400 Subject: [PATCH 046/120] [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 06ca8d212a20b46cb380d3e845a2c67c4ead30c2 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Thu, 2 Nov 2023 05:57:38 +0400 Subject: [PATCH 047/120] [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 fa4a2835939b0661a6c62aa28b2fb5c49d26a100 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Thu, 2 Nov 2023 05:58:52 +0400 Subject: [PATCH 048/120] [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 b06407d20861ee819a78007f5e129c87043dfd14 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Thu, 2 Nov 2023 12:49:58 +0400 Subject: [PATCH 049/120] [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 44ef6a2bff0dee3857d9c4541df3860897791a63 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Fri, 3 Nov 2023 02:11:13 +0400 Subject: [PATCH 050/120] [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 c7d3c48962bbab46db8b4a1f947adc310152d892 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Fri, 3 Nov 2023 15:37:56 +0400 Subject: [PATCH 051/120] [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 80f38b524f3370604def288909fec2b271f1a667 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Fri, 3 Nov 2023 15:38:17 +0400 Subject: [PATCH 052/120] [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 d8f1867e9496cb91a8bee1bd3da8ce3b8b9046ee Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Fri, 3 Nov 2023 16:48:59 +0400 Subject: [PATCH 053/120] [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 5ec276f6f280406a3625c09016bd579fe227896f Mon Sep 17 00:00:00 2001 From: Yurii Kostyukov Date: Fri, 3 Nov 2023 12:10:50 +0300 Subject: [PATCH 054/120] [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 91fe2c3c87d04438bae73765e97800724c6c3d72 Mon Sep 17 00:00:00 2001 From: Yurii Kostyukov Date: Fri, 3 Nov 2023 13:50:09 +0300 Subject: [PATCH 055/120] [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 69cc99b5bc7dd67226a76003787bc7688369e1c7 Mon Sep 17 00:00:00 2001 From: Yurii Kostyukov Date: Tue, 7 Nov 2023 11:08:58 +0300 Subject: [PATCH 056/120] [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 7f3cff439592aad0bb2440c9aa155885f13f41a7 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Sun, 5 Nov 2023 19:08:40 +0400 Subject: [PATCH 057/120] [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 7b5f9a6769fd344d24d25c97165e75efdbf53354 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Mon, 6 Nov 2023 19:53:51 +0400 Subject: [PATCH 058/120] [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 e485e7fc96abdcc9a62b8b1c50e3618368ca3ef2 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Sun, 5 Nov 2023 21:18:12 +0400 Subject: [PATCH 059/120] [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 186693801f890b886451d6eddff87cfde71e1882 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Wed, 8 Nov 2023 00:53:53 +0400 Subject: [PATCH 060/120] [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 435f3927a5767761d51562de299f8ac7e86f1e02 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Wed, 8 Nov 2023 02:02:48 +0400 Subject: [PATCH 061/120] [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 be6ef331fb532b4b98326d40c7d6b7fe26193657 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Wed, 8 Nov 2023 02:06:05 +0400 Subject: [PATCH 062/120] [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 bd7c4b807f0dbd38fffa76d8f58dcb5ad7665fc6 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Wed, 8 Nov 2023 14:29:31 +0400 Subject: [PATCH 063/120] [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 bca927da97066faa4c37170acf404f3b2cdd63f0 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Wed, 8 Nov 2023 18:11:06 +0400 Subject: [PATCH 064/120] [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 85481effb106914e67a4766a1de2e33e686d771e Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Fri, 10 Nov 2023 04:33:01 +0400 Subject: [PATCH 065/120] [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 c28e0e24bed2092c44feb3ae080f701417f9bd2c Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Fri, 10 Nov 2023 04:33:17 +0400 Subject: [PATCH 066/120] [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 067/120] [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 9ae75c9985b59e5732edd17e75e979e0da0c4047 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Sun, 12 Nov 2023 17:11:37 +0400 Subject: [PATCH 068/120] [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 45c7b7cd4d33a39bb064e3e04957b1a09863ca3c Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Tue, 14 Nov 2023 02:03:06 +0400 Subject: [PATCH 069/120] [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 1813fc2bcc7d4fd516f301d5a68ba46c8ee64133 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Fri, 10 Nov 2023 04:33:01 +0400 Subject: [PATCH 070/120] [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 f585c74217a3cc7743c0a99bb903f676fd74ee35 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Wed, 15 Nov 2023 00:57:59 +0400 Subject: [PATCH 071/120] [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 38a378e61cf9184fa51d9f2f5f1ce7e4903b0dc3 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Wed, 15 Nov 2023 01:00:34 +0400 Subject: [PATCH 072/120] [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 dcdd52818cf28b2310f11316a5add73a419a5b22 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Wed, 15 Nov 2023 06:08:44 +0400 Subject: [PATCH 073/120] [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 45c0bb1eff12433e0b0c7e27f9d9c06618644713 Mon Sep 17 00:00:00 2001 From: Sergey Morozov Date: Tue, 14 Nov 2023 19:17:03 +0300 Subject: [PATCH 074/120] [feat] Added Bitwuzla solver in list of available solvers. Added scripts for building bitwuzla from scripts. --- .github/workflows/build.yaml | 13 +- CMakeLists.txt | 15 +- build.sh | 8 +- cmake/find_bitwuzla.cmake | 46 + include/klee/Config/config.h.cmin | 3 + include/klee/Expr/Constraints.h | 6 +- include/klee/Solver/SolverCmdLine.h | 2 + lib/Solver/BitwuzlaBuilder.cpp | 1314 +++++++++++++++++ lib/Solver/BitwuzlaBuilder.h | 140 ++ lib/Solver/BitwuzlaHashConfig.cpp | 20 + lib/Solver/BitwuzlaHashConfig.h | 25 + lib/Solver/BitwuzlaSolver.cpp | 991 +++++++++++++ lib/Solver/BitwuzlaSolver.h | 22 + lib/Solver/CMakeLists.txt | 4 +- lib/Solver/CoreSolver.cpp | 20 +- lib/Solver/SolverCmdLine.cpp | 19 +- scripts/build/common-functions | 31 +- scripts/build/p-bitwuzla-linux-ubuntu.inc | 25 + scripts/build/p-bitwuzla-osx.inc | 14 + scripts/build/p-bitwuzla.inc | 74 + scripts/build/p-klee-linux-ubuntu.inc | 2 + scripts/build/p-klee-osx.inc | 1 + scripts/build/p-klee.inc | 14 + scripts/build/v-bitwuzla.inc | 11 + scripts/build/v-solvers.inc | 5 +- test/Feature/const_array_opt1.c | 1 + .../CrosscheckBitwuzlaAndBitwuzlaTreeInc.c | 11 + test/Solver/CrosscheckCoreZ3Bitwuzla.c | 10 + test/Solver/NoBitwuzla.c | 10 + test/Solver/sina2f.c | 67 + test/lit.cfg | 4 + test/lit.site.cfg.in | 1 + 32 files changed, 2901 insertions(+), 28 deletions(-) create mode 100644 cmake/find_bitwuzla.cmake create mode 100644 lib/Solver/BitwuzlaBuilder.cpp create mode 100644 lib/Solver/BitwuzlaBuilder.h create mode 100644 lib/Solver/BitwuzlaHashConfig.cpp create mode 100644 lib/Solver/BitwuzlaHashConfig.h create mode 100644 lib/Solver/BitwuzlaSolver.cpp create mode 100644 lib/Solver/BitwuzlaSolver.h create mode 100644 scripts/build/p-bitwuzla-linux-ubuntu.inc create mode 100644 scripts/build/p-bitwuzla-osx.inc create mode 100644 scripts/build/p-bitwuzla.inc create mode 100644 scripts/build/v-bitwuzla.inc create mode 100644 test/Solver/CrosscheckBitwuzlaAndBitwuzlaTreeInc.c create mode 100644 test/Solver/CrosscheckCoreZ3Bitwuzla.c create mode 100644 test/Solver/NoBitwuzla.c create mode 100644 test/Solver/sina2f.c diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index dc2c95350c..1813a8ef4a 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -21,7 +21,7 @@ env: LLVM_VERSION: 11 MINISAT_VERSION: "master" REQUIRES_RTTI: 0 - SOLVERS: Z3:STP + SOLVERS: BITWUZLA:Z3:STP STP_VERSION: 2.3.3 TCMALLOC_VERSION: 2.9.1 UCLIBC_VERSION: klee_uclibc_v1.3 @@ -29,6 +29,8 @@ env: USE_LIBCXX: 1 Z3_VERSION: 4.8.15 SQLITE_VERSION: 3400100 + BITWUZLA_VERSION: main + BITWUZLA_COMMIT: 80ef7cd803e1c71b5939c3eb951f1736388f7090 jobs: Linux: @@ -48,6 +50,7 @@ jobs: "Z3 only", "metaSMT", "STP master", + "Bitwuzla only", "Latest klee-uclibc", "Asserts disabled", "No TCMalloc, optimised runtime", @@ -109,6 +112,10 @@ jobs: env: SOLVERS: STP STP_VERSION: master + # Test just using Bitwuzla only + - name: "Bitwuzla only" + env: + SOLVERS: BITWUZLA # Check we can build latest klee-uclibc branch - name: "Latest klee-uclibc" env: @@ -172,6 +179,7 @@ jobs: name: [ "STP", "Z3", + "Bitwuzla", ] include: - name: "STP" @@ -180,6 +188,9 @@ jobs: - name: "Z3" env: SOLVERS: Z3:STP + - name: "Bitwuzla" + env: + SOLVERS: BITWUZLA:Z3 env: ENABLE_OPTIMIZED: 0 COVERAGE: 1 diff --git a/CMakeLists.txt b/CMakeLists.txt index cad45136e7..5ce961bad5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -204,14 +204,19 @@ include(${CMAKE_SOURCE_DIR}/cmake/find_stp.cmake) include(${CMAKE_SOURCE_DIR}/cmake/find_z3.cmake) # metaSMT include(${CMAKE_SOURCE_DIR}/cmake/find_metasmt.cmake) +# bitwuzla +include(${CMAKE_SOURCE_DIR}/cmake/find_bitwuzla.cmake) -if ((NOT ${ENABLE_Z3}) AND (NOT ${ENABLE_STP}) AND (NOT ${ENABLE_METASMT})) + +if ((NOT ${ENABLE_Z3}) AND (NOT ${ENABLE_STP}) AND (NOT ${ENABLE_METASMT}) AND (NOT ${ENABLE_BITWUZLA})) message(FATAL_ERROR "No solver was specified. At least one solver is required." "You should enable a solver by passing one of more the following options" " to cmake:\n" "\"-DENABLE_SOLVER_STP=ON\"\n" "\"-DENABLE_SOLVER_Z3=ON\"\n" - "\"-DENABLE_SOLVER_METASMT=ON\"") + "\"-DENABLE_SOLVER_BITWUZLA=ON\"\n" + "\"-DENABLE_SOLVER_METASMT=ON\" + ") endif() ############################################################################### @@ -473,10 +478,10 @@ endif() ################################################################################ option(ENABLE_FLOATING_POINT "Enable KLEE's floating point extension" OFF) if (ENABLE_FLOATING_POINT) - if (NOT ${ENABLE_Z3}) + if ((NOT ${ENABLE_Z3}) AND (NOT ${ENABLE_BITWUZLA})) message (FATAL_ERROR "Floating point extension is availible only when using Z3 backend." - "You should enable Z3 by passing the following option to cmake:\n" - "\"-DENABLE_SOLVER_Z3=ON\"\n") + "You should enable either Z3 or Bitwuzla by passing the following options to cmake, respectively:\n" + "\"-DENABLE_SOLVER_Z3=ON\" or \"-DENABLE_SOLVER_BITWUZLA=ON\"\n") else() set(ENABLE_FP 1) # For config.h message(STATUS "Floating point extension enabled") diff --git a/build.sh b/build.sh index cc41037dcb..71df1df169 100755 --- a/build.sh +++ b/build.sh @@ -35,7 +35,7 @@ REQUIRES_RTTI=0 ## Solvers Required options # SOLVERS=STP -SOLVERS=STP:Z3 +SOLVERS=BITWUZLA:Z3:STP ## Google Test Required options GTEST_VERSION=1.11.0 @@ -46,7 +46,11 @@ UCLIBC_VERSION=klee_uclibc_v1.3 ## Z3 Required options Z3_VERSION=4.8.15 + STP_VERSION=2.3.3 MINISAT_VERSION=master -BASE="$BASE" KLEE_RUNTIME_BUILD=$KLEE_RUNTIME_BUILD COVERAGE=$COVERAGE ENABLE_DOXYGEN=$ENABLE_DOXYGEN USE_TCMALLOC=$USE_TCMALLOC USE_LIBCXX=$USE_LIBCXX LLVM_VERSION=$LLVM_VERSION ENABLE_OPTIMIZED=$ENABLE_OPTIMIZED ENABLE_DEBUG=$ENABLE_DEBUG DISABLE_ASSERTIONS=$DISABLE_ASSERTIONS REQUIRES_RTTI=$REQUIRES_RTTI SOLVERS=$SOLVERS GTEST_VERSION=$GTEST_VERSION UCLIBC_VERSION=$UCLIBC_VERSION STP_VERSION=$STP_VERSION MINISAT_VERSION=$MINISAT_VERSION Z3_VERSION=$Z3_VERSION SQLITE_VERSION=$SQLITE_VERSION ./scripts/build/build.sh klee --install-system-deps +BITWUZLA_VERSION=main +BITWUZLA_COMMIT=80ef7cd803e1c71b5939c3eb951f1736388f7090 + +BASE="$BASE" KLEE_RUNTIME_BUILD=$KLEE_RUNTIME_BUILD COVERAGE=$COVERAGE ENABLE_DOXYGEN=$ENABLE_DOXYGEN USE_TCMALLOC=$USE_TCMALLOC USE_LIBCXX=$USE_LIBCXX LLVM_VERSION=$LLVM_VERSION ENABLE_OPTIMIZED=$ENABLE_OPTIMIZED ENABLE_DEBUG=$ENABLE_DEBUG DISABLE_ASSERTIONS=$DISABLE_ASSERTIONS REQUIRES_RTTI=$REQUIRES_RTTI SOLVERS=$SOLVERS GTEST_VERSION=$GTEST_VERSION UCLIBC_VERSION=$UCLIBC_VERSION STP_VERSION=$STP_VERSION MINISAT_VERSION=$MINISAT_VERSION Z3_VERSION=$Z3_VERSION BITWUZLA_VERSION=$BITWUZLA_VERSION BITWUZLA_COMMIT=$BITWUZLA_COMMIT SQLITE_VERSION=$SQLITE_VERSION ./scripts/build/build.sh klee --install-system-deps diff --git a/cmake/find_bitwuzla.cmake b/cmake/find_bitwuzla.cmake new file mode 100644 index 0000000000..82e9866dcc --- /dev/null +++ b/cmake/find_bitwuzla.cmake @@ -0,0 +1,46 @@ +#===------------------------------------------------------------------------===# +# +# The KLEE Symbolic Virtual Machine +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +#===------------------------------------------------------------------------===# + +find_package (PkgConfig REQUIRED) +pkg_check_modules(BITWUZLA IMPORTED_TARGET bitwuzla) + +# Set the default so that if the following is true: +# * Bitwuzla was found +# * ENABLE_SOLVER_BITWUZLA is not already set as a cache variable +# +# then the default is set to `ON`. Otherwise set the default to `OFF`. +# A consequence of this is if we fail to detect Bitwuzla the first time +# subsequent calls to CMake will not change the default. + +if(BITWUZLA_FOUND) + set(ENABLE_SOLVER_BITWUZLA_DEFAULT ON) +else() + set(ENABLE_SOLVER_BITWUZLA_DEFAULT OFF) +endif() + +option(ENABLE_SOLVER_BITWUZLA "Enable Bitwuzla solver support" ${ENABLE_SOLVER_BITWUZLA_DEFAULT}) + +if (ENABLE_SOLVER_BITWUZLA) + message(STATUS "Bitwuzla solver support enabled") + if (BITWUZLA_FOUND) + message(STATUS "Found Bitwuzla") + set(ENABLE_BITWUZLA 1) # For config.h + + list(APPEND KLEE_COMPONENT_EXTRA_INCLUDE_DIRS ${BITWUZLA_INCLUDE_DIRS}) + list(APPEND KLEE_SOLVER_LIBRARIES ${BITWUZLA_LINK_LIBRARIES}) + list(APPEND KLEE_SOLVER_INCLUDE_DIRS ${BITWUZLA_INCLUDE_DIRS}) + list(APPEND KLEE_SOLVER_LIBRARY_DIRS ${BITWUZLA_LINK_LIBRARIES}) + + else() + message(FATAL_ERROR "Bitwuzla not found.") + endif() +else() + message(STATUS "Bitwuzla solver support disabled") + set(ENABLE_BITWUZLA 0) # For config.h +endif() diff --git a/include/klee/Config/config.h.cmin b/include/klee/Config/config.h.cmin index 91dbaf6868..1d3f1ac6dd 100644 --- a/include/klee/Config/config.h.cmin +++ b/include/klee/Config/config.h.cmin @@ -13,6 +13,9 @@ /* Using Z3 Solver backend */ #cmakedefine ENABLE_Z3 @ENABLE_Z3@ +/* Using Bitwuzla Solver backend */ +#cmakedefine ENABLE_BITWUZLA @ENABLE_BITWUZLA@ + /* Enable KLEE floating point extension */ #cmakedefine ENABLE_FP @ENABLE_FP@ diff --git a/include/klee/Expr/Constraints.h b/include/klee/Expr/Constraints.h index 75769b3fb4..d81bd9cc7d 100644 --- a/include/klee/Expr/Constraints.h +++ b/include/klee/Expr/Constraints.h @@ -49,7 +49,11 @@ class ConstraintSet { bool isSymcretized(ref expr) const; void rewriteConcretization(const Assignment &a); - ConstraintSet withExpr(ref e) const; + ConstraintSet withExpr(ref e) const { + ConstraintSet copy = ConstraintSet(*this); + copy.addConstraint(e, Assignment()); + return copy; + } std::vector gatherArrays() const; std::vector gatherSymcretizedArrays() const; diff --git a/include/klee/Solver/SolverCmdLine.h b/include/klee/Solver/SolverCmdLine.h index 692f741734..e4e5fdcf03 100644 --- a/include/klee/Solver/SolverCmdLine.h +++ b/include/klee/Solver/SolverCmdLine.h @@ -65,6 +65,8 @@ enum QueryLoggingSolverType { extern llvm::cl::bits QueryLoggingOptions; enum CoreSolverType { + BITWUZLA_SOLVER, + BITWUZLA_TREE_SOLVER, STP_SOLVER, METASMT_SOLVER, DUMMY_SOLVER, diff --git a/lib/Solver/BitwuzlaBuilder.cpp b/lib/Solver/BitwuzlaBuilder.cpp new file mode 100644 index 0000000000..2c47a1440a --- /dev/null +++ b/lib/Solver/BitwuzlaBuilder.cpp @@ -0,0 +1,1314 @@ +//===-- BitwuzlaBuilder.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/Config/config.h" + +#ifdef ENABLE_BITWUZLA + +#include "BitwuzlaBuilder.h" +#include "BitwuzlaHashConfig.h" +#include "klee/ADT/Bits.h" + +#include "klee/Expr/Expr.h" +#include "klee/Solver/Solver.h" +#include "klee/Solver/SolverStats.h" +#include "klee/Support/ErrorHandling.h" + +#include "klee/Support/CompilerWarning.h" +DISABLE_WARNING_PUSH +DISABLE_WARNING_DEPRECATED_DECLARATIONS +#include "llvm/ADT/StringExtras.h" +#include "llvm/Support/CommandLine.h" +DISABLE_WARNING_POP + +namespace klee { + +BitwuzlaArrayExprHash::~BitwuzlaArrayExprHash() {} + +void BitwuzlaArrayExprHash::clear() { + _update_node_hash.clear(); + _array_hash.clear(); +} + +void BitwuzlaArrayExprHash::clearUpdates() { _update_node_hash.clear(); } + +BitwuzlaBuilder::BitwuzlaBuilder(bool autoClearConstructCache) + : autoClearConstructCache(autoClearConstructCache) {} + +BitwuzlaBuilder::~BitwuzlaBuilder() { + _arr_hash.clearUpdates(); + clearSideConstraints(); +} + +Sort BitwuzlaBuilder::getBoolSort() { + // FIXME: cache these + return mk_bool_sort(); +} + +Sort BitwuzlaBuilder::getBvSort(unsigned width) { + // FIXME: cache these + return mk_bv_sort(width); +} + +Sort BitwuzlaBuilder::getArraySort(Sort domainSort, Sort rangeSort) { + // FIXME: cache these + return mk_array_sort(domainSort, rangeSort); +} + +Term BitwuzlaBuilder::buildFreshBoolConst() { return mk_const(getBoolSort()); } + +Term BitwuzlaBuilder::buildArray(const char *name, unsigned indexWidth, + unsigned valueWidth) { + Sort domainSort = getBvSort(indexWidth); + Sort rangeSort = getBvSort(valueWidth); + Sort t = getArraySort(domainSort, rangeSort); + return mk_const(t, std::string(name)); +} + +Term BitwuzlaBuilder::buildConstantArray(const char *name, unsigned indexWidth, + unsigned valueWidth, unsigned value) { + Sort domainSort = getBvSort(indexWidth); + Sort rangeSort = getBvSort(valueWidth); + return mk_const_array(getArraySort(domainSort, rangeSort), + bvConst32(valueWidth, value)); +} + +Term BitwuzlaBuilder::getTrue() { return mk_true(); } + +Term BitwuzlaBuilder::getFalse() { return mk_false(); } + +Term BitwuzlaBuilder::bvOne(unsigned width) { + return mk_bv_one(getBvSort(width)); +} +Term BitwuzlaBuilder::bvZero(unsigned width) { + return mk_bv_zero(getBvSort(width)); +} +Term BitwuzlaBuilder::bvMinusOne(unsigned width) { + return bvZExtConst(width, (uint64_t)-1); +} +Term BitwuzlaBuilder::bvConst32(unsigned width, uint32_t value) { + if (width < 32) { + value &= ((1 << width) - 1); + } + return mk_bv_value_uint64(getBvSort(width), value); +} +Term BitwuzlaBuilder::bvConst64(unsigned width, uint64_t value) { + if (width < 64) { + value &= ((uint64_t(1) << width) - 1); + } + return mk_bv_value_uint64(getBvSort(width), value); +} +Term BitwuzlaBuilder::bvZExtConst(unsigned width, uint64_t value) { + if (width <= 64) { + return bvConst64(width, value); + } + std::vector terms = {bvConst64(64, value)}; + for (width -= 64; width > 64; width -= 64) { + terms.push_back(bvConst64(64, 0)); + } + terms.push_back(bvConst64(width, 0)); + return mk_term(Kind::BV_CONCAT, terms); +} + +Term BitwuzlaBuilder::bvSExtConst(unsigned width, uint64_t value) { + if (width <= 64) { + return bvConst64(width, value); + } + + Sort t = getBvSort(width - 64); + if (value >> 63) { + return mk_term(Kind::BV_CONCAT, + {bvMinusOne(width - 64), bvConst64(64, value)}); + } + return mk_term(Kind::BV_CONCAT, {bvZero(width - 64), bvConst64(64, value)}); +} + +Term BitwuzlaBuilder::bvBoolExtract(Term expr, int bit) { + return mk_term(Kind::EQUAL, {bvExtract(expr, bit, bit), bvOne(1)}); +} + +Term BitwuzlaBuilder::bvExtract(Term expr, unsigned top, unsigned bottom) { + return mk_term(Kind::BV_EXTRACT, {castToBitVector(expr)}, {top, bottom}); +} + +Term BitwuzlaBuilder::eqExpr(Term a, Term b) { + // Handle implicit bitvector/float coercision + Sort aSort = a.sort(); + Sort bSort = b.sort(); + + if (aSort.is_bool() && bSort.is_fp()) { + // Coerce `b` to be a bitvector + b = castToBitVector(b); + } + + if (aSort.is_fp() && bSort.is_bool()) { + // Coerce `a` to be a bitvector + a = castToBitVector(a); + } + return mk_term(Kind::EQUAL, {a, b}); +} + +// logical right shift +Term BitwuzlaBuilder::bvRightShift(Term expr, unsigned shift) { + Term exprAsBv = castToBitVector(expr); + unsigned width = getBVLength(exprAsBv); + + if (shift == 0) { + return expr; + } else if (shift >= width) { + return bvZero(width); // Overshift to zero + } else { + return mk_term(Kind::BV_SHR, {exprAsBv, bvConst32(width, shift)}); + } +} + +// logical left shift +Term BitwuzlaBuilder::bvLeftShift(Term expr, unsigned shift) { + Term exprAsBv = castToBitVector(expr); + unsigned width = getBVLength(exprAsBv); + + if (shift == 0) { + return expr; + } else if (shift >= width) { + return bvZero(width); // Overshift to zero + } else { + return mk_term(Kind::BV_SHL, {exprAsBv, bvConst32(width, shift)}); + } +} + +// left shift by a variable amount on an expression of the specified width +Term BitwuzlaBuilder::bvVarLeftShift(Term expr, Term shift) { + Term exprAsBv = castToBitVector(expr); + Term shiftAsBv = castToBitVector(shift); + + unsigned width = getBVLength(exprAsBv); + Term res = mk_term(Kind::BV_SHL, {exprAsBv, shiftAsBv}); + + // If overshifting, shift to zero + Term ex = bvLtExpr(shiftAsBv, bvConst32(getBVLength(shiftAsBv), width)); + res = iteExpr(ex, res, bvZero(width)); + return res; +} + +// logical right shift by a variable amount on an expression of the specified +// width +Term BitwuzlaBuilder::bvVarRightShift(Term expr, Term shift) { + Term exprAsBv = castToBitVector(expr); + Term shiftAsBv = castToBitVector(shift); + + unsigned width = getBVLength(exprAsBv); + Term res = mk_term(Kind::BV_SHR, {exprAsBv, shiftAsBv}); + + // If overshifting, shift to zero + Term ex = bvLtExpr(shiftAsBv, bvConst32(getBVLength(shiftAsBv), width)); + res = iteExpr(ex, res, bvZero(width)); + return res; +} + +// arithmetic right shift by a variable amount on an expression of the specified +// width +Term BitwuzlaBuilder::bvVarArithRightShift(Term expr, Term shift) { + Term exprAsBv = castToBitVector(expr); + Term shiftAsBv = castToBitVector(shift); + + unsigned width = getBVLength(exprAsBv); + + Term res = mk_term(Kind::BV_ASHR, {exprAsBv, shiftAsBv}); + + // If overshifting, shift to zero + Term ex = bvLtExpr(shiftAsBv, bvConst32(getBVLength(shiftAsBv), width)); + res = iteExpr(ex, res, bvZero(width)); + return res; +} + +Term BitwuzlaBuilder::notExpr(Term expr) { return mk_term(Kind::NOT, {expr}); } +Term BitwuzlaBuilder::andExpr(Term lhs, Term rhs) { + return mk_term(Kind::AND, {lhs, rhs}); +} +Term BitwuzlaBuilder::orExpr(Term lhs, Term rhs) { + return mk_term(Kind::OR, {lhs, rhs}); +} +Term BitwuzlaBuilder::iffExpr(Term lhs, Term rhs) { + return mk_term(Kind::IFF, {lhs, rhs}); +} + +Term BitwuzlaBuilder::bvNotExpr(Term expr) { + return mk_term(Kind::BV_NOT, {castToBitVector(expr)}); +} + +Term BitwuzlaBuilder::bvAndExpr(Term lhs, Term rhs) { + return mk_term(Kind::BV_AND, {castToBitVector(lhs), castToBitVector(rhs)}); +} + +Term BitwuzlaBuilder::bvOrExpr(Term lhs, Term rhs) { + return mk_term(Kind::BV_OR, {castToBitVector(lhs), castToBitVector(rhs)}); +} + +Term BitwuzlaBuilder::bvXorExpr(Term lhs, Term rhs) { + return mk_term(Kind::BV_XOR, {castToBitVector(lhs), castToBitVector(rhs)}); +} + +Term BitwuzlaBuilder::bvSignExtend(Term src, unsigned width) { + Term srcAsBv = castToBitVector(src); + unsigned src_width = srcAsBv.sort().bv_size(); + assert(src_width <= width && "attempted to extend longer data"); + + if (width <= 64) { + return mk_term(Kind::BV_SIGN_EXTEND, {srcAsBv}, {width - src_width}); + } + + Term signBit = bvBoolExtract(srcAsBv, src_width - 1); + Term zeroExtended = + mk_term(Kind::BV_CONCAT, {bvZero(width - src_width), src}); + Term oneExtended = + mk_term(Kind::BV_CONCAT, {bvMinusOne(width - src_width), src}); + + return mk_term(Kind::ITE, {signBit, oneExtended, zeroExtended}); +} + +Term BitwuzlaBuilder::writeExpr(Term array, Term index, Term value) { + return mk_term(Kind::ARRAY_STORE, {array, index, value}); +} + +Term BitwuzlaBuilder::readExpr(Term array, Term index) { + return mk_term(Kind::ARRAY_SELECT, {array, index}); +} + +unsigned BitwuzlaBuilder::getBVLength(Term expr) { + if (!expr.sort().is_bv()) { + klee_error("getBVLength() accepts only bitvector, given %s", + expr.sort().str().c_str()); + } + return expr.sort().bv_size(); +} + +Term BitwuzlaBuilder::iteExpr(Term condition, Term whenTrue, Term whenFalse) { + // Handle implicit bitvector/float coercision + Sort whenTrueSort = whenTrue.sort(); + Sort whenFalseSort = whenFalse.sort(); + + if (whenTrueSort.is_bv() && whenFalseSort.is_fp()) { + // Coerce `whenFalse` to be a bitvector + whenFalse = castToBitVector(whenFalse); + } + + if (whenTrueSort.is_fp() && whenFalseSort.is_bv()) { + // Coerce `whenTrue` to be a bitvector + whenTrue = castToBitVector(whenTrue); + } + return mk_term(Kind::ITE, {condition, whenTrue, whenFalse}); +} + +Term BitwuzlaBuilder::bvLtExpr(Term lhs, Term rhs) { + return mk_term(Kind::BV_ULT, {castToBitVector(lhs), castToBitVector(rhs)}); +} + +Term BitwuzlaBuilder::bvLeExpr(Term lhs, Term rhs) { + return mk_term(Kind::BV_ULE, {castToBitVector(lhs), castToBitVector(rhs)}); +} + +Term BitwuzlaBuilder::sbvLtExpr(Term lhs, Term rhs) { + return mk_term(Kind::BV_SLT, {castToBitVector(lhs), castToBitVector(rhs)}); +} + +Term BitwuzlaBuilder::sbvLeExpr(Term lhs, Term rhs) { + return mk_term(Kind::BV_SLE, {castToBitVector(lhs), castToBitVector(rhs)}); +} + +Term BitwuzlaBuilder::constructAShrByConstant(Term expr, unsigned shift, + Term isSigned) { + Term exprAsBv = castToBitVector(expr); + unsigned width = getBVLength(exprAsBv); + + if (shift == 0) { + return exprAsBv; + } else if (shift >= width) { + return bvZero(width); // Overshift to zero + } else { + // FIXME: Is this really the best way to interact with Bitwuzla? + Term signed_term = + mk_term(Kind::BV_CONCAT, + {bvMinusOne(shift), bvExtract(exprAsBv, width - 1, shift)}); + Term unsigned_term = bvRightShift(exprAsBv, shift); + + return mk_term(Kind::ITE, {isSigned, signed_term, unsigned_term}); + } +} + +Term BitwuzlaBuilder::getInitialArray(const Array *root) { + assert(root); + Term array_expr; + bool hashed = _arr_hash.lookupArrayExpr(root, array_expr); + + if (!hashed) { + // Unique 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->getIdentifier() + unique_id; + + 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(), value->getZExtValue(8)); + } else { + array_expr = + buildArray(unique_name.c_str(), root->getDomain(), root->getRange()); + } + + 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 + // BitwuzlaSolver.cpp + int width_out; + Term 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; + Term 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); + } + } + } + + _arr_hash.hashArrayExpr(root, array_expr); + } + + return array_expr; +} + +Term BitwuzlaBuilder::getInitialRead(const Array *root, unsigned index) { + return readExpr(getInitialArray(root), bvConst32(32, index)); +} + +Term BitwuzlaBuilder::getArrayForUpdate(const Array *root, + const UpdateNode *un) { + // Iterate over the update nodes, until we find a cached version of the node, + // or no more update nodes remain + Term un_expr; + std::vector update_nodes; + for (; un && !_arr_hash.lookupUpdateNodeExpr(un, un_expr); + un = un->next.get()) { + update_nodes.push_back(un); + } + if (!un) { + un_expr = getInitialArray(root); + } + // `un_expr` now holds an expression for the array - either from cache or by + // virtue of being the initial array expression + + // Create and cache solver expressions based on the update nodes starting from + // the oldest + for (const auto &un : + llvm::make_range(update_nodes.crbegin(), update_nodes.crend())) { + un_expr = + writeExpr(un_expr, construct(un->index, 0), construct(un->value, 0)); + + _arr_hash.hashUpdateNodeExpr(un, un_expr); + } + + return un_expr; +} + +Term BitwuzlaBuilder::construct(ref e, int *width_out) { + if (!BitwuzlaHashConfig::UseConstructHashBitwuzla || isa(e)) { + return constructActual(e, width_out); + } else { + ExprHashMap>::iterator it = constructed.find(e); + if (it != constructed.end()) { + if (width_out) + *width_out = it->second.second; + return it->second.first; + } else { + int width; + if (!width_out) + width_out = &width; + Term res = constructActual(e, width_out); + constructed.insert(std::make_pair(e, std::make_pair(res, *width_out))); + return res; + } + } +} + +void BitwuzlaBuilder::FPCastWidthAssert(int *width_out, char const *msg) { + assert(&(ConstantExpr::widthToFloatSemantics(*width_out)) != + &(llvm::APFloat::Bogus()) && + msg); +} + +/** if *width_out!=1 then result is a bitvector, +otherwise it is a bool */ +Term BitwuzlaBuilder::constructActual(ref e, int *width_out) { + + int width; + if (!width_out) + width_out = &width; + ++stats::queryConstructs; + switch (e->getKind()) { + case Expr::Constant: { + ConstantExpr *CE = cast(e); + *width_out = CE->getWidth(); + + // Coerce to bool if necessary. + if (*width_out == 1) + return CE->isTrue() ? getTrue() : getFalse(); + + Term Res; + if (*width_out <= 32) { + // Fast path. + Res = bvConst32(*width_out, CE->getZExtValue(32)); + } else if (*width_out <= 64) { + // Fast path. + Res = bvConst64(*width_out, CE->getZExtValue()); + } else { + llvm::SmallString<129> CEUValue; + CE->getAPValue().toStringUnsigned(CEUValue); + Res = mk_bv_value(mk_bv_sort(CE->getWidth()), CEUValue.str().str(), 10); + } + // Coerce to float if necesary + if (CE->isFloat()) { + Res = castToFloat(Res); + } + return Res; + } + + // Special + case Expr::NotOptimized: { + NotOptimizedExpr *noe = cast(e); + return construct(noe->src, width_out); + } + + case Expr::Read: { + ReadExpr *re = cast(e); + assert(re && re->updates.root); + *width_out = re->updates.root->getRange(); + return readExpr(getArrayForUpdate(re->updates.root, re->updates.head.get()), + construct(re->index, 0)); + } + + case Expr::Select: { + SelectExpr *se = cast(e); + Term cond = construct(se->cond, 0); + Term tExpr = construct(se->trueExpr, width_out); + Term fExpr = construct(se->falseExpr, width_out); + return iteExpr(cond, tExpr, fExpr); + } + + case Expr::Concat: { + ConcatExpr *ce = cast(e); + unsigned numKids = ce->getNumKids(); + std::vector term_args; + term_args.reserve(numKids); + + for (unsigned i = 0; i < numKids; ++i) { + term_args.push_back(construct(ce->getKid(i), 0)); + } + + *width_out = ce->getWidth(); + return mk_term(Kind::BV_CONCAT, term_args); + } + + case Expr::Extract: { + ExtractExpr *ee = cast(e); + Term src = construct(ee->expr, width_out); + *width_out = ee->getWidth(); + if (*width_out == 1) { + return bvBoolExtract(src, ee->offset); + } else { + return bvExtract(src, ee->offset + *width_out - 1, ee->offset); + } + } + + // Casting + + case Expr::ZExt: { + int srcWidth; + CastExpr *ce = cast(e); + Term src = construct(ce->src, &srcWidth); + *width_out = ce->getWidth(); + if (srcWidth == 1) { + return iteExpr(src, bvOne(*width_out), bvZero(*width_out)); + } else { + assert(*width_out > srcWidth && "Invalid width_out"); + return mk_term(Kind::BV_CONCAT, + {bvZero(*width_out - srcWidth), castToBitVector(src)}); + } + } + + case Expr::SExt: { + int srcWidth; + CastExpr *ce = cast(e); + Term src = construct(ce->src, &srcWidth); + *width_out = ce->getWidth(); + if (srcWidth == 1) { + return iteExpr(src, bvMinusOne(*width_out), bvZero(*width_out)); + } else { + return bvSignExtend(src, *width_out); + } + } + + case Expr::FPExt: { + int srcWidth; + FPExtExpr *ce = cast(e); + Term src = castToFloat(construct(ce->src, &srcWidth)); + *width_out = ce->getWidth(); + FPCastWidthAssert(width_out, "Invalid FPExt width"); + assert(*width_out >= srcWidth && "Invalid FPExt"); + // Just use any arounding mode here as we are extending + auto out_widths = getFloatSortFromBitWidth(*width_out); + return mk_term( + Kind::FP_TO_FP_FROM_FP, + {getRoundingModeSort(llvm::APFloat::rmNearestTiesToEven), src}, + {out_widths.first, out_widths.second}); + } + + case Expr::FPTrunc: { + int srcWidth; + FPTruncExpr *ce = cast(e); + Term src = castToFloat(construct(ce->src, &srcWidth)); + *width_out = ce->getWidth(); + FPCastWidthAssert(width_out, "Invalid FPTrunc width"); + assert(*width_out <= srcWidth && "Invalid FPTrunc"); + + auto out_widths = getFloatSortFromBitWidth(*width_out); + return mk_term( + Kind::FP_TO_FP_FROM_FP, + {getRoundingModeSort(llvm::APFloat::rmNearestTiesToEven), src}, + {out_widths.first, out_widths.second}); + } + + case Expr::FPToUI: { + int srcWidth; + FPToUIExpr *ce = cast(e); + Term src = castToFloat(construct(ce->src, &srcWidth)); + *width_out = ce->getWidth(); + FPCastWidthAssert(width_out, "Invalid FPToUI width"); + return mk_term(Kind::FP_TO_UBV, + {getRoundingModeSort(ce->roundingMode), src}, + {ce->getWidth()}); + } + + case Expr::FPToSI: { + int srcWidth; + FPToSIExpr *ce = cast(e); + Term src = castToFloat(construct(ce->src, &srcWidth)); + *width_out = ce->getWidth(); + FPCastWidthAssert(width_out, "Invalid FPToSI width"); + return mk_term(Kind::FP_TO_SBV, + {getRoundingModeSort(ce->roundingMode), src}, + {ce->getWidth()}); + } + + case Expr::UIToFP: { + int srcWidth; + UIToFPExpr *ce = cast(e); + Term src = castToBitVector(construct(ce->src, &srcWidth)); + *width_out = ce->getWidth(); + FPCastWidthAssert(width_out, "Invalid UIToFP width"); + + auto out_widths = getFloatSortFromBitWidth(*width_out); + return mk_term(Kind::FP_TO_FP_FROM_UBV, + {getRoundingModeSort(ce->roundingMode), src}, + {out_widths.first, out_widths.second}); + } + + case Expr::SIToFP: { + int srcWidth; + SIToFPExpr *ce = cast(e); + Term src = castToBitVector(construct(ce->src, &srcWidth)); + *width_out = ce->getWidth(); + FPCastWidthAssert(width_out, "Invalid SIToFP width"); + + auto out_widths = getFloatSortFromBitWidth(*width_out); + return mk_term(Kind::FP_TO_FP_FROM_SBV, + {getRoundingModeSort(ce->roundingMode), src}, + {out_widths.first, out_widths.second}); + } + + // Arithmetic + case Expr::Add: { + AddExpr *ae = cast(e); + Term left = castToBitVector(construct(ae->left, width_out)); + Term right = castToBitVector(construct(ae->right, width_out)); + assert(*width_out != 1 && "uncanonicalized add"); + Term result = mk_term(Kind::BV_ADD, {left, right}); + assert(getBVLength(result) == static_cast(*width_out) && + "width mismatch"); + return result; + } + + case Expr::Sub: { + SubExpr *se = cast(e); + Term left = castToBitVector(construct(se->left, width_out)); + Term right = castToBitVector(construct(se->right, width_out)); + assert(*width_out != 1 && "uncanonicalized sub"); + Term result = mk_term(Kind::BV_SUB, {left, right}); + assert(getBVLength(result) == static_cast(*width_out) && + "width mismatch"); + return result; + } + + case Expr::Mul: { + MulExpr *me = cast(e); + Term right = castToBitVector(construct(me->right, width_out)); + assert(*width_out != 1 && "uncanonicalized mul"); + Term left = castToBitVector(construct(me->left, width_out)); + Term result = mk_term(Kind::BV_MUL, {left, right}); + assert(getBVLength(result) == static_cast(*width_out) && + "width mismatch"); + return result; + } + + case Expr::UDiv: { + UDivExpr *de = cast(e); + Term left = castToBitVector(construct(de->left, width_out)); + assert(*width_out != 1 && "uncanonicalized udiv"); + + if (ConstantExpr *CE = dyn_cast(de->right)) { + if (CE->getWidth() <= 64) { + uint64_t divisor = CE->getZExtValue(); + if (bits64::isPowerOfTwo(divisor)) + return bvRightShift(left, bits64::indexOfSingleBit(divisor)); + } + } + + Term right = castToBitVector(construct(de->right, width_out)); + Term result = mk_term(Kind::BV_UDIV, {left, right}); + assert(getBVLength(result) == static_cast(*width_out) && + "width mismatch"); + return result; + } + + case Expr::SDiv: { + SDivExpr *de = cast(e); + Term left = castToBitVector(construct(de->left, width_out)); + assert(*width_out != 1 && "uncanonicalized sdiv"); + Term right = castToBitVector(construct(de->right, width_out)); + Term result = mk_term(Kind::BV_SDIV, {left, right}); + assert(getBVLength(result) == static_cast(*width_out) && + "width mismatch"); + return result; + } + + case Expr::URem: { + URemExpr *de = cast(e); + Term left = castToBitVector(construct(de->left, width_out)); + assert(*width_out != 1 && "uncanonicalized urem"); + + if (ConstantExpr *CE = dyn_cast(de->right)) { + if (CE->getWidth() <= 64) { + uint64_t divisor = CE->getZExtValue(); + + if (bits64::isPowerOfTwo(divisor)) { + int bits = bits64::indexOfSingleBit(divisor); + assert(bits >= 0 && "bit index cannot be negative"); + assert(bits64::indexOfSingleBit(divisor) < INT32_MAX); + + // special case for modding by 1 or else we bvExtract -1:0 + if (bits == 0) { + return bvZero(*width_out); + } else { + assert(*width_out > bits && "invalid width_out"); + return mk_term(Kind::BV_CONCAT, {bvZero(*width_out - bits), + bvExtract(left, bits - 1, 0)}); + } + } + } + } + + Term right = castToBitVector(construct(de->right, width_out)); + Term result = mk_term(Kind::BV_UREM, {left, right}); + assert(getBVLength(result) == static_cast(*width_out) && + "width mismatch"); + return result; + } + + case Expr::SRem: { + SRemExpr *de = cast(e); + Term left = castToBitVector(construct(de->left, width_out)); + Term right = castToBitVector(construct(de->right, width_out)); + assert(*width_out != 1 && "uncanonicalized srem"); + Term result = mk_term(Kind::BV_SREM, {left, right}); + assert(getBVLength(result) == static_cast(*width_out) && + "width mismatch"); + return result; + } + + // Bitwise + case Expr::Not: { + NotExpr *ne = cast(e); + Term expr = construct(ne->expr, width_out); + if (*width_out == 1) { + return notExpr(expr); + } else { + return bvNotExpr(expr); + } + } + + case Expr::And: { + AndExpr *ae = cast(e); + Term left = construct(ae->left, width_out); + Term right = construct(ae->right, width_out); + if (*width_out == 1) { + return andExpr(left, right); + } else { + return bvAndExpr(left, right); + } + } + + case Expr::Or: { + OrExpr *oe = cast(e); + Term left = construct(oe->left, width_out); + Term right = construct(oe->right, width_out); + if (*width_out == 1) { + return orExpr(left, right); + } else { + return bvOrExpr(left, right); + } + } + + case Expr::Xor: { + XorExpr *xe = cast(e); + Term left = construct(xe->left, width_out); + Term right = construct(xe->right, width_out); + + if (*width_out == 1) { + // XXX check for most efficient? + return iteExpr(left, Term(notExpr(right)), right); + } else { + return bvXorExpr(left, right); + } + } + + case Expr::Shl: { + ShlExpr *se = cast(e); + Term left = construct(se->left, width_out); + assert(*width_out != 1 && "uncanonicalized shl"); + + if (ConstantExpr *CE = dyn_cast(se->right)) { + return bvLeftShift(left, (unsigned)CE->getLimitedValue()); + } else { + int shiftWidth; + Term amount = construct(se->right, &shiftWidth); + return bvVarLeftShift(left, amount); + } + } + + case Expr::LShr: { + LShrExpr *lse = cast(e); + Term left = construct(lse->left, width_out); + assert(*width_out != 1 && "uncanonicalized lshr"); + + if (ConstantExpr *CE = dyn_cast(lse->right)) { + return bvRightShift(left, (unsigned)CE->getLimitedValue()); + } else { + int shiftWidth; + Term amount = construct(lse->right, &shiftWidth); + return bvVarRightShift(left, amount); + } + } + + case Expr::AShr: { + AShrExpr *ase = cast(e); + Term left = castToBitVector(construct(ase->left, width_out)); + assert(*width_out != 1 && "uncanonicalized ashr"); + + if (ConstantExpr *CE = dyn_cast(ase->right)) { + unsigned shift = (unsigned)CE->getLimitedValue(); + Term signedBool = bvBoolExtract(left, *width_out - 1); + return constructAShrByConstant(left, shift, signedBool); + } else { + int shiftWidth; + Term amount = construct(ase->right, &shiftWidth); + return bvVarArithRightShift(left, amount); + } + } + + // Comparison + + case Expr::Eq: { + EqExpr *ee = cast(e); + Term left = construct(ee->left, width_out); + Term right = construct(ee->right, width_out); + if (*width_out == 1) { + if (ConstantExpr *CE = dyn_cast(ee->left)) { + if (CE->isTrue()) + return right; + return notExpr(right); + } else { + return iffExpr(left, right); + } + } else { + *width_out = 1; + return eqExpr(left, right); + } + } + + case Expr::Ult: { + UltExpr *ue = cast(e); + Term left = construct(ue->left, width_out); + Term right = construct(ue->right, width_out); + assert(*width_out != 1 && "uncanonicalized ult"); + *width_out = 1; + return bvLtExpr(left, right); + } + + case Expr::Ule: { + UleExpr *ue = cast(e); + Term left = construct(ue->left, width_out); + Term right = construct(ue->right, width_out); + assert(*width_out != 1 && "uncanonicalized ule"); + *width_out = 1; + return bvLeExpr(left, right); + } + + case Expr::Slt: { + SltExpr *se = cast(e); + Term left = construct(se->left, width_out); + Term right = construct(se->right, width_out); + assert(*width_out != 1 && "uncanonicalized slt"); + *width_out = 1; + return sbvLtExpr(left, right); + } + + case Expr::Sle: { + SleExpr *se = cast(e); + Term left = construct(se->left, width_out); + Term right = construct(se->right, width_out); + assert(*width_out != 1 && "uncanonicalized sle"); + *width_out = 1; + return sbvLeExpr(left, right); + } + + case Expr::FOEq: { + FOEqExpr *fcmp = cast(e); + Term left = castToFloat(construct(fcmp->left, width_out)); + Term right = castToFloat(construct(fcmp->right, width_out)); + *width_out = 1; + return mk_term(Kind::FP_EQUAL, {left, right}); + } + + case Expr::FOLt: { + FOLtExpr *fcmp = cast(e); + Term left = castToFloat(construct(fcmp->left, width_out)); + Term right = castToFloat(construct(fcmp->right, width_out)); + *width_out = 1; + return mk_term(Kind::FP_LT, {left, right}); + } + + case Expr::FOLe: { + FOLeExpr *fcmp = cast(e); + Term left = castToFloat(construct(fcmp->left, width_out)); + Term right = castToFloat(construct(fcmp->right, width_out)); + *width_out = 1; + return mk_term(Kind::FP_LEQ, {left, right}); + } + + case Expr::FOGt: { + FOGtExpr *fcmp = cast(e); + Term left = castToFloat(construct(fcmp->left, width_out)); + Term right = castToFloat(construct(fcmp->right, width_out)); + *width_out = 1; + return mk_term(Kind::FP_GT, {left, right}); + } + + case Expr::FOGe: { + FOGeExpr *fcmp = cast(e); + Term left = castToFloat(construct(fcmp->left, width_out)); + Term right = castToFloat(construct(fcmp->right, width_out)); + *width_out = 1; + return mk_term(Kind::FP_GEQ, {left, right}); + } + + case Expr::IsNaN: { + IsNaNExpr *ine = cast(e); + Term arg = castToFloat(construct(ine->expr, width_out)); + *width_out = 1; + return mk_term(Kind::FP_IS_NAN, {arg}); + } + + case Expr::IsInfinite: { + IsInfiniteExpr *iie = cast(e); + Term arg = castToFloat(construct(iie->expr, width_out)); + *width_out = 1; + return mk_term(Kind::FP_IS_INF, {arg}); + } + + case Expr::IsNormal: { + IsNormalExpr *ine = cast(e); + Term arg = castToFloat(construct(ine->expr, width_out)); + *width_out = 1; + return mk_term(Kind::FP_IS_NORMAL, {arg}); + } + + case Expr::IsSubnormal: { + IsSubnormalExpr *ise = cast(e); + Term arg = castToFloat(construct(ise->expr, width_out)); + *width_out = 1; + return mk_term(Kind::FP_IS_SUBNORMAL, {arg}); + } + + case Expr::FAdd: { + FAddExpr *fadd = cast(e); + Term left = castToFloat(construct(fadd->left, width_out)); + Term right = castToFloat(construct(fadd->right, width_out)); + assert(*width_out != 1 && "uncanonicalized FAdd"); + return mk_term(Kind::FP_ADD, + {getRoundingModeSort(fadd->roundingMode), left, right}); + } + + case Expr::FSub: { + FSubExpr *fsub = cast(e); + Term left = castToFloat(construct(fsub->left, width_out)); + Term right = castToFloat(construct(fsub->right, width_out)); + assert(*width_out != 1 && "uncanonicalized FSub"); + return mk_term(Kind::FP_SUB, + {getRoundingModeSort(fsub->roundingMode), left, right}); + } + + case Expr::FMul: { + FMulExpr *fmul = cast(e); + Term left = castToFloat(construct(fmul->left, width_out)); + Term right = castToFloat(construct(fmul->right, width_out)); + assert(*width_out != 1 && "uncanonicalized FMul"); + return mk_term(Kind::FP_MUL, + {getRoundingModeSort(fmul->roundingMode), left, right}); + } + + case Expr::FDiv: { + FDivExpr *fdiv = cast(e); + Term left = castToFloat(construct(fdiv->left, width_out)); + Term right = castToFloat(construct(fdiv->right, width_out)); + assert(*width_out != 1 && "uncanonicalized FDiv"); + return mk_term(Kind::FP_DIV, + {getRoundingModeSort(fdiv->roundingMode), left, right}); + } + case Expr::FRem: { + FRemExpr *frem = cast(e); + Term left = castToFloat(construct(frem->left, width_out)); + Term right = castToFloat(construct(frem->right, width_out)); + assert(*width_out != 1 && "uncanonicalized FRem"); + return mk_term(Kind::FP_REM, {left, right}); + } + + case Expr::FMax: { + FMaxExpr *fmax = cast(e); + Term left = castToFloat(construct(fmax->left, width_out)); + Term right = castToFloat(construct(fmax->right, width_out)); + assert(*width_out != 1 && "uncanonicalized FMax"); + return mk_term(Kind::FP_MAX, {left, right}); + } + + case Expr::FMin: { + FMinExpr *fmin = cast(e); + Term left = castToFloat(construct(fmin->left, width_out)); + Term right = castToFloat(construct(fmin->right, width_out)); + assert(*width_out != 1 && "uncanonicalized FMin"); + return mk_term(Kind::FP_MIN, {left, right}); + } + + case Expr::FSqrt: { + FSqrtExpr *fsqrt = cast(e); + Term arg = castToFloat(construct(fsqrt->expr, width_out)); + assert(*width_out != 1 && "uncanonicalized FSqrt"); + return mk_term(Kind::FP_SQRT, + {getRoundingModeSort(fsqrt->roundingMode), arg}); + } + case Expr::FRint: { + FRintExpr *frint = cast(e); + Term arg = castToFloat(construct(frint->expr, width_out)); + assert(*width_out != 1 && "uncanonicalized FSqrt"); + return mk_term(Kind::FP_RTI, + {getRoundingModeSort(frint->roundingMode), arg}); + } + + case Expr::FAbs: { + FAbsExpr *fabsExpr = cast(e); + Term arg = castToFloat(construct(fabsExpr->expr, width_out)); + assert(*width_out != 1 && "uncanonicalized FAbs"); + return mk_term(Kind::FP_ABS, {arg}); + } + + case Expr::FNeg: { + FNegExpr *fnegExpr = cast(e); + Term arg = castToFloat(construct(fnegExpr->expr, width_out)); + assert(*width_out != 1 && "uncanonicalized FNeg"); + return mk_term(Kind::FP_NEG, {arg}); + } + +// unused due to canonicalization +#if 0 + case Expr::Ne: +case Expr::Ugt: +case Expr::Uge: +case Expr::Sgt: +case Expr::Sge: +#endif + + default: + assert(0 && "unhandled Expr type"); + return getTrue(); + } +} + +Term BitwuzlaBuilder::fpToIEEEBV(const Term &fp) { + if (!fp.sort().is_fp()) { + klee_error("BitwuzlaBuilder::fpToIEEEBV accepts only floats"); + } + + Term signBit = mk_const(getBvSort(1)); + Term exponentBits = mk_const(getBvSort(fp.sort().fp_exp_size())); + Term significandBits = mk_const(getBvSort(fp.sort().fp_sig_size() - 1)); + + Term floatTerm = + mk_term(Kind::FP_FP, {signBit, exponentBits, significandBits}); + sideConstraints.push_back(mk_term(Kind::EQUAL, {fp, floatTerm})); + + return mk_term(Kind::BV_CONCAT, {signBit, exponentBits, significandBits}); +} + +std::pair +BitwuzlaBuilder::getFloatSortFromBitWidth(unsigned bitWidth) { + switch (bitWidth) { + case Expr::Int16: { + return {5, 11}; + } + case Expr::Int32: { + return {8, 24}; + } + case Expr::Int64: { + return {11, 53}; + } + case Expr::Fl80: { + // Note this is an IEEE754 with a 15 bit exponent + // and 64 bit significand. This is not the same + // as x87 fp80 which has a different binary encoding. + // We can use this Bitwuzla type to get the appropriate + // amount of precision. We just have to be very + // careful which casting between floats and bitvectors. + // + // Note that the number of significand bits includes the "implicit" + // bit (which is not implicit for x87 fp80). + return {15, 64}; + } + case Expr::Int128: { + return {15, 113}; + } + default: + assert( + 0 && + "bitWidth cannot converted to a IEEE-754 binary-* number by Bitwuzla"); + std::abort(); + } +} + +Term BitwuzlaBuilder::castToFloat(const Term &e) { + Sort currentSort = e.sort(); + if (currentSort.is_fp()) { + // Already a float + return e; + } else if (currentSort.is_bv()) { + unsigned bitWidth = currentSort.bv_size(); + switch (bitWidth) { + case Expr::Int16: + case Expr::Int32: + case Expr::Int64: + case Expr::Int128: { + auto out_width = getFloatSortFromBitWidth(bitWidth); + return mk_term(Kind::FP_TO_FP_FROM_BV, {e}, + {out_width.first, out_width.second}); + } + case Expr::Fl80: { + // The bit pattern used by x87 fp80 and what we use in Bitwuzla are + // different + // + // x87 fp80 + // + // Sign Exponent Significand + // [1] [15] [1] [63] + // + // The exponent has bias 16383 and the significand has the integer portion + // as an explicit bit + // + // 79-bit IEEE-754 encoding used in Bitwuzla + // + // Sign Exponent [Significand] + // [1] [15] [63] + // + // Exponent has bias 16383 (2^(15-1) -1) and the significand has + // the integer portion as an implicit bit. + // + // We need to provide the mapping here and also emit a side constraint + // to make sure the explicit bit is appropriately constrained so when + // Bitwuzla generates a model we get the correct bit pattern back. + // + // This assumes Bitwuzla's IEEE semantics, x87 fp80 actually + // has additional semantics due to the explicit bit (See 8.2.2 + // "Unsupported Double Extended-Precision Floating-Point Encodings and + // Pseudo-Denormals" in the Intel 64 and IA-32 Architectures Software + // Developer's Manual) but this encoding means we can't model these + // unsupported values in Bitwuzla. + // + // Note this code must kept in sync with + // `BitwuzlaBuilder::castToBitVector()`. Which performs the inverse + // operation here. + // + // TODO: Experiment with creating a constraint that transforms these + // unsupported bit patterns into a Bitwuzla NaN to approximate the + // behaviour from those values. + + // Note we try very hard here to avoid calling into our functions + // here that do implicit casting so we can never recursively call + // into this function. + Term signBit = mk_term(Kind::BV_EXTRACT, {e}, {79, 79}); + Term exponentBits = mk_term(Kind::BV_EXTRACT, {e}, {78, 64}); + Term significandIntegerBit = mk_term(Kind::BV_EXTRACT, {e}, {63, 63}); + Term significandFractionBits = mk_term(Kind::BV_EXTRACT, {e}, {62, 0}); + + Term ieeeBitPatternAsFloat = mk_term( + Kind::FP_FP, {signBit, exponentBits, significandFractionBits}); + + // Generate side constraint on the significand integer bit. It is not + // used in `ieeeBitPatternAsFloat` so we need to constrain that bit to + // have the correct value so that when Bitwuzla gives a model the bit + // pattern has the right value for x87 fp80. + // + // If the number is a denormal or zero then the implicit integer bit + // is zero otherwise it is one. + Term significandIntegerBitConstrainedValue = + getx87FP80ExplicitSignificandIntegerBit(ieeeBitPatternAsFloat); + Term significandIntegerBitConstraint = + mk_term(Kind::EQUAL, {significandIntegerBit, + significandIntegerBitConstrainedValue}); + + sideConstraints.push_back(significandIntegerBitConstraint); + return ieeeBitPatternAsFloat; + } + default: + llvm_unreachable("Unhandled width when casting bitvector to float"); + } + } else { + llvm_unreachable("Sort cannot be cast to float"); + } +} + +Term BitwuzlaBuilder::castToBitVector(const Term &e) { + Sort currentSort = e.sort(); + if (currentSort.is_bool()) { + return mk_term(Kind::ITE, {e, bvOne(1), bvZero(1)}); + } else if (currentSort.is_bv()) { + // Already a bitvector + return e; + } else if (currentSort.is_fp()) { + // Note this picks a single representation for NaN which means + // `castToBitVector(castToFloat(e))` might not equal `e`. + unsigned exponentBits = currentSort.fp_exp_size(); + unsigned significandBits = + currentSort.fp_sig_size(); // Includes implicit bit + unsigned floatWidth = exponentBits + significandBits; + + switch (floatWidth) { + case Expr::Int16: + case Expr::Int32: + case Expr::Int64: + case Expr::Int128: + return fpToIEEEBV(e); + case 79: { + // This is Expr::Fl80 (64 bit exponent, 15 bit significand) but due to + // the "implicit" bit actually being implicit in x87 fp80 the sum of + // the exponent and significand bitwidth is 79 not 80. + + // Get Bitwuzla's IEEE representation + Term ieeeBits = fpToIEEEBV(e); + + // Construct the x87 fp80 bit representation + Term signBit = mk_term(Kind::BV_EXTRACT, {ieeeBits}, {78, 78}); + Term exponentBits = mk_term(Kind::BV_EXTRACT, {ieeeBits}, {77, 63}); + Term significandIntegerBit = getx87FP80ExplicitSignificandIntegerBit(e); + Term significandFractionBits = + mk_term(Kind::BV_EXTRACT, {ieeeBits}, {62, 0}); + Term x87FP80Bits = mk_term(Kind::BV_CONCAT, + {signBit, exponentBits, significandIntegerBit, + significandFractionBits}); + return x87FP80Bits; + } + default: + llvm_unreachable("Unhandled width when casting float to bitvector"); + } + } else { + llvm_unreachable("Sort cannot be cast to float"); + } +} + +Term BitwuzlaBuilder::getRoundingModeSort(llvm::APFloat::roundingMode rm) { + switch (rm) { + case llvm::APFloat::rmNearestTiesToEven: + return mk_rm_value(RoundingMode::RNE); + case llvm::APFloat::rmTowardPositive: + return mk_rm_value(RoundingMode::RTP); + case llvm::APFloat::rmTowardNegative: + return mk_rm_value(RoundingMode::RTN); + case llvm::APFloat::rmTowardZero: + return mk_rm_value(RoundingMode::RTZ); + case llvm::APFloat::rmNearestTiesToAway: + return mk_rm_value(RoundingMode::RNA); + default: + llvm_unreachable("Unhandled rounding mode"); + } +} + +Term BitwuzlaBuilder::getx87FP80ExplicitSignificandIntegerBit(const Term &e) { +#ifndef NDEBUG + // Check the passed in expression is the right type. + Sort currentSort = e.sort(); + assert(currentSort.is_fp()); + + unsigned exponentBits = currentSort.fp_exp_size(); + unsigned significandBits = currentSort.fp_sig_size(); + assert(exponentBits == 15); + assert(significandBits == 64); +#endif + // If the number is a denormal or zero then the implicit integer bit is zero + // otherwise it is one. Term isDenormal = + Term isDenormal = mk_term(Kind::FP_IS_SUBNORMAL, {e}); + Term isZero = mk_term(Kind::FP_IS_ZERO, {e}); + + // FIXME: Cache these constants somewhere + Sort oneBitBvSort = getBvSort(/*width=*/1); + + Term oneBvOne = mk_bv_value_uint64(oneBitBvSort, 1); + Term zeroBvOne = mk_bv_value_uint64(oneBitBvSort, 0); + + Term significandIntegerBitCondition = orExpr(isDenormal, isZero); + + Term significandIntegerBitConstrainedValue = + mk_term(Kind::ITE, {significandIntegerBitCondition, zeroBvOne, oneBvOne}); + + return significandIntegerBitConstrainedValue; +} +} // namespace klee + +#endif // ENABLE_BITWUZLA diff --git a/lib/Solver/BitwuzlaBuilder.h b/lib/Solver/BitwuzlaBuilder.h new file mode 100644 index 0000000000..9119832f3f --- /dev/null +++ b/lib/Solver/BitwuzlaBuilder.h @@ -0,0 +1,140 @@ +//===-- BitwuzlaBuilder.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 BITWUZLABUILDER_H_ +#define BITWUZLABUILDER_H_ + +#include "klee/Config/config.h" +#include "klee/Expr/ArrayExprHash.h" +#include "klee/Expr/ExprHashMap.h" + +#include +#include + +using namespace bitwuzla; + +namespace klee { + +class BitwuzlaArrayExprHash : public ArrayExprHash { + friend class BitwuzlaBuilder; + +public: + BitwuzlaArrayExprHash(){}; + virtual ~BitwuzlaArrayExprHash(); + void clear(); + void clearUpdates(); +}; + +class BitwuzlaBuilder { +private: + void FPCastWidthAssert(int *width_out, char const *msg); + Term fpToIEEEBV(const Term &); + +protected: + Term bvOne(unsigned width); + Term bvZero(unsigned width); + Term bvMinusOne(unsigned width); + Term bvConst32(unsigned width, uint32_t value); + Term bvConst64(unsigned width, uint64_t value); + Term bvZExtConst(unsigned width, uint64_t value); + Term bvSExtConst(unsigned width, uint64_t value); + Term bvBoolExtract(Term expr, int bit); + Term bvExtract(Term expr, unsigned top, unsigned bottom); + Term eqExpr(Term a, Term b); + + // logical left and right shift (not arithmetic) + Term bvLeftShift(Term expr, unsigned shift); + Term bvRightShift(Term expr, unsigned shift); + Term bvVarLeftShift(Term expr, Term shift); + Term bvVarRightShift(Term expr, Term shift); + Term bvVarArithRightShift(Term expr, Term shift); + + Term notExpr(Term expr); + Term andExpr(Term lhs, Term rhs); + Term orExpr(Term lhs, Term rhs); + Term iffExpr(Term lhs, Term rhs); + + Term bvNotExpr(Term expr); + Term bvAndExpr(Term lhs, Term rhs); + Term bvOrExpr(Term lhs, Term rhs); + Term bvXorExpr(Term lhs, Term rhs); + Term bvSignExtend(Term src, unsigned width); + + // Array operations + Term writeExpr(Term array, Term index, Term value); + Term readExpr(Term array, Term index); + + // ITE-expression constructor + Term iteExpr(Term condition, Term whenTrue, Term whenFalse); + + // Bitvector length + unsigned getBVLength(Term expr); + + // Bitvector comparison + Term bvLtExpr(Term lhs, Term rhs); + Term bvLeExpr(Term lhs, Term rhs); + Term sbvLtExpr(Term lhs, Term rhs); + Term sbvLeExpr(Term lhs, Term rhs); + + Term constructAShrByConstant(Term expr, unsigned shift, Term isSigned); + + Term getInitialArray(const Array *os); + Term getArrayForUpdate(const Array *root, const UpdateNode *un); + + Term constructActual(ref e, int *width_out); + Term construct(ref e, int *width_out); + Term buildArray(const char *name, unsigned indexWidth, unsigned valueWidth); + Term buildConstantArray(const char *name, unsigned indexWidth, + unsigned valueWidth, unsigned value); + + Sort getBoolSort(); + Sort getBvSort(unsigned width); + Sort getArraySort(Sort domainSort, Sort rangeSort); + + std::pair getFloatSortFromBitWidth(unsigned bitWidth); + + // Float casts + Term castToFloat(const Term &e); + Term castToBitVector(const Term &e); + + Term getRoundingModeSort(llvm::APFloat::roundingMode rm); + Term getx87FP80ExplicitSignificandIntegerBit(const Term &e); + + ExprHashMap> constructed; + BitwuzlaArrayExprHash _arr_hash; + bool autoClearConstructCache; + +public: + std::unordered_map> + constant_array_assertions; + // These are additional constraints that are generated during the + // translation to Bitwuzla's constraint language. Clients should assert + // these. + std::vector sideConstraints; + + BitwuzlaBuilder(bool autoClearConstructCache); + ~BitwuzlaBuilder(); + + Term getTrue(); + Term getFalse(); + Term buildFreshBoolConst(); + Term getInitialRead(const Array *os, unsigned index); + + Term construct(ref e) { + Term res = construct(std::move(e), nullptr); + if (autoClearConstructCache) + clearConstructCache(); + return res; + } + void clearConstructCache() { constructed.clear(); } + void clearSideConstraints() { sideConstraints.clear(); } +}; +} // namespace klee + +#endif diff --git a/lib/Solver/BitwuzlaHashConfig.cpp b/lib/Solver/BitwuzlaHashConfig.cpp new file mode 100644 index 0000000000..4ee8cfe429 --- /dev/null +++ b/lib/Solver/BitwuzlaHashConfig.cpp @@ -0,0 +1,20 @@ +//===-- BitwuzlaHashConfig.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 "BitwuzlaHashConfig.h" +#include + +namespace BitwuzlaHashConfig { +llvm::cl::opt UseConstructHashBitwuzla( + "use-construct-hash-bitwuzla", + llvm::cl::desc( + "Use hash-consing during Bitwuzla query construction (default=true)"), + llvm::cl::init(true), llvm::cl::cat(klee::ExprCat)); +} // namespace BitwuzlaHashConfig diff --git a/lib/Solver/BitwuzlaHashConfig.h b/lib/Solver/BitwuzlaHashConfig.h new file mode 100644 index 0000000000..a4a2d97bb1 --- /dev/null +++ b/lib/Solver/BitwuzlaHashConfig.h @@ -0,0 +1,25 @@ +//===-- BitwuzlaHashConfig.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_BITWUZLAHASHCONFIG_H +#define KLEE_BITWUZLAHASHCONFIG_H + +#include "klee/Support/CompilerWarning.h" +DISABLE_WARNING_PUSH +DISABLE_WARNING_DEPRECATED_DECLARATIONS +#include "llvm/Support/CommandLine.h" +DISABLE_WARNING_POP + +#include + +namespace BitwuzlaHashConfig { +extern llvm::cl::opt UseConstructHashBitwuzla; +} // namespace BitwuzlaHashConfig +#endif // KLEE_BITWUZLAHASHCONFIG_H diff --git a/lib/Solver/BitwuzlaSolver.cpp b/lib/Solver/BitwuzlaSolver.cpp new file mode 100644 index 0000000000..3b5d9acfe1 --- /dev/null +++ b/lib/Solver/BitwuzlaSolver.cpp @@ -0,0 +1,991 @@ + +//===-- BitwuzlaSolver.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/Config/config.h" + +#ifdef ENABLE_BITWUZLA + +#include "BitwuzlaBuilder.h" +#include "BitwuzlaSolver.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 + +#include "bitwuzla/cpp/bitwuzla.h" + +namespace { +// NOTE: Very useful for debugging Bitwuzla behaviour. These files can be given +// to the Bitwuzla binary to replay all Bitwuzla API calls using its `-log` +// option. + +llvm::cl::opt BitwuzlaValidateModels( + "debug-bitwuzla-validate-models", llvm::cl::init(false), + llvm::cl::desc( + "When generating Bitwuzla models validate these against the query"), + llvm::cl::cat(klee::SolvingCat)); + +llvm::cl::opt BitwuzlaVerbosityLevel( + "debug-bitwuzla-verbosity", llvm::cl::init(0), + llvm::cl::desc("Bitwuzla verbosity level (default=0)"), + llvm::cl::cat(klee::SolvingCat)); +} // namespace + +#include "klee/Support/CompilerWarning.h" +DISABLE_WARNING_PUSH +DISABLE_WARNING_DEPRECATED_DECLARATIONS +#include "llvm/Support/ErrorHandling.h" +DISABLE_WARNING_POP + +namespace { +bool interrupted = false; + +void signal_handler(int signum) { interrupted = true; } +} // namespace + +namespace klee { + +class BitwuzlaTerminator : public bitwuzla::Terminator { +private: + uint64_t time_limit_micro; + time::Point start; + + bool _isTimeout = false; + +public: + BitwuzlaTerminator(uint64_t); + bool terminate() override; + + bool isTimeout() const { return _isTimeout; } +}; + +BitwuzlaTerminator::BitwuzlaTerminator(uint64_t time_limit_micro) + : Terminator(), time_limit_micro(time_limit_micro), + start(time::getWallTime()) {} + +bool BitwuzlaTerminator::terminate() { + time::Point end = time::getWallTime(); + if ((end - start).toMicroseconds() >= time_limit_micro) { + _isTimeout = true; + return true; + } + if (interrupted) { + return true; + } + return false; +} + +using ConstraintFrames = inc_vector>; +using ExprIncMap = inc_umap>; +using BitwuzlaASTIncMap = inc_umap; +using ExprIncSet = + inc_uset, klee::util::ExprHash, klee::util::ExprCmp>; +using BitwuzlaASTIncSet = inc_uset; + +extern void dump(const ConstraintFrames &); + +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 Bitwuzla 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 BitwuzlaSolverEnv { + using arr_vec = std::vector; + inc_vector objects; + arr_vec objectsForGetModel; + ExprIncMap bitwuzla_ast_expr_to_klee_expr; + BitwuzlaASTIncSet expr_to_track; + inc_umap usedArrayBytes; + ExprIncSet symbolicObjects; + + explicit BitwuzlaSolverEnv() = default; + explicit BitwuzlaSolverEnv(const arr_vec &objects); + + void pop(size_t popSize); + void push(); + void clear(); + + const arr_vec *getObjectsForGetModel(ObjectAssignment oa) const; +}; + +BitwuzlaSolverEnv::BitwuzlaSolverEnv(const arr_vec &objects) + : objectsForGetModel(objects) {} + +void BitwuzlaSolverEnv::pop(size_t popSize) { + if (popSize == 0) + return; + objects.pop(popSize); + objectsForGetModel.clear(); + bitwuzla_ast_expr_to_klee_expr.pop(popSize); + expr_to_track.pop(popSize); + usedArrayBytes.pop(popSize); + symbolicObjects.pop(popSize); +} + +void BitwuzlaSolverEnv::push() { + objects.push(); + bitwuzla_ast_expr_to_klee_expr.push(); + expr_to_track.push(); + usedArrayBytes.push(); + symbolicObjects.push(); +} + +void BitwuzlaSolverEnv::clear() { + objects.clear(); + objectsForGetModel.clear(); + bitwuzla_ast_expr_to_klee_expr.clear(); + expr_to_track.clear(); + usedArrayBytes.clear(); + symbolicObjects.clear(); +} + +const BitwuzlaSolverEnv::arr_vec * +BitwuzlaSolverEnv::getObjectsForGetModel(ObjectAssignment oa) const { + switch (oa) { + case ObjectAssignment::NotNeeded: + return nullptr; + case ObjectAssignment::NeededForObjectsFromEnv: + return &objectsForGetModel; + case ObjectAssignment::NeededForObjectsFromQuery: + return &objects.v; + default: + llvm_unreachable("unknown object assignment"); + } +} + +class BitwuzlaSolverImpl : public SolverImpl { +protected: + std::unique_ptr builder; + Options solverParameters; + +private: + time::Span timeout; + SolverImpl::SolverRunStatus runStatusCode; + + bool internalRunSolver(const ConstraintQuery &query, BitwuzlaSolverEnv &env, + ObjectAssignment needObjects, + std::vector> *values, + ValidityCore *validityCore, bool &hasSolution); + + SolverImpl::SolverRunStatus handleSolverResponse( + Bitwuzla &theSolver, Result satisfiable, const BitwuzlaSolverEnv &env, + ObjectAssignment needObjects, + std::vector> *values, bool &hasSolution); + +protected: + BitwuzlaSolverImpl(); + + virtual Bitwuzla &initNativeBitwuzla(const ConstraintQuery &query, + BitwuzlaASTIncSet &assertions) = 0; + virtual void deinitNativeBitwuzla(Bitwuzla &theSolver) = 0; + virtual void push(Bitwuzla &s) = 0; + + bool computeTruth(const ConstraintQuery &, BitwuzlaSolverEnv &env, + bool &isValid); + bool computeValue(const ConstraintQuery &, BitwuzlaSolverEnv &env, + ref &result); + bool computeInitialValues(const ConstraintQuery &, BitwuzlaSolverEnv &env, + std::vector> &values, + bool &hasSolution); + bool check(const ConstraintQuery &query, BitwuzlaSolverEnv &env, + ref &result); + bool computeValidityCore(const ConstraintQuery &query, BitwuzlaSolverEnv &env, + ValidityCore &validityCore, bool &isValid); + +public: + char *getConstraintLog(const Query &) final; + SolverImpl::SolverRunStatus getOperationStatusCode() final; + void setCoreSolverTimeout(time::Span _timeout) final { timeout = _timeout; } + void enableUnsatCore() { + solverParameters.set(Option::PRODUCE_UNSAT_CORES, true); + } + void disableUnsatCore() { + solverParameters.set(Option::PRODUCE_UNSAT_CORES, false); + } + + // pass virtual functions to children + using SolverImpl::check; + using SolverImpl::computeInitialValues; + using SolverImpl::computeTruth; + using SolverImpl::computeValidityCore; + using SolverImpl::computeValue; +}; + +void deleteNativeBitwuzla(std::optional &theSolver) { + theSolver.reset(); +} + +BitwuzlaSolverImpl::BitwuzlaSolverImpl() + : runStatusCode(SolverImpl::SOLVER_RUN_STATUS_FAILURE) { + builder = std::unique_ptr(new BitwuzlaBuilder( + /*autoClearConstructCache=*/false)); + assert(builder && "unable to create BitwuzlaBuilder"); + + solverParameters.set(Option::PRODUCE_MODELS, true); + + setCoreSolverTimeout(timeout); + + if (ProduceUnsatCore) { + enableUnsatCore(); + } else { + disableUnsatCore(); + } + + // Set verbosity + if (BitwuzlaVerbosityLevel > 0) { + solverParameters.set(Option::VERBOSITY, BitwuzlaVerbosityLevel); + } + + if (BitwuzlaValidateModels) { + solverParameters.set(Option::DBG_CHECK_MODEL, true); + } +} + +char *BitwuzlaSolverImpl::getConstraintLog(const Query &query) { + std::stringstream outputLog; + + // We use a different builder here because we don't want to interfere + // with the solver's builder because it may change the solver builder's + // cache. + std::unique_ptr tempBuilder(new BitwuzlaBuilder(false)); + ConstantArrayFinder constant_arrays_in_query; + + std::function(const Term &)> constantsIn = + [&constantsIn](const Term &term) { + if (term.is_const()) { + return std::unordered_set{term}; + } + std::unordered_set symbols; + for (const auto &child : term.children()) { + for (const auto &childsSymbol : constantsIn(child)) { + symbols.emplace(childsSymbol); + } + } + return symbols; + }; + + std::function declareLog = + [&outputLog](const Term &term) { + outputLog << "(declare-fun " << term.str(10) << " () " + << term.sort().str() << ")\n"; + }; + std::function assertLog = [&outputLog](const Term &term) { + outputLog << "(assert " << term.str(10) << ")\n"; + }; + + std::vector assertions; + std::unordered_set assertionSymbols; + + for (auto const &constraint : query.constraints.cs()) { + Term constraintTerm = tempBuilder->construct(constraint); + assertions.push_back(std::move(constraintTerm)); + constant_arrays_in_query.visit(constraint); + } + + // KLEE Queries are validity queries i.e. + // ∀ X Constraints(X) → query(X) + // but Bitwuzla works in terms of satisfiability so instead we ask the + // the negation of the equivalent i.e. + // ∃ X Constraints(X) ∧ ¬ query(X) + assertions.push_back( + mk_term(Kind::NOT, {tempBuilder->construct(query.expr)})); + constant_arrays_in_query.visit(query.expr); + + for (auto const &constant_array : constant_arrays_in_query.results) { + for (auto const &arrayIndexValueExpr : + tempBuilder->constant_array_assertions[constant_array]) { + assertions.push_back(arrayIndexValueExpr); + } + } + + for (const Term &constraintTerm : assertions) { + std::unordered_set constantsInConstraintTerm = + constantsIn(constraintTerm); + assertionSymbols.insert(constantsInConstraintTerm.begin(), + constantsInConstraintTerm.end()); + } + + for (const Term &symbol : assertionSymbols) { + declareLog(symbol); + } + for (const Term &constraint : assertions) { + assertLog(constraint); + } + + outputLog << "(check-sat)\n"; + + // Client is responsible for freeing the returned C-string + return strdup(outputLog.str().c_str()); +} + +bool BitwuzlaSolverImpl::computeTruth(const ConstraintQuery &query, + BitwuzlaSolverEnv &env, bool &isValid) { + bool hasSolution = false; // to remove compiler warning + bool status = internalRunSolver(query, /*env=*/env, + ObjectAssignment::NotNeeded, /*values=*/NULL, + /*validityCore=*/NULL, hasSolution); + isValid = !hasSolution; + return status; +} + +bool BitwuzlaSolverImpl::computeValue(const ConstraintQuery &query, + BitwuzlaSolverEnv &env, + ref &result) { + std::vector> values; + bool hasSolution; + + // Find the object used in the expression, and compute an assignment + // for them. + 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(env.objectsForGetModel, values); + result = a.evaluate(query.getOriginalQueryExpr()); + + return true; +} + +bool BitwuzlaSolverImpl::computeInitialValues( + const ConstraintQuery &query, BitwuzlaSolverEnv &env, + std::vector> &values, bool &hasSolution) { + return internalRunSolver(query, env, + ObjectAssignment::NeededForObjectsFromEnv, &values, + /*validityCore=*/NULL, hasSolution); +} + +bool BitwuzlaSolverImpl::check(const ConstraintQuery &query, + BitwuzlaSolverEnv &env, + ref &result) { + std::vector> values; + ValidityCore validityCore; + bool hasSolution = false; + bool status = + internalRunSolver(query, env, ObjectAssignment::NeededForObjectsFromQuery, + &values, &validityCore, hasSolution); + if (status) { + result = hasSolution + ? (SolverResponse *)new InvalidResponse(env.objects.v, values) + : (SolverResponse *)new ValidResponse(validityCore); + } + return status; +} + +bool BitwuzlaSolverImpl::computeValidityCore(const ConstraintQuery &query, + BitwuzlaSolverEnv &env, + ValidityCore &validityCore, + bool &isValid) { + bool hasSolution = false; // to remove compiler warning + bool status = + internalRunSolver(query, /*env=*/env, ObjectAssignment::NotNeeded, + /*values=*/NULL, &validityCore, hasSolution); + isValid = !hasSolution; + return status; +} + +bool BitwuzlaSolverImpl::internalRunSolver( + const ConstraintQuery &query, BitwuzlaSolverEnv &env, + ObjectAssignment needObjects, + std::vector> *values, + ValidityCore *validityCore, bool &hasSolution) { + TimerStatIncrementer t(stats::queryTime); + runStatusCode = SolverImpl::SOLVER_RUN_STATUS_FAILURE; + + std::unordered_set all_constant_arrays_in_query; + BitwuzlaASTIncSet 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; + Term bitwuzlaConstraint = builder->construct(constraint); + if (ProduceUnsatCore && validityCore) { + env.bitwuzla_ast_expr_to_klee_expr.insert( + {bitwuzlaConstraint, constraint}); + env.expr_to_track.insert(bitwuzlaConstraint); + } + + exprs.insert(bitwuzlaConstraint); + + constant_arrays_in_query.visit(constraint); + + 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); + } + } + + for (auto constant_array : constant_arrays_in_query.results) { + 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()); + } + + // 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 (!env.objects.v.empty()) + ++stats::queryCounterexamples; + + // Prepare signal handler and terminator fot bitwuzla + auto timeoutInMicroSeconds = static_cast(timeout.toMicroseconds()); + if (!timeoutInMicroSeconds) + timeoutInMicroSeconds = UINT_MAX; + BitwuzlaTerminator terminator(timeoutInMicroSeconds); + + struct sigaction action, old_action; + action.sa_handler = signal_handler; + action.sa_flags = 0; + sigaction(SIGINT, &action, &old_action); + + Bitwuzla &theSolver = initNativeBitwuzla(query, exprs); + theSolver.configure_terminator(&terminator); + + for (size_t i = 0; i < exprs.framesSize(); i++) { + push(theSolver); + for (auto it = exprs.begin(i), ie = exprs.end(i); it != ie; ++it) { + theSolver.assert_formula(*it); + } + } + + Result satisfiable = theSolver.check_sat(); + theSolver.configure_terminator(nullptr); + runStatusCode = handleSolverResponse(theSolver, satisfiable, env, needObjects, + values, hasSolution); + sigaction(SIGINT, &old_action, nullptr); + + if (runStatusCode == SolverImpl::SOLVER_RUN_STATUS_FAILURE) { + if (terminator.isTimeout()) { + runStatusCode = SolverImpl::SOLVER_RUN_STATUS_TIMEOUT; + } + if (interrupted) { + runStatusCode = SolverImpl::SOLVER_RUN_STATUS_INTERRUPTED; + } + } + + if (ProduceUnsatCore && validityCore && satisfiable == Result::UNSAT) { + const std::vector bitwuzla_unsat_core = theSolver.get_unsat_core(); + const std::unordered_set bitwuzla_term_unsat_core( + bitwuzla_unsat_core.begin(), bitwuzla_unsat_core.end()); + + constraints_ty unsatCore; + for (const auto &bitwuzla_constraint : env.expr_to_track) { + if (bitwuzla_term_unsat_core.count(bitwuzla_constraint)) { + ref constraint = + env.bitwuzla_ast_expr_to_klee_expr[bitwuzla_constraint]; + unsatCore.insert(constraint); + } + } + assert(validityCore && "validityCore cannot be nullptr"); + *validityCore = ValidityCore(unsatCore, query.getOriginalQueryExpr()); + + stats::validQueriesSize += theSolver.get_assertions().size(); + stats::validityCoresSize += bitwuzla_unsat_core.size(); + ++stats::queryValidityCores; + } + + deinitNativeBitwuzla(theSolver); + + // Clear the builder's cache to prevent memory usage exploding. + // By using ``autoClearConstructCache=false`` and clearning now + // we allow Term expressions to be shared from an entire + // ``Query`` rather than only sharing within a single call to + // ``builder->construct()``. + builder->clearConstructCache(); + builder->clearSideConstraints(); + if (runStatusCode == SolverImpl::SOLVER_RUN_STATUS_SUCCESS_SOLVABLE || + runStatusCode == SolverImpl::SOLVER_RUN_STATUS_SUCCESS_UNSOLVABLE) { + if (hasSolution) { + ++stats::queriesInvalid; + } else { + ++stats::queriesValid; + } + return true; // success + } + if (runStatusCode == SolverImpl::SOLVER_RUN_STATUS_INTERRUPTED) { + raise(SIGINT); + } + return false; // failed +} + +SolverImpl::SolverRunStatus BitwuzlaSolverImpl::handleSolverResponse( + Bitwuzla &theSolver, Result satisfiable, const BitwuzlaSolverEnv &env, + ObjectAssignment needObjects, + std::vector> *values, bool &hasSolution) { + switch (satisfiable) { + case Result::SAT: { + hasSolution = true; + auto objects = env.getObjectsForGetModel(needObjects); + if (!objects) { + // No assignment is needed + assert(!values); + return SolverImpl::SOLVER_RUN_STATUS_SUCCESS_SOLVABLE; + } + assert(values && "values cannot be nullptr"); + + values->reserve(objects->size()); + for (auto array : *objects) { + SparseStorage data; + + if (env.usedArrayBytes.count(array)) { + std::unordered_set offsetValues; + for (const ref &offsetExpr : env.usedArrayBytes.at(array)) { + Term arrayElementOffsetExpr = + theSolver.get_value(builder->construct(offsetExpr)); + + uint64_t concretizedOffsetValue = + std::stoull(arrayElementOffsetExpr.value(10)); + offsetValues.insert(concretizedOffsetValue); + } + + for (unsigned offset : offsetValues) { + // We can't use Term here so have to do ref counting manually + Term initial_read = builder->getInitialRead(array, offset); + Term initial_read_expr = theSolver.get_value(initial_read); + + uint64_t arrayElementValue = + std::stoull(initial_read_expr.value(10)); + data.store(offset, arrayElementValue); + } + } + + values->emplace_back(std::move(data)); + } + + assert(values->size() == objects->size()); + + return SolverImpl::SOLVER_RUN_STATUS_SUCCESS_SOLVABLE; + } + case Result::UNSAT: + hasSolution = false; + return SolverImpl::SOLVER_RUN_STATUS_SUCCESS_UNSOLVABLE; + case Result::UNKNOWN: { + return SolverImpl::SOLVER_RUN_STATUS_FAILURE; + } + default: + llvm_unreachable("unhandled Bitwuzla result"); + } +} + +SolverImpl::SolverRunStatus BitwuzlaSolverImpl::getOperationStatusCode() { + return runStatusCode; +} + +class BitwuzlaNonIncSolverImpl final : public BitwuzlaSolverImpl { +private: + std::optional theSolver; + +public: + BitwuzlaNonIncSolverImpl() = default; + + /// implementation of BitwuzlaSolverImpl interface + Bitwuzla &initNativeBitwuzla(const ConstraintQuery &query, + BitwuzlaASTIncSet &assertions) override { + theSolver.emplace(solverParameters); + return theSolver.value(); + } + + void deinitNativeBitwuzla(Bitwuzla &) override { + deleteNativeBitwuzla(theSolver); + } + + void push(Bitwuzla &s) override {} + + /// implementation of the SolverImpl interface + bool computeTruth(const Query &query, bool &isValid) override { + BitwuzlaSolverEnv env; + return BitwuzlaSolverImpl::computeTruth(ConstraintQuery(query, false), env, + isValid); + } + bool computeValue(const Query &query, ref &result) override { + BitwuzlaSolverEnv env; + return BitwuzlaSolverImpl::computeValue(ConstraintQuery(query, false), env, + result); + } + bool computeInitialValues(const Query &query, + const std::vector &objects, + std::vector> &values, + bool &hasSolution) override { + BitwuzlaSolverEnv env(objects); + return BitwuzlaSolverImpl::computeInitialValues( + ConstraintQuery(query, false), env, values, hasSolution); + } + bool check(const Query &query, ref &result) override { + BitwuzlaSolverEnv env; + return BitwuzlaSolverImpl::check(ConstraintQuery(query, false), env, + result); + } + bool computeValidityCore(const Query &query, ValidityCore &validityCore, + bool &isValid) override { + BitwuzlaSolverEnv env; + return BitwuzlaSolverImpl::computeValidityCore( + ConstraintQuery(query, false), env, validityCore, isValid); + } + void notifyStateTermination(std::uint32_t id) override {} +}; + +BitwuzlaSolver::BitwuzlaSolver() + : Solver(std::make_unique()) {} + +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 BitwuzlaIncNativeSolver { +private: + std::optional nativeSolver; + Options solverParameters; + /// underlying solver frames + /// saved only for calculating distances from next queries + ConstraintFrames frames; + + void pop(size_t popSize); + +public: + BitwuzlaSolverEnv env; + std::uint32_t stateID = 0; + bool isRecycled = false; + + BitwuzlaIncNativeSolver(Options solverParameters) + : solverParameters(solverParameters) {} + ~BitwuzlaIncNativeSolver(); + + void clear(); + + void distance(const ConstraintQuery &query, ConstraintDistance &delta) const; + + void popPush(ConstraintDistance &delta); + + Bitwuzla &getOrInit(); + + bool isConsistent() const { + klee_warning("Empty isConsistent() check"); + return true; + } + + void dump() const { ::klee::dump(frames); } +}; + +void BitwuzlaIncNativeSolver::pop(size_t popSize) { + if (!nativeSolver.has_value() || !popSize) + return; + nativeSolver.value().pop(popSize); +} + +void BitwuzlaIncNativeSolver::popPush(ConstraintDistance &delta) { + env.pop(delta.toPopSize); + pop(delta.toPopSize); + frames.pop(delta.toPopSize); + frames.extend(delta.toPush.constraints); +} + +Bitwuzla &BitwuzlaIncNativeSolver::getOrInit() { + if (!nativeSolver.has_value()) { + nativeSolver.emplace(solverParameters); + } + return nativeSolver.value(); +} + +BitwuzlaIncNativeSolver::~BitwuzlaIncNativeSolver() { + if (nativeSolver.has_value()) { + deleteNativeBitwuzla(nativeSolver); + } +} + +void BitwuzlaIncNativeSolver::clear() { + if (!nativeSolver.has_value()) + return; + env.clear(); + frames.clear(); + nativeSolver.emplace(solverParameters); + isRecycled = false; +} + +void BitwuzlaIncNativeSolver::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 BitwuzlaTreeSolverImpl final : public BitwuzlaSolverImpl { +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: + BitwuzlaTreeSolverImpl(size_t maxSolvers) : maxSolvers(maxSolvers){}; + + /// implementation of BitwuzlaSolverImpl interface + Bitwuzla &initNativeBitwuzla(const ConstraintQuery &query, + BitwuzlaASTIncSet &assertions) override { + return currentSolver->getOrInit(); + } + void deinitNativeBitwuzla(Bitwuzla &theSolver) override { + assert(currentSolver->isConsistent()); + solvers.push_back(std::move(currentSolver)); + } + void push(Bitwuzla &s) override { s.push(1); } + + /// 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 BitwuzlaTreeSolverImpl::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 BitwuzlaTreeSolverImpl::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(solverParameters); + else + setSolver(free_it, /*recycle=*/true); + return; + } + } + assert(min_it != solvers.end()); + delta = min_delta; + setSolver(min_it); +} + +ConstraintQuery BitwuzlaTreeSolverImpl::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 BitwuzlaTreeSolverImpl::computeTruth(const Query &query, bool &isValid) { + auto q = prepare(query); + return BitwuzlaSolverImpl::computeTruth(q, currentSolver->env, isValid); +} + +bool BitwuzlaTreeSolverImpl::computeValue(const Query &query, + ref &result) { + auto q = prepare(query); + return BitwuzlaSolverImpl::computeValue(q, currentSolver->env, result); +} + +bool BitwuzlaTreeSolverImpl::computeInitialValues( + const Query &query, const std::vector &objects, + std::vector> &values, bool &hasSolution) { + auto q = prepare(query); + currentSolver->env.objectsForGetModel = objects; + return BitwuzlaSolverImpl::computeInitialValues(q, currentSolver->env, values, + hasSolution); +} + +bool BitwuzlaTreeSolverImpl::check(const Query &query, + ref &result) { + auto q = prepare(query); + return BitwuzlaSolverImpl::check(q, currentSolver->env, result); +} + +bool BitwuzlaTreeSolverImpl::computeValidityCore(const Query &query, + ValidityCore &validityCore, + bool &isValid) { + auto q = prepare(query); + return BitwuzlaSolverImpl::computeValidityCore(q, currentSolver->env, + validityCore, isValid); +} + +void BitwuzlaTreeSolverImpl::notifyStateTermination(std::uint32_t id) { + for (auto &s : solvers) + if (s->stateID == id) + s->isRecycled = true; +} + +BitwuzlaTreeSolver::BitwuzlaTreeSolver(unsigned maxSolvers) + : Solver(std::make_unique(maxSolvers)) {} + +} // namespace klee +#endif // ENABLE_BITWUZLA diff --git a/lib/Solver/BitwuzlaSolver.h b/lib/Solver/BitwuzlaSolver.h new file mode 100644 index 0000000000..613b416c5a --- /dev/null +++ b/lib/Solver/BitwuzlaSolver.h @@ -0,0 +1,22 @@ +#ifndef BITWUZLASOLVER_H_ +#define BITWUZLASOLVER_H_ + +#include "klee/Solver/Solver.h" + +namespace klee { + +/// BitwuzlaSolver - A complete solver based on Bitwuzla +class BitwuzlaSolver : public Solver { +public: + /// BitwuzlaSolver - Construct a new BitwuzlaSolver. + BitwuzlaSolver(); +}; + +class BitwuzlaTreeSolver : public Solver { +public: + BitwuzlaTreeSolver(unsigned maxSolvers); +}; + +} // namespace klee + +#endif diff --git a/lib/Solver/CMakeLists.txt b/lib/Solver/CMakeLists.txt index 9ee7805b64..b4523d1594 100644 --- a/lib/Solver/CMakeLists.txt +++ b/lib/Solver/CMakeLists.txt @@ -9,6 +9,9 @@ add_library(kleaverSolver AlphaEquivalenceSolver.cpp AssignmentValidatingSolver.cpp + BitwuzlaBuilder.cpp + BitwuzlaHashConfig.cpp + BitwuzlaSolver.cpp CachingSolver.cpp CexCachingSolver.cpp ConstantDivision.cpp @@ -49,7 +52,6 @@ target_include_directories(kleaverSolver PRIVATE ${KLEE_INCLUDE_DIRS} ${LLVM_INC target_compile_options(kleaverSolver PRIVATE ${KLEE_COMPONENT_CXX_FLAGS}) target_compile_definitions(kleaverSolver PRIVATE ${KLEE_COMPONENT_CXX_DEFINES}) - install(TARGETS kleaverSolver EXPORT run_klee DESTINATION "${RUN_KLEE_LIB_DEST}" diff --git a/lib/Solver/CoreSolver.cpp b/lib/Solver/CoreSolver.cpp index ff6f9cf76e..a82dfc6a44 100644 --- a/lib/Solver/CoreSolver.cpp +++ b/lib/Solver/CoreSolver.cpp @@ -7,6 +7,7 @@ // //===----------------------------------------------------------------------===// +#include "BitwuzlaSolver.h" #include "MetaSMTSolver.h" #include "STPSolver.h" #include "Z3Solver.h" @@ -28,7 +29,7 @@ DISABLE_WARNING_POP namespace klee { std::unique_ptr createCoreSolver(CoreSolverType cst) { - bool isTreeSolver = cst == Z3_TREE_SOLVER; + bool isTreeSolver = (cst == Z3_TREE_SOLVER || cst == BITWUZLA_TREE_SOLVER); if (!isTreeSolver && MaxSolversApproxTreeInc > 0) klee_warning("--%s option is ignored because --%s is not z3-tree", MaxSolversApproxTreeInc.ArgStr.str().c_str(), @@ -74,13 +75,28 @@ std::unique_ptr createCoreSolver(CoreSolverType cst) { if (isTreeSolver) { if (MaxSolversApproxTreeInc > 0) return std::make_unique(type, MaxSolversApproxTreeInc); - klee_warning("--%s is 0, so falling back to non tree-incremental solver", + 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"); return NULL; +#endif + case BITWUZLA_TREE_SOLVER: + case BITWUZLA_SOLVER: +#ifdef ENABLE_BITWUZLA + klee_message("Using Bitwuzla solver backend"); + if (isTreeSolver) { + if (MaxSolversApproxTreeInc > 0) + return std::make_unique(MaxSolversApproxTreeInc); + klee_warning("--%s is 0, so falling back to non tree-incremental solver", + MaxSolversApproxTreeInc.ArgStr.str().c_str()); + } + return std::make_unique(); +#else + klee_message("Not compiled with Bitwuzla support"); + return NULL; #endif case NO_SOLVER: klee_message("Invalid solver"); diff --git a/lib/Solver/SolverCmdLine.cpp b/lib/Solver/SolverCmdLine.cpp index 4974abe1f8..41f8324e7c 100644 --- a/lib/Solver/SolverCmdLine.cpp +++ b/lib/Solver/SolverCmdLine.cpp @@ -186,15 +186,23 @@ cl::opt MetaSMTBackend( #endif /* ENABLE_METASMT */ // Pick the default core solver based on configuration -#ifdef ENABLE_Z3 +#ifdef ENABLE_BITWUZLA +#define STP_IS_DEFAULT_STR "" +#define METASMT_IS_DEFAULT_STR "" +#define Z3_IS_DEFAULT_STR "" +#define BITWUZLA_IS_DEFAULT_STR " (default)" +#define DEFAULT_CORE_SOLVER BITWUZLA_SOLVER +#elif ENABLE_Z3 #define STP_IS_DEFAULT_STR "" #define METASMT_IS_DEFAULT_STR "" #define Z3_IS_DEFAULT_STR " (default)" +#define BITWUZLA_IS_DEFAULT_STR "" #define DEFAULT_CORE_SOLVER Z3_SOLVER #elif ENABLE_STP #define STP_IS_DEFAULT_STR " (default)" #define METASMT_IS_DEFAULT_STR "" #define Z3_IS_DEFAULT_STR "" +#define BITWUZLA_IS_DEFAULT_STR "" #define DEFAULT_CORE_SOLVER STP_SOLVER #elif ENABLE_METASMT #define STP_IS_DEFAULT_STR "" @@ -202,6 +210,7 @@ cl::opt MetaSMTBackend( #define Z3_IS_DEFAULT_STR "" #define DEFAULT_CORE_SOLVER METASMT_SOLVER #define Z3_IS_DEFAULT_STR "" +#define BITWUZLA_IS_DEFAULT_STR "" #else #error "Unsupported solver configuration" #endif @@ -209,6 +218,10 @@ cl::opt MetaSMTBackend( cl::opt CoreSolverToUse( "solver-backend", cl::desc("Specifiy the core solver backend to use"), cl::values( + clEnumValN(BITWUZLA_SOLVER, "bitwuzla", + "Bitwuzla" BITWUZLA_IS_DEFAULT_STR), + clEnumValN(BITWUZLA_TREE_SOLVER, "bitwuzla-tree", + "Bitwuzla tree-incremental solver"), clEnumValN(STP_SOLVER, "stp", "STP" STP_IS_DEFAULT_STR), clEnumValN(METASMT_SOLVER, "metasmt", "metaSMT" METASMT_IS_DEFAULT_STR), clEnumValN(DUMMY_SOLVER, "dummy", "Dummy solver"), @@ -224,6 +237,7 @@ cl::opt DebugCrossCheckCoreSolverWith( clEnumValN(METASMT_SOLVER, "metasmt", "metaSMT"), clEnumValN(DUMMY_SOLVER, "dummy", "Dummy solver"), clEnumValN(Z3_SOLVER, "z3", "Z3"), + clEnumValN(BITWUZLA_SOLVER, "bitwuzla", "Bitwuzla"), clEnumValN(NO_SOLVER, "none", "Do not crosscheck (default)")), cl::init(NO_SOLVER), cl::cat(SolvingCat)); @@ -235,11 +249,12 @@ llvm::cl::opt llvm::cl::opt SymbolicAllocationThreshold( "symbolic-allocation-threshold", llvm::cl::desc("Maximum possible sum of sizes for all symbolic allocation " - "before minimazation (default 1Kb)"), + "before minimization (default 1Kb)"), llvm::cl::init(1024), llvm::cl::cat(klee::SolvingCat)); } // namespace klee #undef STP_IS_DEFAULT_STR #undef METASMT_IS_DEFAULT_STR #undef Z3_IS_DEFAULT_STR +#undef BITWUZLA_IS_DEFAULT_STR #undef DEFAULT_CORE_SOLVER diff --git a/scripts/build/common-functions b/scripts/build/common-functions index c964419f60..65027f0bd3 100644 --- a/scripts/build/common-functions +++ b/scripts/build/common-functions @@ -8,11 +8,18 @@ function git_clone_or_update() { if [[ ! -e "${destination}/.git" ]]; then git clone $([ "${branch}x" != "x" ] && echo "--depth 1 -b ${branch}" || echo "") "$url" "$destination" else - cd "$destination" + pushd "$destination" git pull if [[ ! -z "$branch" ]]; then git checkout "${branch}" fi + popd + fi + + if [[ $# -ge 4 ]]; then + pushd "$destination" + git checkout $4 + popd fi } @@ -20,12 +27,12 @@ function get_git_hash() { local url="$1" local branch="$2" local commit_id="" - + # List remote git branches and get the commit id of the branch - commit_id="$(git ls-remote -h "$url" |grep "$branch" | cut -d$'\t' -f 1)" - + commit_id="$(git ls-remote -h "$url" | grep "$branch" | cut -d$'\t' -f 1)" + # If that doesn't work use the branch instead of the commit id - if [[ -z "${commit_id}" ]]; then + if [[ -z "${commit_id}" ]]; then echo "${branch}" else echo "${commit_id:0:7}" @@ -33,10 +40,10 @@ function get_git_hash() { } function with_sudo() { - echo "Checking sudo $@" - if [[ $(whoami) != "root" ]]; then - sudo "$@" - else - "$@" - fi -} \ No newline at end of file + echo "Checking sudo $@" + if [[ $(whoami) != "root" ]]; then + sudo "$@" + else + "$@" + fi +} diff --git a/scripts/build/p-bitwuzla-linux-ubuntu.inc b/scripts/build/p-bitwuzla-linux-ubuntu.inc new file mode 100644 index 0000000000..cd585c7e31 --- /dev/null +++ b/scripts/build/p-bitwuzla-linux-ubuntu.inc @@ -0,0 +1,25 @@ +# Build dependencies Bitwuzla +install_build_dependencies_bitwuzla() { + source "${DIR}/common-functions" + with_sudo apt update -y + + dependencies=( + build-essential + + ninja-build + python3 + python3-pip + cmake + git + ) + + #Install essential dependencies + with_sudo apt -y --no-install-recommends install "${dependencies[@]}" + + with_sudo apt-get update -y + with_sudo apt-get -y --no-install-recommends install pkg-config cmake-data m4 + + with_sudo pip3 install --user meson + base_path="$(python3 -m site --user-base)" + export PATH="$PATH:${base_path}/bin" +} diff --git a/scripts/build/p-bitwuzla-osx.inc b/scripts/build/p-bitwuzla-osx.inc new file mode 100644 index 0000000000..af4cc8f651 --- /dev/null +++ b/scripts/build/p-bitwuzla-osx.inc @@ -0,0 +1,14 @@ +install_build_dependencies_bitwuzla() { + dependencies=( + ninja + python3 + python3-pip + cmake + git + pkg-config + ) + brew install "${dependencies[@]}" + with_sudo pip3 install --user meson + base_path="$(python3 -m site --user-base)" + export PATH="$PATH:${base_path}/bin" +} diff --git a/scripts/build/p-bitwuzla.inc b/scripts/build/p-bitwuzla.inc new file mode 100644 index 0000000000..87a28ea827 --- /dev/null +++ b/scripts/build/p-bitwuzla.inc @@ -0,0 +1,74 @@ +# Build scripts for Bitwuzla +# Variables that any artifact of this package might depend on +setup_build_variables_bitwuzla() { + BITWUZLA_SUFFIX="${SANITIZER_SUFFIX}" + + BITWUZLA_BUILD_PATH="${BASE}/bitwuzla-${BITWUZLA_VERSION}-build${BITWUZLA_SUFFIX}" + BITWUZLA_INSTALL_PATH="${BASE}/bitwuzla-${BITWUZLA_VERSION}-install${BITWUZLA_SUFFIX}" + bitwuzla_url="https://github.com/bitwuzla/bitwuzla.git" + + return 0 +} + +download_bitwuzla() { + source "${DIR}/common-functions" + # Download Bitwuzla + git_clone_or_update "${bitwuzla_url}" "${BASE}/bitwuzla-${BITWUZLA_VERSION}" "${BITWUZLA_VERSION}" "${BITWUZLA_COMMIT}" +} + +build_bitwuzla() { + pushd "${BASE}/bitwuzla-${BITWUZLA_VERSION}" + + args=(--build-dir "${BITWUZLA_BUILD_PATH}" --prefix "${BITWUZLA_INSTALL_PATH}" --static --no-unit-testing) + + if [[ -n "${SANITIZER_SUFFIX:-}" ]]; then + if [[ "${SANITIZER_BUILD:-}" == "address" ]]; then + args+=("--asan") + fi + if [[ "${SANITIZER_BUILD:-}" == "undefined" ]]; then + args+=("--ubsan") + fi + args+=("--assertions" "debug") + else + args+=("--no-assertions" "release") + fi + + ./configure.py "${args[@]}" + popd + cd "${BITWUZLA_BUILD_PATH}" || return 1 + yes n | ninja install + touch "${BITWUZLA_INSTALL_PATH}/.bitwuzla_installed" +} + +install_bitwuzla() { + return 0 +} + +# Check if the binary artifact is installed +is_installed_bitwuzla() { + ( + setup_build_variables_bitwuzla + [[ -f "${BITWUZLA_INSTALL_PATH}/.bitwuzla_installed" ]] + ) || return 1 +} + +setup_artifact_variables_bitwuzla() { + setup_build_variables_bitwuzla +} + +get_build_artifacts_bitwuzla() { + ( + setup_build_variables_bitwuzla + echo "${BITWUZLA_INSTALL_PATH}" + ) +} + +get_docker_config_id_bitwuzla() { + ( + source "${DIR}/common-functions" + setup_build_variables_bitwuzla + + biwuzla_remote_commit="$(get_git_hash "${bitwuzla_url}" "${BITWUZLA_VERSION}")" + echo "${biwuzla_remote_commit}" + ) +} diff --git a/scripts/build/p-klee-linux-ubuntu.inc b/scripts/build/p-klee-linux-ubuntu.inc index 8bf39a199b..a67a061615 100644 --- a/scripts/build/p-klee-linux-ubuntu.inc +++ b/scripts/build/p-klee-linux-ubuntu.inc @@ -10,6 +10,8 @@ install_build_dependencies_klee() { python3-setuptools python3-pip python3-wheel + pkg-config + cmake-data ) if [[ "${SOLVERS:-}" == "metaSMT" ]]; then diff --git a/scripts/build/p-klee-osx.inc b/scripts/build/p-klee-osx.inc index 0561e28f68..4f5b063599 100644 --- a/scripts/build/p-klee-osx.inc +++ b/scripts/build/p-klee-osx.inc @@ -9,6 +9,7 @@ install_build_dependencies_klee() { pip3 install --user --upgrade lit tabulate + brew install pkg-config # Get path of package location base_path=$(python3 -m site --user-base) export PATH="${base_path}/bin:$PATH" diff --git a/scripts/build/p-klee.inc b/scripts/build/p-klee.inc index 248d3a9bb7..b484cc9281 100644 --- a/scripts/build/p-klee.inc +++ b/scripts/build/p-klee.inc @@ -67,6 +67,7 @@ fi local KLEE_Z3_CONFIGURE_OPTION=("-DENABLE_SOLVER_Z3=OFF") local KLEE_STP_CONFIGURE_OPTION=("-DENABLE_SOLVER_STP=OFF") local KLEE_METASMT_CONFIGURE_OPTION=("-DENABLE_SOLVER_METASMT=OFF") + local KLEE_BITWUZLA_CONFIGURE_OPTION=("-DENABLE_SOLVER_BITWUZLA=OFF") KLEE_FLOATING_POINT=( "-DENABLE_FLOATING_POINT=FALSE" "-DENABLE_FP_RUNTIME=FALSE" @@ -106,6 +107,18 @@ fi "-DMETASMT_DEFAULT_BACKEND=${METASMT_DEFAULT}" ) ;; + bitwuzla) + KLEE_BITWUZLA_CONFIGURE_OPTION=( + "-DENABLE_SOLVER_BITWUZLA=TRUE" + ) + + CMAKE_PREFIX_PATH+=("${BITWUZLA_INSTALL_PATH}") + KLEE_FLOATING_POINT=( + "-DENABLE_FLOATING_POINT=TRUE" + "-DENABLE_FP_RUNTIME=TRUE" + ) + echo "bitwuzla" + ;; *) echo "Unknown solver ${solver}" exit 1 @@ -116,6 +129,7 @@ fi "${KLEE_Z3_CONFIGURE_OPTION[@]}" "${KLEE_STP_CONFIGURE_OPTION[@]}" "${KLEE_METASMT_CONFIGURE_OPTION[@]}" + "${KLEE_BITWUZLA_CONFIGURE_OPTION[@]}" "${KLEE_FLOATING_POINT[@]}" ) diff --git a/scripts/build/v-bitwuzla.inc b/scripts/build/v-bitwuzla.inc new file mode 100644 index 0000000000..bccd375853 --- /dev/null +++ b/scripts/build/v-bitwuzla.inc @@ -0,0 +1,11 @@ +# Build information for Bitwuzla solver +required_variables_bitwuzla=( + "BITWUZLA_VERSION" + "BITWUZLA_COMMIT" +) + +artifact_dependency_bitwuzla=("sanitizer") + +install_build_dependencies_bitwuzla() { + return 0 +} diff --git a/scripts/build/v-solvers.inc b/scripts/build/v-solvers.inc index 9d6bfdc857..74cdac1f5a 100644 --- a/scripts/build/v-solvers.inc +++ b/scripts/build/v-solvers.inc @@ -15,7 +15,8 @@ required_variables_check_solvers() { [[ "${solver}" == "z3" ]] && continue [[ "${solver}" == "stp" ]] && continue [[ "${solver}" == "metasmt" ]] && continue - + [[ "${solver}" == "bitwuzla" ]] && continue + echo "Unknown solver: \"$solver\"" exit 1 done @@ -51,7 +52,7 @@ setup_variables_solvers() { [[ "${solver}" == "z3" ]] && SELECTED_SOLVERS+=("z3") && continue [[ "${solver}" == "stp" ]] && SELECTED_SOLVERS+=("stp") && continue [[ "${solver}" == "metasmt" ]] && SELECTED_SOLVERS+=("metasmt") && continue - + [[ "${solver}" == "bitwuzla" ]] && SELECTED_SOLVERS+=("bitwuzla") && continue echo "Unknown solver: \"$solver\"" exit 1 done diff --git a/test/Feature/const_array_opt1.c b/test/Feature/const_array_opt1.c index 7482d48232..a70223e36d 100644 --- a/test/Feature/const_array_opt1.c +++ b/test/Feature/const_array_opt1.c @@ -1,5 +1,6 @@ // REQUIRES: not-msan // REQUIRES: not-ubsan +// REQUIRES: not-bitwuzla // Disabling msan and ubsan because it times out on CI // RUN: %clang %s -emit-llvm %O0opt -c -o %t.bc // RUN: rm -rf %t.klee-out diff --git a/test/Solver/CrosscheckBitwuzlaAndBitwuzlaTreeInc.c b/test/Solver/CrosscheckBitwuzlaAndBitwuzlaTreeInc.c new file mode 100644 index 0000000000..f0e1dfc757 --- /dev/null +++ b/test/Solver/CrosscheckBitwuzlaAndBitwuzlaTreeInc.c @@ -0,0 +1,11 @@ +// REQUIRES: bitwuzla +// 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=bitwuzla-tree --max-solvers-approx-tree-inc=4 --debug-crosscheck-core-solver=bitwuzla --debug-bitwuzla-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=bitwuzla-tree --max-solvers-approx-tree-inc=64 --debug-crosscheck-core-solver=bitwuzla --debug-bitwuzla-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 = 18 +// CHECK: KLEE: done: partially completed paths = 0 diff --git a/test/Solver/CrosscheckCoreZ3Bitwuzla.c b/test/Solver/CrosscheckCoreZ3Bitwuzla.c new file mode 100644 index 0000000000..f50a0dd2fc --- /dev/null +++ b/test/Solver/CrosscheckCoreZ3Bitwuzla.c @@ -0,0 +1,10 @@ +// REQUIRES: z3 +// REQUIRES: bitwuzla +// 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=z3 --use-forked-solver=false --debug-crosscheck-core-solver=bitwuzla --use-guided-search=none %t1.bc 2>&1 | FileCheck %s + +#include "ExerciseSolver.c.inc" + +// CHECK: KLEE: done: completed paths = 18 +// CHECK: KLEE: done: partially completed paths = 0 diff --git a/test/Solver/NoBitwuzla.c b/test/Solver/NoBitwuzla.c new file mode 100644 index 0000000000..a4a915a9d6 --- /dev/null +++ b/test/Solver/NoBitwuzla.c @@ -0,0 +1,10 @@ +// REQUIRES: not-bitwuzla +// RUN: %clang %s -emit-llvm %O0opt -c -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: not %klee --output-dir=%t.klee-out --solver-backend=bitwuzla %t1.bc 2>&1 | FileCheck %s +// CHECK: Not compiled with Bitwuzla support +// CHECK: ERROR: Failed to create core solver + +int main(int argc, char **argv) { + return 0; +} diff --git a/test/Solver/sina2f.c b/test/Solver/sina2f.c new file mode 100644 index 0000000000..fb7179d785 --- /dev/null +++ b/test/Solver/sina2f.c @@ -0,0 +1,67 @@ +// REQUIRES: bitwuzla +// REQUIRES: not-asan +// REQUIRES: not-msan +// RUN: %clang %s -emit-llvm %O0opt -g -c -o %t1.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --strip-unwanted-calls --delete-dead-loops=false --emit-all-errors --mock-all-externals --use-forked-solver=false --solver-backend=bitwuzla-tree --max-solvers-approx-tree-inc=16 --max-memory=6008 --optimize --skip-not-lazy-initialized --output-source=false --output-stats=false --output-istats=false --use-sym-size-alloc=true --cex-cache-validity-cores --fp-runtime --x86FP-as-x87FP80 --symbolic-allocation-threshold=8192 --allocate-determ --allocate-determ-size=3072 --allocate-determ-start-address=0x00030000000 --mem-trigger-cof --use-alpha-equivalence=true --track-coverage=all --use-iterative-deepening-search=max-cycles --max-solver-time=5s --max-cycles-before-stuck=15 --only-output-states-covering-new --dump-states-on-halt=true --search=dfs --search=random-state --cover-on-the-fly=true --delay-cover-on-the-fly=27 --max-time=29 %t1.bc 2>&1 | FileCheck %s +#include "klee-test-comp.c" + +/* + * Benchmarks contributed by Divyesh Unadkat[1,2], Supratik Chakraborty[1], Ashutosh Gupta[1] + * [1] Indian Institute of Technology Bombay, Mumbai + * [2] TCS Innovation labs, Pune + * + */ + +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", "sina2f.c", 10, "reach_error"); } +extern void abort(void); +void assume_abort_if_not(int cond) { + if (!cond) { + abort(); + } +} +void __VERIFIER_assert(int cond) { + if (!(cond)) { + ERROR : { + reach_error(); + abort(); + } + } +} +extern int __VERIFIER_nondet_int(void); +void *malloc(unsigned int size); + +int N; + +int main() { + N = __VERIFIER_nondet_int(); + if (N <= 0) + return 1; + assume_abort_if_not(N <= 2147483647 / sizeof(int)); + + int i; + long long sum[1]; + long long *a = malloc(sizeof(long long) * N); + + sum[0] = 1; + for (i = 0; i < N; i++) { + a[i] = 1; + } + + for (i = 0; i < N; i++) { + sum[0] = sum[0] + a[i]; + } + + for (i = 0; i < N; i++) { + a[i] = a[i] + sum[0]; + } + + for (i = 0; i < N; i++) { + __VERIFIER_assert(a[i] == N); + } + return 1; +} + +// CHECK: KLEE: done diff --git a/test/lit.cfg b/test/lit.cfg index 11308ae424..d2af70f065 100644 --- a/test/lit.cfg +++ b/test/lit.cfg @@ -210,6 +210,10 @@ if config.enable_metasmt: config.available_features.add('metasmt') else: config.available_features.add('not-metasmt') +if config.enable_bitwuzla: + config.available_features.add('bitwuzla') +else: + config.available_features.add('not-bitwuzla') # 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 0712644706..fb4ed1c586 100644 --- a/test/lit.site.cfg.in +++ b/test/lit.site.cfg.in @@ -52,6 +52,7 @@ 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_bitwuzla = True if @ENABLE_BITWUZLA@ == 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 From d9e7223303189537a3a15219fcec0a35fbeb5056 Mon Sep 17 00:00:00 2001 From: dim8art Date: Tue, 21 Nov 2023 14:10:38 +0300 Subject: [PATCH 075/120] typo --- include/klee/Expr/AlphaBuilder.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/klee/Expr/AlphaBuilder.h b/include/klee/Expr/AlphaBuilder.h index 9095c489e2..7012411908 100644 --- a/include/klee/Expr/AlphaBuilder.h +++ b/include/klee/Expr/AlphaBuilder.h @@ -40,4 +40,4 @@ class AlphaBuilder final : public ExprVisitor { } // namespace klee -#endif /*KLEE_ALPHA_VERSION_BUILDER_H*/ +#endif /*KLEE_ALPHA_BUILDER_H*/ From 2bcba82193fee7e18608fbc98882c67b495fe8f2 Mon Sep 17 00:00:00 2001 From: dim8art Date: Tue, 21 Nov 2023 20:46:25 +0300 Subject: [PATCH 076/120] Add lazy calculation of constraint dsu --- include/klee/Expr/Constraints.h | 5 +- .../klee/Expr/IndependentConstraintSetUnion.h | 19 +++--- lib/Core/ExecutionState.cpp | 1 + lib/Expr/Constraints.cpp | 53 +++++++++------ lib/Expr/IndependentConstraintSetUnion.cpp | 67 +++++++++++++++---- 5 files changed, 102 insertions(+), 43 deletions(-) diff --git a/include/klee/Expr/Constraints.h b/include/klee/Expr/Constraints.h index d81bd9cc7d..f4c0e22db8 100644 --- a/include/klee/Expr/Constraints.h +++ b/include/klee/Expr/Constraints.h @@ -43,6 +43,7 @@ class ConstraintSet { const std::vector> &ics); explicit ConstraintSet(constraints_ty cs); explicit ConstraintSet(); + void fork(); void addConstraint(ref e, const Assignment &delta); void addSymcrete(ref s, const Assignment &concretization); @@ -90,7 +91,7 @@ class ConstraintSet { constraints_ty _constraints; symcretes_ty _symcretes; Assignment _concretization; - IndependentConstraintSetUnion _independentElements; + std::shared_ptr _independentElements; }; class PathConstraints { @@ -100,6 +101,8 @@ class PathConstraints { void advancePath(KInstruction *ki); void advancePath(const Path &path); + void fork(); + ExprHashSet addConstraint(ref e, const Assignment &delta, Path::PathIndex currIndex); ExprHashSet addConstraint(ref e, const Assignment &delta); diff --git a/include/klee/Expr/IndependentConstraintSetUnion.h b/include/klee/Expr/IndependentConstraintSetUnion.h index 3d6eb0f14c..783dadc256 100644 --- a/include/klee/Expr/IndependentConstraintSetUnion.h +++ b/include/klee/Expr/IndependentConstraintSetUnion.h @@ -12,18 +12,22 @@ class IndependentConstraintSetUnion ExprEitherSymcreteHash, ExprEitherSymcreteCmp> { public: Assignment concretization; + std::vector> constraintQueue; + Assignment updateQueue; + Assignment removeQueue; public: ExprHashMap> concretizedExprs; public: - void updateConcretization(const Assignment &c); + void updateConcretization(const Assignment &delta); void removeConcretization(const Assignment &remove); + void calculateUpdateConcretizationQueue(); + void calculateRemoveConcretizationQueue(); void reEvaluateConcretization(const Assignment &newConcretization); - IndependentConstraintSetUnion getConcretizedVersion() const; - IndependentConstraintSetUnion - getConcretizedVersion(const Assignment &c) const; + IndependentConstraintSetUnion getConcretizedVersion(); + IndependentConstraintSetUnion getConcretizedVersion(const Assignment &c); IndependentConstraintSetUnion(); IndependentConstraintSetUnion(const constraints_ty &is, @@ -35,14 +39,13 @@ class IndependentConstraintSetUnion addIndependentConstraintSetUnion(const IndependentConstraintSetUnion &icsu); void getAllDependentConstraintSets( - ref e, - std::vector> &result) const; + ref e, std::vector> &result); void getAllIndependentConstraintSets( - ref e, - std::vector> &result) const; + ref e, std::vector> &result); void addExpr(ref e); void addSymcrete(ref s); + void calculateQueue(); }; } // namespace klee diff --git a/lib/Core/ExecutionState.cpp b/lib/Core/ExecutionState.cpp index 31d60372dd..8227e81436 100644 --- a/lib/Core/ExecutionState.cpp +++ b/lib/Core/ExecutionState.cpp @@ -178,6 +178,7 @@ ExecutionState::ExecutionState(const ExecutionState &state) gepExprBases(state.gepExprBases), prevTargets_(state.prevTargets_), targets_(state.targets_), prevHistory_(state.prevHistory_), history_(state.history_), isTargeted_(state.isTargeted_) { + constraints.fork(); queryMetaData.id = state.id; } diff --git a/lib/Expr/Constraints.cpp b/lib/Expr/Constraints.cpp index 17ae8e50bc..aa963d6cbc 100644 --- a/lib/Expr/Constraints.cpp +++ b/lib/Expr/Constraints.cpp @@ -183,14 +183,18 @@ class ExprReplaceVisitor3 : public ExprVisitor { ConstraintSet::ConstraintSet(constraints_ty cs, symcretes_ty symcretes, Assignment concretization) : _constraints(cs), _symcretes(symcretes), _concretization(concretization), - _independentElements(_constraints, _symcretes, _concretization) {} + _independentElements(new IndependentConstraintSetUnion( + _constraints, _symcretes, _concretization)) {} ConstraintSet::ConstraintSet(ref ics) : _constraints(ics->getConstraints()), _symcretes(ics->getSymcretes()), - _concretization(ics->concretization), _independentElements(ics) {} + _concretization(ics->concretization), + _independentElements(new IndependentConstraintSetUnion(ics)) {} ConstraintSet::ConstraintSet( - const std::vector> &factors) { + const std::vector> &factors) + : _independentElements(new IndependentConstraintSetUnion( + _constraints, _symcretes, _concretization)) { for (auto ics : factors) { constraints_ty constraints = ics->getConstraints(); SymcreteOrderedSet symcretes = ics->getSymcretes(); @@ -198,13 +202,19 @@ ConstraintSet::ConstraintSet( _constraints.insert(constraints.begin(), constraints.end()); _symcretes.insert(symcretes.begin(), symcretes.end()); _concretization.addIndependentAssignment(ics->concretization); - _independentElements.addIndependentConstraintSetUnion(icsu); + _independentElements->addIndependentConstraintSetUnion(icsu); } } ConstraintSet::ConstraintSet(constraints_ty cs) : ConstraintSet(cs, {}, {}) {} -ConstraintSet::ConstraintSet() {} +ConstraintSet::ConstraintSet() + : _independentElements(new IndependentConstraintSetUnion()) {} + +void ConstraintSet::fork() { + _independentElements = std::make_shared( + IndependentConstraintSetUnion(*_independentElements)); +} void ConstraintSet::addConstraint(ref e, const Assignment &delta) { _constraints.insert(e); @@ -212,8 +222,8 @@ void ConstraintSet::addConstraint(ref e, const Assignment &delta) { for (auto &i : delta.bindings) { _concretization.bindings.replace({i.first, i.second}); } - _independentElements.updateConcretization(delta); - _independentElements.addExpr(e); + _independentElements->updateConcretization(delta); + _independentElements->addExpr(e); } IDType Symcrete::idCounter = 0; @@ -221,14 +231,14 @@ IDType Symcrete::idCounter = 0; void ConstraintSet::addSymcrete(ref s, const Assignment &concretization) { _symcretes.insert(s); - _independentElements.addSymcrete(s); + _independentElements->addSymcrete(s); Assignment dependentConcretization; for (auto i : s->dependentArrays()) { _concretization.bindings.replace({i, concretization.bindings.at(i)}); dependentConcretization.bindings.replace( {i, concretization.bindings.at(i)}); } - _independentElements.updateConcretization(dependentConcretization); + _independentElements->updateConcretization(dependentConcretization); } bool ConstraintSet::isSymcretized(ref expr) const { @@ -246,14 +256,15 @@ void ConstraintSet::rewriteConcretization(const Assignment &a) { _concretization.bindings.replace({i.first, i.second}); } } - _independentElements.updateConcretization(a); + _independentElements->updateConcretization(a); } ConstraintSet ConstraintSet::getConcretizedVersion() const { ConstraintSet cs; - cs._independentElements = _independentElements.getConcretizedVersion(); + cs._independentElements = std::make_shared( + _independentElements->getConcretizedVersion()); - for (auto &e : cs._independentElements.is()) { + for (auto &e : cs._independentElements->is()) { if (isa(e)) { cs._constraints.insert(cast(e)->value()); } @@ -264,9 +275,9 @@ ConstraintSet ConstraintSet::getConcretizedVersion() const { ConstraintSet ConstraintSet::getConcretizedVersion( const Assignment &newConcretization) const { ConstraintSet cs; - cs._independentElements = - _independentElements.getConcretizedVersion(newConcretization); - for (auto &e : cs._independentElements.is()) { + cs._independentElements = std::make_shared( + _independentElements->getConcretizedVersion(newConcretization)); + for (auto &e : cs._independentElements->is()) { cs._constraints.insert(cast(e)->value()); } return cs; @@ -292,8 +303,8 @@ void ConstraintSet::dump() const { this->print(llvm::errs()); } void ConstraintSet::changeCS(constraints_ty &cs) { _constraints = cs; - _independentElements = - IndependentConstraintSetUnion(_constraints, _symcretes, _concretization); + _independentElements = std::make_shared( + IndependentConstraintSetUnion(_constraints, _symcretes, _concretization)); } const constraints_ty &ConstraintSet::cs() const { return _constraints; } @@ -302,7 +313,7 @@ const symcretes_ty &ConstraintSet::symcretes() const { return _symcretes; } const IndependentConstraintSetUnion & ConstraintSet::independentElements() const { - return _independentElements; + return *_independentElements; } const Path &PathConstraints::path() const { return _path; } @@ -330,6 +341,8 @@ PathConstraints::orderedCS() const { void PathConstraints::advancePath(KInstruction *ki) { _path.advance(ki); } +void PathConstraints::fork() { constraints.fork(); } + ExprHashSet PathConstraints::addConstraint(ref e, const Assignment &delta, Path::PathIndex currIndex) { auto expr = Simplificator::simplifyExpr(constraints, e); @@ -560,13 +573,13 @@ Simplificator::composeExprDependencies(const ExprHashMap &upper, void ConstraintSet::getAllIndependentConstraintsSets( ref queryExpr, std::vector> &result) const { - _independentElements.getAllIndependentConstraintSets(queryExpr, result); + _independentElements->getAllIndependentConstraintSets(queryExpr, result); } void ConstraintSet::getAllDependentConstraintsSets( ref queryExpr, std::vector> &result) const { - _independentElements.getAllDependentConstraintSets(queryExpr, result); + _independentElements->getAllDependentConstraintSets(queryExpr, result); } std::vector ConstraintSet::gatherArrays() const { diff --git a/lib/Expr/IndependentConstraintSetUnion.cpp b/lib/Expr/IndependentConstraintSetUnion.cpp index 0dcbf7154b..74fa369b14 100644 --- a/lib/Expr/IndependentConstraintSetUnion.cpp +++ b/lib/Expr/IndependentConstraintSetUnion.cpp @@ -49,30 +49,48 @@ void IndependentConstraintSetUnion::addIndependentConstraintSetUnion( const IndependentConstraintSetUnion &icsu) { add(icsu); concretization.addIndependentAssignment(icsu.concretization); + updateQueue.addIndependentAssignment(icsu.updateQueue); + removeQueue.addIndependentAssignment(icsu.removeQueue); + constraintQueue.insert(constraintQueue.begin(), icsu.constraintQueue.begin(), + icsu.constraintQueue.end()); } void IndependentConstraintSetUnion::updateConcretization( const Assignment &delta) { + for (auto &it : delta.bindings) { + updateQueue.bindings.replace({it.first, it.second}); + removeQueue.bindings.remove(it.first); + } +} + +void IndependentConstraintSetUnion::removeConcretization( + const Assignment &remove) { + for (auto &it : remove.bindings) { + removeQueue.bindings.replace({it.first, it.second}); + updateQueue.bindings.remove(it.first); + } +} + +void IndependentConstraintSetUnion::calculateUpdateConcretizationQueue() { for (auto &e : roots) { ref ics = disjointSets.at(e); - Assignment part = delta.part(ics->getSymcretes()); + Assignment part = updateQueue.part(ics->getSymcretes()); ics = ics->updateConcretization(part, concretizedExprs); disjointSets.insert_or_assign(e, ics); } - for (auto &it : delta.bindings) { + for (auto &it : updateQueue.bindings) { concretization.bindings.replace({it.first, it.second}); } } -void IndependentConstraintSetUnion::removeConcretization( - const Assignment &remove) { +void IndependentConstraintSetUnion::calculateRemoveConcretizationQueue() { for (auto &e : roots) { ref ics = disjointSets.at(e); - Assignment part = remove.part(ics->getSymcretes()); + Assignment part = removeQueue.part(ics->getSymcretes()); ics = ics->removeConcretization(part, concretizedExprs); disjointSets.insert_or_assign(e, ics); } - for (auto &it : remove.bindings) { + for (auto &it : removeQueue.bindings) { concretization.bindings.remove(it.first); } } @@ -93,8 +111,8 @@ void IndependentConstraintSetUnion::reEvaluateConcretization( } void IndependentConstraintSetUnion::getAllIndependentConstraintSets( - ref e, - std::vector> &result) const { + ref e, std::vector> &result) { + calculateQueue(); ref compare = new IndependentConstraintSet(new ExprEitherSymcrete::left(e)); for (auto &r : roots) { @@ -106,8 +124,8 @@ void IndependentConstraintSetUnion::getAllIndependentConstraintSets( } void IndependentConstraintSetUnion::getAllDependentConstraintSets( - ref e, - std::vector> &result) const { + ref e, std::vector> &result) { + calculateQueue(); ref compare = new IndependentConstraintSet(new ExprEitherSymcrete::left(e)); for (auto &r : roots) { @@ -119,15 +137,16 @@ void IndependentConstraintSetUnion::getAllDependentConstraintSets( } void IndependentConstraintSetUnion::addExpr(ref e) { - addValue(new ExprEitherSymcrete::left(e)); + constraintQueue.push_back(new ExprEitherSymcrete::left(e)); } void IndependentConstraintSetUnion::addSymcrete(ref s) { - addValue(new ExprEitherSymcrete::right(s)); + constraintQueue.push_back(new ExprEitherSymcrete::right(s)); } IndependentConstraintSetUnion -IndependentConstraintSetUnion::getConcretizedVersion() const { +IndependentConstraintSetUnion::getConcretizedVersion() { + calculateQueue(); IndependentConstraintSetUnion icsu; for (auto &i : roots) { ref root = disjointSets.at(i); @@ -141,14 +160,34 @@ IndependentConstraintSetUnion::getConcretizedVersion() const { icsu.concretization.addIndependentAssignment(root->concretization); } icsu.concretizedExprs = concretizedExprs; + icsu.calculateQueue(); return icsu; } IndependentConstraintSetUnion IndependentConstraintSetUnion::getConcretizedVersion( - const Assignment &newConcretization) const { + const Assignment &newConcretization) { + calculateQueue(); IndependentConstraintSetUnion icsu = *this; icsu.reEvaluateConcretization(newConcretization); + icsu.calculateQueue(); return icsu.getConcretizedVersion(); } + +void IndependentConstraintSetUnion::calculateQueue() { + calculateUpdateConcretizationQueue(); + calculateRemoveConcretizationQueue(); + while (!constraintQueue.empty()) { + addValue(constraintQueue[constraintQueue.size() - 1]); + constraintQueue.pop_back(); + } + calculateUpdateConcretizationQueue(); + calculateRemoveConcretizationQueue(); + // Calculations are done twice for constraints already in dsu and for newly + // added constraints. Because IndependentSet update and remove concretization + // functions work only with difference between new and old concretization, no + // extra work is done + removeQueue.bindings = Assignment::bindings_ty(); + updateQueue.bindings = Assignment::bindings_ty(); +} } // namespace klee From c35bad9b632ed3ee404e6a77b802eecb062a6bc0 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Thu, 16 Nov 2023 03:04:54 +0400 Subject: [PATCH 077/120] [chore] Update `GuidedSearcher::selectState` --- include/klee/Module/KModule.h | 6 ++++++ lib/Core/Executor.cpp | 2 +- lib/Core/Searcher.cpp | 8 ++++---- lib/Core/Searcher.h | 1 + lib/Core/TargetedExecutionManager.cpp | 5 ++--- lib/Core/TargetedExecutionManager.h | 8 +------- test/Industry/if2.c | 2 +- 7 files changed, 16 insertions(+), 16 deletions(-) diff --git a/include/klee/Module/KModule.h b/include/klee/Module/KModule.h index 83cef2cce5..dfd00c101f 100644 --- a/include/klee/Module/KModule.h +++ b/include/klee/Module/KModule.h @@ -197,6 +197,12 @@ struct KBlockCompare { } }; +struct KFunctionCompare { + bool operator()(const KFunction *a, const KFunction *b) const { + return a->id < b->id; + } +}; + class KConstant { public: /// Actual LLVM constant this represents. diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index 48a2b4ae09..397c68572a 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -6763,7 +6763,7 @@ void Executor::runFunctionAsMain(Function *f, int argc, char **argv, if (guidanceKind == GuidanceKind::ErrorGuidance) { std::map, - klee::TargetedExecutionManager::KFunctionLess> + klee::KFunctionCompare> prepTargets; if (FunctionCallReproduce == "") { auto &paths = interpreterOpts.Paths.value(); diff --git a/lib/Core/Searcher.cpp b/lib/Core/Searcher.cpp index f2d91cfd79..f42f798141 100644 --- a/lib/Core/Searcher.cpp +++ b/lib/Core/Searcher.cpp @@ -193,12 +193,12 @@ weight_type TargetedSearcher::getWeight(ExecutionState *es) { ExecutionState &GuidedSearcher::selectState() { unsigned size = historiesAndTargets.size(); - index = theRNG.getInt32() % (size + 1); + interleave ^= 1; ExecutionState *state = nullptr; - if (index == size) { + if (interleave || !size) { state = &baseSearcher->selectState(); } else { - index = index % size; + index = theRNG.getInt32() % size; auto &historyTargetPair = historiesAndTargets[index]; ref history = historyTargetPair.first; ref target = historyTargetPair.second; @@ -657,7 +657,7 @@ class MaxCyclesMetric final : public IterativeDeepeningSearcher::Metric { return state.isCycled(maxCycles); } void increaseLimit() final { - maxCycles *= 2ULL; + maxCycles *= 4ULL; klee_message("increased max-cycles to %llu", maxCycles); } }; diff --git a/lib/Core/Searcher.h b/lib/Core/Searcher.h index 8b8224f85c..f0b7e8d2b5 100644 --- a/lib/Core/Searcher.h +++ b/lib/Core/Searcher.h @@ -169,6 +169,7 @@ class GuidedSearcher final : public Searcher, public TargetManagerSubscriber { DistanceCalculator &distanceCalculator; RNG &theRNG; unsigned index{1}; + bool interleave = true; TargetForestHistoryTargetSet localHistoryTargets; std::vector baseAddedStates; diff --git a/lib/Core/TargetedExecutionManager.cpp b/lib/Core/TargetedExecutionManager.cpp index d323180908..ab4b67f3df 100644 --- a/lib/Core/TargetedExecutionManager.cpp +++ b/lib/Core/TargetedExecutionManager.cpp @@ -493,13 +493,12 @@ KFunction *TargetedExecutionManager::tryResolveEntryFunction( return resKf; } -std::map, - TargetedExecutionManager::KFunctionLess> +std::map, KFunctionCompare> TargetedExecutionManager::prepareTargets(KModule *kmodule, SarifReport paths) { Locations locations = collectAllLocations(paths); LocationToBlocks locToBlocks = prepareAllLocations(kmodule, locations); - std::map, KFunctionLess> whitelists; + std::map, KFunctionCompare> whitelists; for (auto &result : paths.results) { bool isFullyResolved = tryResolveLocations(result, locToBlocks); diff --git a/lib/Core/TargetedExecutionManager.h b/lib/Core/TargetedExecutionManager.h index 93ea108a07..e5f72e935b 100644 --- a/lib/Core/TargetedExecutionManager.h +++ b/lib/Core/TargetedExecutionManager.h @@ -115,17 +115,11 @@ class TargetedExecutionManager { StatesSet localStates; public: - struct KFunctionLess { - bool operator()(const KFunction *a, const KFunction *b) const { - return a->id < b->id; - } - }; - explicit TargetedExecutionManager(CodeGraphInfo &codeGraphInfo_, TargetManager &targetManager_) : codeGraphInfo(codeGraphInfo_), targetManager(targetManager_) {} ~TargetedExecutionManager() = default; - std::map, KFunctionLess> + std::map, KFunctionCompare> prepareTargets(KModule *kmodule, SarifReport paths); void reportFalseNegative(ExecutionState &state, ReachWithError error); diff --git a/test/Industry/if2.c b/test/Industry/if2.c index e41a4a0a0e..b35cb487bf 100644 --- a/test/Industry/if2.c +++ b/test/Industry/if2.c @@ -14,4 +14,4 @@ int main(int x) { // 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 -// CHECK-DISTANCE: KLEE: (0, 1, 1) for Target 1: error in function main (lines 8 to 8) +// CHECK-DISTANCE: KLEE: (0, 1, 0) for Target 1: error in function main (lines 8 to 8) From 0b27fb6259a63740df77f7954a3fd75b3cae3664 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Fri, 17 Nov 2023 15:23:59 +0400 Subject: [PATCH 078/120] [fix] Convert all x86FP to x87FP80 in `FPToX87FP80Ext` [fix] `X86FPAsX87FP80` should consider bitcasts too --- lib/Core/Executor.cpp | 107 ++++++++++++++++++++++++-------------- lib/Core/ExecutorUtil.cpp | 37 +++++++++++-- lib/Expr/Expr.cpp | 8 ++- 3 files changed, 106 insertions(+), 46 deletions(-) diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index 397c68572a..c9852154fc 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -663,6 +663,39 @@ Executor::~Executor() { /***/ +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) { + 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::initializeGlobalObject(ExecutionState &state, ObjectState *os, const Constant *c, unsigned offset) { const auto targetData = kmodule->targetData.get(); @@ -698,6 +731,12 @@ void Executor::initializeGlobalObject(ExecutionState &state, ObjectState *os, unsigned StoreBits = targetData->getTypeStoreSizeInBits(c->getType()); ref C = evalConstant(c, state.roundingMode); + if (c->getType()->isFloatingPointTy() && + Context::get().getPointerWidth() == 32) { + C = X87FP80ToFPTrunc(C, getWidthForLLVMType(c->getType()), + state.roundingMode); + } + // Extend the constant if necessary; assert(StoreBits >= C->getWidth() && "Invalid store size!"); if (StoreBits > C->getWidth()) @@ -2463,40 +2502,6 @@ 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; @@ -3338,6 +3343,20 @@ void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) { BitCastInst *bc = cast(ki->inst); llvm::Type *castToType = bc->getType(); + + if (X86FPAsX87FP80 && result->getWidth() == Expr::Fl80 && + !castToType->isFloatingPointTy() && + Context::get().getPointerWidth() == 32) { + result = X87FP80ToFPTrunc( + result, getWidthForLLVMType(bc->getOperand(0)->getType()), + state.roundingMode); + } + + if (X86FPAsX87FP80 && castToType->isFloatingPointTy() && + Context::get().getPointerWidth() == 32) { + result = FPToX87FP80Ext(result); + } + if (castToType->isPointerTy()) { castToType = castToType->getPointerElementType(); } @@ -3715,9 +3734,12 @@ 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) - return terminateStateOnExecError(state, "Invalid FPTrunc"); - ref result = FPTruncExpr::create(arg, resultType, state.roundingMode); + ref result = arg; + if (arg->getWidth() > resultType) + result = FPTruncExpr::create(arg, resultType, state.roundingMode); + if (X86FPAsX87FP80 && Context::get().getPointerWidth() == 32) { + result = FPToX87FP80Ext(result); + } bindLocal(ki, state, result); break; } @@ -3728,9 +3750,14 @@ 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) - return terminateStateOnExecError(state, "Invalid FPExt"); - ref result = FPExtExpr::create(arg, resultType); + ref result = arg; + if (arg->getWidth() < resultType) { + // return terminateStateOnExecError(state, "Invalid FPExt"); + result = FPExtExpr::create(arg, resultType); + } + if (X86FPAsX87FP80 && Context::get().getPointerWidth() == 32) { + result = FPToX87FP80Ext(result); + } bindLocal(ki, state, result); break; } diff --git a/lib/Core/ExecutorUtil.cpp b/lib/Core/ExecutorUtil.cpp index ef3a100f0e..ce19fa74bf 100644 --- a/lib/Core/ExecutorUtil.cpp +++ b/lib/Core/ExecutorUtil.cpp @@ -36,13 +36,28 @@ using namespace llvm; namespace klee { extern llvm::cl::opt X86FPAsX87FP80; +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 // ENABLE_FP + 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) { + if (Context::get().getPointerWidth() == 32) { result = FPExtExpr::create(arg, resultType); } #else @@ -340,8 +355,22 @@ ref Executor::evalConstantExpr(const llvm::ConstantExpr *ce, return op1->LShr(op2); case Instruction::AShr: return op1->AShr(op2); - case Instruction::BitCast: - return op1; + case Instruction::BitCast: { + ref result = op1; + + if (X86FPAsX87FP80 && result->getWidth() == Expr::Fl80 && + !ce->getType()->isFloatingPointTy() && + Context::get().getPointerWidth() == 32) { + result = cast( + X87FP80ToFPTrunc(result, getWidthForLLVMType(type), rm)); + } + + if (X86FPAsX87FP80 && ce->getType()->isFloatingPointTy() && + Context::get().getPointerWidth() == 32) { + result = cast(FPToX87FP80Ext(result)); + } + return result; + } case Instruction::IntToPtr: return op1->ZExt(getWidthForLLVMType(type)); diff --git a/lib/Expr/Expr.cpp b/lib/Expr/Expr.cpp index ec1ecd9235..90f2380709 100644 --- a/lib/Expr/Expr.cpp +++ b/lib/Expr/Expr.cpp @@ -1821,9 +1821,13 @@ ref FPTruncExpr::create(const ref &e, Width w, return e; } else if (ConstantExpr *CE = dyn_cast(e)) { return CE->FPTrunc(w, rm); - } else { - return FPTruncExpr::alloc(e, w, rm); + } else if (FPExtExpr *ExtE = dyn_cast(e)) { + if (ExtE->src->getWidth() == w) { + return ExtE->src; + } } + + return FPTruncExpr::alloc(e, w, rm); } ref FPToUIExpr::create(const ref &e, Width w, From 9c1caa951185304a7cf474bc78bbfb95ab0e6584 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Fri, 17 Nov 2023 20:04:34 +0400 Subject: [PATCH 079/120] [fix] Restore `newSize` in case `newSize > maxSize` --- lib/Core/AddressManager.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/Core/AddressManager.cpp b/lib/Core/AddressManager.cpp index f763e0d3e0..b0219fb9ea 100644 --- a/lib/Core/AddressManager.cpp +++ b/lib/Core/AddressManager.cpp @@ -25,9 +25,15 @@ void *AddressManager::allocate(ref address, uint64_t size) { } } else { if (sizeLocation == objects.end() || !sizeLocation->second) { - uint64_t newSize = (uint64_t)1 - << (sizeof(size) * CHAR_BIT - - __builtin_clzll(std::max((uint64_t)1, size))); + uint64_t newSize = std::max((uint64_t)1, size); + int clz = __builtin_clzll(std::max((uint64_t)1, newSize)); + int popcount = __builtin_popcountll(std::max((uint64_t)1, newSize)); + if (popcount > 1) { + newSize = (uint64_t)1 << (sizeof(newSize) * CHAR_BIT - clz); + } + if (newSize > maxSize) { + newSize = std::max((uint64_t)1, size); + } assert(!objects.empty()); MemoryObject *mo = objects.begin()->second; newMO = memory->allocate(newSize, mo->isLocal, mo->isGlobal, From 1df90e8d06fa8cc9e71cbabf6936804fb0f5b38e Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Sat, 18 Nov 2023 02:17:39 +0400 Subject: [PATCH 080/120] [chore] `ExprEitherSymcrete` ->`ExprOrSymcrete` --- include/klee/ADT/DisjointSetUnion.h | 2 +- include/klee/ADT/Either.h | 3 -- .../klee/Expr/IndependentConstraintSetUnion.h | 6 ++-- include/klee/Expr/IndependentSet.h | 20 ++++++------- lib/Expr/Constraints.cpp | 6 ++-- lib/Expr/IndependentConstraintSetUnion.cpp | 14 +++++----- lib/Expr/IndependentSet.cpp | 28 +++++++++---------- 7 files changed, 37 insertions(+), 42 deletions(-) diff --git a/include/klee/ADT/DisjointSetUnion.h b/include/klee/ADT/DisjointSetUnion.h index 41c1a0296b..9a3673af64 100644 --- a/include/klee/ADT/DisjointSetUnion.h +++ b/include/klee/ADT/DisjointSetUnion.h @@ -21,7 +21,7 @@ DISABLE_WARNING_POP #include namespace klee { -using ExprEitherSymcrete = either; +using ExprOrSymcrete = either; template , diff --git a/include/klee/ADT/Either.h b/include/klee/ADT/Either.h index 81b2d8e51c..c941d33103 100644 --- a/include/klee/ADT/Either.h +++ b/include/klee/ADT/Either.h @@ -46,7 +46,6 @@ template class 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; @@ -83,7 +82,6 @@ template class either_left : public either { } 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; @@ -134,7 +132,6 @@ template class either_right : public either { } 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; diff --git a/include/klee/Expr/IndependentConstraintSetUnion.h b/include/klee/Expr/IndependentConstraintSetUnion.h index 783dadc256..c4ce9a4559 100644 --- a/include/klee/Expr/IndependentConstraintSetUnion.h +++ b/include/klee/Expr/IndependentConstraintSetUnion.h @@ -8,11 +8,11 @@ namespace klee { class IndependentConstraintSetUnion - : public DisjointSetUnion, IndependentConstraintSet, - ExprEitherSymcreteHash, ExprEitherSymcreteCmp> { + : public DisjointSetUnion, IndependentConstraintSet, + ExprOrSymcreteHash, ExprOrSymcreteCmp> { public: Assignment concretization; - std::vector> constraintQueue; + std::vector> constraintQueue; Assignment updateQueue; Assignment removeQueue; diff --git a/include/klee/Expr/IndependentSet.h b/include/klee/Expr/IndependentSet.h index c1c69f2f72..cbcf9ec752 100644 --- a/include/klee/Expr/IndependentSet.h +++ b/include/klee/Expr/IndependentSet.h @@ -22,17 +22,15 @@ DISABLE_WARNING_POP #include namespace klee { -using ExprEitherSymcrete = either; +using ExprOrSymcrete = either; -struct ExprEitherSymcreteHash { - unsigned operator()(const ref &e) const { - return e->hash(); - } +struct ExprOrSymcreteHash { + unsigned operator()(const ref &e) const { return e->hash(); } }; -struct ExprEitherSymcreteCmp { - bool operator()(const ref &a, - const ref &b) const { +struct ExprOrSymcreteCmp { + bool operator()(const ref &a, + const ref &b) const { return a == b; } }; @@ -100,8 +98,8 @@ inline llvm::raw_ostream &operator<<(llvm::raw_ostream &os, class IndependentConstraintSet { private: using InnerSetUnion = - DisjointSetUnion, IndependentConstraintSet, - ExprEitherSymcreteHash, ExprEitherSymcreteCmp>; + DisjointSetUnion, IndependentConstraintSet, + ExprOrSymcreteHash, ExprOrSymcreteCmp>; void initIndependentConstraintSet(ref e); void initIndependentConstraintSet(ref s); @@ -137,7 +135,7 @@ class IndependentConstraintSet { Assignment &assign) const; IndependentConstraintSet(); - explicit IndependentConstraintSet(ref v); + explicit IndependentConstraintSet(ref v); IndependentConstraintSet(const IndependentConstraintSet &ics); void print(llvm::raw_ostream &os) const; diff --git a/lib/Expr/Constraints.cpp b/lib/Expr/Constraints.cpp index aa963d6cbc..b88c204555 100644 --- a/lib/Expr/Constraints.cpp +++ b/lib/Expr/Constraints.cpp @@ -265,8 +265,8 @@ ConstraintSet ConstraintSet::getConcretizedVersion() const { _independentElements->getConcretizedVersion()); for (auto &e : cs._independentElements->is()) { - if (isa(e)) { - cs._constraints.insert(cast(e)->value()); + if (isa(e)) { + cs._constraints.insert(cast(e)->value()); } } return cs; @@ -278,7 +278,7 @@ ConstraintSet ConstraintSet::getConcretizedVersion( cs._independentElements = std::make_shared( _independentElements->getConcretizedVersion(newConcretization)); for (auto &e : cs._independentElements->is()) { - cs._constraints.insert(cast(e)->value()); + cs._constraints.insert(cast(e)->value()); } return cs; } diff --git a/lib/Expr/IndependentConstraintSetUnion.cpp b/lib/Expr/IndependentConstraintSetUnion.cpp index 74fa369b14..b2c67e5a14 100644 --- a/lib/Expr/IndependentConstraintSetUnion.cpp +++ b/lib/Expr/IndependentConstraintSetUnion.cpp @@ -20,13 +20,13 @@ IndependentConstraintSetUnion::IndependentConstraintSetUnion( ref ics) { auto exprs = ics->exprs; for (ref e : exprs) { - auto v = ref(new ExprEitherSymcrete::left(e)); + auto v = ref(new ExprOrSymcrete::left(e)); rank.insert_or_assign(v, 0); internalStorage.insert(v); } for (ref s : ics->symcretes) { - auto v = ref(new ExprEitherSymcrete::right(s)); + auto v = ref(new ExprOrSymcrete::right(s)); rank.insert_or_assign(v, 0); internalStorage.insert(v); } @@ -114,7 +114,7 @@ void IndependentConstraintSetUnion::getAllIndependentConstraintSets( ref e, std::vector> &result) { calculateQueue(); ref compare = - new IndependentConstraintSet(new ExprEitherSymcrete::left(e)); + new IndependentConstraintSet(new ExprOrSymcrete::left(e)); for (auto &r : roots) { ref ics = disjointSets.at(r); if (!IndependentConstraintSet::intersects(ics, compare)) { @@ -127,7 +127,7 @@ void IndependentConstraintSetUnion::getAllDependentConstraintSets( ref e, std::vector> &result) { calculateQueue(); ref compare = - new IndependentConstraintSet(new ExprEitherSymcrete::left(e)); + new IndependentConstraintSet(new ExprOrSymcrete::left(e)); for (auto &r : roots) { ref ics = disjointSets.at(r); if (IndependentConstraintSet::intersects(ics, compare)) { @@ -137,11 +137,11 @@ void IndependentConstraintSetUnion::getAllDependentConstraintSets( } void IndependentConstraintSetUnion::addExpr(ref e) { - constraintQueue.push_back(new ExprEitherSymcrete::left(e)); + constraintQueue.push_back(new ExprOrSymcrete::left(e)); } void IndependentConstraintSetUnion::addSymcrete(ref s) { - constraintQueue.push_back(new ExprEitherSymcrete::right(s)); + constraintQueue.push_back(new ExprOrSymcrete::right(s)); } IndependentConstraintSetUnion @@ -152,7 +152,7 @@ IndependentConstraintSetUnion::getConcretizedVersion() { ref root = disjointSets.at(i); if (root->concretization.bindings.empty()) { for (ref expr : root->exprs) { - icsu.addValue(new ExprEitherSymcrete::left(expr)); + icsu.addValue(new ExprOrSymcrete::left(expr)); } } else { icsu.add(root->concretizedSets); diff --git a/lib/Expr/IndependentSet.cpp b/lib/Expr/IndependentSet.cpp index d01b234f17..888dc52fdd 100644 --- a/lib/Expr/IndependentSet.cpp +++ b/lib/Expr/IndependentSet.cpp @@ -34,7 +34,7 @@ IndependentConstraintSet::updateConcretization( continue; } concretizedExprs[i] = e; - DSU.addValue(new ExprEitherSymcrete::left(e)); + DSU.addValue(new ExprOrSymcrete::left(e)); } for (ref s : symcretes) { ref e = EqExpr::create(ics->concretization.evaluate(s->symcretized), @@ -43,7 +43,7 @@ IndependentConstraintSet::updateConcretization( assert(ce->isTrue() && "Attempt to add invalid constraint"); continue; } - DSU.addValue(new ExprEitherSymcrete::left(e)); + DSU.addValue(new ExprOrSymcrete::left(e)); } auto concretizationConstraints = ics->concretization.createConstraintsFromAssignment(); @@ -52,7 +52,7 @@ IndependentConstraintSet::updateConcretization( assert(ce->isTrue() && "Attempt to add invalid constraint"); continue; } - DSU.addValue(new ExprEitherSymcrete::left(e)); + DSU.addValue(new ExprOrSymcrete::left(e)); } ics->concretizedSets = DSU; return ics; @@ -76,7 +76,7 @@ IndependentConstraintSet::removeConcretization( continue; } concretizedExprs[i] = e; - DSU.addValue(new ExprEitherSymcrete::left(e)); + DSU.addValue(new ExprOrSymcrete::left(e)); } for (ref s : symcretes) { ref e = EqExpr::create(ics->concretization.evaluate(s->symcretized), @@ -85,7 +85,7 @@ IndependentConstraintSet::removeConcretization( assert(ce->isTrue() && "Attempt to add invalid constraint"); continue; } - DSU.addValue(new ExprEitherSymcrete::left(e)); + DSU.addValue(new ExprOrSymcrete::left(e)); } auto concretizationConstraints = ics->concretization.createConstraintsFromAssignment(); @@ -94,7 +94,7 @@ IndependentConstraintSet::removeConcretization( assert(ce->isTrue() && "Attempt to add invalid constraint"); continue; } - DSU.addValue(new ExprEitherSymcrete::left(e)); + DSU.addValue(new ExprOrSymcrete::left(e)); } ics->concretizedSets = DSU; @@ -123,11 +123,11 @@ void IndependentConstraintSet::addValuesToAssignment( IndependentConstraintSet::IndependentConstraintSet() {} -IndependentConstraintSet::IndependentConstraintSet(ref v) { - if (isa(v)) { - initIndependentConstraintSet(cast(v)->value()); +IndependentConstraintSet::IndependentConstraintSet(ref v) { + if (isa(v)) { + initIndependentConstraintSet(cast(v)->value()); } else { - initIndependentConstraintSet(cast(v)->value()); + initIndependentConstraintSet(cast(v)->value()); } } @@ -350,7 +350,7 @@ IndependentConstraintSet::merge(ref A, assert(ce->isTrue() && "Attempt to add invalid constraint"); continue; } - DSU.addValue(new ExprEitherSymcrete::left(e)); + DSU.addValue(new ExprOrSymcrete::left(e)); } for (ref s : a->symcretes) { ref e = EqExpr::create(a->concretization.evaluate(s->symcretized), @@ -359,7 +359,7 @@ IndependentConstraintSet::merge(ref A, assert(ce->isTrue() && "Attempt to add invalid constraint"); continue; } - DSU.addValue(new ExprEitherSymcrete::left(e)); + DSU.addValue(new ExprOrSymcrete::left(e)); } auto concretizationConstraints = a->concretization.createConstraintsFromAssignment(); @@ -368,7 +368,7 @@ IndependentConstraintSet::merge(ref A, assert(ce->isTrue() && "Attempt to add invalid constraint"); continue; } - DSU.addValue(new ExprEitherSymcrete::left(e)); + DSU.addValue(new ExprOrSymcrete::left(e)); } a->concretizedSets = DSU; @@ -405,7 +405,7 @@ void calculateArraysInFactors( } std::vector result; ref queryExprSet = - new IndependentConstraintSet(new ExprEitherSymcrete::left(queryExpr)); + new IndependentConstraintSet(new ExprOrSymcrete::left(queryExpr)); queryExprSet->calculateArrayReferences(result); returnSet.insert(result.begin(), result.end()); returnVector.insert(returnVector.begin(), returnSet.begin(), returnSet.end()); From 5d91554e2dfccf13269bbddacae2d18d894dce9e Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Mon, 20 Nov 2023 04:18:13 +0400 Subject: [PATCH 081/120] [fix] `AlphaBuilder` --- include/klee/Expr/AlphaBuilder.h | 2 ++ lib/Expr/AlphaBuilder.cpp | 14 ++++++++++-- lib/Solver/AlphaEquivalenceSolver.cpp | 33 +++++++-------------------- 3 files changed, 22 insertions(+), 27 deletions(-) diff --git a/include/klee/Expr/AlphaBuilder.h b/include/klee/Expr/AlphaBuilder.h index 7012411908..6a965c3962 100644 --- a/include/klee/Expr/AlphaBuilder.h +++ b/include/klee/Expr/AlphaBuilder.h @@ -25,6 +25,7 @@ class AlphaBuilder final : public ExprVisitor { private: ArrayCache &arrayCache; unsigned index = 0; + bool reverse = false; const Array *visitArray(const Array *arr); UpdateList visitUpdateList(UpdateList u); @@ -36,6 +37,7 @@ class AlphaBuilder final : public ExprVisitor { constraints_ty visitConstraints(constraints_ty cs); ref build(ref v); const Array *buildArray(const Array *arr) { return visitArray(arr); } + ref reverseBuild(ref v); }; } // namespace klee diff --git a/lib/Expr/AlphaBuilder.cpp b/lib/Expr/AlphaBuilder.cpp index b3b98723c9..13fb00073f 100644 --- a/lib/Expr/AlphaBuilder.cpp +++ b/lib/Expr/AlphaBuilder.cpp @@ -16,7 +16,7 @@ namespace klee { const Array *AlphaBuilder::visitArray(const Array *arr) { - if (alphaArrayMap.find(arr) == alphaArrayMap.end()) { + if (!reverse && alphaArrayMap.find(arr) == alphaArrayMap.end()) { ref source = arr->source; ref size = visit(arr->getSize()); @@ -35,7 +35,11 @@ const Array *AlphaBuilder::visitArray(const Array *arr) { reverseAlphaArrayMap[arr] = arr; } } - return alphaArrayMap[arr]; + if (reverse) { + return reverseAlphaArrayMap[arr]; + } else { + return alphaArrayMap[arr]; + } } UpdateList AlphaBuilder::visitUpdateList(UpdateList u) { @@ -81,5 +85,11 @@ ref AlphaBuilder::build(ref v) { reverseExprMap[Expr::createIsZero(e)] = Expr::createIsZero(v); return e; } +ref AlphaBuilder::reverseBuild(ref v) { + reverse = true; + ref e = visit(v); + reverse = false; + return e; +} } // namespace klee diff --git a/lib/Solver/AlphaEquivalenceSolver.cpp b/lib/Solver/AlphaEquivalenceSolver.cpp index 4c0cc81fa3..d8b6011c78 100644 --- a/lib/Solver/AlphaEquivalenceSolver.cpp +++ b/lib/Solver/AlphaEquivalenceSolver.cpp @@ -54,7 +54,7 @@ class AlphaEquivalenceSolver : public SolverImpl { void setCoreSolverTimeout(time::Span timeout); void notifyStateTermination(std::uint32_t id); ValidityCore changeVersion(const ValidityCore &validityCore, - const ExprHashMap> &reverse); + AlphaBuilder &builder); std::vector changeVersion(const std::vector &objects, AlphaBuilder &builder); @@ -66,24 +66,20 @@ class AlphaEquivalenceSolver : public SolverImpl { changeVersion(const Assignment &a, const ArrayCache::ArrayHashMap &reverse); ref changeVersion(ref res, - const AlphaBuilder &builder); - ref createAlphaVersion(ref res, - const AlphaBuilder &builder); + AlphaBuilder &builder); }; ValidityCore AlphaEquivalenceSolver::changeVersion(const ValidityCore &validityCore, - const ExprHashMap> &reverse) { + AlphaBuilder &builder) { ValidityCore reverseValidityCore; if (isa(validityCore.expr)) { reverseValidityCore.expr = validityCore.expr; } else { - assert(reverse.find(validityCore.expr) != reverse.end()); - reverseValidityCore.expr = reverse.at(validityCore.expr); + reverseValidityCore.expr = builder.reverseBuild(validityCore.expr); } for (auto e : validityCore.constraints) { - assert(reverse.find(e) != reverse.end()); - reverseValidityCore.constraints.insert(reverse.at(e)); + reverseValidityCore.constraints.insert(builder.reverseBuild(e)); } return reverseValidityCore; } @@ -123,7 +119,7 @@ Assignment AlphaEquivalenceSolver::changeVersion( ref AlphaEquivalenceSolver::changeVersion(ref res, - const AlphaBuilder &builder) { + AlphaBuilder &builder) { ref reverseRes; if (!isa(res) && !isa(res)) { return res; @@ -136,24 +132,12 @@ AlphaEquivalenceSolver::changeVersion(ref res, } else { ValidityCore validityCore; res->tryGetValidityCore(validityCore); - validityCore = changeVersion(validityCore, builder.reverseExprMap); + validityCore = changeVersion(validityCore, builder); 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); @@ -205,7 +189,6 @@ bool AlphaEquivalenceSolver::check(const Query &query, constraints_ty alphaQuery = builder.visitConstraints(query.constraints.cs()); ref alphaQueryExpr = builder.build(query.expr); - result = createAlphaVersion(result, builder); if (!solver->impl->check( Query(ConstraintSet(alphaQuery, {}, {}), alphaQueryExpr, query.id), result)) { @@ -228,7 +211,7 @@ bool AlphaEquivalenceSolver::computeValidityCore(const Query &query, validityCore, isValid)) { return false; } - validityCore = changeVersion(validityCore, builder.reverseExprMap); + validityCore = changeVersion(validityCore, builder); return true; } From c71f2cb0c90a6abd1bc480cadb1983c951ceb497 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Mon, 20 Nov 2023 04:19:29 +0400 Subject: [PATCH 082/120] [fix] `CexCachingSolver` --- lib/Solver/CexCachingSolver.cpp | 45 +++++++++++++++++++++++---------- 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/lib/Solver/CexCachingSolver.cpp b/lib/Solver/CexCachingSolver.cpp index 3cd4947c9f..038af68e2e 100644 --- a/lib/Solver/CexCachingSolver.cpp +++ b/lib/Solver/CexCachingSolver.cpp @@ -93,6 +93,7 @@ class CexCachingSolver : public SolverImpl { } bool getResponse(const Query &query, ref &result); + void setResponse(const Query &query, ref &result); public: CexCachingSolver(std::unique_ptr solver) @@ -132,8 +133,9 @@ struct isValidOrSatisfyingResponse { isValidOrSatisfyingResponse(KeyType &_key) : key(_key) {} bool operator()(ref a) const { - return isa(a) || (isa(a) && - cast(a)->satisfies(key)); + return isa(a) || + (isa(a) && + cast(a)->satisfiesOrConstant(key)); } }; @@ -208,6 +210,17 @@ bool CexCachingSolver::searchForResponse(KeyType &key, return false; } +KeyType makeKey(const Query &query) { + KeyType 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); + key.insert(neg); + return key; +} + /// lookupResponse - Lookup a cached result for the given \arg query. /// /// \param query - The query to lookup. @@ -217,10 +230,7 @@ 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) { - key = KeyType(query.constraints.cs().begin(), query.constraints.cs().end()); - for (ref s : query.constraints.symcretes()) { - key.insert(s->symcretized); - } + key = makeKey(query); ref neg = Expr::createIsZero(query.expr); if (ConstantExpr *CE = dyn_cast(neg)) { if (CE->isFalse()) { @@ -228,8 +238,6 @@ bool CexCachingSolver::lookupResponse(const Query &query, KeyType &key, ++stats::queryCexCacheHits; return true; } - } else { - key.insert(neg); } bool found = searchForResponse(key, result); @@ -243,8 +251,7 @@ 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, result)) { return true; } @@ -252,6 +259,14 @@ bool CexCachingSolver::getResponse(const Query &query, return false; } + setResponse(query, result); + return true; +} + +void CexCachingSolver::setResponse(const Query &query, + ref &result) { + KeyType key = makeKey(query); + if (isa(result)) { // Memorize the result. std::pair res = @@ -261,7 +276,7 @@ bool CexCachingSolver::getResponse(const Query &query, } if (DebugCexCacheCheckBinding) { - if (!cast(result)->satisfiesOrConstant(key)) { + if (!cast(result)->satisfiesOrConstant(key, false)) { query.dump(); result->dump(); klee_error("Generated assignment doesn't match query"); @@ -281,8 +296,6 @@ bool CexCachingSolver::getResponse(const Query &query, if (isa(result) || isa(result)) { cache.insert(key, result); } - - return true; } /// @@ -364,6 +377,12 @@ bool CexCachingSolver::computeValue(const Query &query, ref &result) { assert(isa(result) && "assignment evaluation did not result in constant"); + + if (cast(result)->isTrue()) { + setResponse(query.negateExpr(), a); + } else if (cast(result)->isFalse()) { + setResponse(query, a); + } return true; } From dad6ccd99c14aa72d69c6b545ea1342b5b9e1ccb Mon Sep 17 00:00:00 2001 From: Aleksei Babushkin Date: Sat, 11 Nov 2023 14:29:44 +0300 Subject: [PATCH 083/120] [fix] SparseStorage::print --- lib/ADT/SparseStorage.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/ADT/SparseStorage.cpp b/lib/ADT/SparseStorage.cpp index dc24e7d993..1cfe3319b4 100644 --- a/lib/ADT/SparseStorage.cpp +++ b/lib/ADT/SparseStorage.cpp @@ -18,7 +18,7 @@ void SparseStorage::print(llvm::raw_ostream &os, if (firstPrinted) { os << ", "; } - os << element.first << ": " << element.second; + os << element.first << ": " << llvm::utostr(element.second); firstPrinted = true; } os << "} default: "; @@ -35,7 +35,7 @@ void SparseStorage::print(llvm::raw_ostream &os, } os << "] default: "; } - os << defaultValue; + os << llvm::utostr(defaultValue); } template <> From 2cd78c430cf3786859d67748e9055cb3e91fe097 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Mon, 20 Nov 2023 23:38:01 +0400 Subject: [PATCH 084/120] [fix] `sizeOfSetRange` --- include/klee/ADT/SparseStorage.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/klee/ADT/SparseStorage.h b/include/klee/ADT/SparseStorage.h index a06f63391f..a78df85770 100644 --- a/include/klee/ADT/SparseStorage.h +++ b/include/klee/ADT/SparseStorage.h @@ -75,7 +75,7 @@ class SparseStorage { for (auto i : internalStorage) { sizeOfRange = std::max(i.first, sizeOfRange); } - return sizeOfRange; + return internalStorage.empty() ? 0 : sizeOfRange + 1; } bool operator==(const SparseStorage &another) const { From 3b482991b6867fa5c2379f3bf43573cdb7bd0aa2 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Tue, 21 Nov 2023 04:38:55 +0400 Subject: [PATCH 085/120] [fix] Disable `AlignSymbolicPointers` by default --- 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 c9852154fc..36d82de01d 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -162,7 +162,7 @@ cl::opt AlignSymbolicPointers("align-symbolic-pointers", cl::desc("Makes symbolic pointers aligned according" "to the used type system (default=true)"), - cl::init(true), cl::cat(ExecCat)); + cl::init(false), cl::cat(ExecCat)); cl::opt ExternCallsCanReturnNull("extern-calls-can-return-null", cl::init(false), From 15b79ad08975ee700c52a8455660a2094dddb519 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Tue, 21 Nov 2023 14:05:01 +0400 Subject: [PATCH 086/120] [chore] Install meson locally --- scripts/build/p-bitwuzla-linux-ubuntu.inc | 2 +- scripts/build/p-bitwuzla-osx.inc | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/build/p-bitwuzla-linux-ubuntu.inc b/scripts/build/p-bitwuzla-linux-ubuntu.inc index cd585c7e31..f36ab25d5e 100644 --- a/scripts/build/p-bitwuzla-linux-ubuntu.inc +++ b/scripts/build/p-bitwuzla-linux-ubuntu.inc @@ -19,7 +19,7 @@ install_build_dependencies_bitwuzla() { with_sudo apt-get update -y with_sudo apt-get -y --no-install-recommends install pkg-config cmake-data m4 - with_sudo pip3 install --user meson + pip3 install --user meson base_path="$(python3 -m site --user-base)" export PATH="$PATH:${base_path}/bin" } diff --git a/scripts/build/p-bitwuzla-osx.inc b/scripts/build/p-bitwuzla-osx.inc index af4cc8f651..27df98058e 100644 --- a/scripts/build/p-bitwuzla-osx.inc +++ b/scripts/build/p-bitwuzla-osx.inc @@ -7,8 +7,8 @@ install_build_dependencies_bitwuzla() { git pkg-config ) - brew install "${dependencies[@]}" - with_sudo pip3 install --user meson + brew install "${dependencies[@]}" + pip3 install --user meson base_path="$(python3 -m site --user-base)" export PATH="$PATH:${base_path}/bin" } From c71b0d38fc83757e9b44bb6846ae639cfa1327d5 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Wed, 22 Nov 2023 04:52:05 +0400 Subject: [PATCH 087/120] [fix] Preserve `floatReplacements` --- lib/Core/Executor.cpp | 4 ++++ test/Floats/copysign.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index 36d82de01d..90a1fe07f9 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -609,6 +609,10 @@ llvm::Module *Executor::setModule( preservedFunctions.push_back("memcmp"); preservedFunctions.push_back("memmove"); + for (const auto &p : klee::floatReplacements) { + preservedFunctions.push_back(p.second.c_str()); + } + if (FunctionCallReproduce != "") { preservedFunctions.push_back(FunctionCallReproduce.c_str()); } diff --git a/test/Floats/copysign.c b/test/Floats/copysign.c index 03f3cb4851..80a5921322 100644 --- a/test/Floats/copysign.c +++ b/test/Floats/copysign.c @@ -16,4 +16,4 @@ int main() { return 2; } } -// CHECK: KLEE: done: completed paths = 4 +// CHECK: KLEE: done: completed paths = {{4|6}} From 218f70d474d65883d90590fd7936010e2e13c453 Mon Sep 17 00:00:00 2001 From: Aleksei Babushkin Date: Tue, 21 Nov 2023 19:40:42 +0300 Subject: [PATCH 088/120] [feat] Add new memory usage checks --- lib/Core/ExecutionState.cpp | 2 ++ lib/Core/ExecutionState.h | 3 +++ lib/Core/Executor.cpp | 40 ++++++++++++++++++++++++++++++++++++- lib/Core/Executor.h | 3 +++ lib/Core/Memory.h | 4 ++++ 5 files changed, 51 insertions(+), 1 deletion(-) diff --git a/lib/Core/ExecutionState.cpp b/lib/Core/ExecutionState.cpp index 8227e81436..6c5d4f9128 100644 --- a/lib/Core/ExecutionState.cpp +++ b/lib/Core/ExecutionState.cpp @@ -75,6 +75,7 @@ void ExecutionStack::pushFrame(KInstIterator caller, KFunction *kf) { ++stackBalance; assert(valueStack_.size() == callStack_.size()); assert(valueStack_.size() == infoStack_.size()); + stackSize += kf->getNumRegisters(); } void ExecutionStack::popFrame() { @@ -94,6 +95,7 @@ void ExecutionStack::popFrame() { --stackBalance; assert(valueStack_.size() == callStack_.size()); assert(valueStack_.size() == infoStack_.size()); + stackSize -= kf->getNumRegisters(); } bool CallStackFrame::equals(const CallStackFrame &other) const { diff --git a/lib/Core/ExecutionState.h b/lib/Core/ExecutionState.h index 9e74c4ef37..80211f8175 100644 --- a/lib/Core/ExecutionState.h +++ b/lib/Core/ExecutionState.h @@ -37,6 +37,7 @@ DISABLE_WARNING_DEPRECATED_DECLARATIONS #include "llvm/IR/Function.h" DISABLE_WARNING_POP +#include #include #include #include @@ -119,6 +120,7 @@ struct ExecutionStack { call_stack_ty callStack_; info_stack_ty infoStack_; call_stack_ty uniqueFrames_; + size_t stackSize = 0; unsigned stackBalance = 0; public: @@ -133,6 +135,7 @@ struct ExecutionStack { inline const call_stack_ty &uniqueFrames() const { return uniqueFrames_; } inline unsigned size() const { return callStack_.size(); } + inline size_t stackRegisterSize() const { return stackSize; } inline bool empty() const { return callStack_.empty(); } }; diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index 90a1fe07f9..06c4379936 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -170,6 +170,17 @@ cl::opt "and return null (default=false)"), cl::cat(ExecCat)); +cl::opt OSCopySizeMemoryCheckThreshold( + "os-copy-size-mem-check-threshold", cl::init(100000), + cl::desc("Check memory usage when this amount of bytes dense OS is copied"), + cl::cat(ExecCat)); + +cl::opt StackCopySizeMemoryCheckThreshold( + "stack-copy-size-mem-check-threshold", cl::init(100000), + cl::desc("Check memory usage when state with stack this big (in bytes) is " + "copied"), + cl::cat(ExecCat)); + enum class MockMutableGlobalsPolicy { None, PrimitiveFields, @@ -2651,6 +2662,12 @@ void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) { Executor::StatePair branches = fork(state, cond, ifTrueBlock, ifFalseBlock, BranchType::Conditional); + if (branches.first && branches.second) { + maxNewStateStackSize = + std::max(maxNewStateStackSize, + branches.first->stack.stackRegisterSize() * 8); + } + // NOTE: There is a hidden dependency here, markBranchVisited // requires that we still be in the context of the branch // instruction (it reuses its statistic id). Should be cleaned @@ -4173,7 +4190,10 @@ bool Executor::checkMemoryUsage() { // We need to avoid calling GetTotalMallocUsage() often because it // is O(elts on freelist). This is really bad since we start // to pummel the freelist once we hit the memory cap. - if ((stats::instructions & 0xFFFFU) != 0) // every 65536 instructions + // every 65536 instructions + if ((stats::instructions & 0xFFFFU) != 0 && + maxNewWriteableOSSize < OSCopySizeMemoryCheckThreshold && + maxNewStateStackSize < StackCopySizeMemoryCheckThreshold) return true; // check memory limit @@ -4511,6 +4531,8 @@ void Executor::executeStep(ExecutionState &state) { terminateStateEarly(state, "max-cycles exceeded.", StateTerminationType::MaxCycles); } else { + maxNewWriteableOSSize = 0; + maxNewStateStackSize = 0; KInstruction *ki = state.pc; stepInstruction(state); executeInstruction(state, ki); @@ -6019,6 +6041,8 @@ void Executor::collectReads( !targetType->getRawType()->isPointerTy()) { result = makeMockValue(state, "mockGlobalValue", result->getWidth()); ObjectState *wos = state.addressSpace.getWriteable(mo, os); + maxNewWriteableOSSize = + std::max(maxNewWriteableOSSize, wos->getSparseStorageEntries()); wos->write(mo->getOffsetExpr(address), result); } @@ -6168,6 +6192,8 @@ void Executor::executeMemoryOperation( state->addPointerResolution(address, mo); if (isWrite) { ObjectState *wos = state->addressSpace.getWriteable(mo, os); + maxNewWriteableOSSize = + std::max(maxNewWriteableOSSize, wos->getSparseStorageEntries()); wos->getDynamicType()->handleMemoryAccess( targetType, mo->getOffsetExpr(address), ConstantExpr::alloc(size, Context::get().getPointerWidth()), true); @@ -6193,6 +6219,8 @@ void Executor::executeMemoryOperation( !targetType->getRawType()->isPointerTy()) { result = makeMockValue(*state, "mockGlobalValue", result->getWidth()); ObjectState *wos = state->addressSpace.getWriteable(mo, os); + maxNewWriteableOSSize = + std::max(maxNewWriteableOSSize, wos->getSparseStorageEntries()); wos->write(mo->getOffsetExpr(address), result); } @@ -6288,6 +6316,8 @@ void Executor::executeMemoryOperation( const ObjectState *os = op.second; ObjectState *wos = state->addressSpace.getWriteable(mo, os); + maxNewWriteableOSSize = + std::max(maxNewWriteableOSSize, wos->getSparseStorageEntries()); if (wos->readOnly) { branches = forkInternal(*state, Expr::createIsZero(unboundConditions[i]), @@ -6357,6 +6387,8 @@ void Executor::executeMemoryOperation( if (isWrite) { ObjectState *wos = bound->addressSpace.getWriteable(mo, os); + maxNewWriteableOSSize = + std::max(maxNewWriteableOSSize, wos->getSparseStorageEntries()); wos->getDynamicType()->handleMemoryAccess( targetType, mo->getOffsetExpr(address), ConstantExpr::alloc(size, Context::get().getPointerWidth()), true); @@ -6379,6 +6411,8 @@ void Executor::executeMemoryOperation( !targetType->getRawType()->isPointerTy()) { result = makeMockValue(*bound, "mockGlobalValue", result->getWidth()); ObjectState *wos = bound->addressSpace.getWriteable(mo, os); + maxNewWriteableOSSize = + std::max(maxNewWriteableOSSize, wos->getSparseStorageEntries()); wos->write(mo->getOffsetExpr(address), result); } @@ -6568,6 +6602,8 @@ void Executor::updateStateWithSymcretes(ExecutionState &state, auto wos = new ObjectState( *(state.addressSpace.getWriteable(op.first, op.second))); + maxNewWriteableOSSize = + std::max(maxNewWriteableOSSize, wos->getSparseStorageEntries()); wos->swapObjectHack(newMO); state.addressSpace.unbindObject(op.first); state.addressSpace.bindObject(newMO, wos); @@ -7408,6 +7444,8 @@ void Executor::doImpliedValueConcretization(ExecutionState &state, ref e, assert(!os->readOnly && "not possible? read only object with static read?"); ObjectState *wos = state.addressSpace.getWriteable(mo, os); + maxNewWriteableOSSize = + std::max(maxNewWriteableOSSize, wos->getSparseStorageEntries()); wos->write(CE, it->second); } } diff --git a/lib/Core/Executor.h b/lib/Core/Executor.h index a1a1e3c380..1a55ee4d5e 100644 --- a/lib/Core/Executor.h +++ b/lib/Core/Executor.h @@ -123,6 +123,9 @@ class Executor : public Interpreter { private: int *errno_addr; + size_t maxNewWriteableOSSize = 0; + size_t maxNewStateStackSize = 0; + 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/Memory.h b/lib/Core/Memory.h index 7b072ddcf1..6d3bb3b987 100644 --- a/lib/Core/Memory.h +++ b/lib/Core/Memory.h @@ -246,6 +246,10 @@ class ObjectState { void setReadOnly(bool ro) { readOnly = ro; } + size_t getSparseStorageEntries() { + return knownSymbolics.storage().size() + unflushedMask.storage().size(); + } + void swapObjectHack(MemoryObject *mo) { object = mo; } ref read(ref offset, Expr::Width width) const; From e100a787312ee66872eb3ee89116861575fdde3c Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Wed, 22 Nov 2023 23:28:48 +0400 Subject: [PATCH 089/120] [chore] Update options default values --- lib/Core/Executor.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index 06c4379936..9d3c39eb64 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -171,12 +171,12 @@ cl::opt cl::cat(ExecCat)); cl::opt OSCopySizeMemoryCheckThreshold( - "os-copy-size-mem-check-threshold", cl::init(100000), + "os-copy-size-mem-check-threshold", cl::init(10000), cl::desc("Check memory usage when this amount of bytes dense OS is copied"), cl::cat(ExecCat)); cl::opt StackCopySizeMemoryCheckThreshold( - "stack-copy-size-mem-check-threshold", cl::init(100000), + "stack-copy-size-mem-check-threshold", cl::init(10000), cl::desc("Check memory usage when state with stack this big (in bytes) is " "copied"), cl::cat(ExecCat)); From 88975c2d8821683892809dde91d187301e1cd661 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Wed, 22 Nov 2023 23:53:45 +0400 Subject: [PATCH 090/120] [fix] Continue searching for the error if the state is not reproducible --- lib/Core/ExecutionState.h | 2 +- lib/Core/Executor.cpp | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/lib/Core/ExecutionState.h b/lib/Core/ExecutionState.h index 80211f8175..74ba2c67d4 100644 --- a/lib/Core/ExecutionState.h +++ b/lib/Core/ExecutionState.h @@ -380,7 +380,7 @@ class ExecutionState { ExprHashMap, llvm::Type *>> gepExprBases; - ReachWithError error = ReachWithError::None; + mutable ReachWithError error = ReachWithError::None; std::atomic terminationReasonType{ HaltExecution::NotHalt}; diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index 9d3c39eb64..ba3e5b53f2 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -7290,6 +7290,13 @@ Assignment Executor::computeConcretization(const ConstraintSet &constraints, bool isReproducible(const klee::Symbolic &symb) { auto arr = symb.array; bool bad = IrreproducibleSource::classof(arr->source.get()); + if (auto liSource = dyn_cast(arr->source.get())) { + std::vector arrays; + findObjects(liSource->pointer, arrays); + for (auto innerArr : arrays) { + bad |= IrreproducibleSource::classof(innerArr->source.get()); + } + } if (bad) klee_warning_once(arr->source.get(), "A irreproducible symbolic %s reaches a test", @@ -7359,6 +7366,13 @@ bool Executor::getSymbolicSolution(const ExecutionState &state, KTest &res) { std::copy_if(state.symbolics.begin(), state.symbolics.end(), std::back_inserter(symbolics), isReproducible); + // we cannot be sure that an irreproducible state proves the presence of an + // error + if (allObjects.size() != uninitObjects.size() || + state.symbolics.size() != symbolics.size()) { + state.error = ReachWithError::None; + } + std::vector> values; std::vector objects; for (auto &symbolic : symbolics) { From cab6da9ff07aea45f6321e3519469a232e1af461 Mon Sep 17 00:00:00 2001 From: Sergey Morozov Date: Wed, 22 Nov 2023 19:59:03 +0300 Subject: [PATCH 091/120] [feat] Added flag to dump all states if function specified in function-call-reproduce has not been reached. --- include/klee/Core/Interpreter.h | 2 ++ include/klee/Core/TerminationTypes.h | 1 + lib/Core/Executor.cpp | 33 ++++++++++++++----- lib/Core/Executor.h | 2 ++ scripts/kleef | 5 +-- test/Feature/CoverOnTheFly.c | 4 +-- test/Feature/DumpStatesOnHalt.c | 2 +- ...ChenFlurMukhopadhyay-2012SAS-Fig1-alloca.c | 2 +- .../CoverageBranches/CostasArray-17.c | 4 +-- .../CoverageBranches/egcd3-ll_valuebound10.c | 2 +- test/Industry/CoverageBranches/matrix-2-2.c | 2 +- ...r.3.ufo.UNBOUNDED.pals+Problem12_label00.c | 2 +- test/Industry/egcd3-ll_valuebound10.c | 2 +- test/Industry/ll_create_rec-alloca-2.c | 4 +-- ...or2c-lazyMod.adding.1.prop1-back-serstep.c | 2 +- .../pals_floodmax.5.2.ufo.BOUNDED-10.pals.c | 2 +- test/Solver/sina2f.c | 2 +- .../2020-02-24-count-paths-nodump.c | 4 +-- test/regression/2023-10-06-Dubois-015.c | 2 +- test/regression/2023-10-13-kbfiltr.i.cil-2.c | 2 +- tools/klee/main.cpp | 6 +++- 21 files changed, 57 insertions(+), 30 deletions(-) diff --git a/include/klee/Core/Interpreter.h b/include/klee/Core/Interpreter.h index 766380b486..43280ff28f 100644 --- a/include/klee/Core/Interpreter.h +++ b/include/klee/Core/Interpreter.h @@ -177,6 +177,8 @@ class Interpreter { virtual void setHaltExecution(HaltExecution::Reason value) = 0; + virtual HaltExecution::Reason getHaltExecution() = 0; + virtual void setInhibitForking(bool value) = 0; virtual void prepareForEarlyExit() = 0; diff --git a/include/klee/Core/TerminationTypes.h b/include/klee/Core/TerminationTypes.h index 786cf610d6..a08b3585e7 100644 --- a/include/klee/Core/TerminationTypes.h +++ b/include/klee/Core/TerminationTypes.h @@ -97,6 +97,7 @@ enum Reason { CovCheck, NoMoreStates, ReachedTarget, + UnreachedTarget, ErrorOnWhichShouldExit, Interrupt, MaxDepth, diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index ba3e5b53f2..8fab82715d 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -238,17 +238,24 @@ llvm::cl::opt X86FPAsX87FP80( cl::desc("Convert X86 fp values to X87FP80 during computation according to " "GCC behavior (default=false)"), cl::cat(ExecCat)); + +cl::opt DumpStatesOnHalt( + "dump-states-on-halt", cl::init(HaltExecution::Reason::Unspecified), + cl::values( + clEnumValN(HaltExecution::Reason::NotHalt, "none", + "Do not dump test cases for all active states on exit."), + clEnumValN(HaltExecution::Reason::UnreachedTarget, "unreached", + "Dump test cases for all active states on exit if error not " + "reached."), + clEnumValN(HaltExecution::Reason::Unspecified, "all", + "Dump test cases for all active states on exit (default)")), + cl::cat(TestGenCat)); } // namespace klee namespace { /*** Test generation options ***/ -cl::opt DumpStatesOnHalt( - "dump-states-on-halt", cl::init(true), - cl::desc("Dump test cases for all active states on exit (default=true)"), - cl::cat(TestGenCat)); - cl::opt OnlyOutputStatesCoveringNew( "only-output-states-covering-new", cl::init(false), cl::desc("Only output test cases covering new code (default=false)"), @@ -4259,11 +4266,19 @@ void Executor::decreaseConfidenceFromStoppedStates( } void Executor::doDumpStates() { - if (!DumpStatesOnHalt || states.empty()) { + if (DumpStatesOnHalt == HaltExecution::Reason::NotHalt || + (DumpStatesOnHalt == HaltExecution::Reason::UnreachedTarget && + haltExecution == HaltExecution::Reason::ReachedTarget) || + states.empty()) { interpreterHandler->incPathsExplored(states.size()); return; } + if (FunctionCallReproduce != "" && + haltExecution != HaltExecution::Reason::ReachedTarget) { + haltExecution = HaltExecution::UnreachedTarget; + } + klee_message("halting execution, dumping remaining states"); for (const auto &state : pausedStates) terminateStateEarly(*state, "Execution halting (paused state).", @@ -7368,9 +7383,11 @@ bool Executor::getSymbolicSolution(const ExecutionState &state, KTest &res) { // we cannot be sure that an irreproducible state proves the presence of an // error - if (allObjects.size() != uninitObjects.size() || - state.symbolics.size() != symbolics.size()) { + if (uninitObjects.size() > 0 || state.symbolics.size() != symbolics.size()) { state.error = ReachWithError::None; + } else if (FunctionCallReproduce != "" && + state.error == ReachWithError::Reachable) { + setHaltExecution(HaltExecution::ReachedTarget); } std::vector> values; diff --git a/lib/Core/Executor.h b/lib/Core/Executor.h index 1a55ee4d5e..0f8d8eaf69 100644 --- a/lib/Core/Executor.h +++ b/lib/Core/Executor.h @@ -782,6 +782,8 @@ class Executor : public Interpreter { haltExecution = value; } + HaltExecution::Reason getHaltExecution() override { return haltExecution; } + void setInhibitForking(bool value) override { inhibitForking = value; } void prepareForEarlyExit() override; diff --git a/scripts/kleef b/scripts/kleef index 35f0e4ac65..160d723fba 100755 --- a/scripts/kleef +++ b/scripts/kleef @@ -74,9 +74,10 @@ def klee_options( cmd += [ "--use-alpha-equivalence=false", "--function-call-reproduce=reach_error", + "--dump-states-on-halt-with-function-call-reproduce", # "--max-cycles=0", # "--tc-type=bug", - "--dump-states-on-halt=false", # Explicitly do not dump states + "--dump-states-on-halt=unreached", # 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", @@ -99,7 +100,7 @@ def klee_options( "--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 + "--dump-states-on-halt=all", # Check in case we missed some oncovered instructions "--search=dfs", "--search=random-state", ] diff --git a/test/Feature/CoverOnTheFly.c b/test/Feature/CoverOnTheFly.c index 37e4381614..73bd550f2c 100644 --- a/test/Feature/CoverOnTheFly.c +++ b/test/Feature/CoverOnTheFly.c @@ -1,8 +1,8 @@ -// ASAN fails because KLEE does not cleanup states with -dump-states-on-halt=false +// ASAN fails because KLEE does not cleanup states with -dump-states-on-halt=none // 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 --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 +// RUN: %klee --only-output-states-covering-new --max-instructions=2000 --timer-interval=1ms --delay-cover-on-the-fly=1ms --dump-states-on-halt=none --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" diff --git a/test/Feature/DumpStatesOnHalt.c b/test/Feature/DumpStatesOnHalt.c index aca8d7c810..9bda0cb83a 100644 --- a/test/Feature/DumpStatesOnHalt.c +++ b/test/Feature/DumpStatesOnHalt.c @@ -1,6 +1,6 @@ // RUN: %clang %s -g -emit-llvm %O0opt -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --max-instructions=1 --dump-states-on-halt=true %t1.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --max-instructions=1 --dump-states-on-halt=all %t1.bc 2>&1 | FileCheck %s // RUN: test -f %t.klee-out/test000001.ktest int main(int argc, char **argv) { diff --git a/test/Industry/CoverageBranches/ChenFlurMukhopadhyay-2012SAS-Fig1-alloca.c b/test/Industry/CoverageBranches/ChenFlurMukhopadhyay-2012SAS-Fig1-alloca.c index 99f638327a..fff21e4d2b 100644 --- a/test/Industry/CoverageBranches/ChenFlurMukhopadhyay-2012SAS-Fig1-alloca.c +++ b/test/Industry/CoverageBranches/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-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: %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=all %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 diff --git a/test/Industry/CoverageBranches/CostasArray-17.c b/test/Industry/CoverageBranches/CostasArray-17.c index 088a33fbb0..6f2bcea325 100644 --- a/test/Industry/CoverageBranches/CostasArray-17.c +++ b/test/Industry/CoverageBranches/CostasArray-17.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-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 --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=all --search=dfs %t1.bc // RUN: rm -f %t*.gcda %t*.gcno %t*.gcov // RUN: %cc -DGCOV %s %libkleeruntest -Wl,-rpath %libkleeruntestdir -o %t_runner --coverage @@ -10,7 +10,7 @@ // 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 --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=all --search=dfs %t1.bc // RUN: rm -f %t*.gcda %t*.gcno %t*.gcov // RUN: %cc -DGCOV %s %libkleeruntest -Wl,-rpath %libkleeruntestdir -o %t_runner --coverage diff --git a/test/Industry/CoverageBranches/egcd3-ll_valuebound10.c b/test/Industry/CoverageBranches/egcd3-ll_valuebound10.c index d5405512d8..9d433194b3 100644 --- a/test/Industry/CoverageBranches/egcd3-ll_valuebound10.c +++ b/test/Industry/CoverageBranches/egcd3-ll_valuebound10.c @@ -1,6 +1,6 @@ // 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 --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=all --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 diff --git a/test/Industry/CoverageBranches/matrix-2-2.c b/test/Industry/CoverageBranches/matrix-2-2.c index d25bd92255..6170da72fe 100644 --- a/test/Industry/CoverageBranches/matrix-2-2.c +++ b/test/Industry/CoverageBranches/matrix-2-2.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-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: %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=all --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 diff --git a/test/Industry/CoverageBranches/pals_lcr.3.ufo.UNBOUNDED.pals+Problem12_label00.c b/test/Industry/CoverageBranches/pals_lcr.3.ufo.UNBOUNDED.pals+Problem12_label00.c index 2b7a4dd7e1..c1fc602469 100644 --- a/test/Industry/CoverageBranches/pals_lcr.3.ufo.UNBOUNDED.pals+Problem12_label00.c +++ b/test/Industry/CoverageBranches/pals_lcr.3.ufo.UNBOUNDED.pals+Problem12_label00.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 --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 --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=all --search=dfs --search=random-state --use-iterative-deepening-search=max-cycles --max-cycles=4 %t1.bc // RUN: rm -f %t*.gcda %t*.gcno %t*.gcov // RUN: %cc -DGCOV %s %libkleeruntest -Wl,-rpath %libkleeruntestdir -o %t_runner --coverage diff --git a/test/Industry/egcd3-ll_valuebound10.c b/test/Industry/egcd3-ll_valuebound10.c index cf89ea4af7..5811f1f44d 100644 --- a/test/Industry/egcd3-ll_valuebound10.c +++ b/test/Industry/egcd3-ll_valuebound10.c @@ -1,7 +1,7 @@ // 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 --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=all --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 diff --git a/test/Industry/ll_create_rec-alloca-2.c b/test/Industry/ll_create_rec-alloca-2.c index a91b65235c..27b037bf35 100644 --- a/test/Industry/ll_create_rec-alloca-2.c +++ b/test/Industry/ll_create_rec-alloca-2.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 --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 --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=all --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 @@ -9,7 +9,7 @@ // 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 --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=all --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 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 6048923249..19bcbffe5e 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 @@ -2,7 +2,7 @@ // 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 -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=none -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/Solver/pals_floodmax.5.2.ufo.BOUNDED-10.pals.c b/test/Solver/pals_floodmax.5.2.ufo.BOUNDED-10.pals.c index 4341173c1d..fb8ace55c5 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 --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 +// 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=all -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/Solver/sina2f.c b/test/Solver/sina2f.c index fb7179d785..628a8e0e8b 100644 --- a/test/Solver/sina2f.c +++ b/test/Solver/sina2f.c @@ -3,7 +3,7 @@ // REQUIRES: not-msan // RUN: %clang %s -emit-llvm %O0opt -g -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --strip-unwanted-calls --delete-dead-loops=false --emit-all-errors --mock-all-externals --use-forked-solver=false --solver-backend=bitwuzla-tree --max-solvers-approx-tree-inc=16 --max-memory=6008 --optimize --skip-not-lazy-initialized --output-source=false --output-stats=false --output-istats=false --use-sym-size-alloc=true --cex-cache-validity-cores --fp-runtime --x86FP-as-x87FP80 --symbolic-allocation-threshold=8192 --allocate-determ --allocate-determ-size=3072 --allocate-determ-start-address=0x00030000000 --mem-trigger-cof --use-alpha-equivalence=true --track-coverage=all --use-iterative-deepening-search=max-cycles --max-solver-time=5s --max-cycles-before-stuck=15 --only-output-states-covering-new --dump-states-on-halt=true --search=dfs --search=random-state --cover-on-the-fly=true --delay-cover-on-the-fly=27 --max-time=29 %t1.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --strip-unwanted-calls --delete-dead-loops=false --emit-all-errors --mock-all-externals --use-forked-solver=false --solver-backend=bitwuzla-tree --max-solvers-approx-tree-inc=16 --max-memory=6008 --optimize --skip-not-lazy-initialized --output-source=false --output-stats=false --output-istats=false --use-sym-size-alloc=true --cex-cache-validity-cores --fp-runtime --x86FP-as-x87FP80 --symbolic-allocation-threshold=8192 --allocate-determ --allocate-determ-size=3072 --allocate-determ-start-address=0x00030000000 --mem-trigger-cof --use-alpha-equivalence=true --track-coverage=all --use-iterative-deepening-search=max-cycles --max-solver-time=5s --max-cycles-before-stuck=15 --only-output-states-covering-new --dump-states-on-halt=all --search=dfs --search=random-state --cover-on-the-fly=true --delay-cover-on-the-fly=27 --max-time=29 %t1.bc 2>&1 | FileCheck %s #include "klee-test-comp.c" /* diff --git a/test/regression/2020-02-24-count-paths-nodump.c b/test/regression/2020-02-24-count-paths-nodump.c index c066886c20..83af8e919b 100644 --- a/test/regression/2020-02-24-count-paths-nodump.c +++ b/test/regression/2020-02-24-count-paths-nodump.c @@ -1,8 +1,8 @@ -// ASAN fails because KLEE does not cleanup states with -dump-states-on-halt=false +// ASAN fails because KLEE does not cleanup states with -dump-states-on-halt=none // REQUIRES: not-asan // RUN: %clang %s -emit-llvm %O0opt -g -c -o %t.bc // RUN: rm -rf %t.klee-out -// RUN: %klee -dump-states-on-halt=false -max-instructions=1 -output-dir=%t.klee-out %t.bc 2>&1 | FileCheck %s +// RUN: %klee -dump-states-on-halt=none -max-instructions=1 -output-dir=%t.klee-out %t.bc 2>&1 | FileCheck %s int main(int argc, char **argv) { // just do something diff --git a/test/regression/2023-10-06-Dubois-015.c b/test/regression/2023-10-06-Dubois-015.c index c782d694b5..a7917dc82d 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-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 +// 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=all --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 57a75af0b9..f65ab2393b 100644 --- a/test/regression/2023-10-13-kbfiltr.i.cil-2.c +++ b/test/regression/2023-10-13-kbfiltr.i.cil-2.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-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: %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=all --emit-all-errors=true --search=bfs %t1.bc // RUN: ls %t.klee-out | grep _1.xml | wc -l | grep 8 #include "klee-test-comp.c" diff --git a/tools/klee/main.cpp b/tools/klee/main.cpp index 766013544b..e0ec4b2092 100644 --- a/tools/klee/main.cpp +++ b/tools/klee/main.cpp @@ -369,6 +369,7 @@ cl::opt XMLMetadataProgramHash( namespace klee { extern cl::opt MaxTime; extern cl::opt FunctionCallReproduce; +extern cl::opt DumpStatesOnHalt; class ExecutionState; } // namespace klee @@ -586,7 +587,10 @@ void KleeHandler::processTestCase(const ExecutionState &state, unsigned id = ++m_numTotalTests; if (!WriteNone && (FunctionCallReproduce == "" || strcmp(suffix, "assert.err") == 0 || - strcmp(suffix, "reachable.err") == 0)) { + strcmp(suffix, "reachable.err") == 0 || + (DumpStatesOnHalt == HaltExecution::Reason::UnreachedTarget && + m_interpreter->getHaltExecution() == + HaltExecution::Reason::UnreachedTarget))) { KTest ktest; ktest.numArgs = m_argc; ktest.args = m_argv; From 241358a48f1ce50981a583f5cbce6a238279374b Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Tue, 21 Nov 2023 07:00:02 +0400 Subject: [PATCH 092/120] [chore] Update tests --- test/Floats/cast_union_loose.c | 53 ++++ test/Floats/cast_union_loose.yml | 18 ++ test/Floats/cast_union_tight.c | 46 +++ test/Floats/cast_union_tight.yml | 18 ++ test/Floats/coverage-error-call.prp | 2 + test/Floats/double_req_bl_0670.c | 279 ++++++++++++++++++ test/Floats/double_req_bl_0670.yml | 15 + .../CoverageErrorCall/btor2c-lazyMod.mul6.c | 4 +- ...or2c-lazyMod.adding.1.prop1-back-serstep.c | 2 +- 9 files changed, 434 insertions(+), 3 deletions(-) create mode 100644 test/Floats/cast_union_loose.c create mode 100644 test/Floats/cast_union_loose.yml create mode 100644 test/Floats/cast_union_tight.c create mode 100644 test/Floats/cast_union_tight.yml create mode 100644 test/Floats/coverage-error-call.prp create mode 100644 test/Floats/double_req_bl_0670.c create mode 100644 test/Floats/double_req_bl_0670.yml diff --git a/test/Floats/cast_union_loose.c b/test/Floats/cast_union_loose.c new file mode 100644 index 0000000000..6dbf5c77a9 --- /dev/null +++ b/test/Floats/cast_union_loose.c @@ -0,0 +1,53 @@ +// It requires bitwuzla because the script currently runs with bitwuzla solver backend +// REQUIRES: bitwuzla +// RUN: %kleef --property-file=%S/coverage-error-call.prp --max-memory=7000000000 --max-cputime-soft=30 --32 %s + +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", "cast_union_loose.c", 3, "reach_error"); } +/* Example from "Abstract Domains for Bit-Level Machine Integer and + Floating-point Operations" by Miné, published in WING 12. +*/ + +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(); + abort(); + } + } + return; +} + +union u { + int i[2]; + double d; +}; + +double cast(int i) { + union u x, y; + x.i[0] = 0x43300000; + y.i[0] = x.i[0]; + x.i[1] = 0x80000000; + y.i[1] = i ^ x.i[1]; + return y.d - x.d; +} + +int main() { + int a; + double r; + + a = __VERIFIER_nondet_int(); + assume_abort_if_not(a >= -10000 && a <= 10000); + + r = cast(a); + __VERIFIER_assert(r >= -10000. && r <= 10000.); + return 0; +} diff --git a/test/Floats/cast_union_loose.yml b/test/Floats/cast_union_loose.yml new file mode 100644 index 0000000000..27094e3abe --- /dev/null +++ b/test/Floats/cast_union_loose.yml @@ -0,0 +1,18 @@ +format_version: '2.0' + +# old file name: cast_union_loose_false-unreach-call_true-termination.c +input_files: 'cast_union_loose.c' + +properties: + - property_file: ../properties/termination.prp + expected_verdict: true + - property_file: ../properties/unreach-call.prp + expected_verdict: false + - property_file: ../properties/coverage-error-call.prp + - property_file: ../properties/coverage-branches.prp + - property_file: ../properties/coverage-conditions.prp + - property_file: ../properties/coverage-statements.prp + +options: + language: C + data_model: ILP32 diff --git a/test/Floats/cast_union_tight.c b/test/Floats/cast_union_tight.c new file mode 100644 index 0000000000..a5f5e5fe44 --- /dev/null +++ b/test/Floats/cast_union_tight.c @@ -0,0 +1,46 @@ +// It requires bitwuzla because the script currently runs with bitwuzla solver backend +// REQUIRES: bitwuzla +// RUN: %kleef --property-file=%S/coverage-error-call.prp --max-memory=7000000000 --max-cputime-soft=30 --32 %s + +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", "cast_union_tight.c", 3, "reach_error"); } +/* Example from "Abstract Domains for Bit-Level Machine Integer and + Floating-point Operations" by Miné, published in WING 12. +*/ + +extern int __VERIFIER_nondet_int(void); +void __VERIFIER_assert(int cond) { + if (!(cond)) { + ERROR : { + reach_error(); + abort(); + } + } + return; +} + +union u { + int i[2]; + double d; +}; + +double cast(int i) { + union u x, y; + x.i[0] = 0x43300000; + y.i[0] = x.i[0]; + x.i[1] = 0x80000000; + y.i[1] = i ^ x.i[1]; + return y.d - x.d; +} + +int main() { + int a; + double r; + + a = __VERIFIER_nondet_int(); + + r = cast(a); + __VERIFIER_assert(r == a); + return 0; +} diff --git a/test/Floats/cast_union_tight.yml b/test/Floats/cast_union_tight.yml new file mode 100644 index 0000000000..7bea04b7f8 --- /dev/null +++ b/test/Floats/cast_union_tight.yml @@ -0,0 +1,18 @@ +format_version: '2.0' + +# old file name: cast_union_tight_false-unreach-call_true-termination.c +input_files: 'cast_union_tight.c' + +properties: + - property_file: ../properties/termination.prp + expected_verdict: true + - property_file: ../properties/unreach-call.prp + expected_verdict: false + - property_file: ../properties/coverage-error-call.prp + - property_file: ../properties/coverage-branches.prp + - property_file: ../properties/coverage-conditions.prp + - property_file: ../properties/coverage-statements.prp + +options: + language: C + data_model: ILP32 diff --git a/test/Floats/coverage-error-call.prp b/test/Floats/coverage-error-call.prp new file mode 100644 index 0000000000..496ed998fa --- /dev/null +++ b/test/Floats/coverage-error-call.prp @@ -0,0 +1,2 @@ +COVER( init(main()), FQL(COVER EDGES(@CALL(reach_error))) ) + diff --git a/test/Floats/double_req_bl_0670.c b/test/Floats/double_req_bl_0670.c new file mode 100644 index 0000000000..0ecac476be --- /dev/null +++ b/test/Floats/double_req_bl_0670.c @@ -0,0 +1,279 @@ +// It requires bitwuzla because the script currently runs with bitwuzla solver backend +// REQUIRES: bitwuzla +// RUN: %kleef --property-file=%S/coverage-error-call.prp --max-memory=7000000000 --max-cputime-soft=30 --32 %s + +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", "double_req_bl_0670.c", 3, "reach_error"); } +extern double __VERIFIER_nondet_double(); + +typedef int __int32_t; +typedef unsigned int __uint32_t; + +/* A union which permits us to convert between a double and two 32 bit + ints. */ +typedef union { + double value; + struct { + __uint32_t lsw; + __uint32_t msw; + } parts; +} ieee_double_shape_type; + +double fabs_double(double x) { + __uint32_t high; + do { + ieee_double_shape_type gh_u; + gh_u.value = (x); + (high) = gh_u.parts.msw; + } while (0); + do { + ieee_double_shape_type sh_u; + sh_u.value = (x); + sh_u.parts.msw = (high & 0x7fffffff); + (x) = sh_u.value; + } while (0); + return x; +} + +/* + * Preprocessed code for the function libs/newlib/math/s_atan.c + */ + +static const double atanhi_atan[] = { + 4.63647609000806093515e-01, + 7.85398163397448278999e-01, + 9.82793723247329054082e-01, + 1.57079632679489655800e+00, +}; + +static const double atanlo_atan[] = { + 2.26987774529616870924e-17, + 3.06161699786838301793e-17, + 1.39033110312309984516e-17, + 6.12323399573676603587e-17, +}; + +static const double aT_atan[] = { + 3.33333333333329318027e-01, + -1.99999999998764832476e-01, + 1.42857142725034663711e-01, + -1.11111104054623557880e-01, + 9.09088713343650656196e-02, + -7.69187620504482999495e-02, + 6.66107313738753120669e-02, + -5.83357013379057348645e-02, + 4.97687799461593236017e-02, + -3.65315727442169155270e-02, + 1.62858201153657823623e-02, +}; + +static const double one_atan = 1.0, pi_o_4 = 7.8539816339744827900E-01, + pi_o_2 = 1.5707963267948965580E+00, + pi = 3.1415926535897931160E+00, huge_atan = 1.0e300; + +double atan_double(double x) { + double w, s1, s2, z; + __int32_t ix, hx, id; + + do { + ieee_double_shape_type gh_u; + gh_u.value = (x); + (hx) = gh_u.parts.msw; + } while (0); + ix = hx & 0x7fffffff; + if (ix >= 0x44100000) { + __uint32_t low; + do { + ieee_double_shape_type gl_u; + gl_u.value = (x); + (low) = gl_u.parts.lsw; + } while (0); + if (ix > 0x7ff00000 || (ix == 0x7ff00000 && (low != 0))) + return x + x; + if (hx > 0) + return atanhi_atan[3] + atanlo_atan[3]; + else + return -atanhi_atan[3] - atanlo_atan[3]; + } + if (ix < 0x3fdc0000) { + if (ix < 0x3e200000) { + if (huge_atan + x > one_atan) + return x; + } + id = -1; + } else { + x = fabs_double(x); + if (ix < 0x3ff30000) { + if (ix < 0x3fe60000) { + id = 0; + x = (2.0 * x - one_atan) / (2.0 + x); + } else { + id = 1; + x = (x - one_atan) / (x + one_atan); + } + } else { + if (ix < 0x40038000) { + id = 2; + x = (x - 1.5) / (one_atan + 1.5 * x); + } else { + id = 3; + x = -1.0 / x; + } + } + } + + z = x * x; + w = z * z; + + s1 = z * (aT_atan[0] + + w * (aT_atan[2] + + w * (aT_atan[4] + + w * (aT_atan[6] + w * (aT_atan[8] + w * aT_atan[10]))))); + s2 = + w * + (aT_atan[1] + + w * (aT_atan[3] + w * (aT_atan[5] + w * (aT_atan[7] + w * aT_atan[9])))); + if (id < 0) + return x - x * (s1 + s2); + else { + z = atanhi_atan[id] - ((x * (s1 + s2) - atanlo_atan[id]) - x); + return (hx < 0) ? -z : z; + } +} + +/* + * Preprocessed code for the function libs/newlib/math/e_atan2.c (Constants are + * defined in requrements/includes/math_constants_double.h) + */ + +static const double tiny_atan2 = 1.0e-300, zero_atan2 = 0.0, + pi_lo_atan2 = 1.2246467991473531772E-16; + +double __ieee754_atan2(double y, double x) { + double z; + __int32_t k, m, hx, hy, ix, iy; + __uint32_t lx, ly; + + do { + ieee_double_shape_type ew_u; + ew_u.value = (x); + (hx) = ew_u.parts.msw; + (lx) = ew_u.parts.lsw; + } while (0); + ix = hx & 0x7fffffff; + do { + ieee_double_shape_type ew_u; + ew_u.value = (y); + (hy) = ew_u.parts.msw; + (ly) = ew_u.parts.lsw; + } while (0); + iy = hy & 0x7fffffff; + if (((ix | ((lx | -lx) >> 31)) > 0x7ff00000) || + ((iy | ((ly | -ly) >> 31)) > 0x7ff00000)) + return x + y; + if (((hx - 0x3ff00000) | lx) == 0) + return atan_double(y); + m = ((hy >> 31) & 1) | ((hx >> 30) & 2); + + if ((iy | ly) == 0) { + switch (m) { + case 0: + case 1: + return y; + case 2: + return pi + tiny_atan2; + case 3: + return -pi - tiny_atan2; + } + } + + if ((ix | lx) == 0) + return (hy < 0) ? -pi_o_2 - tiny_atan2 : pi_o_2 + tiny_atan2; + + if (ix == 0x7ff00000) { + if (iy == 0x7ff00000) { + switch (m) { + case 0: + return pi_o_4 + tiny_atan2; + case 1: + return -pi_o_4 - tiny_atan2; + case 2: + return 3.0 * pi_o_4 + tiny_atan2; + case 3: + return -3.0 * pi_o_4 - tiny_atan2; + } + } else { + switch (m) { + case 0: + return zero_atan2; + case 1: + return -zero_atan2; + case 2: + return pi + tiny_atan2; + case 3: + return -pi - tiny_atan2; + } + } + } + + if (iy == 0x7ff00000) + return (hy < 0) ? -pi_o_2 - tiny_atan2 : pi_o_2 + tiny_atan2; + + k = (iy - ix) >> 20; + if (k > 60) + z = pi_o_2 + 0.5 * pi_lo_atan2; + else if (hx < 0 && k < -60) + z = 0.0; + else + z = atan_double(fabs_double(y / x)); + switch (m) { + case 0: + return z; + case 1: { + __uint32_t zh; + do { + ieee_double_shape_type gh_u; + gh_u.value = (z); + (zh) = gh_u.parts.msw; + } while (0); + do { + ieee_double_shape_type sh_u; + sh_u.value = (z); + sh_u.parts.msw = (zh ^ 0x80000000); + (z) = sh_u.value; + } while (0); + } + return z; + case 2: + return pi - (z - pi_lo_atan2); + default: + return (z - pi_lo_atan2) - pi; + } +} + +// nan check for doubles +int isnan_double(double x) { return x != x; } + +int main() { + + /* REQ-BL-0670: + * The atan2 and atan2f procedures shall return NaN if any argument is NaN. + */ + + double x = __VERIFIER_nondet_double(); + double y = __VERIFIER_nondet_double(); + + if (isnan_double(x) || isnan_double(y)) { + + double res = __ieee754_atan2(y, x); + + // x is NAN, y is any or vice versa, the result shall be NAN + if (!isnan_double(res)) { + { reach_error(); } + return 1; + } + } + + return 0; +} diff --git a/test/Floats/double_req_bl_0670.yml b/test/Floats/double_req_bl_0670.yml new file mode 100644 index 0000000000..dfe3bebd6a --- /dev/null +++ b/test/Floats/double_req_bl_0670.yml @@ -0,0 +1,15 @@ +format_version: '2.0' + +# old file name: double_req_bl_0670_true-unreach-call.c +input_files: 'double_req_bl_0670.c' + +properties: + - property_file: ../properties/unreach-call.prp + expected_verdict: true + - property_file: ../properties/coverage-branches.prp + - property_file: ../properties/coverage-conditions.prp + - property_file: ../properties/coverage-statements.prp + +options: + language: C + data_model: ILP32 diff --git a/test/Industry/CoverageErrorCall/btor2c-lazyMod.mul6.c b/test/Industry/CoverageErrorCall/btor2c-lazyMod.mul6.c index f11474a141..f0261d2008 100644 --- a/test/Industry/CoverageErrorCall/btor2c-lazyMod.mul6.c +++ b/test/Industry/CoverageErrorCall/btor2c-lazyMod.mul6.c @@ -1,5 +1,5 @@ -// It requires Z3 because the script currently runs with Z3 solver backend -// REQUIRES: z3 +// It requires bitwuzla because the script currently runs with bitwuzla solver backend +// REQUIRES: bitwuzla // 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 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 19bcbffe5e..8314734367 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 @@ -2,7 +2,7 @@ // 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 -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=none -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=all -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 From 592da1c7c6197ba58e256cd58734fbbd7a6a1342 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Thu, 23 Nov 2023 05:39:44 +0400 Subject: [PATCH 093/120] [chore] Update `build.sh` --- build.sh | 2 +- scripts/kleef | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/build.sh b/build.sh index 71df1df169..24f537596b 100755 --- a/build.sh +++ b/build.sh @@ -31,7 +31,7 @@ LLVM_VERSION=14 ENABLE_OPTIMIZED=1 ENABLE_DEBUG=0 DISABLE_ASSERTIONS=1 -REQUIRES_RTTI=0 +REQUIRES_RTTI=1 ## Solvers Required options # SOLVERS=STP diff --git a/scripts/kleef b/scripts/kleef index 160d723fba..58017a8fc8 100755 --- a/scripts/kleef +++ b/scripts/kleef @@ -86,8 +86,13 @@ def klee_options( # "--target-assert", # Target ] if max_time: + max_time = float(max_time) + if max_time and int(max_time) > 30: + max_time = int(max_time * 0.99) + else: + max_time = int(max_time * 0.9) cmd += [ - f"--max-time={int(max_time)}", # Use the whole time + f"--max-time={max_time}", ] if f_cov: From 20d6e2eb4d11cebf0c014b4dc3ccdb84f226cebb Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Tue, 21 Nov 2023 04:53:53 +0400 Subject: [PATCH 094/120] [chore] Update `kleef` --- scripts/kleef | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/scripts/kleef b/scripts/kleef index 58017a8fc8..2dd0bd016d 100755 --- a/scripts/kleef +++ b/scripts/kleef @@ -22,9 +22,9 @@ def klee_options( write_ktests, ): if max_time and int(max_time) > 30: - MAX_SOLVER_TIME = 10 + MAX_SOLVER_TIME = 15 else: - MAX_SOLVER_TIME = 5 + MAX_SOLVER_TIME = 10 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 @@ -33,10 +33,11 @@ def klee_options( "--external-calls=all", "--use-forked-solver=false", # "--solver-backend=stp", - "--solver-backend=z3-tree", + # "--solver-backend=z3-tree", + "--solver-backend=bitwuzla-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", + "--libc=klee", "--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 @@ -53,7 +54,6 @@ def klee_options( # "--libc=uclibc", # "--posix-runtime", "--fp-runtime", - "--x86FP-as-x87FP80=false", # "--max-sym-array-size=4096", "--symbolic-allocation-threshold=8192", "--uninit-memory-test-multiplier=10", @@ -68,19 +68,21 @@ def klee_options( "--allocate-determ", f"--allocate-determ-size={min(int(max_memory * 0.6), 3 * 1024)}", "--allocate-determ-start-address=0x00030000000", + "--x86FP-as-x87FP80", ] if f_err: cmd += [ - "--use-alpha-equivalence=false", + "--optimize=true", + "--use-alpha-equivalence=true", "--function-call-reproduce=reach_error", - "--dump-states-on-halt-with-function-call-reproduce", # "--max-cycles=0", # "--tc-type=bug", "--dump-states-on-halt=unreached", # 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=bfs", # "--search=nurs:covnew", "--search=random-path","--search=dfs", "--use-batching-search", # "--search=distance","--search=random-path","--use-batching-search", # "--target-assert", # Target @@ -97,8 +99,10 @@ def klee_options( if f_cov: cmd += [ + "--optimize=false", "--mem-trigger-cof", # Start on the fly tests generation after approaching memory cup "--use-alpha-equivalence=true", + "--optimize-aggressive=false", "--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", @@ -273,6 +277,7 @@ class KLEEF(object): def run(self): test_output_dir = self.test_results_path / self.source.name + test_output_dir = self.test_results_path # Clean-up from previous runs if needed shutil.rmtree(test_output_dir, ignore_errors=True) From 4ab8cfa285d9f7ed52b4de34a1c79fd8a073a43b Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Sat, 9 Dec 2023 16:09:34 +0400 Subject: [PATCH 095/120] [chore] Update `differential-shellcheck.yml` --- .github/workflows/differential-shellcheck.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/differential-shellcheck.yml b/.github/workflows/differential-shellcheck.yml index 55bba98245..8595473f42 100644 --- a/.github/workflows/differential-shellcheck.yml +++ b/.github/workflows/differential-shellcheck.yml @@ -4,9 +4,9 @@ name: Differential ShellCheck on: push: - branches: [master] + branches: [main] pull_request: - branches: [master] + branches: [main] permissions: contents: read From 261d9667fe1b380d855f6ff0b3d4070930e7e4aa Mon Sep 17 00:00:00 2001 From: Sergey Morozov Date: Tue, 12 Dec 2023 15:32:24 +0300 Subject: [PATCH 096/120] [feat] Introduces KValue --- base class for all KLEEs wrappers around llvm::* structures (KInstruction, KConstant, etc.) [feat] Model unsized globals as objects of symbolic size. --- include/klee/Core/Context.h | 2 + include/klee/Expr/SourceBuilder.h | 8 +- include/klee/Expr/SymbolicSource.h | 8 +- include/klee/Module/KCallable.h | 44 ++-- include/klee/Module/KInstruction.h | 24 ++- include/klee/Module/KModule.h | 72 +++++-- include/klee/Module/KValue.h | 60 ++++++ include/klee/Module/LocationInfo.h | 2 + lib/Core/DistanceCalculator.cpp | 10 +- lib/Core/ExecutionState.cpp | 17 +- lib/Core/ExecutionState.h | 2 +- lib/Core/Executor.cpp | 203 ++++++++++-------- lib/Core/Executor.h | 14 +- lib/Core/ExecutorUtil.cpp | 158 +++++++------- lib/Core/ExternalDispatcher.cpp | 4 +- lib/Core/SpecialFunctionHandler.cpp | 12 +- lib/Core/StatsTracker.cpp | 8 +- lib/Core/TargetCalculator.cpp | 16 +- lib/Core/TargetManager.cpp | 7 +- lib/Core/TargetedExecutionManager.cpp | 12 +- lib/Expr/ExprPPrinter.cpp | 15 +- lib/Expr/Parser.cpp | 6 +- lib/Expr/Path.cpp | 2 +- lib/Expr/SourceBuilder.cpp | 3 +- lib/Expr/SymbolicSource.cpp | 8 +- lib/Module/CMakeLists.txt | 1 + lib/Module/CodeGraphInfo.cpp | 28 +-- lib/Module/KInstruction.cpp | 19 +- lib/Module/KModule.cpp | 64 +++--- lib/Module/KValue.cpp | 30 +++ lib/Module/LocationInfo.cpp | 23 ++ lib/Module/SarifReport.cpp | 4 +- lib/Solver/BitwuzlaSolver.cpp | 2 +- .../SymbolicSizes/SymbolicSizeUnsizedGlobal.c | 14 ++ 34 files changed, 579 insertions(+), 323 deletions(-) create mode 100644 include/klee/Module/KValue.h create mode 100644 lib/Module/KValue.cpp create mode 100644 test/Feature/SymbolicSizes/SymbolicSizeUnsizedGlobal.c diff --git a/include/klee/Core/Context.h b/include/klee/Core/Context.h index 64f209baaa..34298eb37e 100644 --- a/include/klee/Core/Context.h +++ b/include/klee/Core/Context.h @@ -40,6 +40,8 @@ class Context { /// Returns width of the pointer in bits Expr::Width getPointerWidth() const { return PointerWidth; } + + Expr::Width getPointerWidthInBytes() const { return PointerWidth / CHAR_BIT; } }; } // namespace klee diff --git a/include/klee/Expr/SourceBuilder.h b/include/klee/Expr/SourceBuilder.h index 6869ad0753..9a3e2035ee 100644 --- a/include/klee/Expr/SourceBuilder.h +++ b/include/klee/Expr/SourceBuilder.h @@ -1,13 +1,13 @@ #ifndef KLEE_SOURCEBUILDER_H #define KLEE_SOURCEBUILDER_H -#include "klee/ADT/Ref.h" -#include "klee/ADT/SparseStorage.h" #include "klee/Expr/SymbolicSource.h" -#include "klee/Module/KModule.h" namespace klee { +template class SparseStorage; +template class ref; + class SourceBuilder { public: SourceBuilder() = delete; @@ -18,7 +18,7 @@ class SourceBuilder { static ref uninitialized(unsigned version, const KInstruction *allocSite); static ref - symbolicSizeConstantAddress(unsigned version, const KInstruction *allocSite, + symbolicSizeConstantAddress(unsigned version, const KValue *allocSite, ref size); static ref makeSymbolic(const std::string &name, unsigned version); diff --git a/include/klee/Expr/SymbolicSource.h b/include/klee/Expr/SymbolicSource.h index 5829855543..6853e4715d 100644 --- a/include/klee/Expr/SymbolicSource.h +++ b/include/klee/Expr/SymbolicSource.h @@ -23,7 +23,9 @@ namespace klee { class Array; class Expr; class ConstantExpr; +struct KGlobalVariable; class KModule; +struct KValue; struct KInstruction; class SymbolicSource { @@ -125,10 +127,10 @@ class UninitializedSource : public SymbolicSource { class SymbolicSizeConstantAddressSource : public SymbolicSource { public: const unsigned version; - const KInstruction *allocSite; + const KValue *allocSite; ref size; - SymbolicSizeConstantAddressSource(unsigned _version, - const KInstruction *_allocSite, + + SymbolicSizeConstantAddressSource(unsigned _version, const KValue *_allocSite, ref _size) : version(_version), allocSite(_allocSite), size(_size) {} diff --git a/include/klee/Module/KCallable.h b/include/klee/Module/KCallable.h index ade28cfc82..a54a1c32dc 100644 --- a/include/klee/Module/KCallable.h +++ b/include/klee/Module/KCallable.h @@ -12,6 +12,7 @@ #include +#include "klee/Module/KValue.h" #include "klee/Support/CompilerWarning.h" DISABLE_WARNING_PUSH DISABLE_WARNING_DEPRECATED_DECLARATIONS @@ -19,57 +20,52 @@ DISABLE_WARNING_DEPRECATED_DECLARATIONS #include "llvm/IR/Function.h" #include "llvm/IR/InlineAsm.h" #include "llvm/IR/LLVMContext.h" +#include "llvm/Support/Casting.h" DISABLE_WARNING_POP namespace klee { /// Wrapper for callable objects passed in callExternalFunction -class KCallable { -public: - enum CallableKind { CK_Function, CK_InlineAsm }; - -private: - const CallableKind Kind; +class KCallable : public KValue { +protected: + KCallable(llvm::Value *value, KValue::Kind kind) : KValue(value, kind) {} public: - KCallable(CallableKind Kind) : Kind(Kind) {} - - CallableKind getKind() const { return Kind; } - - virtual llvm::StringRef getName() const = 0; virtual llvm::FunctionType *getFunctionType() const = 0; - virtual llvm::Value *getValue() = 0; - virtual ~KCallable() = default; + static bool classof(const KValue *rhs) { + return rhs->getKind() == KValue::Kind::FUNCTION || + rhs->getKind() == KValue::Kind::INLINE_ASM; + } }; class KInlineAsm : public KCallable { private: + /* Prepared name of ASM code */ + std::string name; + static unsigned getFreshAsmId() { static unsigned globalId = 0; return globalId++; } - llvm::InlineAsm *value; - std::string name; - public: - KInlineAsm(llvm::InlineAsm *value) - : KCallable(CK_InlineAsm), value(value), + KInlineAsm(llvm::InlineAsm *inlineAsm) + : KCallable(inlineAsm, KValue::Kind::INLINE_ASM), name("__asm__" + llvm::Twine(getFreshAsmId()).str()) {} llvm::StringRef getName() const override { return name; } llvm::FunctionType *getFunctionType() const override { - return value->getFunctionType(); + return inlineAsm()->getFunctionType(); } - llvm::Value *getValue() override { return value; } - - static bool classof(const KCallable *callable) { - return callable->getKind() == CK_InlineAsm; + static bool classof(const KValue *rhs) { + return rhs->getKind() == KValue::Kind::INLINE_ASM; } - llvm::InlineAsm *getInlineAsm() { return value; } + [[nodiscard]] llvm::InlineAsm *inlineAsm() const { + return llvm::dyn_cast(value); + } }; } // namespace klee diff --git a/include/klee/Module/KInstruction.h b/include/klee/Module/KInstruction.h index a4ee2c9c44..872f433d63 100644 --- a/include/klee/Module/KInstruction.h +++ b/include/klee/Module/KInstruction.h @@ -11,6 +11,8 @@ #define KLEE_KINSTRUCTION_H #include "KModule.h" +#include "KValue.h" + #include "klee/Config/Version.h" #include "klee/Support/CompilerWarning.h" #include "llvm/IR/Argument.h" @@ -37,7 +39,7 @@ static const unsigned MAGIC_HASH_CONSTANT = 39; /// KInstruction - Intermediate instruction representation used /// during execution. -struct KInstruction { +struct KInstruction : public KValue { struct Index { unsigned long instID; @@ -66,7 +68,9 @@ struct KInstruction { } }; - llvm::Instruction *inst; + llvm::Instruction *inst() const { + return llvm::dyn_cast_or_null(value); + } /// Value numbers for each operand. -1 is an invalid value, /// otherwise negative numbers are indices (negated and offset by @@ -113,14 +117,24 @@ struct KInstruction { [[nodiscard]] inline KFunction *getKFunction() const { return getKBlock()->parent; } - bool operator<(const KInstruction &other) const { - return getID() < other.getID(); + + [[nodiscard]] bool operator<(const KValue &rhs) const override { + if (getKind() == rhs.getKind()) { + return getID() < cast(rhs).getID(); + } else { + return getKind() < rhs.getKind(); + } } + [[nodiscard]] inline KModule *getKModule() const { return getKFunction()->parent; } - unsigned hash() const { return getID().hash(); } + [[nodiscard]] unsigned hash() const override { return getID().hash(); } + + static bool classof(const KValue *rhs) { + return rhs->getKind() == Kind::INSTRUCTION; + } }; struct KGEPInstruction : KInstruction { diff --git a/include/klee/Module/KModule.h b/include/klee/Module/KModule.h index dfd00c101f..388cd73b14 100644 --- a/include/klee/Module/KModule.h +++ b/include/klee/Module/KModule.h @@ -13,12 +13,14 @@ #include "klee/Config/Version.h" #include "klee/Core/Interpreter.h" #include "klee/Module/KCallable.h" +#include "klee/Module/KValue.h" #include "klee/Support/CompilerWarning.h" DISABLE_WARNING_PUSH DISABLE_WARNING_DEPRECATED_DECLARATIONS #include "llvm/ADT/ArrayRef.h" #include "llvm/IR/CFG.h" +#include "llvm/Support/Casting.h" DISABLE_WARNING_POP #include @@ -57,11 +59,14 @@ template class ref; enum KBlockType { Base, Call, Return }; -struct KBlock { +struct KBlock : public KValue { KFunction *parent; - llvm::BasicBlock *basicBlock; KInstruction **instructions; + [[nodiscard]] llvm::BasicBlock *basicBlock() const { + return llvm::dyn_cast_or_null(value); + } + public: KBlock(KFunction *, llvm::BasicBlock *, KModule *, const std::unordered_map &, @@ -74,7 +79,7 @@ struct KBlock { virtual KBlockType getKBlockType() const { return KBlockType::Base; } static bool classof(const KBlock *) { return true; } - unsigned getNumInstructions() const noexcept { return basicBlock->size(); } + unsigned getNumInstructions() const noexcept { return basicBlock()->size(); } KInstruction *getFirstInstruction() const noexcept { return instructions[0]; } KInstruction *getLastInstruction() const noexcept { return instructions[getNumInstructions() - 1]; @@ -84,6 +89,10 @@ struct KBlock { /// Block number in function [[nodiscard]] uintptr_t getId() const; + + static bool classof(const KValue *rhs) { + return rhs->getKind() == Kind::BLOCK ? classof(cast(rhs)) : false; + } }; typedef std::function KBlockPredicate; @@ -107,6 +116,10 @@ struct KCallBlock : KBlock { bool internal() const; bool kleeHandled() const; KFunction *getKFunction() const; + + static bool classof(const KValue *rhs) { + return rhs->getKind() == Kind::BLOCK ? classof(cast(rhs)) : false; + } }; struct KReturnBlock : KBlock { @@ -120,6 +133,10 @@ struct KReturnBlock : KBlock { return E->getKBlockType() == KBlockType::Return; } KBlockType getKBlockType() const override { return KBlockType::Return; }; + + static bool classof(const KValue *rhs) { + return rhs->getKind() == Kind::BLOCK ? classof(cast(rhs)) : false; + } }; struct KFunction : public KCallable { @@ -129,9 +146,12 @@ struct KFunction : public KCallable { public: KModule *parent; - llvm::Function *function; KInstruction **instructions; + [[nodiscard]] llvm::Function *function() const { + return llvm::dyn_cast_or_null(value); + } + [[nodiscard]] KInstruction *getInstructionByRegister(size_t reg) const; std::unordered_map instructionMap; @@ -158,12 +178,8 @@ struct KFunction : public KCallable { unsigned getArgRegister(unsigned index) const { return index; } - llvm::StringRef getName() const override { - return function ? function->getName() : ""; - } - llvm::FunctionType *getFunctionType() const override { - return function->getFunctionType(); + return function()->getFunctionType(); } const std::unordered_map &getLabelMap() { @@ -175,10 +191,8 @@ struct KFunction : public KCallable { return labelMap; } - llvm::Value *getValue() override { return function; } - - static bool classof(const KCallable *callable) { - return callable->getKind() == CK_Function; + static bool classof(const KValue *callable) { + return callable->getKind() == KValue::Kind::FUNCTION; } [[nodiscard]] size_t getLine() const; @@ -203,10 +217,12 @@ struct KFunctionCompare { } }; -class KConstant { +struct KConstant : public KValue { public: /// Actual LLVM constant this represents. - llvm::Constant *ct; + [[nodiscard]] llvm::Constant *ct() const { + return llvm::dyn_cast_or_null(value); + }; /// The constant ID. unsigned id; @@ -216,6 +232,28 @@ class KConstant { KInstruction *ki; KConstant(llvm::Constant *, unsigned, KInstruction *); + + [[nodiscard]] static bool classof(const KValue *rhs) { + return rhs->getKind() == KValue::Kind::CONSTANT; + } +}; + +struct KGlobalVariable : public KValue { +public: + KGlobalVariable(llvm::GlobalVariable *global); + + [[nodiscard]] llvm::GlobalVariable *globalVariable() const { + return llvm::dyn_cast_or_null(value); + } + + [[nodiscard]] static bool classof(const KValue *rhs) { + return rhs->getKind() == KValue::Kind::GLOBAL_VARIABLE; + } + + // Filename where the global variable is defined + [[nodiscard]] std::string getSourceFilepath() const; + // Line number where the global variable is defined + [[nodiscard]] size_t getLine() const; }; class KModule { @@ -248,6 +286,10 @@ class KModule { constantMap; KConstant *getKConstant(const llvm::Constant *c); + std::unordered_map> + globalMap; + std::unique_ptr constantTable; // Functions which are part of KLEE runtime diff --git a/include/klee/Module/KValue.h b/include/klee/Module/KValue.h new file mode 100644 index 0000000000..1a6367fc26 --- /dev/null +++ b/include/klee/Module/KValue.h @@ -0,0 +1,60 @@ +#ifndef KVALUE_H +#define KVALUE_H + +namespace llvm { +class Value; +class StringRef; +} // namespace llvm + +namespace klee { + +struct KValue { +public: + /* Enum of kinds for llvm rtti purposes */ + enum Kind { + BLOCK, + CONSTANT, + GLOBAL_VARIABLE, + FUNCTION, + INLINE_ASM, + INSTRUCTION, + VALUE, + }; + +protected: + /* Wrapped llvm::Value */ + llvm::Value *const value; + + /* Kind of KValue required for llvm rtti purposes */ + const Kind kind; + + /* Inner constructor for setting kind */ + KValue(llvm::Value *const value, const Kind kind) + : value(value), kind(kind) {} + +public: + /* Construct KValue from raw llvm::Value. */ + KValue(llvm::Value *const value) : KValue(value, Kind::VALUE) { + /* NB: heirs of this class should use inner constructor instead. + This constructor exposes convenient public interface. */ + } + + /* Unwraps KValue to receive inner value. */ + [[nodiscard]] llvm::Value *unwrap() const; + + /* Returns name of inner value if so exists. */ + [[nodiscard]] virtual llvm::StringRef getName() const; + + [[nodiscard]] virtual bool operator<(const KValue &rhs) const; + [[nodiscard]] virtual unsigned hash() const; + + /* Kind of value. Serves for llvm rtti purposes. */ + [[nodiscard]] Kind getKind() const { return kind; } + [[nodiscard]] static bool classof(const KValue *rhs) { return true; } + + virtual ~KValue() = default; +}; + +} // namespace klee + +#endif // KVALUE_H diff --git a/include/klee/Module/LocationInfo.h b/include/klee/Module/LocationInfo.h index 36ac6bec4d..6aaa84b8a2 100644 --- a/include/klee/Module/LocationInfo.h +++ b/include/klee/Module/LocationInfo.h @@ -15,6 +15,7 @@ namespace llvm { class Function; +class GlobalVariable; class Instruction; class Module; } // namespace llvm @@ -29,6 +30,7 @@ struct LocationInfo { LocationInfo getLocationInfo(const llvm::Function *func); LocationInfo getLocationInfo(const llvm::Instruction *inst); +LocationInfo getLocationInfo(const llvm::GlobalVariable *global); } // namespace klee diff --git a/lib/Core/DistanceCalculator.cpp b/lib/Core/DistanceCalculator.cpp index 26aa37350a..c5877bb09a 100644 --- a/lib/Core/DistanceCalculator.cpp +++ b/lib/Core/DistanceCalculator.cpp @@ -106,7 +106,7 @@ DistanceResult DistanceCalculator::getDistance( unsigned int minCallWeight = UINT_MAX, minSfNum = UINT_MAX, sfNum = 0; auto sfi = frames.rbegin(), sfe = frames.rend(); bool strictlyAfterKB = - sfi != sfe && sfi->kf->parent->inMainModule(*sfi->kf->function); + sfi != sfe && sfi->kf->parent->inMainModule(*sfi->kf->function()); for (; sfi != sfe; sfi++, sfNum++) { unsigned callWeight; if (distanceInCallGraph(sfi->kf, kb, callWeight, distanceToTargetFunction, @@ -140,8 +140,8 @@ bool DistanceCalculator::distanceInCallGraph( KFunction *kf, KBlock *origKB, unsigned int &distance, const FunctionDistanceMap &distanceToTargetFunction, KBlock *targetKB, bool strictlyAfterKB) const { - auto &dist = codeGraphInfo.getDistance(origKB->basicBlock); - if (kf == targetKB->parent && dist.count(targetKB->basicBlock)) { + auto &dist = codeGraphInfo.getDistance(origKB->basicBlock()); + if (kf == targetKB->parent && dist.count(targetKB->basicBlock())) { distance = 0; return true; } @@ -149,7 +149,7 @@ bool DistanceCalculator::distanceInCallGraph( distance = UINT_MAX; bool cannotReachItself = strictlyAfterKB && !codeGraphInfo.hasCycle(origKB); for (auto kCallBlock : kf->kCallBlocks) { - if (!dist.count(kCallBlock->basicBlock) || + if (!dist.count(kCallBlock->basicBlock()) || (cannotReachItself && origKB == kCallBlock)) continue; for (auto calledFunction : kCallBlock->calledFunctions) { @@ -167,7 +167,7 @@ WeightResult DistanceCalculator::tryGetLocalWeight( const auto &dist = codeGraphInfo.getDistance(kb); weight = UINT_MAX; for (auto end : localTargets) { - auto it = dist.find(end->basicBlock); + auto it = dist.find(end->basicBlock()); if (it != dist.end()) weight = std::min(it->second, weight); } diff --git a/lib/Core/ExecutionState.cpp b/lib/Core/ExecutionState.cpp index 6c5d4f9128..1d4d06f927 100644 --- a/lib/Core/ExecutionState.cpp +++ b/lib/Core/ExecutionState.cpp @@ -208,7 +208,7 @@ ExecutionState *ExecutionState::withStackFrame(KInstIterator caller, ExecutionState *newState = new ExecutionState(*this); newState->setID(); newState->pushFrame(caller, kf); - newState->initPC = kf->blockMap[&*kf->function->begin()]->instructions; + newState->initPC = kf->blockMap[&*kf->function()->begin()]->instructions; newState->pc = newState->initPC; newState->prevPC = newState->pc; return newState; @@ -387,9 +387,9 @@ void ExecutionState::dumpStack(llvm::raw_ostream &out) const { const CallStackFrame &csf = stack.callStack().at(ri); const StackFrame &sf = stack.valueStack().at(ri); - Function *f = csf.kf->function; + Function *f = csf.kf->function(); out << "\t#" << i; - auto assemblyLine = target->getKModule()->getAsmLine(target->inst); + auto assemblyLine = target->getKModule()->getAsmLine(target->inst()); if (assemblyLine.has_value()) { std::stringstream AsmStream; AsmStream << std::setw(8) << std::setfill('0') << assemblyLine.value(); @@ -431,14 +431,16 @@ void ExecutionState::addCexPreference(const ref &cond) { } BasicBlock *ExecutionState::getInitPCBlock() const { - return initPC->inst->getParent(); + return initPC->inst()->getParent(); } BasicBlock *ExecutionState::getPrevPCBlock() const { - return prevPC->inst->getParent(); + return prevPC->inst()->getParent(); } -BasicBlock *ExecutionState::getPCBlock() const { return pc->inst->getParent(); } +BasicBlock *ExecutionState::getPCBlock() const { + return pc->inst()->getParent(); +} void ExecutionState::increaseLevel() { llvm::BasicBlock *srcbb = getPrevPCBlock(); @@ -446,7 +448,8 @@ void ExecutionState::increaseLevel() { KFunction *kf = prevPC->parent->parent; KModule *kmodule = kf->parent; - if (prevPC->inst->isTerminator() && kmodule->inMainModule(*kf->function)) { + 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(prevPC->parent); diff --git a/lib/Core/ExecutionState.h b/lib/Core/ExecutionState.h index 74ba2c67d4..dd0fd13427 100644 --- a/lib/Core/ExecutionState.h +++ b/lib/Core/ExecutionState.h @@ -498,7 +498,7 @@ class ExecutionState { inline bool isCycled(unsigned long long bound) const { if (bound == 0) return false; - if (prevPC->inst->isTerminator() && stack.size() > 0) { + 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; diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index 8fab82715d..89fe7eb2f8 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -751,7 +751,7 @@ void Executor::initializeGlobalObject(ExecutionState &state, ObjectState *os, offset + i * elementSize); } else if (!isa(c) && !isa(c)) { unsigned StoreBits = targetData->getTypeStoreSizeInBits(c->getType()); - ref C = evalConstant(c, state.roundingMode); + ref C = evalConstant(c, state.roundingMode); if (c->getType()->isFloatingPointTy() && Context::get().getPointerWidth() == 32) { @@ -762,7 +762,7 @@ void Executor::initializeGlobalObject(ExecutionState &state, ObjectState *os, // Extend the constant if necessary; assert(StoreBits >= C->getWidth() && "Invalid store size!"); if (StoreBits > C->getWidth()) - C = C->ZExt(StoreBits); + C = ZExtExpr::create(C, StoreBits); os->write(offset, C); } @@ -903,10 +903,10 @@ void Executor::allocateGlobalObjects(ExecutionState &state) { for (const GlobalVariable &v : m->globals()) { std::size_t globalObjectAlignment = getAllocationAlignment(&v); Type *ty = v.getValueType(); - std::uint64_t size = 0; + ref size = Expr::createPointer(0); if (ty->isSized()) { // size includes padding - size = kmodule->targetData->getTypeAllocSize(ty); + size = Expr::createPointer(kmodule->targetData->getTypeAllocSize(ty)); } if (v.isDeclaration()) { // FIXME: We have no general way of handling unknown external @@ -922,30 +922,33 @@ void Executor::allocateGlobalObjects(ExecutionState &state) { // XXX - DWD - hardcode some things until we decide how to fix. #ifndef WINDOWS if (v.getName() == "_ZTVN10__cxxabiv117__class_type_infoE") { - size = 0x2C; + size = Expr::createPointer(0x2C); } else if (v.getName() == "_ZTVN10__cxxabiv120__si_class_type_infoE") { - size = 0x2C; + size = Expr::createPointer(0x2C); } else if (v.getName() == "_ZTVN10__cxxabiv121__vmi_class_type_infoE") { - size = 0x2C; + size = Expr::createPointer(0x2C); } #endif - if (size == 0) { - klee_warning("Unable to find size for global variable: %.*s (use will " - "result in out of bounds access)", + if (size->isZero()) { + const Array *array = makeArray( + Expr::createPointer(Context::get().getPointerWidthInBytes()), + SourceBuilder::irreproducible(v.getName().str())); + size = Expr::createTempRead(array, Context::get().getPointerWidth()); + klee_warning("Unable to find size for global variable: %.*s (model " + "size as symbolic with irreproducible content)", static_cast(v.getName().size()), v.getName().data()); } } - MemoryObject *mo = - memory->allocate(size, /*isLocal=*/false, - /*isGlobal=*/true, false, /*allocSite=*/&v, - /*alignment=*/globalObjectAlignment); + MemoryObject *mo = allocate(state, size, /*isLocal=*/false, + /*isGlobal=*/true, /*allocSite=*/&v, + /*alignment=*/globalObjectAlignment); if (!mo) klee_error("out of memory"); globalObjects.emplace(&v, mo); - globalAddresses.emplace(&v, mo->getBaseConstantExpr()); + globalAddresses.emplace(&v, mo->getBaseExpr()); } } @@ -998,26 +1001,32 @@ void Executor::initializeGlobalObjects(ExecutionState &state) { state, mo, typeSystemManager->getWrappedType(v.getType()), false, nullptr); - if (v.isDeclaration() && mo->size) { - // Program already running -> object already initialized. - // Read concrete value and write it to our copy. - void *addr; - if (v.getName() == "__dso_handle") { - addr = &__dso_handle; // wtf ? + if (v.isDeclaration()) { + if (isa(mo->getSizeExpr())) { + // Program already running -> object already initialized. + // Read concrete value and write it to our copy. + void *addr; + if (v.getName() == "__dso_handle") { + addr = &__dso_handle; // wtf ? + } else { + addr = externalDispatcher->resolveSymbol(v.getName().str()); + } + if (MockAllExternals && !addr) { + executeMakeSymbolic( + state, mo, typeSystemManager->getWrappedType(v.getType()), + SourceBuilder::irreproducible("mockExternGlobalObject"), false); + } else if (!addr) { + klee_error("Unable to load symbol(%.*s) while initializing globals", + static_cast(v.getName().size()), v.getName().data()); + } else { + for (unsigned offset = 0; offset < mo->size; offset++) { + os->write8(offset, static_cast(addr)[offset]); + } + } } else { - addr = externalDispatcher->resolveSymbol(v.getName().str()); - } - if (MockAllExternals && !addr) { executeMakeSymbolic( state, mo, typeSystemManager->getWrappedType(v.getType()), - SourceBuilder::irreproducible("mockExternGlobalObject"), false); - } else if (!addr) { - klee_error("Unable to load symbol(%.*s) while initializing globals", - static_cast(v.getName().size()), v.getName().data()); - } else { - for (unsigned offset = 0; offset < mo->size; offset++) { - os->write8(offset, static_cast(addr)[offset]); - } + SourceBuilder::irreproducible("unsizedGlobal"), false); } } else if (v.hasInitializer()) { if (!v.isConstant() && kmodule->inMainModule(v) && @@ -1544,7 +1553,7 @@ void Executor::addConstraint(ExecutionState &state, ref condition) { const Cell &Executor::eval(const KInstruction *ki, unsigned index, ExecutionState &state, StackFrame &sf, bool isSymbolic) { - assert(index < ki->inst->getNumOperands()); + assert(index < ki->inst()->getNumOperands()); int vnumber = ki->operands[index]; assert(vnumber != -1 && @@ -1698,7 +1707,7 @@ void Executor::printDebugInstructions(ExecutionState &state) { (*stream) << " " << state.pc->getSourceLocationString() << ':'; } { - auto asmLine = state.pc->getKModule()->getAsmLine(state.pc->inst); + auto asmLine = state.pc->getKModule()->getAsmLine(state.pc->inst()); if (asmLine.has_value()) { (*stream) << asmLine.value() << ':'; } @@ -1712,7 +1721,7 @@ void Executor::printDebugInstructions(ExecutionState &state) { if (DebugPrintInstructions.isSet(STDERR_ALL) || DebugPrintInstructions.isSet(FILE_ALL)) - (*stream) << ':' << *(state.pc->inst); + (*stream) << ':' << *(state.pc->inst()); (*stream) << '\n'; @@ -1733,7 +1742,7 @@ void Executor::stepInstruction(ExecutionState &state) { ++stats::instructions; ++state.steppedInstructions; - if (isa(state.pc->inst) || isa(state.pc->inst)) { + if (isa(state.pc->inst()) || isa(state.pc->inst())) { ++state.steppedMemoryInstructions; } state.prevPC = state.pc; @@ -1783,7 +1792,11 @@ MemoryObject *Executor::serializeLandingpad(ExecutionState &state, llvm::GlobalValue *clause_type = dyn_cast(clause_bitcast->getOperand(0)); - ti_addr = globalAddresses[clause_type]->getZExtValue(); + // Since global variable may have symbolic address, + // here we must guarantee that the address of clause is + // constant (which seems to be true). + ti_addr = + cast(globalAddresses[clause_type])->getZExtValue(); } else if (current_clause->isNullValue()) { ti_addr = 0; } else { @@ -1843,8 +1856,10 @@ MemoryObject *Executor::serializeLandingpad(ExecutionState &state, return nullptr; } + // We assume again that the clause_value is a + // constant global. std::uint64_t const ti_addr = - globalAddresses[clause_value]->getZExtValue(); + cast(globalAddresses[clause_value])->getZExtValue(); const std::size_t old_size = serialized.size(); serialized.resize(old_size + 8); @@ -1888,7 +1903,7 @@ void Executor::unwindToNextLandingpad(ExecutionState &state) { for (std::size_t i = startIndex; i > lowestStackIndex; i--) { auto const &sf = state.stack.callStack().at(i); - Instruction *inst = sf.caller ? sf.caller->inst : nullptr; + Instruction *inst = sf.caller ? sf.caller->inst() : nullptr; if (popFrames) { state.popFrame(); @@ -1993,7 +2008,7 @@ ref Executor::getEhTypeidFor(ref type_info) { void Executor::executeCall(ExecutionState &state, KInstruction *ki, Function *f, std::vector> &arguments) { - Instruction *i = ki->inst; + Instruction *i = ki->inst(); if (isa_and_nonnull(i)) return; if (f && f->isDeclaration()) { @@ -2316,7 +2331,7 @@ void Executor::executeCall(ExecutionState &state, KInstruction *ki, Function *f, KFunction *kf = kmodule->functionMap[f]; state.pushFrame(state.prevPC, kf); - transferToBasicBlock(&*kf->function->begin(), state.getPrevPCBlock(), + transferToBasicBlock(&*kf->function()->begin(), state.getPrevPCBlock(), state); if (statsTracker) @@ -2401,7 +2416,7 @@ void Executor::executeCall(ExecutionState &state, KInstruction *ki, Function *f, StackFrame &sf = state.stack.valueStack().back(); MemoryObject *mo = sf.varargs = - memory->allocate(size, true, false, false, state.prevPC->inst, + memory->allocate(size, true, false, false, state.prevPC->inst(), (requires16ByteAlignment ? 16 : 8)); if (!mo && size) { terminateStateOnExecError(state, "out of memory (varargs)"); @@ -2484,8 +2499,8 @@ void Executor::transferToBasicBlock(KBlock *kdst, BasicBlock *src, // XXX this lookup has to go ? state.pc = kdst->instructions; state.increaseLevel(); - if (state.pc->inst->getOpcode() == Instruction::PHI) { - PHINode *first = static_cast(state.pc->inst); + if (state.pc->inst()->getOpcode() == Instruction::PHI) { + PHINode *first = static_cast(state.pc->inst()); state.incomingBBIndex = first->getBasicBlockIndex(src); } increaseProgressVelocity(state, kdst); @@ -2525,7 +2540,7 @@ void Executor::checkNullCheckAfterDeref(ref cond, ExecutionState &state, } void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) { - Instruction *i = ki->inst; + Instruction *i = ki->inst(); if (guidanceKind == GuidanceKind::ErrorGuidance) { for (auto kvp : state.targetForest) { @@ -2545,7 +2560,7 @@ void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) { case Instruction::Ret: { ReturnInst *ri = cast(i); KInstIterator kcaller = state.stack.callStack().back().caller; - Instruction *caller = kcaller ? kcaller->inst : nullptr; + Instruction *caller = kcaller ? kcaller->inst() : nullptr; bool isVoidReturn = (ri->getNumOperands() == 0); ref result = ConstantExpr::alloc(0, Expr::Bool); @@ -2991,7 +3006,7 @@ void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) { do { if (!first && MockExternalCalls) { free = nullptr; - if (ki->inst->getType()->isSized()) { + if (ki->inst()->getType()->isSized()) { prepareMockValue(state, "mockExternResult", ki); } } else { @@ -3280,7 +3295,7 @@ void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) { executeMemoryOperation( state, false, typeSystemManager->getWrappedType( - cast(ki->inst)->getPointerOperandType()), + cast(ki->inst())->getPointerOperandType()), base, 0, ki); break; } @@ -3290,14 +3305,15 @@ void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) { executeMemoryOperation( state, true, typeSystemManager->getWrappedType( - cast(ki->inst)->getPointerOperandType()), + cast(ki->inst())->getPointerOperandType()), base, value, ki); break; } case Instruction::GetElementPtr: { KGEPInstruction *kgepi = static_cast(ki); - GetElementPtrInst *gepInst = static_cast(kgepi->inst); + GetElementPtrInst *gepInst = + static_cast(kgepi->inst()); ref base = eval(ki, 0, state).value; ref offset = ConstantExpr::create(0, base->getWidth()); @@ -3368,7 +3384,7 @@ void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) { case Instruction::BitCast: { ref result = eval(ki, 0, state).value; - BitCastInst *bc = cast(ki->inst); + BitCastInst *bc = cast(ki->inst()); llvm::Type *castToType = bc->getType(); @@ -4129,7 +4145,7 @@ void Executor::computeOffsetsSeqTy(KGEPInstruction *kgepi, const Value *operand = it.getOperand(); if (const Constant *c = dyn_cast(operand)) { ref index = - evalConstant(c, llvm::APFloat::rmNearestTiesToEven) + cast(evalConstant(c, llvm::APFloat::rmNearestTiesToEven)) ->SExt(Context::get().getPointerWidth()); ref addend = index->Mul( ConstantExpr::alloc(elementSize, Context::get().getPointerWidth())); @@ -4161,14 +4177,14 @@ void Executor::computeOffsets(KGEPInstruction *kgepi, TypeIt ib, TypeIt ie) { } void Executor::bindInstructionConstants(KInstruction *KI) { - if (GetElementPtrInst *gepi = dyn_cast(KI->inst)) { + if (GetElementPtrInst *gepi = dyn_cast(KI->inst())) { KGEPInstruction *kgepi = static_cast(KI); computeOffsets(kgepi, gep_type_begin(gepi), gep_type_end(gepi)); - } else if (InsertValueInst *ivi = dyn_cast(KI->inst)) { + } else if (InsertValueInst *ivi = dyn_cast(KI->inst())) { KGEPInstruction *kgepi = static_cast(KI); computeOffsets(kgepi, iv_type_begin(ivi), iv_type_end(ivi)); assert(kgepi->indices.empty() && "InsertValue constant offset expected"); - } else if (ExtractValueInst *evi = dyn_cast(KI->inst)) { + } else if (ExtractValueInst *evi = dyn_cast(KI->inst())) { KGEPInstruction *kgepi = static_cast(KI); computeOffsets(kgepi, ev_type_begin(evi), ev_type_end(evi)); assert(kgepi->indices.empty() && "ExtractValue constant offset expected"); @@ -4408,7 +4424,7 @@ void Executor::reportProgressTowardsTargets(std::string prefix, repr << ": "; } repr << "in function " + - target->getBlock()->parent->function->getName().str(); + target->getBlock()->parent->function()->getName().str(); repr << " (lines "; repr << target->getBlock()->getFirstInstruction()->getLine(); repr << " to "; @@ -4784,10 +4800,10 @@ Executor::getLastNonKleeInternalInstruction(const ExecutionState &state) { itE--; const KInstruction *ki = nullptr; - if (kmodule->internalFunctions.count(it->kf->function) == 0) { + if (kmodule->internalFunctions.count(it->kf->function()) == 0) { ki = state.prevPC; // Cannot return yet because even though - // it->function is not an internal function it might of + // it->function() is not an internal function it might of // been called from an internal function. } @@ -4797,7 +4813,7 @@ Executor::getLastNonKleeInternalInstruction(const ExecutionState &state) { for (; it != itE; ++it) { // check calling instruction and if it is contained in a KLEE internal // function - const Function *f = (*it->caller).inst->getParent()->getParent(); + const Function *f = (*it->caller).inst()->getParent()->getParent(); if (kmodule->internalFunctions.count(f)) { ki = nullptr; continue; @@ -4871,7 +4887,7 @@ void Executor::terminateStateOnError(ExecutionState &state, std::string message = messaget.str(); static std::set> emittedErrors; const KInstruction *ki = getLastNonKleeInternalInstruction(state); - Instruction *lastInst = ki->inst; + Instruction *lastInst = ki->inst(); if ((EmitAllErrors || emittedErrors.insert(std::make_pair(lastInst, message)).second) && @@ -4892,7 +4908,7 @@ void Executor::terminateStateOnError(ExecutionState &state, if (!filepath.empty()) { msg << "File: " << filepath << '\n' << "Line: " << ki->getLine() << '\n'; { - auto asmLine = ki->getKModule()->getAsmLine(ki->inst); + auto asmLine = ki->getKModule()->getAsmLine(ki->inst()); if (asmLine.has_value()) { msg << "assembly.ll line: " << asmLine.value() << '\n'; } @@ -4964,7 +4980,7 @@ void Executor::callExternalFunction(ExecutionState &state, KInstruction *target, std::vector> &arguments) { // check if specialFunctionHandler wants it if (const auto *func = dyn_cast(callable)) { - if (specialFunctionHandler->handle(state, func->function, target, + if (specialFunctionHandler->handle(state, func->function(), target, arguments)) return; } @@ -4991,9 +5007,9 @@ void Executor::callExternalFunction(ExecutionState &state, KInstruction *target, if (AllExternalWarnings) klee_warning("%s", os.str().c_str()); else if (!SuppressExternalWarnings) - klee_warning_once(callable->getValue(), "%s", os.str().c_str()); + klee_warning_once(callable->unwrap(), "%s", os.str().c_str()); - if (target->inst->getType()->isSized()) { + if (target->inst()->getType()->isSized()) { prepareMockValue(state, "mockExternResult", target); } return; @@ -5102,7 +5118,7 @@ void Executor::callExternalFunction(ExecutionState &state, KInstruction *target, if (AllExternalWarnings) klee_warning("%s", os.str().c_str()); else - klee_warning_once(callable->getValue(), "%s", os.str().c_str()); + klee_warning_once(callable->unwrap(), "%s", os.str().c_str()); } int roundingMode = LLVMRoundingModeToCRoundingMode(state.roundingMode); @@ -5113,12 +5129,12 @@ void Executor::callExternalFunction(ExecutionState &state, KInstruction *target, return; } - bool success = externalDispatcher->executeCall(callable, target->inst, args, + bool success = externalDispatcher->executeCall(callable, target->inst(), args, roundingMode); if (!success) { if (MockExternalCalls) { - if (target->inst->getType()->isSized()) { + if (target->inst()->getType()->isSized()) { prepareMockValue(state, "mockExternResult", target); } } else { @@ -5142,7 +5158,7 @@ void Executor::callExternalFunction(ExecutionState &state, KInstruction *target, (uint64_t)&error, assignment); #endif - Type *resultType = target->inst->getType(); + Type *resultType = target->inst()->getType(); if (resultType != Type::getVoidTy(kmodule->module->getContext())) { ref e = ConstantExpr::fromMemory((void *)args, getWidthForLLVMType(resultType)); @@ -5219,7 +5235,7 @@ void Executor::executeAlloc(ExecutionState &state, ref size, bool isLocal, const ObjectState *reallocFrom, size_t allocationAlignment, bool checkOutOfMemory) { static unsigned allocations = 0; - const llvm::Value *allocSite = state.prevPC->inst; + const llvm::Value *allocSite = state.prevPC->inst(); if (allocationAlignment == 0) { allocationAlignment = getAllocationAlignment(allocSite); } @@ -5578,10 +5594,13 @@ MemoryObject *Executor::allocate(ExecutionState &state, ref size, Expr::Width pointerWidthInBits = Context::get().getPointerWidth(); /* Create symbol for array */ - KInstruction *ki = nullptr; + KValue *ki = nullptr; if (!lazyInitializationSource) { - auto inst = cast(allocSite); - ki = kmodule->getKBlock(inst->getParent())->parent->instructionMap[inst]; + if (auto inst = dyn_cast(allocSite)) { + ki = kmodule->getKBlock(inst->getParent())->parent->instructionMap[inst]; + } else if (auto global = dyn_cast(allocSite)) { + ki = kmodule->globalMap[global].get(); + } } const Array *addressArray = makeArray( @@ -6046,7 +6065,8 @@ void Executor::collectReads( ref result = os->read(mo->getOffsetExpr(address), type); - if (X86FPAsX87FP80 && state.prevPC->inst->getType()->isFloatingPointTy() && + if (X86FPAsX87FP80 && + state.prevPC->inst()->getType()->isFloatingPointTy() && Context::get().getPointerWidth() == 32) { result = FPToX87FP80Ext(result); } @@ -6071,7 +6091,8 @@ void Executor::executeMemoryOperation( KInstruction *target /* undef if write */) { KInstruction *ki = estate.prevPC; if (X86FPAsX87FP80 && isWrite) { - auto valueOperand = cast(ki->inst)->getValueOperand(); + auto valueOperand = + cast(ki->inst())->getValueOperand(); if (valueOperand->getType()->isFloatingPointTy() && Context::get().getPointerWidth() == 32) { value = @@ -6080,7 +6101,7 @@ void Executor::executeMemoryOperation( } } Expr::Width type = (isWrite ? value->getWidth() - : getWidthForLLVMType(target->inst->getType())); + : getWidthForLLVMType(target->inst()->getType())); unsigned bytes = Expr::getMinBytesForWidth(type); ref base = address; @@ -6221,7 +6242,7 @@ void Executor::executeMemoryOperation( } else { result = os->read(mo->getOffsetExpr(address), type); - if (X86FPAsX87FP80 && ki->inst->getType()->isFloatingPointTy() && + if (X86FPAsX87FP80 && ki->inst()->getType()->isFloatingPointTy() && Context::get().getPointerWidth() == 32) { result = FPToX87FP80Ext(result); } @@ -6416,7 +6437,7 @@ void Executor::executeMemoryOperation( } else { ref result = os->read(mo->getOffsetExpr(address), type); - if (X86FPAsX87FP80 && ki->inst->getType()->isFloatingPointTy() && + if (X86FPAsX87FP80 && ki->inst()->getType()->isFloatingPointTy() && Context::get().getPointerWidth() == 32) { result = FPToX87FP80Ext(result); } @@ -6458,7 +6479,7 @@ bool Executor::lazyInitializeObject(ExecutionState &state, ref address, KType *targetType, uint64_t size, bool isLocal, IDType &id, bool isSymbolic) { assert(!isa(address)); - const llvm::Value *allocSite = target ? target->inst : nullptr; + const llvm::Value *allocSite = target ? target->inst() : nullptr; std::pair, ref> moBasePair; unsigned timestamp = 0; if (state.getBase(address, moBasePair)) { @@ -6533,7 +6554,7 @@ bool Executor::lazyInitializeObject(ExecutionState &state, ref address, IDType Executor::lazyInitializeLocalObject(ExecutionState &state, StackFrame &sf, ref address, const KInstruction *target) { - AllocaInst *ai = cast(target->inst); + AllocaInst *ai = cast(target->inst()); unsigned elementSize = kmodule->targetData->getTypeStoreSize(ai->getAllocatedType()); ref size = Expr::createPointer(elementSize); @@ -6800,7 +6821,7 @@ ExecutionState *Executor::formState(Function *f, int argc, char **argv, MemoryObject *arg = allocate(*state, Expr::createPointer(len + 1), /*isLocal=*/false, /*isGlobal=*/true, - /*allocSite=*/state->pc->inst, /*alignment=*/8); + /*allocSite=*/state->pc->inst(), /*alignment=*/8); if (!arg) klee_error("Could not allocate memory for function arguments"); @@ -6885,10 +6906,10 @@ void Executor::runFunctionAsMain(Function *f, int argc, char **argv, for (auto &startFunctionAndWhiteList : prepTargets) { auto kf = - kmodule->functionMap.at(startFunctionAndWhiteList.first->function); + kmodule->functionMap.at(startFunctionAndWhiteList.first->function()); if (startFunctionAndWhiteList.second->empty()) { klee_warning("No targets found for %s", - kf->function->getName().str().c_str()); + kf->function()->getName().str().c_str()); continue; } auto whitelist = startFunctionAndWhiteList.second; @@ -6994,7 +7015,7 @@ bool isReturnValueFromInitBlock(const ExecutionState &state, const llvm::Value *value) { return state.initPC->parent->getKBlockType() == KBlockType::Call && state.initPC == state.initPC->parent->getLastInstruction() && - state.initPC->parent->getFirstInstruction()->inst == value; + state.initPC->parent->getFirstInstruction()->inst() == value; } ref Executor::makeSymbolicValue(llvm::Value *value, @@ -7016,9 +7037,9 @@ ref Executor::makeSymbolicValue(llvm::Value *value, void Executor::prepareSymbolicValue(ExecutionState &state, StackFrame &frame, KInstruction *target) { - ref result = makeSymbolicValue(target->inst, state); + ref result = makeSymbolicValue(target->inst(), state); bindLocal(target, frame, result); - if (isa(target->inst)) { + if (isa(target->inst())) { lazyInitializeLocalObject(state, frame, result, target); } } @@ -7028,7 +7049,7 @@ void Executor::prepareMockValue(ExecutionState &state, StackFrame &frame, KInstruction *target) { ref result = makeMockValue(state, name, width); bindLocal(target, frame, result); - if (isa(target->inst)) { + if (isa(target->inst())) { lazyInitializeLocalObject(state, frame, result, target); } } @@ -7036,7 +7057,7 @@ void Executor::prepareMockValue(ExecutionState &state, StackFrame &frame, void Executor::prepareMockValue(ExecutionState &state, const std::string &name, KInstruction *target) { Expr::Width width = - kmodule->targetData->getTypeSizeInBits(target->inst->getType()); + kmodule->targetData->getTypeSizeInBits(target->inst()->getType()); prepareMockValue(state, state.stack.valueStack().back(), name, width, target); } @@ -7055,9 +7076,9 @@ void Executor::prepareSymbolicArg(ExecutionState &state, StackFrame &frame, unsigned index) { KFunction *kf = frame.kf; #if LLVM_VERSION_CODE >= LLVM_VERSION(10, 0) - Argument *arg = kf->function->getArg(index); + Argument *arg = kf->function()->getArg(index); #else - Argument *arg = &kf->function->arg_begin()[index]; + Argument *arg = &kf->function()->arg_begin()[index]; #endif ref result = makeSymbolicValue(arg, state); bindArgument(kf, index, frame, result); @@ -7065,7 +7086,7 @@ void Executor::prepareSymbolicArg(ExecutionState &state, StackFrame &frame, void Executor::prepareSymbolicArgs(ExecutionState &state, StackFrame &frame) { KFunction *kf = frame.kf; - unsigned argSize = kf->function->arg_size(); + unsigned argSize = kf->function()->arg_size(); for (unsigned argNo = 0; argNo < argSize; ++argNo) { prepareSymbolicArg(state, frame, argNo); } @@ -7598,7 +7619,7 @@ void Executor::dumpStates() { for (auto sfIt = es->stack.callStack().begin(), sf_ie = es->stack.callStack().end(); sfIt != sf_ie; ++sfIt) { - *os << "('" << sfIt->kf->function->getName().str() << "',"; + *os << "('" << sfIt->kf->function()->getName().str() << "',"; if (next == es->stack.callStack().end()) { *os << es->prevPC->getLine() << "), "; } else { diff --git a/lib/Core/Executor.h b/lib/Core/Executor.h index 0f8d8eaf69..1ed917040b 100644 --- a/lib/Core/Executor.h +++ b/lib/Core/Executor.h @@ -180,7 +180,7 @@ class Executor : public Interpreter { /// Map of globals to their bound address. This also includes /// globals that have no representative object (i.e. functions). - std::map> globalAddresses; + std::map> globalAddresses; /// Map of legal function addresses to the corresponding Function. /// Used to validate and dereference function pointers. @@ -531,9 +531,9 @@ class Executor : public Interpreter { /// Evaluates an LLVM constant expression. The optional argument ki /// is the instruction where this constant was encountered, or NULL /// if not applicable/unavailable. - ref evalConstantExpr(const llvm::ConstantExpr *c, - llvm::APFloat::roundingMode rm, - const KInstruction *ki = NULL); + ref evalConstantExpr(const llvm::ConstantExpr *c, + llvm::APFloat::roundingMode rm, + const KInstruction *ki = NULL); /// Evaluates an LLVM float comparison. the operands are two float /// expressions. @@ -543,9 +543,9 @@ class Executor : public Interpreter { /// Evaluates an LLVM constant. The optional argument ki is the /// instruction where this constant was encountered, or NULL if /// not applicable/unavailable. - ref evalConstant(const llvm::Constant *c, - llvm::APFloat::roundingMode rm, - const KInstruction *ki = NULL); + ref evalConstant(const llvm::Constant *c, + llvm::APFloat::roundingMode rm, + const KInstruction *ki = NULL); /// Return a unique constant value for the given expression in the /// given state, if it has one (i.e. it provably only has a single diff --git a/lib/Core/ExecutorUtil.cpp b/lib/Core/ExecutorUtil.cpp index ce19fa74bf..534f264fee 100644 --- a/lib/Core/ExecutorUtil.cpp +++ b/lib/Core/ExecutorUtil.cpp @@ -69,9 +69,9 @@ ref FPToX87FP80Ext(ref arg) { return result; } -ref Executor::evalConstant(const Constant *c, - llvm::APFloat::roundingMode rm, - const KInstruction *ki) { +ref Executor::evalConstant(const Constant *c, + llvm::APFloat::roundingMode rm, + const KInstruction *ki) { if (!ki) { KConstant *kc = kmodule->getKConstant(c); if (kc) @@ -98,7 +98,7 @@ ref Executor::evalConstant(const Constant *c, return Expr::createPointer(0); } else if (isa(c) || isa(c)) { if (getWidthForLLVMType(c->getType()) == 0) { - if (isa(ki->inst)) { + if (isa(ki->inst())) { klee_warning_once( 0, "Using zero size array fix for landingpad instruction filter"); return ConstantExpr::create(0, 1); @@ -274,12 +274,12 @@ ref Executor::evaluateFCmp(unsigned int predicate, return result; } -ref Executor::evalConstantExpr(const llvm::ConstantExpr *ce, - llvm::APFloat::roundingMode rm, - const KInstruction *ki) { +ref Executor::evalConstantExpr(const llvm::ConstantExpr *ce, + llvm::APFloat::roundingMode rm, + const KInstruction *ki) { llvm::Type *type = ce->getType(); - ref op1(0), op2(0), op3(0); + ref op1(0), op2(0), op3(0); int numOperands = ce->getNumOperands(); if (numOperands > 0) @@ -294,23 +294,28 @@ ref Executor::evalConstantExpr(const llvm::ConstantExpr *ce, case Instruction::SDiv: case Instruction::UDiv: case Instruction::SRem: - case Instruction::URem: - if (op2->getLimitedValue() == 0) { - std::string msg( - "Division/modulo by zero during constant folding at location "); - llvm::raw_string_ostream os(msg); - os << (ki ? ki->getSourceLocationString() : "[unknown]"); - klee_error("%s", os.str().c_str()); + case Instruction::URem: { + if (auto op2Const = dyn_cast(op2)) { + if (op2Const->getLimitedValue() == 0) { + std::string msg( + "Division/modulo by zero during constant folding at location "); + llvm::raw_string_ostream os(msg); + os << (ki ? ki->getSourceLocationString() : "[unknown]"); + klee_error("%s", os.str().c_str()); + } } break; + } case Instruction::Shl: case Instruction::LShr: case Instruction::AShr: - if (op2->getLimitedValue() >= op1->getWidth()) { - std::string msg("Overshift during constant folding at location "); - llvm::raw_string_ostream os(msg); - os << (ki ? ki->getSourceLocationString() : "[unknown]"); - klee_error("%s", os.str().c_str()); + if (auto op2Const = dyn_cast(op2)) { + if (op2Const->getLimitedValue() >= op1->getWidth()) { + std::string msg("Overshift during constant folding at location "); + llvm::raw_string_ostream os(msg); + os << (ki ? ki->getSourceLocationString() : "[unknown]"); + klee_error("%s", os.str().c_str()); + } } } @@ -324,37 +329,37 @@ ref Executor::evalConstantExpr(const llvm::ConstantExpr *ce, klee_error("%s", os.str().c_str()); case Instruction::Trunc: - return op1->Extract(0, getWidthForLLVMType(type)); + return ExtractExpr::create(op1, 0, getWidthForLLVMType(type)); case Instruction::ZExt: - return op1->ZExt(getWidthForLLVMType(type)); + return ZExtExpr::create(op1, getWidthForLLVMType(type)); case Instruction::SExt: - return op1->SExt(getWidthForLLVMType(type)); + return SExtExpr::create(op1, getWidthForLLVMType(type)); case Instruction::Add: - return op1->Add(op2); + return AddExpr::create(op1, op2); case Instruction::Sub: - return op1->Sub(op2); + return SubExpr::create(op1, op2); case Instruction::Mul: - return op1->Mul(op2); + return MulExpr::create(op1, op2); case Instruction::SDiv: - return op1->SDiv(op2); + return SDivExpr::create(op1, op2); case Instruction::UDiv: - return op1->UDiv(op2); + return UDivExpr::create(op1, op2); case Instruction::SRem: - return op1->SRem(op2); + return SRemExpr::create(op1, op2); case Instruction::URem: - return op1->URem(op2); + return URemExpr::create(op1, op2); case Instruction::And: - return op1->And(op2); + return AndExpr::create(op1, op2); case Instruction::Or: - return op1->Or(op2); + return OrExpr::create(op1, op2); case Instruction::Xor: - return op1->Xor(op2); + return XorExpr::create(op1, op2); case Instruction::Shl: - return op1->Shl(op2); + return ShlExpr::create(op1, op2); case Instruction::LShr: - return op1->LShr(op2); + return LShrExpr::create(op1, op2); case Instruction::AShr: - return op1->AShr(op2); + return AShrExpr::create(op1, op2); case Instruction::BitCast: { ref result = op1; @@ -373,37 +378,43 @@ ref Executor::evalConstantExpr(const llvm::ConstantExpr *ce, } case Instruction::IntToPtr: - return op1->ZExt(getWidthForLLVMType(type)); + return ZExtExpr::create(op1, getWidthForLLVMType(type)); case Instruction::PtrToInt: - return op1->ZExt(getWidthForLLVMType(type)); + return ZExtExpr::create(op1, getWidthForLLVMType(type)); case Instruction::GetElementPtr: { - ref base = op1->ZExt(Context::get().getPointerWidth()); + ref base = ZExtExpr::create(op1, Context::get().getPointerWidth()); for (gep_type_iterator ii = gep_type_begin(ce), ie = gep_type_end(ce); ii != ie; ++ii) { - ref indexOp = - evalConstant(cast(ii.getOperand()), rm, ki); + ref indexOp = evalConstant(cast(ii.getOperand()), rm, ki); if (indexOp->isZero()) continue; // Handle a struct index, which adds its field offset to the pointer. if (auto STy = ii.getStructTypeOrNull()) { - unsigned ElementIdx = indexOp->getZExtValue(); + auto indexOpConst = dyn_cast(indexOp); + if (!indexOpConst) { + klee_error( + "Found non-constant index in evaluation of llvm::ConstantExpr"); + } + unsigned ElementIdx = indexOpConst->getZExtValue(); const StructLayout *SL = kmodule->targetData->getStructLayout(STy); - base = base->Add( - ConstantExpr::alloc(APInt(Context::get().getPointerWidth(), - SL->getElementOffset(ElementIdx)))); + base = AddExpr::create( + base, ConstantExpr::alloc(APInt(Context::get().getPointerWidth(), + SL->getElementOffset(ElementIdx)))); continue; } // For array or vector indices, scale the index by the size of the type. // Indices can be negative - base = base->Add(indexOp->SExt(Context::get().getPointerWidth()) - ->Mul(ConstantExpr::alloc( - APInt(Context::get().getPointerWidth(), - kmodule->targetData->getTypeAllocSize( - ii.getIndexedType()))))); + base = AddExpr::create( + base, + MulExpr::create( + SExtExpr::create(indexOp, Context::get().getPointerWidth()), + ConstantExpr::alloc(APInt(Context::get().getPointerWidth(), + kmodule->targetData->getTypeAllocSize( + ii.getIndexedType()))))); } return base; } @@ -413,25 +424,25 @@ ref Executor::evalConstantExpr(const llvm::ConstantExpr *ce, default: assert(0 && "unhandled ICmp predicate"); case ICmpInst::ICMP_EQ: - return op1->Eq(op2); + return EqExpr::create(op1, op2); case ICmpInst::ICMP_NE: - return op1->Ne(op2); + return NeExpr::create(op1, op2); case ICmpInst::ICMP_UGT: - return op1->Ugt(op2); + return UgtExpr::create(op1, op2); case ICmpInst::ICMP_UGE: - return op1->Uge(op2); + return UgeExpr::create(op1, op2); case ICmpInst::ICMP_ULT: - return op1->Ult(op2); + return UltExpr::create(op1, op2); case ICmpInst::ICMP_ULE: - return op1->Ule(op2); + return UleExpr::create(op1, op2); case ICmpInst::ICMP_SGT: - return op1->Sgt(op2); + return SgtExpr::create(op1, op2); case ICmpInst::ICMP_SGE: - return op1->Sge(op2); + return SgeExpr::create(op1, op2); case ICmpInst::ICMP_SLT: - return op1->Slt(op2); + return SltExpr::create(op1, op2); case ICmpInst::ICMP_SLE: - return op1->Sle(op2); + return SleExpr::create(op1, op2); } } @@ -439,46 +450,43 @@ ref Executor::evalConstantExpr(const llvm::ConstantExpr *ce, return op1->isTrue() ? op2 : op3; case Instruction::FAdd: - return op1->FAdd(op2, rm); + return FAddExpr::create(op1, op2, rm); case Instruction::FSub: - return op1->FSub(op2, rm); + return FSubExpr::create(op1, op2, rm); case Instruction::FMul: - return op1->FMul(op2, rm); + return FMulExpr::create(op1, op2, rm); case Instruction::FDiv: - return op1->FDiv(op2, rm); + return FDivExpr::create(op1, op2, rm); case Instruction::FRem: { - return op1->FRem(op2, rm); + return FRemExpr::create(op1, op2, rm); } case Instruction::FPTrunc: { Expr::Width width = getWidthForLLVMType(ce->getType()); - return op1->FPTrunc(width, rm); + return FPTruncExpr::create(op1, width, rm); } case Instruction::FPExt: { Expr::Width width = getWidthForLLVMType(ce->getType()); - return op1->FPExt(width); + return FPExtExpr::create(op1, width); } case Instruction::UIToFP: { Expr::Width width = getWidthForLLVMType(ce->getType()); - return op1->UIToFP(width, rm); + return UIToFPExpr::create(op1, width, rm); } case Instruction::SIToFP: { Expr::Width width = getWidthForLLVMType(ce->getType()); - return op1->SIToFP(width, rm); + return SIToFPExpr::create(op1, width, rm); } case Instruction::FPToUI: { Expr::Width width = getWidthForLLVMType(ce->getType()); - return op1->FPToUI(width, rm); + return FPToUIExpr::create(op1, width, rm); } case Instruction::FPToSI: { Expr::Width width = getWidthForLLVMType(ce->getType()); - return op1->FPToSI(width, rm); + return FPToSIExpr::create(op1, width, rm); } case Instruction::FCmp: { - ref result = evaluateFCmp(ce->getPredicate(), op1, op2); - if (ConstantExpr *CE = dyn_cast(result)) { - return ref(CE); - } + return evaluateFCmp(ce->getPredicate(), op1, op2); } assert(0 && "floating point ConstantExprs unsupported"); } diff --git a/lib/Core/ExternalDispatcher.cpp b/lib/Core/ExternalDispatcher.cpp index 551c121f9d..642dd7a7ae 100644 --- a/lib/Core/ExternalDispatcher.cpp +++ b/lib/Core/ExternalDispatcher.cpp @@ -346,11 +346,11 @@ Function *ExternalDispatcherImpl::createDispatcher(KCallable *target, llvm::CallInst *result; if (auto *func = dyn_cast(target)) { auto dispatchTarget = module->getOrInsertFunction( - target->getName(), FTy, func->function->getAttributes()); + target->getName(), FTy, func->function()->getAttributes()); result = Builder.CreateCall(dispatchTarget, llvm::ArrayRef(args, args + i)); } else if (auto *asmValue = dyn_cast(target)) { - result = Builder.CreateCall(asmValue->getInlineAsm(), + result = Builder.CreateCall(asmValue->inlineAsm(), llvm::ArrayRef(args, args + i)); } else { assert(0 && "Unhandled KCallable derived class"); diff --git a/lib/Core/SpecialFunctionHandler.cpp b/lib/Core/SpecialFunctionHandler.cpp index a9d7457a88..82dc7f5388 100644 --- a/lib/Core/SpecialFunctionHandler.cpp +++ b/lib/Core/SpecialFunctionHandler.cpp @@ -269,7 +269,7 @@ bool SpecialFunctionHandler::handle(ExecutionState &state, Function *f, Handler h = it->second.first; bool hasReturnValue = it->second.second; // FIXME: Check this... add test? - if (!hasReturnValue && !target->inst->use_empty()) { + if (!hasReturnValue && !target->inst()->use_empty()) { executor.terminateStateOnExecError( state, "expected return value from void special function"); } else { @@ -626,7 +626,7 @@ void SpecialFunctionHandler::handleWarning(ExecutionState &state, std::string msg_str = readStringAtAddress(state, arguments[0]); klee_warning("%s: %s", - state.stack.callStack().back().kf->function->getName().data(), + state.stack.callStack().back().kf->function()->getName().data(), msg_str.c_str()); } @@ -639,7 +639,7 @@ void SpecialFunctionHandler::handleWarningOnce( std::string msg_str = readStringAtAddress(state, arguments[0]); klee_warning_once( 0, "%s: %s", - state.stack.callStack().back().kf->function->getName().data(), + state.stack.callStack().back().kf->function()->getName().data(), msg_str.c_str()); } @@ -692,7 +692,7 @@ void SpecialFunctionHandler::handleGetObjSize( target, *it->second, ConstantExpr::create(mo->size, executor.kmodule->targetData->getTypeSizeInBits( - target->inst->getType()))); + target->inst()->getType()))); } } @@ -744,7 +744,7 @@ void SpecialFunctionHandler::handleErrnoLocation( target, state, ConstantExpr::create((uint64_t)errno_addr, executor.kmodule->targetData->getTypeSizeInBits( - target->inst->getType()))); + target->inst()->getType()))); } void SpecialFunctionHandler::handleCalloc(ExecutionState &state, KInstruction *target, @@ -864,7 +864,7 @@ void SpecialFunctionHandler::handleDefineFixedObject( uint64_t address = cast(arguments[0])->getZExtValue(); uint64_t size = cast(arguments[1])->getZExtValue(); MemoryObject *mo = - executor.memory->allocateFixed(address, size, state.prevPC->inst); + executor.memory->allocateFixed(address, size, state.prevPC->inst()); executor.bindObjectInState( state, mo, executor.typeSystemManager->getUnknownType(), false); mo->isUserSpecified = true; // XXX hack; diff --git a/lib/Core/StatsTracker.cpp b/lib/Core/StatsTracker.cpp index c2b9b4769d..4f25d8dbf0 100644 --- a/lib/Core/StatsTracker.cpp +++ b/lib/Core/StatsTracker.cpp @@ -244,12 +244,12 @@ StatsTracker::StatsTracker(Executor &_executor, std::string _objectFilename, if (OutputIStats) { unsigned id = ki->getGlobalIndex(); theStatisticManager->setIndex(id); - if (instructionIsCoverable(ki->inst)) { + if (instructionIsCoverable(ki->inst())) { ++stats::uncoveredInstructions; } } - if (BranchInst *bi = dyn_cast(ki->inst)) + if (BranchInst *bi = dyn_cast(ki->inst())) if (!bi->isUnconditional()) numBranches++; } @@ -390,7 +390,7 @@ void StatsTracker::stepInstruction(ExecutionState &es) { } } - Instruction *inst = es.pc->inst; + Instruction *inst = es.pc->inst(); const KInstruction *ki = es.pc; auto &sf = es.stack.infoStack().back(); theStatisticManager->setIndex(ki->getGlobalIndex()); @@ -444,7 +444,7 @@ void StatsTracker::framePushed(ExecutionState &es, if (UseCallPaths) { CallPathNode *parent = parentFrame ? parentFrame->callPathNode : 0; CallPathNode *cp = callPathManager.getCallPath( - parent, csf.caller ? csf.caller->inst : 0, csf.kf->function); + parent, csf.caller ? csf.caller->inst() : 0, csf.kf->function()); isf.callPathNode = cp; cp->count++; } diff --git a/lib/Core/TargetCalculator.cpp b/lib/Core/TargetCalculator.cpp index 36c23a9026..1b19982b34 100644 --- a/lib/Core/TargetCalculator.cpp +++ b/lib/Core/TargetCalculator.cpp @@ -123,8 +123,8 @@ void TargetCalculator::update( for (auto state : localStates) { KFunction *kf = state->prevPC->parent->parent; KModule *km = kf->parent; - if (state->prevPC->inst->isTerminator() && - km->inMainModule(*kf->function)) { + if (state->prevPC->inst()->isTerminator() && + km->inMainModule(*kf->function())) { update(*state); } } @@ -169,8 +169,8 @@ bool TargetCalculator::uncoveredBlockPredicate(ExecutionState *state, calledKFunction->numInstructions; } if (fBranches.at(kblock) != cb) { - result |= - kblock->basicBlock->getTerminator()->getNumSuccessors() > cb.size(); + result |= kblock->basicBlock()->getTerminator()->getNumSuccessors() > + cb.size(); } } } @@ -185,7 +185,8 @@ TargetHashSet TargetCalculator::calculate(ExecutionState &state) { KBlock *kb = kf->blockMap[bb]; kb = !isa(kb) || (kb->getLastInstruction() != state.pc) ? kb - : kf->blockMap[state.pc->parent->basicBlock->getTerminator() + : kf->blockMap[state.pc->parent->basicBlock() + ->getTerminator() ->getSuccessor(0)]; for (auto sfi = state.stack.callStack().rbegin(), sfe = state.stack.callStack().rend(); @@ -225,7 +226,7 @@ TargetHashSet TargetCalculator::calculate(ExecutionState &state) { if (fBranches.at(block) != cb) { for (unsigned index = 0; index < - block->basicBlock->getTerminator()->getNumSuccessors(); + block->basicBlock()->getTerminator()->getNumSuccessors(); ++index) { if (!cb.count(index)) targets.insert(CoverBranchTarget::create(block, index)); @@ -244,7 +245,8 @@ TargetHashSet TargetCalculator::calculate(ExecutionState &state) { kb = !isa(kb) || (kb->getLastInstruction() != sfi->caller) ? kb - : kf->blockMap[sfi->caller->parent->basicBlock->getTerminator() + : kf->blockMap[sfi->caller->parent->basicBlock() + ->getTerminator() ->getSuccessor(0)]; } } diff --git a/lib/Core/TargetManager.cpp b/lib/Core/TargetManager.cpp index 9dcaedcd86..f72e329135 100644 --- a/lib/Core/TargetManager.cpp +++ b/lib/Core/TargetManager.cpp @@ -111,7 +111,8 @@ void TargetManager::updateReached(ExecutionState &state) { auto kf = prevKI->parent->parent; auto kmodule = kf->parent; - if (prevKI->inst->isTerminator() && kmodule->inMainModule(*kf->function)) { + if (prevKI->inst()->isTerminator() && + kmodule->inMainModule(*kf->function())) { ref target; if (state.getPrevPCBlock()->getTerminator()->getNumSuccessors() == 0) { @@ -262,9 +263,9 @@ bool TargetManager::isReachedTarget(const ExecutionState &state, if (isa(target)) { if (state.prevPC->parent == target->getBlock()) { if (state.prevPC == target->getBlock()->getLastInstruction() && - state.prevPC->inst->getSuccessor( + state.prevPC->inst()->getSuccessor( cast(target)->getBranchCase()) == - state.pc->parent->basicBlock) { + state.pc->parent->basicBlock()) { result = Done; } else { result = Continue; diff --git a/lib/Core/TargetedExecutionManager.cpp b/lib/Core/TargetedExecutionManager.cpp index ab4b67f3df..98862ede39 100644 --- a/lib/Core/TargetedExecutionManager.cpp +++ b/lib/Core/TargetedExecutionManager.cpp @@ -322,7 +322,7 @@ TargetedExecutionManager::prepareAllLocations(KModule *kmodule, fileNameToFunctions; for (const auto &kfunc : kmodule->functions) { - fileNameToFunctions[kfunc->getSourceFilepath()].insert(kfunc->function); + fileNameToFunctions[kfunc->getSourceFilepath()].insert(kfunc->function()); } for (auto it = locations.begin(); it != locations.end(); ++it) { @@ -379,18 +379,18 @@ bool TargetedExecutionManager::canReach(const ref &from, } const auto &blockDist = codeGraphInfo.getDistance(fromBlock); - if (blockDist.count(toBlock->basicBlock) != 0) { + if (blockDist.count(toBlock->basicBlock()) != 0) { return true; } } else { const auto &funcDist = codeGraphInfo.getDistance(fromKf); - if (funcDist.count(toKf->function) != 0) { + if (funcDist.count(toKf->function()) != 0) { return true; } const auto &backwardFuncDist = codeGraphInfo.getBackwardDistance(fromKf); - if (backwardFuncDist.count(toKf->function) != 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->function) == 0) { + if (funcDist.count(curKf->function()) == 0) { const auto &curFuncDist = codeGraphInfo.getDistance(curKf); - if (curFuncDist.count(resKf->function) == 0) { + if (curFuncDist.count(resKf->function()) == 0) { curKf = nullptr; } else { i = j; diff --git a/lib/Expr/ExprPPrinter.cpp b/lib/Expr/ExprPPrinter.cpp index 5ffba87725..4d5fdc2554 100644 --- a/lib/Expr/ExprPPrinter.cpp +++ b/lib/Expr/ExprPPrinter.cpp @@ -390,7 +390,20 @@ class PPrinter : public ExprPPrinter { s->constantValues.print(PC.getStream(), Density::Sparse); } else if (auto s = dyn_cast(source)) { PC << s->version << " "; - s->allocSite->getID().print(PC.getStream()); + switch (s->allocSite->getKind()) { + case KValue::Kind::INSTRUCTION: { + cast(s->allocSite)->getID().print(PC.getStream()); + break; + } + case KValue::Kind::GLOBAL_VARIABLE: { + PC.getStream() << "[" << cast(s->allocSite)->getName() + << "]"; + break; + } + default: { + llvm_unreachable("unknown kind of alloc site"); + } + } PC << " " << s->size; } else if (auto s = dyn_cast(source)) { PC << s->version << " "; diff --git a/lib/Expr/Parser.cpp b/lib/Expr/Parser.cpp index a144437fd8..95c2d09a38 100644 --- a/lib/Expr/Parser.cpp +++ b/lib/Expr/Parser.cpp @@ -608,10 +608,10 @@ SourceResult ParserImpl::ParseArgumentSource() { auto argNo = dyn_cast(argNoExpr.get())->getZExtValue(); auto index = dyn_cast(indexExpr.get())->getZExtValue(); #if LLVM_VERSION_CODE >= LLVM_VERSION(10, 0) - auto arg = km->functionNameMap[name.getString()]->function->getArg(argNo); + auto arg = km->functionNameMap[name.getString()]->function()->getArg(argNo); #else auto arg = - &km->functionNameMap[name.getString()]->function->arg_begin()[argNo]; + &km->functionNameMap[name.getString()]->function()->arg_begin()[argNo]; #endif return SourceBuilder::argument(*arg, index, km); } @@ -628,7 +628,7 @@ SourceResult ParserImpl::ParseInstructionSource() { auto KF = km->functionNameMap[FName.getString()]; auto KB = KF->getLabelMap().at(Label.getString()); auto KI = KB->instructions[KIIndex]; - return SourceBuilder::instruction(*KI->inst, index, km); + return SourceBuilder::instruction(*KI->inst(), index, km); } SourceResult ParserImpl::ParseAlphaSource() { diff --git a/lib/Expr/Path.cpp b/lib/Expr/Path.cpp index 829e73b374..e3be1e0d25 100644 --- a/lib/Expr/Path.cpp +++ b/lib/Expr/Path.cpp @@ -150,7 +150,7 @@ Path Path::parse(const std::string &str, const KModule &km) { Path::TransitionKind Path::getTransitionKind(KBlock *a, KBlock *b) { if (auto cb = dyn_cast(a)) { - if (cb->calledFunctions.count(b->parent->function) && + if (cb->calledFunctions.count(b->parent->function()) && b == b->parent->entryKBlock) { return TransitionKind::StepInto; } diff --git a/lib/Expr/SourceBuilder.cpp b/lib/Expr/SourceBuilder.cpp index 866f89da6d..680cc747b6 100644 --- a/lib/Expr/SourceBuilder.cpp +++ b/lib/Expr/SourceBuilder.cpp @@ -3,6 +3,7 @@ #include "klee/Expr/Expr.h" #include "klee/Expr/SymbolicSource.h" #include "klee/Module/KModule.h" +#include "klee/Module/KValue.h" using namespace klee; @@ -21,7 +22,7 @@ SourceBuilder::uninitialized(unsigned version, const KInstruction *allocSite) { } ref SourceBuilder::symbolicSizeConstantAddress( - unsigned version, const KInstruction *allocSite, ref size) { + unsigned version, const KValue *allocSite, ref size) { ref r( new SymbolicSizeConstantAddressSource(version, allocSite, size)); r->computeHash(); diff --git a/lib/Expr/SymbolicSource.cpp b/lib/Expr/SymbolicSource.cpp index 1f78147c2b..f0321ec55a 100644 --- a/lib/Expr/SymbolicSource.cpp +++ b/lib/Expr/SymbolicSource.cpp @@ -5,6 +5,7 @@ #include "klee/Expr/ExprUtil.h" #include "klee/Module/KInstruction.h" #include "klee/Module/KModule.h" +#include "klee/Module/KValue.h" DISABLE_WARNING_PUSH DISABLE_WARNING_DEPRECATED_DECLARATIONS @@ -102,8 +103,11 @@ int SymbolicSizeConstantAddressSource::internalCompare( return size < ub.size ? -1 : 1; } if (allocSite != ub.allocSite) { - return allocSite->getGlobalIndex() < ub.allocSite->getGlobalIndex() ? -1 - : 1; + if (allocSite->getKind() == ub.allocSite->getKind()) { + return *allocSite < *ub.allocSite ? -1 : 1; + } else { + return allocSite->getKind() < ub.allocSite->getKind() ? -1 : 1; + } } return 0; diff --git a/lib/Module/CMakeLists.txt b/lib/Module/CMakeLists.txt index bca27a10ea..19d9c11dbe 100644 --- a/lib/Module/CMakeLists.txt +++ b/lib/Module/CMakeLists.txt @@ -18,6 +18,7 @@ set(KLEE_MODULE_COMPONENT_SRCS KInstruction.cpp KModule.cpp KType.cpp + KValue.cpp LowerSwitch.cpp ModuleUtil.cpp Optimize.cpp diff --git a/lib/Module/CodeGraphInfo.cpp b/lib/Module/CodeGraphInfo.cpp index 71bb259ee1..4823460b87 100644 --- a/lib/Module/CodeGraphInfo.cpp +++ b/lib/Module/CodeGraphInfo.cpp @@ -68,7 +68,7 @@ void CodeGraphInfo::calculateBackwardDistance(Block *bb) { } void CodeGraphInfo::calculateDistance(KFunction *kf) { - auto f = kf->function; + auto f = kf->function(); auto &functionMap = kf->parent->functionMap; auto &dist = functionDistance[f]; auto &sort = functionSortedDistance[f]; @@ -83,7 +83,7 @@ void CodeGraphInfo::calculateDistance(KFunction *kf) { if (!calledFunction || calledFunction->isDeclaration()) continue; if (dist.count(calledFunction) == 0) { - auto d = dist[currKF->function] + 1; + auto d = dist[currKF->function()] + 1; dist[calledFunction] = d; sort.emplace_back(calledFunction, d); auto callKF = functionMap[calledFunction]; @@ -96,7 +96,7 @@ void CodeGraphInfo::calculateDistance(KFunction *kf) { } void CodeGraphInfo::calculateBackwardDistance(KFunction *kf) { - auto f = kf->function; + auto f = kf->function(); auto &callMap = kf->parent->callMap; auto &bdist = functionBackwardDistance[f]; auto &bsort = functionSortedBackwardDistance[f]; @@ -124,7 +124,7 @@ void CodeGraphInfo::calculateFunctionBranches(KFunction *kf) { for (auto &kb : kf->blocks) { fbranches[kb.get()]; for (unsigned branch = 0; - branch < kb->basicBlock->getTerminator()->getNumSuccessors(); + branch < kb->basicBlock()->getTerminator()->getNumSuccessors(); ++branch) { fbranches[kb.get()].insert(branch); } @@ -134,10 +134,10 @@ void CodeGraphInfo::calculateFunctionConditionalBranches(KFunction *kf) { std::map> &fbranches = functionConditionalBranches[kf]; for (auto &kb : kf->blocks) { - if (kb->basicBlock->getTerminator()->getNumSuccessors() > 1) { + if (kb->basicBlock()->getTerminator()->getNumSuccessors() > 1) { fbranches[kb.get()]; for (unsigned branch = 0; - branch < kb->basicBlock->getTerminator()->getNumSuccessors(); + branch < kb->basicBlock()->getTerminator()->getNumSuccessors(); ++branch) { fbranches[kb.get()].insert(branch); } @@ -158,31 +158,31 @@ const BlockDistanceMap &CodeGraphInfo::getDistance(Block *b) { } bool CodeGraphInfo::hasCycle(KBlock *kb) { - auto b = kb->basicBlock; + auto b = kb->basicBlock(); if (!blockDistance.count(b)) calculateDistance(b); return blockCycles.count(b); } const BlockDistanceMap &CodeGraphInfo::getDistance(KBlock *kb) { - return getDistance(kb->basicBlock); + return getDistance(kb->basicBlock()); } const BlockDistanceMap &CodeGraphInfo::getBackwardDistance(KBlock *kb) { - if (blockBackwardDistance.count(kb->basicBlock) == 0) - calculateBackwardDistance(kb->basicBlock); - return blockBackwardDistance.at(kb->basicBlock); + if (blockBackwardDistance.count(kb->basicBlock()) == 0) + calculateBackwardDistance(kb->basicBlock()); + return blockBackwardDistance.at(kb->basicBlock()); } const FunctionDistanceMap &CodeGraphInfo::getDistance(KFunction *kf) { - auto f = kf->function; + auto f = kf->function(); if (functionDistance.count(f) == 0) calculateDistance(kf); return functionDistance.at(f); } const FunctionDistanceMap &CodeGraphInfo::getBackwardDistance(KFunction *kf) { - auto f = kf->function; + auto f = kf->function(); if (functionBackwardDistance.count(f) == 0) calculateBackwardDistance(kf); return functionBackwardDistance.at(f); @@ -204,7 +204,7 @@ void CodeGraphInfo::getNearestPredicateSatisfying(KBlock *from, if (predicate(currBB) && currBB != from) { result.insert(currBB); } else { - for (auto 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/KInstruction.cpp b/lib/Module/KInstruction.cpp index 09497d344c..97f9002385 100644 --- a/lib/Module/KInstruction.cpp +++ b/lib/Module/KInstruction.cpp @@ -50,9 +50,10 @@ KInstruction::KInstruction( &_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); + : KValue(_inst, KValue::Kind::INSTRUCTION), 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]; @@ -62,10 +63,10 @@ KInstruction::KInstruction( operands[j + 1] = getOperandNum(v, _instructionToRegisterMap, _km, this); } } else { - unsigned numOperands = inst->getNumOperands(); + unsigned numOperands = inst()->getNumOperands(); operands = new int[numOperands]; for (unsigned j = 0; j < numOperands; j++) { - Value *v = inst->getOperand(j); + Value *v = inst()->getOperand(j); operands[j] = getOperandNum(v, _instructionToRegisterMap, _km, this); } } @@ -74,17 +75,17 @@ KInstruction::KInstruction( KInstruction::~KInstruction() { delete[] operands; } size_t KInstruction::getLine() const { - auto locationInfo = getLocationInfo(inst); + auto locationInfo = getLocationInfo(inst()); return locationInfo.line; } size_t KInstruction::getColumn() const { - auto locationInfo = getLocationInfo(inst); + auto locationInfo = getLocationInfo(inst()); return locationInfo.column; } std::string KInstruction::getSourceFilepath() const { - auto locationInfo = getLocationInfo(inst); + auto locationInfo = getLocationInfo(inst()); return locationInfo.file; } @@ -101,7 +102,7 @@ std::string KInstruction::getSourceLocationString() const { std::string KInstruction::toString() const { return llvm::utostr(getIndex()) + " at " + parent->toString() + " (" + - inst->getOpcodeName() + ")"; + inst()->getOpcodeName() + ")"; } unsigned KInstruction::getGlobalIndex() const { return globalIndex; } diff --git a/lib/Module/KModule.cpp b/lib/Module/KModule.cpp index 64e1d3037c..6d686f1a6e 100644 --- a/lib/Module/KModule.cpp +++ b/lib/Module/KModule.cpp @@ -401,11 +401,16 @@ void KModule::manifest(InterpreterHandler *ih, functions.push_back(std::move(kf)); } + for (auto &global : module->globals()) { + globalMap.emplace(&global, new KGlobalVariable(&global)); + } + /* Compute various interesting properties */ for (auto &kf : functions) { - if (functionEscapes(kf->function)) - escapingFunctions.insert(kf->function); + if (functionEscapes(kf->function())) { + escapingFunctions.insert(kf->function()); + } } for (auto &declaration : declarations) { @@ -416,18 +421,18 @@ void KModule::manifest(InterpreterHandler *ih, for (auto &kfp : functions) { for (auto kcb : kfp->kCallBlocks) { bool isInlineAsm = false; - const CallBase &cs = cast(*kcb->kcallInstruction->inst); + const CallBase &cs = cast(*kcb->kcallInstruction->inst()); if (isa(cs.getCalledOperand())) { isInlineAsm = true; } if (kcb->calledFunctions.empty() && !isInlineAsm && (guidance != Interpreter::GuidanceKind::ErrorGuidance || - !inMainModule(*kfp->function))) { + !inMainModule(*kfp->function()))) { kcb->calledFunctions.insert(escapingFunctions.begin(), escapingFunctions.end()); } for (auto calledFunction : kcb->calledFunctions) { - callMap[calledFunction].insert(kfp->function); + callMap[calledFunction].insert(kfp->function()); } } } @@ -546,17 +551,28 @@ unsigned KModule::getGlobalIndex(const llvm::Instruction *inst) const { /***/ -KConstant::KConstant(llvm::Constant *_ct, unsigned _id, KInstruction *_ki) { - ct = _ct; +KConstant::KConstant(llvm::Constant *_ct, unsigned _id, KInstruction *_ki) + : KValue(_ct, Kind::CONSTANT) { id = _id; ki = _ki; } +KGlobalVariable::KGlobalVariable(llvm::GlobalVariable *global) + : KValue(global, KValue::Kind::GLOBAL_VARIABLE) {} + +std::string KGlobalVariable::getSourceFilepath() const { + getLocationInfo(globalVariable()).file; +} +// Line number where the global variable is defined +size_t KGlobalVariable::getLine() const { + getLocationInfo(globalVariable()).line; +} + 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) { + : KCallable(_function, Kind::FUNCTION), globalIndex(globalIndexInc++), + parent(_km), entryKBlock(nullptr), numInstructions(0) { + for (auto &BasicBlock : *function()) { numInstructions += BasicBlock.size(); } instructions = new KInstruction *[numInstructions]; @@ -565,14 +581,14 @@ KFunction::KFunction(llvm::Function *_function, KModule *_km, unsigned n = 0; // The first arg_size() registers are reserved for formals. unsigned rnum = getNumArgs(); - for (auto &bb : *function) { + for (auto &bb : *function()) { for (auto &instr : bb) { instructionToRegisterMap[&instr] = rnum++; } } - for (llvm::Function::iterator bbit = function->begin(), - bbie = function->end(); + for (llvm::Function::iterator bbit = function()->begin(), + bbie = function()->end(); bbit != bbie; ++bbit) { KBlock *kb; Instruction *fit = &bbit->front(); @@ -599,25 +615,25 @@ KFunction::KFunction(llvm::Function *_function, KModule *_km, &instructions[n], globalIndexInc); } for (unsigned i = 0, ie = kb->getNumInstructions(); i < ie; i++, n++) { - instructionMap[instructions[n]->inst] = instructions[n]; + instructionMap[instructions[n]->inst()] = instructions[n]; } blockMap[&*bbit] = kb; blocks.push_back(std::unique_ptr(kb)); } if (blocks.size() > 0) { - assert(function->begin() != function->end()); - entryKBlock = blockMap[&*function->begin()]; + assert(function()->begin() != function()->end()); + entryKBlock = blockMap[&*function()->begin()]; } } size_t KFunction::getLine() const { - auto locationInfo = getLocationInfo(function); + auto locationInfo = getLocationInfo(function()); return locationInfo.line; } std::string KFunction::getSourceFilepath() const { - auto locationInfo = getLocationInfo(function); + auto locationInfo = getLocationInfo(function()); return locationInfo.file; } @@ -631,7 +647,7 @@ KBlock::KBlock( KFunction *_kfunction, llvm::BasicBlock *block, KModule *km, const std::unordered_map &instructionToRegisterMap, KInstruction **instructionsKF, unsigned &globalIndexInc) - : parent(_kfunction), basicBlock(block) { + : KValue(block, KValue::Kind::BLOCK), parent(_kfunction) { instructions = instructionsKF; for (auto &it : *block) { @@ -696,21 +712,21 @@ KReturnBlock::KReturnBlock( std::string KBlock::getLabel() const { std::string _label; llvm::raw_string_ostream label_stream(_label); - basicBlock->printAsOperand(label_stream, false); + basicBlock()->printAsOperand(label_stream, false); std::string label = label_stream.str(); return label; } std::string KBlock::toString() const { - return getLabel() + " in function " + parent->function->getName().str(); + 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()]; + return instructions[reg - function()->arg_size()]; } -size_t KFunction::getNumArgs() const { return function->arg_size(); } +size_t KFunction::getNumArgs() const { return function()->arg_size(); } size_t KFunction::getNumRegisters() const { - return function->arg_size() + numInstructions; + return function()->arg_size() + numInstructions; } diff --git a/lib/Module/KValue.cpp b/lib/Module/KValue.cpp new file mode 100644 index 0000000000..b540906e52 --- /dev/null +++ b/lib/Module/KValue.cpp @@ -0,0 +1,30 @@ +#include "klee/Support/CompilerWarning.h" +#include + +DISABLE_WARNING_PUSH +DISABLE_WARNING_DEPRECATED_DECLARATIONS +#include "llvm/ADT/StringRef.h" +#include "llvm/IR/Value.h" +DISABLE_WARNING_POP + +#include +#include + +using namespace klee; + +llvm::Value *KValue::unwrap() const { return value; } + +llvm::StringRef KValue::getName() const { + return value && value->hasName() ? value->getName() : ""; +} + +bool KValue::operator<(const KValue &rhs) const { + if (getName() != rhs.getName()) { + return getName() < rhs.getName(); + } + return std::less{}(unwrap(), rhs.unwrap()); +} + +[[nodiscard]] unsigned KValue::hash() const { + return std::hash{}(getName().str()); +} diff --git a/lib/Module/LocationInfo.cpp b/lib/Module/LocationInfo.cpp index 274a55e25d..6395970b08 100644 --- a/lib/Module/LocationInfo.cpp +++ b/lib/Module/LocationInfo.cpp @@ -12,6 +12,7 @@ DISABLE_WARNING_PUSH DISABLE_WARNING_DEPRECATED_DECLARATIONS +#include "llvm/ADT/SmallVector.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/IR/AssemblyAnnotationWriter.h" #include "llvm/IR/DebugInfoMetadata.h" @@ -60,4 +61,26 @@ LocationInfo getLocationInfo(const llvm::Instruction *inst) { return getLocationInfo(inst->getParent()->getParent()); } +LocationInfo getLocationInfo(const llvm::GlobalVariable *globalVar) { + // Retrieve debug information associated with global variable. + // LLVM does not expose API for getting single DINode with location + // information. + llvm::SmallVector debugInfo; + globalVar->getDebugInfo(debugInfo); + + for (const llvm::DIGlobalVariableExpression *debugInfoEntry : debugInfo) { + // Return location from any debug info for global variable. + if (const llvm::DIGlobalVariable *debugInfoGlobalVar = + debugInfoEntry->getVariable()) { + // Assume that global variable declared at line 0. + return {debugInfoGlobalVar->getFilename().str(), + debugInfoGlobalVar->getLine(), 0}; + } + } + + // Fallback to empty location if there is no appropriate debug + // info. + return {"", 0, 0}; +} + } // namespace klee diff --git a/lib/Module/SarifReport.cpp b/lib/Module/SarifReport.cpp index 6cc323a87a..aa1b403e89 100644 --- a/lib/Module/SarifReport.cpp +++ b/lib/Module/SarifReport.cpp @@ -335,8 +335,8 @@ bool Location::isInside(KBlock *block, const Instructions &origInsts) const { } else { 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) && + auto opCode = block->instructions[i]->inst()->getOpcode(); + if (!isa(block->instructions[i]->inst()) && inst->getLine() <= endLine && inst->getLine() >= startLine && inst->getColumn() <= *endColumn && inst->getColumn() >= *startColumn && diff --git a/lib/Solver/BitwuzlaSolver.cpp b/lib/Solver/BitwuzlaSolver.cpp index 3b5d9acfe1..8c53cf506d 100644 --- a/lib/Solver/BitwuzlaSolver.cpp +++ b/lib/Solver/BitwuzlaSolver.cpp @@ -771,7 +771,7 @@ class BitwuzlaIncNativeSolver { Bitwuzla &getOrInit(); bool isConsistent() const { - klee_warning("Empty isConsistent() check"); + // klee_warning("Empty isConsistent() check"); return true; } diff --git a/test/Feature/SymbolicSizes/SymbolicSizeUnsizedGlobal.c b/test/Feature/SymbolicSizes/SymbolicSizeUnsizedGlobal.c new file mode 100644 index 0000000000..37383aee60 --- /dev/null +++ b/test/Feature/SymbolicSizes/SymbolicSizeUnsizedGlobal.c @@ -0,0 +1,14 @@ +// 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 --symbolic-allocation-threshold=0 %t1.bc 2>&1 | FileCheck %s + +extern int GLOBAL[]; + +int main() { + // CHECK: SymbolicSizeUnsizedGlobal.c:[[@LINE+1]]: memory error: out of bound pointer + GLOBAL[1] = 0; + // CHECK: SymbolicSizeUnsizedGlobal.c:[[@LINE+1]]: memory error: out of bound pointer + GLOBAL[2] = 0; + // CHECK-NOT: SymbolicSizeUnsizedGlobal.c:[[@LINE+1]]: memory error: out of bound pointer + GLOBAL[0] = 0; +} From d9f3156b3fa21add3566464777b03770206812d9 Mon Sep 17 00:00:00 2001 From: Sergey Morozov Date: Thu, 14 Dec 2023 19:12:00 +0300 Subject: [PATCH 097/120] [refactor] The KValue was stripped of public constructor and made abstract. --- include/klee/Module/KCallable.h | 18 +++++++--- include/klee/Module/KModule.h | 24 +++++++++++--- include/klee/Module/KValue.h | 12 ++----- lib/Module/KModule.cpp | 58 ++++++++++++++++++++++++++++++--- lib/Module/KValue.cpp | 13 +------- 5 files changed, 91 insertions(+), 34 deletions(-) diff --git a/include/klee/Module/KCallable.h b/include/klee/Module/KCallable.h index a54a1c32dc..72ae9f5b44 100644 --- a/include/klee/Module/KCallable.h +++ b/include/klee/Module/KCallable.h @@ -10,8 +10,6 @@ #ifndef KLEE_KCALLABLE_H #define KLEE_KCALLABLE_H -#include - #include "klee/Module/KValue.h" #include "klee/Support/CompilerWarning.h" DISABLE_WARNING_PUSH @@ -23,9 +21,12 @@ DISABLE_WARNING_DEPRECATED_DECLARATIONS #include "llvm/Support/Casting.h" DISABLE_WARNING_POP +#include +#include + namespace klee { /// Wrapper for callable objects passed in callExternalFunction -class KCallable : public KValue { +struct KCallable : public KValue { protected: KCallable(llvm::Value *value, KValue::Kind kind) : KValue(value, kind) {} @@ -38,7 +39,7 @@ class KCallable : public KValue { } }; -class KInlineAsm : public KCallable { +struct KInlineAsm : public KCallable { private: /* Prepared name of ASM code */ std::string name; @@ -66,6 +67,15 @@ class KInlineAsm : public KCallable { [[nodiscard]] llvm::InlineAsm *inlineAsm() const { return llvm::dyn_cast(value); } + + [[nodiscard]] bool operator<(const KValue &rhs) const override { + return getKind() == rhs.getKind() + ? getName() < llvm::cast(rhs).getName() + : getKind() < rhs.getKind(); + } + [[nodiscard]] unsigned hash() const override { + return std::hash{}(name); + } }; } // namespace klee diff --git a/include/klee/Module/KModule.h b/include/klee/Module/KModule.h index 388cd73b14..d46daf029d 100644 --- a/include/klee/Module/KModule.h +++ b/include/klee/Module/KModule.h @@ -89,9 +89,13 @@ struct KBlock : public KValue { /// Block number in function [[nodiscard]] uintptr_t getId() const; + [[nodiscard]] unsigned inModuleID() const; + + [[nodiscard]] bool operator<(const KValue &rhs) const override; + [[nodiscard]] unsigned hash() const override; static bool classof(const KValue *rhs) { - return rhs->getKind() == Kind::BLOCK ? classof(cast(rhs)) : false; + return rhs->getKind() == Kind::BLOCK && classof(cast(rhs)); } }; @@ -118,7 +122,7 @@ struct KCallBlock : KBlock { KFunction *getKFunction() const; static bool classof(const KValue *rhs) { - return rhs->getKind() == Kind::BLOCK ? classof(cast(rhs)) : false; + return rhs->getKind() == Kind::BLOCK && classof(cast(rhs)); } }; @@ -135,7 +139,7 @@ struct KReturnBlock : KBlock { KBlockType getKBlockType() const override { return KBlockType::Return; }; static bool classof(const KValue *rhs) { - return rhs->getKind() == Kind::BLOCK ? classof(cast(rhs)) : false; + return rhs->getKind() == Kind::BLOCK && classof(cast(rhs)); } }; @@ -198,6 +202,9 @@ struct KFunction : public KCallable { [[nodiscard]] size_t getLine() const; [[nodiscard]] std::string getSourceFilepath() const; + [[nodiscard]] bool operator<(const KValue &rhs) const override; + [[nodiscard]] unsigned hash() const override; + /// Unique index for KFunction and KInstruction inside KModule /// from 0 to [KFunction + KInstruction] [[nodiscard]] inline unsigned getGlobalIndex() const { return globalIndex; } @@ -236,11 +243,17 @@ struct KConstant : public KValue { [[nodiscard]] static bool classof(const KValue *rhs) { return rhs->getKind() == KValue::Kind::CONSTANT; } + + [[nodiscard]] bool operator<(const KValue &rhs) const override; + [[nodiscard]] unsigned hash() const override; }; struct KGlobalVariable : public KValue { public: - KGlobalVariable(llvm::GlobalVariable *global); + // ID of the global variable + const unsigned id; + + KGlobalVariable(llvm::GlobalVariable *global, unsigned id); [[nodiscard]] llvm::GlobalVariable *globalVariable() const { return llvm::dyn_cast_or_null(value); @@ -250,6 +263,9 @@ struct KGlobalVariable : public KValue { return rhs->getKind() == KValue::Kind::GLOBAL_VARIABLE; } + [[nodiscard]] bool operator<(const KValue &rhs) const override; + [[nodiscard]] unsigned hash() const override; + // Filename where the global variable is defined [[nodiscard]] std::string getSourceFilepath() const; // Line number where the global variable is defined diff --git a/include/klee/Module/KValue.h b/include/klee/Module/KValue.h index 1a6367fc26..857d7651af 100644 --- a/include/klee/Module/KValue.h +++ b/include/klee/Module/KValue.h @@ -28,25 +28,19 @@ struct KValue { /* Kind of KValue required for llvm rtti purposes */ const Kind kind; - /* Inner constructor for setting kind */ + /* Inner constructor for setting value and kind */ KValue(llvm::Value *const value, const Kind kind) : value(value), kind(kind) {} public: - /* Construct KValue from raw llvm::Value. */ - KValue(llvm::Value *const value) : KValue(value, Kind::VALUE) { - /* NB: heirs of this class should use inner constructor instead. - This constructor exposes convenient public interface. */ - } - /* Unwraps KValue to receive inner value. */ [[nodiscard]] llvm::Value *unwrap() const; /* Returns name of inner value if so exists. */ [[nodiscard]] virtual llvm::StringRef getName() const; - [[nodiscard]] virtual bool operator<(const KValue &rhs) const; - [[nodiscard]] virtual unsigned hash() const; + [[nodiscard]] virtual bool operator<(const KValue &rhs) const = 0; + [[nodiscard]] virtual unsigned hash() const = 0; /* Kind of value. Serves for llvm rtti purposes. */ [[nodiscard]] Kind getKind() const { return kind; } diff --git a/lib/Module/KModule.cpp b/lib/Module/KModule.cpp index 6d686f1a6e..0aac22578e 100644 --- a/lib/Module/KModule.cpp +++ b/lib/Module/KModule.cpp @@ -401,8 +401,9 @@ void KModule::manifest(InterpreterHandler *ih, functions.push_back(std::move(kf)); } + unsigned globalID = 0; for (auto &global : module->globals()) { - globalMap.emplace(&global, new KGlobalVariable(&global)); + globalMap.emplace(&global, new KGlobalVariable(&global, globalID++)); } /* Compute various interesting properties */ @@ -557,15 +558,32 @@ KConstant::KConstant(llvm::Constant *_ct, unsigned _id, KInstruction *_ki) ki = _ki; } -KGlobalVariable::KGlobalVariable(llvm::GlobalVariable *global) - : KValue(global, KValue::Kind::GLOBAL_VARIABLE) {} +bool KConstant::operator<(const KValue &rhs) const { + return getKind() == rhs.getKind() ? id < cast(rhs).id + : getKind() < rhs.getKind(); +} + +unsigned KConstant::hash() const { return id; } + +KGlobalVariable::KGlobalVariable(llvm::GlobalVariable *global, unsigned id) + : KValue(global, KValue::Kind::GLOBAL_VARIABLE), id(id) {} std::string KGlobalVariable::getSourceFilepath() const { - getLocationInfo(globalVariable()).file; + return getLocationInfo(globalVariable()).file; } // Line number where the global variable is defined size_t KGlobalVariable::getLine() const { - getLocationInfo(globalVariable()).line; + return getLocationInfo(globalVariable()).line; +} + +bool KGlobalVariable::operator<(const KValue &rhs) const { + return getKind() == rhs.getKind() ? id < cast(rhs).id + : getKind() < rhs.getKind(); +} +unsigned KGlobalVariable::hash() const { + // It is good enough value to use it as hash as ID of globals + // different. + return id; } KFunction::KFunction(llvm::Function *_function, KModule *_km, @@ -669,6 +687,23 @@ KBlock::KBlock( } } +unsigned KBlock::inModuleID() const { + return parent->getGlobalIndex() + static_cast(getId()); +} + +bool KBlock::operator<(const KValue &rhs) const { + // Additional comparison on block types is redundant, + // as inModuleID defines the position of block. + return getKind() == rhs.getKind() + ? inModuleID() < cast(rhs).inModuleID() + : getKind() < rhs.getKind(); +} + +unsigned KBlock::hash() const { + // Use position of a block as a hash + return inModuleID(); +} + KCallBlock::KCallBlock( KFunction *_kfunction, llvm::BasicBlock *block, KModule *km, const std::unordered_map &instructionToRegisterMap, @@ -726,6 +761,19 @@ uintptr_t KBlock::getId() const { return instructions - parent->instructions; } KInstruction *KFunction::getInstructionByRegister(size_t reg) const { return instructions[reg - function()->arg_size()]; } + +bool KFunction::operator<(const KValue &rhs) const { + return getKind() == rhs.getKind() + ? KFunctionCompare{}(this, cast(&rhs)) + : getKind() < rhs.getKind(); +} + +unsigned KFunction::hash() const { + // It is good enough value to use it as + // index is unique. + return id; +} + size_t KFunction::getNumArgs() const { return function()->arg_size(); } size_t KFunction::getNumRegisters() const { return function()->arg_size() + numInstructions; diff --git a/lib/Module/KValue.cpp b/lib/Module/KValue.cpp index b540906e52..d506e612e2 100644 --- a/lib/Module/KValue.cpp +++ b/lib/Module/KValue.cpp @@ -1,5 +1,5 @@ +#include "klee/Module/KValue.h" #include "klee/Support/CompilerWarning.h" -#include DISABLE_WARNING_PUSH DISABLE_WARNING_DEPRECATED_DECLARATIONS @@ -17,14 +17,3 @@ llvm::Value *KValue::unwrap() const { return value; } llvm::StringRef KValue::getName() const { return value && value->hasName() ? value->getName() : ""; } - -bool KValue::operator<(const KValue &rhs) const { - if (getName() != rhs.getName()) { - return getName() < rhs.getName(); - } - return std::less{}(unwrap(), rhs.unwrap()); -} - -[[nodiscard]] unsigned KValue::hash() const { - return std::hash{}(getName().str()); -} From 86e19ba1b503e0459c1a65bd01bc52345f8870ec Mon Sep 17 00:00:00 2001 From: Sergey Morozov Date: Mon, 18 Dec 2023 16:45:01 +0300 Subject: [PATCH 098/120] [refactor] KBlock made abstract, reduntant VALUE constant from KValueKind enum. --- include/klee/Module/KModule.h | 47 ++++++++++++++++++++++++----------- include/klee/Module/KValue.h | 1 - lib/Expr/SymbolicSource.cpp | 6 +---- lib/Module/KModule.cpp | 39 ++++++++++++++++++----------- 4 files changed, 59 insertions(+), 34 deletions(-) diff --git a/include/klee/Module/KModule.h b/include/klee/Module/KModule.h index d46daf029d..5b8871b2e2 100644 --- a/include/klee/Module/KModule.h +++ b/include/klee/Module/KModule.h @@ -67,18 +67,17 @@ struct KBlock : public KValue { return llvm::dyn_cast_or_null(value); } -public: +private: + const KBlockType blockKind; + +protected: KBlock(KFunction *, llvm::BasicBlock *, KModule *, const std::unordered_map &, - KInstruction **, unsigned &globalIndexInc); - KBlock() = delete; + KInstruction **, unsigned &globalIndexInc, KBlockType blockType); KBlock(const KBlock &) = delete; KBlock &operator=(const KBlock &) = delete; - virtual ~KBlock() = default; - - virtual KBlockType getKBlockType() const { return KBlockType::Base; } - static bool classof(const KBlock *) { return true; } +public: unsigned getNumInstructions() const noexcept { return basicBlock()->size(); } KInstruction *getFirstInstruction() const noexcept { return instructions[0]; } KInstruction *getLastInstruction() const noexcept { @@ -89,11 +88,19 @@ struct KBlock : public KValue { /// Block number in function [[nodiscard]] uintptr_t getId() const; - [[nodiscard]] unsigned inModuleID() const; + // Block number in module + [[nodiscard]] unsigned getGlobalIndex() const; + + /// Util methods defined for KValue [[nodiscard]] bool operator<(const KValue &rhs) const override; [[nodiscard]] unsigned hash() const override; + /// For LLVM RTTI purposes in KBlock inheritance system + [[nodiscard]] KBlockType getKBlockType() const { return blockKind; } + static bool classof(const KBlock *) { return true; } + + /// For LLVM RTTI purposes in KValue inheritance system static bool classof(const KValue *rhs) { return rhs->getKind() == Kind::BLOCK && classof(cast(rhs)); } @@ -101,12 +108,28 @@ struct KBlock : public KValue { typedef std::function KBlockPredicate; +struct KBasicBlock : public KBlock { +public: + KBasicBlock(KFunction *, llvm::BasicBlock *, KModule *, + const std::unordered_map &, + KInstruction **, unsigned &globalIndexInc); + + /// For LLVM RTTI purposes in KBlock inheritance system + static bool classof(const KBlock *rhs) { + return rhs->getKBlockType() == KBlockType::Base; + } + + /// For LLVM RTTI purposes in KValue inheritance system + static bool classof(const KValue *rhs) { + return rhs->getKind() == Kind::BLOCK && classof(cast(rhs)); + } +}; + struct KCallBlock : KBlock { KInstruction *kcallInstruction; std::set calledFunctions; public: - KCallBlock() = delete; KCallBlock(KFunction *, llvm::BasicBlock *, KModule *, const std::unordered_map &, std::set, KInstruction **, @@ -115,7 +138,6 @@ struct KCallBlock : KBlock { static bool classof(const KBlock *E) { return E->getKBlockType() == KBlockType::Call; } - KBlockType getKBlockType() const override { return KBlockType::Call; }; bool intrinsic() const; bool internal() const; bool kleeHandled() const; @@ -128,7 +150,6 @@ struct KCallBlock : KBlock { struct KReturnBlock : KBlock { public: - KReturnBlock() = delete; KReturnBlock(KFunction *, llvm::BasicBlock *, KModule *, const std::unordered_map &, KInstruction **, unsigned &globalIndexInc); @@ -136,7 +157,6 @@ struct KReturnBlock : KBlock { static bool classof(const KBlock *E) { return E->getKBlockType() == KBlockType::Return; } - KBlockType getKBlockType() const override { return KBlockType::Return; }; static bool classof(const KValue *rhs) { return rhs->getKind() == Kind::BLOCK && classof(cast(rhs)); @@ -174,11 +194,10 @@ struct KFunction : public KCallable { bool kleeHandled = false; explicit KFunction(llvm::Function *, KModule *, unsigned &); - KFunction() = delete; KFunction(const KFunction &) = delete; KFunction &operator=(const KFunction &) = delete; - ~KFunction(); + ~KFunction() override; unsigned getArgRegister(unsigned index) const { return index; } diff --git a/include/klee/Module/KValue.h b/include/klee/Module/KValue.h index 857d7651af..278ebed39d 100644 --- a/include/klee/Module/KValue.h +++ b/include/klee/Module/KValue.h @@ -18,7 +18,6 @@ struct KValue { FUNCTION, INLINE_ASM, INSTRUCTION, - VALUE, }; protected: diff --git a/lib/Expr/SymbolicSource.cpp b/lib/Expr/SymbolicSource.cpp index f0321ec55a..2dc798d32d 100644 --- a/lib/Expr/SymbolicSource.cpp +++ b/lib/Expr/SymbolicSource.cpp @@ -103,11 +103,7 @@ int SymbolicSizeConstantAddressSource::internalCompare( return size < ub.size ? -1 : 1; } if (allocSite != ub.allocSite) { - if (allocSite->getKind() == ub.allocSite->getKind()) { - return *allocSite < *ub.allocSite ? -1 : 1; - } else { - return allocSite->getKind() < ub.allocSite->getKind() ? -1 : 1; - } + return *allocSite < *ub.allocSite ? -1 : 1; } return 0; diff --git a/lib/Module/KModule.cpp b/lib/Module/KModule.cpp index 0aac22578e..f7ce474bdb 100644 --- a/lib/Module/KModule.cpp +++ b/lib/Module/KModule.cpp @@ -619,9 +619,9 @@ KFunction::KFunction(llvm::Function *_function, KModule *_km, if (f) { calledFunctions.insert(f); } - auto *ckb = - new KCallBlock(this, &*bbit, parent, instructionToRegisterMap, - calledFunctions, &instructions[n], globalIndexInc); + auto *ckb = new KCallBlock(this, &*bbit, parent, instructionToRegisterMap, + std::move(calledFunctions), &instructions[n], + globalIndexInc); kCallBlocks.push_back(ckb); kb = ckb; } else if (SplitReturns && isa(lit)) { @@ -629,8 +629,8 @@ KFunction::KFunction(llvm::Function *_function, KModule *_km, &instructions[n], globalIndexInc); returnKBlocks.push_back(kb); } else { - kb = new KBlock(this, &*bbit, parent, instructionToRegisterMap, - &instructions[n], globalIndexInc); + kb = new KBasicBlock(this, &*bbit, parent, instructionToRegisterMap, + &instructions[n], globalIndexInc); } for (unsigned i = 0, ie = kb->getNumInstructions(); i < ie; i++, n++) { instructionMap[instructions[n]->inst()] = instructions[n]; @@ -664,8 +664,10 @@ KFunction::~KFunction() { KBlock::KBlock( KFunction *_kfunction, llvm::BasicBlock *block, KModule *km, const std::unordered_map &instructionToRegisterMap, - KInstruction **instructionsKF, unsigned &globalIndexInc) - : KValue(block, KValue::Kind::BLOCK), parent(_kfunction) { + KInstruction **instructionsKF, unsigned &globalIndexInc, + KBlockType blockType) + : KValue(block, KValue::Kind::BLOCK), blockKind(blockType), + parent(_kfunction) { instructions = instructionsKF; for (auto &it : *block) { @@ -687,21 +689,21 @@ KBlock::KBlock( } } -unsigned KBlock::inModuleID() const { - return parent->getGlobalIndex() + static_cast(getId()); +unsigned KBlock::getGlobalIndex() const { + return getFirstInstruction()->getGlobalIndex(); } bool KBlock::operator<(const KValue &rhs) const { // Additional comparison on block types is redundant, - // as inModuleID defines the position of block. + // as getGlobalIndex defines the position of block. return getKind() == rhs.getKind() - ? inModuleID() < cast(rhs).inModuleID() + ? getGlobalIndex() < cast(rhs).getGlobalIndex() : getKind() < rhs.getKind(); } unsigned KBlock::hash() const { // Use position of a block as a hash - return inModuleID(); + return getGlobalIndex(); } KCallBlock::KCallBlock( @@ -710,7 +712,7 @@ KCallBlock::KCallBlock( std::set _calledFunctions, KInstruction **instructionsKF, unsigned &globalIndexInc) : KBlock::KBlock(_kfunction, block, km, instructionToRegisterMap, - instructionsKF, globalIndexInc), + instructionsKF, globalIndexInc, KBlockType::Call), kcallInstruction(this->instructions[0]), calledFunctions(std::move(_calledFunctions)) {} @@ -737,12 +739,21 @@ KFunction *KCallBlock::getKFunction() const { : nullptr; } +KBasicBlock::KBasicBlock(KFunction *_kfunction, llvm::BasicBlock *block, + KModule *km, + const std::unordered_map + &instructionToRegisterMap, + KInstruction **instructionsKF, + unsigned &globalIndexInc) + : KBlock::KBlock(_kfunction, block, km, instructionToRegisterMap, + instructionsKF, globalIndexInc, KBlockType::Base) {} + KReturnBlock::KReturnBlock( KFunction *_kfunction, llvm::BasicBlock *block, KModule *km, const std::unordered_map &instructionToRegisterMap, KInstruction **instructionsKF, unsigned &globalIndexInc) : KBlock::KBlock(_kfunction, block, km, instructionToRegisterMap, - instructionsKF, globalIndexInc) {} + instructionsKF, globalIndexInc, KBlockType::Return) {} std::string KBlock::getLabel() const { std::string _label; From f0fabeb4cc7cfa21fd3bab03cdea0b0dec529fc6 Mon Sep 17 00:00:00 2001 From: Sergey Morozov Date: Thu, 21 Dec 2023 15:03:50 +0300 Subject: [PATCH 099/120] [refactor] Added ByteWidth type. Separated symbolicSizeConstantAddress factory method for instructions and global variables. Added consistency check in bitwuzla. --- include/klee/Core/Context.h | 4 +++- include/klee/Expr/Expr.h | 5 +++++ include/klee/Expr/SourceBuilder.h | 9 ++++++++- lib/Core/Executor.cpp | 25 ++++++++++++++++--------- lib/Expr/Expr.cpp | 4 ++++ lib/Expr/SourceBuilder.cpp | 11 ++++++++++- lib/Solver/BitwuzlaSolver.cpp | 3 +-- 7 files changed, 47 insertions(+), 14 deletions(-) diff --git a/include/klee/Core/Context.h b/include/klee/Core/Context.h index 34298eb37e..57a9a0f706 100644 --- a/include/klee/Core/Context.h +++ b/include/klee/Core/Context.h @@ -41,7 +41,9 @@ class Context { /// Returns width of the pointer in bits Expr::Width getPointerWidth() const { return PointerWidth; } - Expr::Width getPointerWidthInBytes() const { return PointerWidth / CHAR_BIT; } + Expr::ByteWidth getPointerWidthInBytes() const { + return (PointerWidth + CHAR_BIT - 1) / CHAR_BIT; + } }; } // namespace klee diff --git a/include/klee/Expr/Expr.h b/include/klee/Expr/Expr.h index 9937999e2e..c0cf039458 100644 --- a/include/klee/Expr/Expr.h +++ b/include/klee/Expr/Expr.h @@ -138,6 +138,10 @@ class Expr { /// The type of an expression is simply its width, in bits. typedef unsigned Width; + /// Width of an expression in bytes. + /// ByteWidth = (Width + CHAR_BIT - 1) / CHAR_BIT + typedef unsigned ByteWidth; + // NOTE: The prefix "Int" in no way implies the integer type of expression. // For example, Int64 can indicate i64, double or <2 * i32> in different // cases. @@ -292,6 +296,7 @@ class Expr { virtual Kind getKind() const = 0; virtual Width getWidth() const = 0; + ByteWidth getByteWidth() const; virtual unsigned getNumKids() const = 0; virtual ref getKid(unsigned i) const = 0; diff --git a/include/klee/Expr/SourceBuilder.h b/include/klee/Expr/SourceBuilder.h index 9a3e2035ee..f922a29861 100644 --- a/include/klee/Expr/SourceBuilder.h +++ b/include/klee/Expr/SourceBuilder.h @@ -5,6 +5,9 @@ namespace klee { +class KInstruction; +class KGlobalVariable; + template class SparseStorage; template class ref; @@ -18,8 +21,12 @@ class SourceBuilder { static ref uninitialized(unsigned version, const KInstruction *allocSite); static ref - symbolicSizeConstantAddress(unsigned version, const KValue *allocSite, + symbolicSizeConstantAddress(unsigned version, const KInstruction *allocSite, ref size); + static ref + symbolicSizeConstantAddress(unsigned version, + const KGlobalVariable *allocSite, ref size); + static ref makeSymbolic(const std::string &name, unsigned version); static ref lazyInitializationAddress(ref pointer); diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index 89fe7eb2f8..6cad5cd367 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -5593,22 +5593,29 @@ MemoryObject *Executor::allocate(ExecutionState &state, ref size, Expr::Width pointerWidthInBits = Context::get().getPointerWidth(); - /* Create symbol for array */ - KValue *ki = nullptr; + /// Determine source for address array: + /// * LI source if allocate occures on lazi initialization + /// * Otherwise choose source depending on the allocation site + ref sourceAddressArray; if (!lazyInitializationSource) { if (auto inst = dyn_cast(allocSite)) { - ki = kmodule->getKBlock(inst->getParent())->parent->instructionMap[inst]; + KInstruction *ki = + kmodule->getKBlock(inst->getParent())->parent->instructionMap[inst]; + sourceAddressArray = SourceBuilder::symbolicSizeConstantAddress( + updateNameVersion(state, "const_arr"), ki, size); } else if (auto global = dyn_cast(allocSite)) { - ki = kmodule->globalMap[global].get(); + KGlobalVariable *kgb = kmodule->globalMap[global].get(); + sourceAddressArray = SourceBuilder::symbolicSizeConstantAddress( + updateNameVersion(state, "const_arr"), kgb, size); } + } else { + sourceAddressArray = + SourceBuilder::lazyInitializationAddress(lazyInitializationSource); } + /* Create symbol for array */ const Array *addressArray = makeArray( - Expr::createPointer(pointerWidthInBits / CHAR_BIT), - lazyInitializationSource - ? SourceBuilder::lazyInitializationAddress(lazyInitializationSource) - : SourceBuilder::symbolicSizeConstantAddress( - updateNameVersion(state, "const_arr"), ki, size)); + Expr::createPointer(pointerWidthInBits / CHAR_BIT), sourceAddressArray); ref addressExpr = Expr::createTempRead(addressArray, pointerWidthInBits); diff --git a/lib/Expr/Expr.cpp b/lib/Expr/Expr.cpp index 90f2380709..c6fa1b844d 100644 --- a/lib/Expr/Expr.cpp +++ b/lib/Expr/Expr.cpp @@ -527,6 +527,10 @@ ref Expr::createTrue() { return ConstantExpr::create(1, Expr::Bool); } ref Expr::createFalse() { return ConstantExpr::create(0, Expr::Bool); } +Expr::ByteWidth Expr::getByteWidth() const { + return (getWidth() + CHAR_BIT - 1) / CHAR_BIT; +} + void Expr::print(llvm::raw_ostream &os) const { ExprPPrinter::printSingleExpr(os, const_cast(this)); } diff --git a/lib/Expr/SourceBuilder.cpp b/lib/Expr/SourceBuilder.cpp index 680cc747b6..b49111e4f6 100644 --- a/lib/Expr/SourceBuilder.cpp +++ b/lib/Expr/SourceBuilder.cpp @@ -2,6 +2,7 @@ #include "klee/ADT/SparseStorage.h" #include "klee/Expr/Expr.h" #include "klee/Expr/SymbolicSource.h" +#include "klee/Module/KInstruction.h" #include "klee/Module/KModule.h" #include "klee/Module/KValue.h" @@ -22,7 +23,15 @@ SourceBuilder::uninitialized(unsigned version, const KInstruction *allocSite) { } ref SourceBuilder::symbolicSizeConstantAddress( - unsigned version, const KValue *allocSite, ref size) { + unsigned version, const KInstruction *allocSite, ref size) { + ref r = + new SymbolicSizeConstantAddressSource(version, allocSite, size); + r->computeHash(); + return r; +} + +ref SourceBuilder::symbolicSizeConstantAddress( + unsigned version, const KGlobalVariable *allocSite, ref size) { ref r( new SymbolicSizeConstantAddressSource(version, allocSite, size)); r->computeHash(); diff --git a/lib/Solver/BitwuzlaSolver.cpp b/lib/Solver/BitwuzlaSolver.cpp index 8c53cf506d..8c7263f0d5 100644 --- a/lib/Solver/BitwuzlaSolver.cpp +++ b/lib/Solver/BitwuzlaSolver.cpp @@ -771,8 +771,7 @@ class BitwuzlaIncNativeSolver { Bitwuzla &getOrInit(); bool isConsistent() const { - // klee_warning("Empty isConsistent() check"); - return true; + return frames.framesSize() == env.objects.framesSize(); } void dump() const { ::klee::dump(frames); } From 572400540999df0f06ee7791c0032d6e06e592e7 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Mon, 18 Dec 2023 14:10:18 +0400 Subject: [PATCH 100/120] [chore] Remove submodules --- .gitmodules | 6 ------ json | 1 - optional | 1 - 3 files changed, 8 deletions(-) delete mode 100644 .gitmodules delete mode 160000 json delete mode 160000 optional diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index d21b6002fc..0000000000 --- a/.gitmodules +++ /dev/null @@ -1,6 +0,0 @@ -[submodule "json"] - path = json - url = https://github.com/nlohmann/json.git -[submodule "optional"] - path = optional - url = https://github.com/martinmoene/optional-lite.git diff --git a/json b/json deleted file mode 160000 index 6af826d0bd..0000000000 --- a/json +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 6af826d0bdb55e4b69e3ad817576745335f243ca diff --git a/optional b/optional deleted file mode 160000 index 0723abd03b..0000000000 --- a/optional +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 0723abd03b25fb11997fcb6cff6471408fc33072 From d2382751af4c09509eeb19568fb4ad2135707a68 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhnik Date: Mon, 25 Dec 2023 01:36:43 +0400 Subject: [PATCH 101/120] [chore] Add `json` and `optional` into `build.sh` --- .github/workflows/build.yaml | 2 + CMakeLists.txt | 4 +- Dockerfile | 2 + build.sh | 8 +++- scripts/build/p-json-linux-ubuntu.inc | 15 ++++++++ scripts/build/p-json-osx.inc | 6 +++ scripts/build/p-json.inc | 46 +++++++++++++++++++++++ scripts/build/p-klee.inc | 4 +- scripts/build/p-optional-linux-ubuntu.inc | 15 ++++++++ scripts/build/p-optional-osx.inc | 6 +++ scripts/build/p-optional.inc | 46 +++++++++++++++++++++++ scripts/build/v-json.inc | 10 +++++ scripts/build/v-klee.inc | 4 +- scripts/build/v-optional.inc | 10 +++++ 14 files changed, 172 insertions(+), 6 deletions(-) create mode 100644 scripts/build/p-json-linux-ubuntu.inc create mode 100644 scripts/build/p-json-osx.inc create mode 100644 scripts/build/p-json.inc create mode 100644 scripts/build/p-optional-linux-ubuntu.inc create mode 100644 scripts/build/p-optional-osx.inc create mode 100644 scripts/build/p-optional.inc create mode 100644 scripts/build/v-json.inc create mode 100644 scripts/build/v-optional.inc diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 1813a8ef4a..2ce3cc004b 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -31,6 +31,8 @@ env: SQLITE_VERSION: 3400100 BITWUZLA_VERSION: main BITWUZLA_COMMIT: 80ef7cd803e1c71b5939c3eb951f1736388f7090 + JSON_VERSION: v3.11.3 + OPTIONAL_VERSION: v3.5.0 jobs: Linux: diff --git a/CMakeLists.txt b/CMakeLists.txt index 5ce961bad5..9fdcf66504 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -678,8 +678,8 @@ configure_file(${CMAKE_SOURCE_DIR}/include/klee/Config/CompileTimeInfo.h.cmin ################################################################################ include_directories("${CMAKE_BINARY_DIR}/include") include_directories("${CMAKE_SOURCE_DIR}/include") -include_directories("${CMAKE_SOURCE_DIR}/json/include") -include_directories("${CMAKE_SOURCE_DIR}/optional/include") +include_directories("${OPTIONAL_SRC_DIR}/include") +include_directories("${JSON_SRC_DIR}/include") # set(KLEE_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/include ${CMAKE_BINARY_DIR}/include) ################################################################################ diff --git a/Dockerfile b/Dockerfile index d345ff5c63..ffa874e484 100644 --- a/Dockerfile +++ b/Dockerfile @@ -34,6 +34,8 @@ ENV Z3_VERSION=4.8.15 ENV USE_LIBCXX=1 ENV KLEE_RUNTIME_BUILD="Debug+Asserts" ENV SQLITE_VERSION=3400100 +ENV JSON_VERSION=v3.11.3 +ENV OPTIONAL_VERSION=v3.5.0 LABEL maintainer="KLEE Developers" # TODO remove adding sudo package diff --git a/build.sh b/build.sh index 24f537596b..5be34884e4 100755 --- a/build.sh +++ b/build.sh @@ -40,6 +40,12 @@ SOLVERS=BITWUZLA:Z3:STP ## Google Test Required options GTEST_VERSION=1.11.0 +## json options +JSON_VERSION=v3.11.3 + +## optional options +OPTIONAL_VERSION=v3.5.0 + ## UClibC Required options UCLIBC_VERSION=klee_uclibc_v1.3 # LLVM_VERSION is also required for UClibC @@ -53,4 +59,4 @@ MINISAT_VERSION=master BITWUZLA_VERSION=main BITWUZLA_COMMIT=80ef7cd803e1c71b5939c3eb951f1736388f7090 -BASE="$BASE" KLEE_RUNTIME_BUILD=$KLEE_RUNTIME_BUILD COVERAGE=$COVERAGE ENABLE_DOXYGEN=$ENABLE_DOXYGEN USE_TCMALLOC=$USE_TCMALLOC USE_LIBCXX=$USE_LIBCXX LLVM_VERSION=$LLVM_VERSION ENABLE_OPTIMIZED=$ENABLE_OPTIMIZED ENABLE_DEBUG=$ENABLE_DEBUG DISABLE_ASSERTIONS=$DISABLE_ASSERTIONS REQUIRES_RTTI=$REQUIRES_RTTI SOLVERS=$SOLVERS GTEST_VERSION=$GTEST_VERSION UCLIBC_VERSION=$UCLIBC_VERSION STP_VERSION=$STP_VERSION MINISAT_VERSION=$MINISAT_VERSION Z3_VERSION=$Z3_VERSION BITWUZLA_VERSION=$BITWUZLA_VERSION BITWUZLA_COMMIT=$BITWUZLA_COMMIT SQLITE_VERSION=$SQLITE_VERSION ./scripts/build/build.sh klee --install-system-deps +BASE="$BASE" KLEE_RUNTIME_BUILD=$KLEE_RUNTIME_BUILD COVERAGE=$COVERAGE ENABLE_DOXYGEN=$ENABLE_DOXYGEN USE_TCMALLOC=$USE_TCMALLOC USE_LIBCXX=$USE_LIBCXX LLVM_VERSION=$LLVM_VERSION ENABLE_OPTIMIZED=$ENABLE_OPTIMIZED ENABLE_DEBUG=$ENABLE_DEBUG DISABLE_ASSERTIONS=$DISABLE_ASSERTIONS REQUIRES_RTTI=$REQUIRES_RTTI SOLVERS=$SOLVERS GTEST_VERSION=$GTEST_VERSION UCLIBC_VERSION=$UCLIBC_VERSION STP_VERSION=$STP_VERSION MINISAT_VERSION=$MINISAT_VERSION Z3_VERSION=$Z3_VERSION BITWUZLA_VERSION=$BITWUZLA_VERSION BITWUZLA_COMMIT=$BITWUZLA_COMMIT SQLITE_VERSION=$SQLITE_VERSION JSON_VERSION=$JSON_VERSION OPTIONAL_VERSION=$OPTIONAL_VERSION ./scripts/build/build.sh klee --install-system-deps diff --git a/scripts/build/p-json-linux-ubuntu.inc b/scripts/build/p-json-linux-ubuntu.inc new file mode 100644 index 0000000000..37538f86a1 --- /dev/null +++ b/scripts/build/p-json-linux-ubuntu.inc @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +install_build_dependencies_json() { + source "${DIR}/common-functions" + with_sudo apt update -y + + dependencies=( + ca-certificates + wget + unzip + git + ) + + #Install essential dependencies + with_sudo apt -y --no-install-recommends install "${dependencies[@]}" +} diff --git a/scripts/build/p-json-osx.inc b/scripts/build/p-json-osx.inc new file mode 100644 index 0000000000..4ca06662d8 --- /dev/null +++ b/scripts/build/p-json-osx.inc @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +install_build_dependencies_json() { + # Install essential dependency + # Ignore if already installed + brew install wget || /usr/bin/true +} diff --git a/scripts/build/p-json.inc b/scripts/build/p-json.inc new file mode 100644 index 0000000000..66a1ee6f54 --- /dev/null +++ b/scripts/build/p-json.inc @@ -0,0 +1,46 @@ +#!/usr/bin/env bash +setup_build_variables_json() { + JSON_INSTALL_PATH="${BASE}/json-${JSON_VERSION}" + json_url="https://github.com/nlohmann/json.git" + return 0 +} + +download_json() { + source "${DIR}/common-functions" + # Download json + git_clone_or_update "${json_url}" "${JSON_INSTALL_PATH}" "${JSON_VERSION}" + touch "${JSON_INSTALL_PATH}"/.is_installed +} + +build_json() { + return 0 +} + +install_json() { + return 0 +} + +is_installed_json() { + ( + setup_build_variables_json + [[ -f "${JSON_INSTALL_PATH}"/.is_installed ]] + ) || return 1 +} + +get_build_artifacts_json() { + ( + setup_build_variables_json + echo "${JSON_INSTALL_PATH}" + ) +} + +setup_artifact_variables_json() { + setup_build_variables_json +} + +get_docker_config_id_json() { + ( + setup_build_variables_json + echo "${JSON_VERSION}" + ) +} diff --git a/scripts/build/p-klee.inc b/scripts/build/p-klee.inc index b484cc9281..dd8ba17aff 100644 --- a/scripts/build/p-klee.inc +++ b/scripts/build/p-klee.inc @@ -19,6 +19,8 @@ build_klee() { local CMAKE_ARGUMENTS=( "-DLLVM_DIR=${LLVM_INSTALL}" "-DGTEST_SRC_DIR=${GTEST_INSTALL_PATH}" + "-DJSON_SRC_DIR=${JSON_INSTALL_PATH}" + "-DOPTIONAL_SRC_DIR=${OPTIONAL_INSTALL_PATH}" "-DENABLE_UNIT_TESTS=TRUE" "-DENABLE_SYSTEM_TESTS=TRUE" "-DENABLE_DOXYGEN=${ENABLE_DOXYGEN}" @@ -254,4 +256,4 @@ is_installed_klee() { setup_artifact_variables_klee() { setup_build_variables_klee -} \ No newline at end of file +} diff --git a/scripts/build/p-optional-linux-ubuntu.inc b/scripts/build/p-optional-linux-ubuntu.inc new file mode 100644 index 0000000000..802e1cfac9 --- /dev/null +++ b/scripts/build/p-optional-linux-ubuntu.inc @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +install_build_dependencies_optional() { + source "${DIR}/common-functions" + with_sudo apt update -y + + dependencies=( + ca-certificates + wget + unzip + git + ) + + #Install essential dependencies + with_sudo apt -y --no-install-recommends install "${dependencies[@]}" +} diff --git a/scripts/build/p-optional-osx.inc b/scripts/build/p-optional-osx.inc new file mode 100644 index 0000000000..3031bab898 --- /dev/null +++ b/scripts/build/p-optional-osx.inc @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +install_build_dependencies_optional() { + # Install essential dependency + # Ignore if already installed + brew install wget || /usr/bin/true +} diff --git a/scripts/build/p-optional.inc b/scripts/build/p-optional.inc new file mode 100644 index 0000000000..37b66d1744 --- /dev/null +++ b/scripts/build/p-optional.inc @@ -0,0 +1,46 @@ +#!/usr/bin/env bash +setup_build_variables_optional() { + OPTIONAL_INSTALL_PATH="${BASE}/optional-${OPTIONAL_VERSION}" + optional_url="https://github.com/martinmoene/optional-lite.git" + return 0 +} + +download_optional() { + source "${DIR}/common-functions" + # Download optional + git_clone_or_update "${optional_url}" "${OPTIONAL_INSTALL_PATH}" "${OPTIONAL_VERSION}" + touch "${OPTIONAL_INSTALL_PATH}"/.is_installed +} + +build_optional() { + return 0 +} + +install_optional() { + return 0 +} + +is_installed_optional() { + ( + setup_build_variables_optional + [[ -f "${OPTIONAL_INSTALL_PATH}"/.is_installed ]] + ) || return 1 +} + +get_build_artifacts_optional() { + ( + setup_build_variables_optional + echo "${OPTIONAL_INSTALL_PATH}" + ) +} + +setup_artifact_variables_optional() { + setup_build_variables_optional +} + +get_docker_config_id_optional() { + ( + setup_build_variables_optional + echo "${OPTIONAL_VERSION}" + ) +} diff --git a/scripts/build/v-json.inc b/scripts/build/v-json.inc new file mode 100644 index 0000000000..46335d4c62 --- /dev/null +++ b/scripts/build/v-json.inc @@ -0,0 +1,10 @@ +#!/usr/bin/env bash +# shellcheck disable=SC2034 + +# Build information for json +required_variables_json=( + "JSON_VERSION" +) + +# Artifacts json depends on +artifact_dependency_json=("") diff --git a/scripts/build/v-klee.inc b/scripts/build/v-klee.inc index 4b0f1085f1..df0f3b0263 100644 --- a/scripts/build/v-klee.inc +++ b/scripts/build/v-klee.inc @@ -16,7 +16,7 @@ required_variables_check_klee() { # On which artifacts does KLEE depend on artifact_dependency_klee(){ - local dependencies=("llvm" "solvers" "gtest" "sqlite" "cmake") + local dependencies=("llvm" "solvers" "gtest" "sqlite" "cmake" "json" "optional") if [[ "${OS}" != "osx" ]]; then dependencies+=(uclibc) fi @@ -34,7 +34,7 @@ runtime_artifact_dependency_klee(){ if [[ "${OS}" != "osx" ]]; then echo "uclibc" fi - dependencies+=("llvm" "solvers" "gtest" "sqlite") + dependencies+=("llvm" "solvers" "gtest" "sqlite" "json" "optional") [[ "${USE_TCMALLOC:-}" -eq 1 ]] && dependencies+=("tcmalloc") [[ "${USE_LIBCXX:-}" -eq 1 ]] && dependencies+=("libcxx") diff --git a/scripts/build/v-optional.inc b/scripts/build/v-optional.inc new file mode 100644 index 0000000000..dbf9f79ef7 --- /dev/null +++ b/scripts/build/v-optional.inc @@ -0,0 +1,10 @@ +#!/usr/bin/env bash +# shellcheck disable=SC2034 + +# Build information for optional +required_variables_optional=( + "OPTIONAL_VERSION" +) + +# Artifacts optional depends on +artifact_dependency_optional=("") From 416962987e9db306c2a114dd988b8716c014b0b0 Mon Sep 17 00:00:00 2001 From: Aleksei Babushkin Date: Thu, 28 Dec 2023 19:34:52 +0500 Subject: [PATCH 102/120] [chore] replace nonstd::optional with std::optional --- .github/workflows/build.yaml | 1 - CMakeLists.txt | 1 - Dockerfile | 1 - build.sh | 5 +- include/klee/Core/Interpreter.h | 9 ++-- include/klee/Module/SarifReport.h | 58 +++++++++++------------ include/klee/Module/Target.h | 6 +-- lib/Module/SarifReport.cpp | 30 ++++++------ scripts/build/p-klee.inc | 1 - scripts/build/p-optional-linux-ubuntu.inc | 15 ------ scripts/build/p-optional-osx.inc | 6 --- scripts/build/p-optional.inc | 46 ------------------ scripts/build/v-klee.inc | 4 +- scripts/build/v-optional.inc | 10 ---- tools/klee/main.cpp | 6 +-- 15 files changed, 56 insertions(+), 143 deletions(-) delete mode 100644 scripts/build/p-optional-linux-ubuntu.inc delete mode 100644 scripts/build/p-optional-osx.inc delete mode 100644 scripts/build/p-optional.inc delete mode 100644 scripts/build/v-optional.inc diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 2ce3cc004b..91e11e7431 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -32,7 +32,6 @@ env: BITWUZLA_VERSION: main BITWUZLA_COMMIT: 80ef7cd803e1c71b5939c3eb951f1736388f7090 JSON_VERSION: v3.11.3 - OPTIONAL_VERSION: v3.5.0 jobs: Linux: diff --git a/CMakeLists.txt b/CMakeLists.txt index 9fdcf66504..72ef2d30fb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -678,7 +678,6 @@ configure_file(${CMAKE_SOURCE_DIR}/include/klee/Config/CompileTimeInfo.h.cmin ################################################################################ include_directories("${CMAKE_BINARY_DIR}/include") include_directories("${CMAKE_SOURCE_DIR}/include") -include_directories("${OPTIONAL_SRC_DIR}/include") include_directories("${JSON_SRC_DIR}/include") # set(KLEE_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/include ${CMAKE_BINARY_DIR}/include) diff --git a/Dockerfile b/Dockerfile index ffa874e484..52fc4fc719 100644 --- a/Dockerfile +++ b/Dockerfile @@ -35,7 +35,6 @@ ENV USE_LIBCXX=1 ENV KLEE_RUNTIME_BUILD="Debug+Asserts" ENV SQLITE_VERSION=3400100 ENV JSON_VERSION=v3.11.3 -ENV OPTIONAL_VERSION=v3.5.0 LABEL maintainer="KLEE Developers" # TODO remove adding sudo package diff --git a/build.sh b/build.sh index 5be34884e4..2bd37ea984 100755 --- a/build.sh +++ b/build.sh @@ -43,9 +43,6 @@ GTEST_VERSION=1.11.0 ## json options JSON_VERSION=v3.11.3 -## optional options -OPTIONAL_VERSION=v3.5.0 - ## UClibC Required options UCLIBC_VERSION=klee_uclibc_v1.3 # LLVM_VERSION is also required for UClibC @@ -59,4 +56,4 @@ MINISAT_VERSION=master BITWUZLA_VERSION=main BITWUZLA_COMMIT=80ef7cd803e1c71b5939c3eb951f1736388f7090 -BASE="$BASE" KLEE_RUNTIME_BUILD=$KLEE_RUNTIME_BUILD COVERAGE=$COVERAGE ENABLE_DOXYGEN=$ENABLE_DOXYGEN USE_TCMALLOC=$USE_TCMALLOC USE_LIBCXX=$USE_LIBCXX LLVM_VERSION=$LLVM_VERSION ENABLE_OPTIMIZED=$ENABLE_OPTIMIZED ENABLE_DEBUG=$ENABLE_DEBUG DISABLE_ASSERTIONS=$DISABLE_ASSERTIONS REQUIRES_RTTI=$REQUIRES_RTTI SOLVERS=$SOLVERS GTEST_VERSION=$GTEST_VERSION UCLIBC_VERSION=$UCLIBC_VERSION STP_VERSION=$STP_VERSION MINISAT_VERSION=$MINISAT_VERSION Z3_VERSION=$Z3_VERSION BITWUZLA_VERSION=$BITWUZLA_VERSION BITWUZLA_COMMIT=$BITWUZLA_COMMIT SQLITE_VERSION=$SQLITE_VERSION JSON_VERSION=$JSON_VERSION OPTIONAL_VERSION=$OPTIONAL_VERSION ./scripts/build/build.sh klee --install-system-deps +BASE="$BASE" KLEE_RUNTIME_BUILD=$KLEE_RUNTIME_BUILD COVERAGE=$COVERAGE ENABLE_DOXYGEN=$ENABLE_DOXYGEN USE_TCMALLOC=$USE_TCMALLOC USE_LIBCXX=$USE_LIBCXX LLVM_VERSION=$LLVM_VERSION ENABLE_OPTIMIZED=$ENABLE_OPTIMIZED ENABLE_DEBUG=$ENABLE_DEBUG DISABLE_ASSERTIONS=$DISABLE_ASSERTIONS REQUIRES_RTTI=$REQUIRES_RTTI SOLVERS=$SOLVERS GTEST_VERSION=$GTEST_VERSION UCLIBC_VERSION=$UCLIBC_VERSION STP_VERSION=$STP_VERSION MINISAT_VERSION=$MINISAT_VERSION Z3_VERSION=$Z3_VERSION BITWUZLA_VERSION=$BITWUZLA_VERSION BITWUZLA_COMMIT=$BITWUZLA_COMMIT SQLITE_VERSION=$SQLITE_VERSION JSON_VERSION=$JSON_VERSION ./scripts/build/build.sh klee --install-system-deps diff --git a/include/klee/Core/Interpreter.h b/include/klee/Core/Interpreter.h index 43280ff28f..0a15abc56d 100644 --- a/include/klee/Core/Interpreter.h +++ b/include/klee/Core/Interpreter.h @@ -16,15 +16,12 @@ #include #include #include +#include #include #include #include #include -#include - -using nonstd::optional; - struct KTest; namespace llvm { @@ -114,9 +111,9 @@ class Interpreter { /// symbolic execution on concrete programs. unsigned MakeConcreteSymbolic; GuidanceKind Guidance; - nonstd::optional Paths; + std::optional Paths; - InterpreterOptions(nonstd::optional Paths) + InterpreterOptions(std::optional Paths) : MakeConcreteSymbolic(false), Guidance(GuidanceKind::NoGuidance), Paths(std::move(Paths)) {} }; diff --git a/include/klee/Module/SarifReport.h b/include/klee/Module/SarifReport.h index 09a59d4d25..834809504d 100644 --- a/include/klee/Module/SarifReport.h +++ b/include/klee/Module/SarifReport.h @@ -10,6 +10,7 @@ #ifndef KLEE_SARIF_REPORT_H #define KLEE_SARIF_REPORT_H +#include #include #include #include @@ -17,24 +18,22 @@ #include "klee/ADT/Ref.h" #include -#include using json = nlohmann::json; -using nonstd::optional; namespace nlohmann { -template struct adl_serializer> { - static void to_json(json &j, const nonstd::optional &opt) { - if (opt == nonstd::nullopt) { +template struct adl_serializer> { + static void to_json(json &j, const std::optional &opt) { + if (opt == std::nullopt) { j = nullptr; } else { j = *opt; } } - static void from_json(const json &j, nonstd::optional &opt) { + static void from_json(const json &j, std::optional &opt) { if (j.is_null()) { - opt = nonstd::nullopt; + opt = std::nullopt; } else { opt = j.get(); } @@ -60,28 +59,28 @@ struct FunctionInfo; struct KBlock; struct ArtifactLocationJson { - optional uri; + std::optional uri; }; struct RegionJson { - optional startLine; - optional endLine; - optional startColumn; - optional endColumn; + std::optional startLine; + std::optional endLine; + std::optional startColumn; + std::optional endColumn; }; struct PhysicalLocationJson { - optional artifactLocation; - optional region; + std::optional artifactLocation; + std::optional region; }; struct LocationJson { - optional physicalLocation; + std::optional physicalLocation; }; struct ThreadFlowLocationJson { - optional location; - optional metadata; + std::optional location; + std::optional metadata; }; struct ThreadFlowJson { @@ -109,10 +108,10 @@ static void from_json(const json &j, Fingerprints &p) { } struct ResultJson { - optional ruleId; - optional message; - optional id; - optional fingerprints; + std::optional ruleId; + std::optional message; + std::optional id; + std::optional fingerprints; std::vector locations; std::vector codeFlows; }; @@ -186,13 +185,13 @@ struct Location { std::string filename; unsigned int startLine; unsigned int endLine; - optional startColumn; - optional endColumn; + std::optional startColumn; + std::optional endColumn; static ref create(std::string filename_, unsigned int startLine_, - optional endLine_, - optional startColumn_, - optional endColumn_); + std::optional endLine_, + std::optional startColumn_, + std::optional endColumn_); ~Location(); std::size_t hash() const { return hashValue; } @@ -240,8 +239,9 @@ struct Location { } Location(std::string filename_, unsigned int startLine_, - optional endLine_, optional startColumn_, - optional endColumn_) + std::optional endLine_, + std::optional startColumn_, + std::optional endColumn_) : filename(filename_), startLine(startLine_), endLine(endLine_.has_value() ? *endLine_ : startLine_), startColumn(startColumn_), @@ -262,7 +262,7 @@ struct RefLocationCmp { struct Result { std::vector> locations; - std::vector> metadatas; + std::vector> metadatas; std::string id; std::vector errors; }; diff --git a/include/klee/Module/Target.h b/include/klee/Module/Target.h index 98eb3c900a..2475584259 100644 --- a/include/klee/Module/Target.h +++ b/include/klee/Module/Target.h @@ -28,19 +28,19 @@ DISABLE_WARNING_DEPRECATED_DECLARATIONS DISABLE_WARNING_POP #include +#include #include #include #include #include namespace klee { -using nonstd::optional; struct ErrorLocation { unsigned int startLine; unsigned int endLine; - optional startColumn; - optional endColumn; + std::optional startColumn; + std::optional endColumn; ErrorLocation(const klee::ref &loc); ErrorLocation(const KInstruction *ki); diff --git a/lib/Module/SarifReport.cpp b/lib/Module/SarifReport.cpp index aa1b403e89..58f1e70621 100644 --- a/lib/Module/SarifReport.cpp +++ b/lib/Module/SarifReport.cpp @@ -25,23 +25,23 @@ using namespace klee; namespace { bool isOSSeparator(char c) { return c == '/' || c == '\\'; } -optional> +std::optional> tryConvertLocationJson(const LocationJson &locationJson) { const auto &physicalLocation = locationJson.physicalLocation; if (!physicalLocation.has_value()) { - return nonstd::nullopt; + return std::nullopt; } const auto &artifactLocation = physicalLocation->artifactLocation; if (!artifactLocation.has_value() || !artifactLocation->uri.has_value()) { - return nonstd::nullopt; + return std::nullopt; } const auto filename = std::move(*(artifactLocation->uri)); const auto ®ion = physicalLocation->region; if (!region.has_value() || !region->startLine.has_value()) { - return nonstd::nullopt; + return std::nullopt; } return Location::create(std::move(filename), *(region->startLine), @@ -51,7 +51,7 @@ tryConvertLocationJson(const LocationJson &locationJson) { std::vector tryConvertRuleJson(const std::string &ruleId, const std::string &toolName, - const optional &errorMessage) { + const std::optional &errorMessage) { if (toolName == "SecB") { if ("NullDereference" == ruleId) { return {ReachWithError::MustBeNullPointerException}; @@ -121,9 +121,9 @@ tryConvertRuleJson(const std::string &ruleId, const std::string &toolName, } } -optional tryConvertResultJson(const ResultJson &resultJson, - const std::string &toolName, - const std::string &id) { +std::optional tryConvertResultJson(const ResultJson &resultJson, + const std::string &toolName, + const std::string &id) { std::vector errors = {}; if (!resultJson.ruleId.has_value()) { errors = {ReachWithError::Reachable}; @@ -132,12 +132,12 @@ optional tryConvertResultJson(const ResultJson &resultJson, tryConvertRuleJson(*resultJson.ruleId, toolName, resultJson.message); if (errors.size() == 0) { klee_warning("undefined error in %s result", id.c_str()); - return nonstd::nullopt; + return std::nullopt; } } std::vector> locations; - std::vector> metadatas; + std::vector> metadatas; if (resultJson.codeFlows.size() > 0) { assert(resultJson.codeFlows.size() == 1); @@ -146,7 +146,7 @@ optional tryConvertResultJson(const ResultJson &resultJson, const auto &threadFlow = resultJson.codeFlows[0].threadFlows[0]; for (auto &threadFlowLocation : threadFlow.locations) { if (!threadFlowLocation.location.has_value()) { - return nonstd::nullopt; + return std::nullopt; } auto maybeLocation = tryConvertLocationJson(*threadFlowLocation.location); @@ -164,7 +164,7 @@ optional tryConvertResultJson(const ResultJson &resultJson, } if (locations.empty()) { - return nonstd::nullopt; + return std::nullopt; } return Result{std::move(locations), std::move(metadatas), id, @@ -288,9 +288,9 @@ Location::EquivLocationHashSet Location::cachedLocations; Location::LocationHashSet Location::locations; ref Location::create(std::string filename_, unsigned int startLine_, - optional endLine_, - optional startColumn_, - optional endColumn_) { + std::optional endLine_, + std::optional startColumn_, + std::optional endColumn_) { Location *loc = new Location(filename_, startLine_, endLine_, startColumn_, endColumn_); std::pair success = diff --git a/scripts/build/p-klee.inc b/scripts/build/p-klee.inc index dd8ba17aff..83379129a6 100644 --- a/scripts/build/p-klee.inc +++ b/scripts/build/p-klee.inc @@ -20,7 +20,6 @@ build_klee() { "-DLLVM_DIR=${LLVM_INSTALL}" "-DGTEST_SRC_DIR=${GTEST_INSTALL_PATH}" "-DJSON_SRC_DIR=${JSON_INSTALL_PATH}" - "-DOPTIONAL_SRC_DIR=${OPTIONAL_INSTALL_PATH}" "-DENABLE_UNIT_TESTS=TRUE" "-DENABLE_SYSTEM_TESTS=TRUE" "-DENABLE_DOXYGEN=${ENABLE_DOXYGEN}" diff --git a/scripts/build/p-optional-linux-ubuntu.inc b/scripts/build/p-optional-linux-ubuntu.inc deleted file mode 100644 index 802e1cfac9..0000000000 --- a/scripts/build/p-optional-linux-ubuntu.inc +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env bash -install_build_dependencies_optional() { - source "${DIR}/common-functions" - with_sudo apt update -y - - dependencies=( - ca-certificates - wget - unzip - git - ) - - #Install essential dependencies - with_sudo apt -y --no-install-recommends install "${dependencies[@]}" -} diff --git a/scripts/build/p-optional-osx.inc b/scripts/build/p-optional-osx.inc deleted file mode 100644 index 3031bab898..0000000000 --- a/scripts/build/p-optional-osx.inc +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env bash -install_build_dependencies_optional() { - # Install essential dependency - # Ignore if already installed - brew install wget || /usr/bin/true -} diff --git a/scripts/build/p-optional.inc b/scripts/build/p-optional.inc deleted file mode 100644 index 37b66d1744..0000000000 --- a/scripts/build/p-optional.inc +++ /dev/null @@ -1,46 +0,0 @@ -#!/usr/bin/env bash -setup_build_variables_optional() { - OPTIONAL_INSTALL_PATH="${BASE}/optional-${OPTIONAL_VERSION}" - optional_url="https://github.com/martinmoene/optional-lite.git" - return 0 -} - -download_optional() { - source "${DIR}/common-functions" - # Download optional - git_clone_or_update "${optional_url}" "${OPTIONAL_INSTALL_PATH}" "${OPTIONAL_VERSION}" - touch "${OPTIONAL_INSTALL_PATH}"/.is_installed -} - -build_optional() { - return 0 -} - -install_optional() { - return 0 -} - -is_installed_optional() { - ( - setup_build_variables_optional - [[ -f "${OPTIONAL_INSTALL_PATH}"/.is_installed ]] - ) || return 1 -} - -get_build_artifacts_optional() { - ( - setup_build_variables_optional - echo "${OPTIONAL_INSTALL_PATH}" - ) -} - -setup_artifact_variables_optional() { - setup_build_variables_optional -} - -get_docker_config_id_optional() { - ( - setup_build_variables_optional - echo "${OPTIONAL_VERSION}" - ) -} diff --git a/scripts/build/v-klee.inc b/scripts/build/v-klee.inc index df0f3b0263..eb5815dc53 100644 --- a/scripts/build/v-klee.inc +++ b/scripts/build/v-klee.inc @@ -16,7 +16,7 @@ required_variables_check_klee() { # On which artifacts does KLEE depend on artifact_dependency_klee(){ - local dependencies=("llvm" "solvers" "gtest" "sqlite" "cmake" "json" "optional") + local dependencies=("llvm" "solvers" "gtest" "sqlite" "cmake" "json") if [[ "${OS}" != "osx" ]]; then dependencies+=(uclibc) fi @@ -34,7 +34,7 @@ runtime_artifact_dependency_klee(){ if [[ "${OS}" != "osx" ]]; then echo "uclibc" fi - dependencies+=("llvm" "solvers" "gtest" "sqlite" "json" "optional") + dependencies+=("llvm" "solvers" "gtest" "sqlite" "json") [[ "${USE_TCMALLOC:-}" -eq 1 ]] && dependencies+=("tcmalloc") [[ "${USE_LIBCXX:-}" -eq 1 ]] && dependencies+=("libcxx") diff --git a/scripts/build/v-optional.inc b/scripts/build/v-optional.inc deleted file mode 100644 index dbf9f79ef7..0000000000 --- a/scripts/build/v-optional.inc +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env bash -# shellcheck disable=SC2034 - -# Build information for optional -required_variables_optional=( - "OPTIONAL_VERSION" -) - -# Artifacts optional depends on -artifact_dependency_optional=("") diff --git a/tools/klee/main.cpp b/tools/klee/main.cpp index e0ec4b2092..d6c5cca118 100644 --- a/tools/klee/main.cpp +++ b/tools/klee/main.cpp @@ -1177,7 +1177,7 @@ void externalsAndGlobalsCheck(const llvm::Module *m) { } static Interpreter *theInterpreter = 0; -static nonstd::optional paths = nonstd::nullopt; +static std::optional paths = std::nullopt; static std::atomic_bool interrupted{false}; @@ -1352,10 +1352,10 @@ static SarifReport parseInputPathTree(const std::string &inputPathTreePath) { return klee::convertAndFilterSarifJson(sarifJson); } -static nonstd::optional parseStaticAnalysisInput() { +static std::optional parseStaticAnalysisInput() { if (AnalysisReproduce != "") return parseInputPathTree(AnalysisReproduce); - return nonstd::nullopt; + return std::nullopt; } static int run_klee_on_function(int pArgc, char **pArgv, char **pEnvp, From fd8a45b9b5a5dce73ad252e2a9d2852f37eb86ae Mon Sep 17 00:00:00 2001 From: Aleksei Babushkin Date: Thu, 28 Dec 2023 15:55:43 +0500 Subject: [PATCH 103/120] [fix] klee-test-comp.c: remove unused function that fails to compile --- 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 413011abea..34e805e588 100644 --- a/include/klee-test-comp.c +++ b/include/klee-test-comp.c @@ -98,6 +98,7 @@ double __VERIFIER_nondet_double(void) { return x; } +/* void *__VERIFIER_nondet_pointer(void) { int size = 1024; char *obj = (char *)calloc(1, size); @@ -105,6 +106,7 @@ void *__VERIFIER_nondet_pointer(void) { return obj; } +*/ float __VERIFIER_nondet_float(void) { float x; From 23192d8fa1854dc134f79b33b491c75942b6bd34 Mon Sep 17 00:00:00 2001 From: Aleksei Babushkin Date: Thu, 28 Dec 2023 19:35:52 +0500 Subject: [PATCH 104/120] [feat] add entry point multiplex, remove interactive mode --- include/klee/Module/SarifReport.h | 3 + lib/Core/Executor.cpp | 69 +--- lib/Core/Executor.h | 2 +- lib/Core/TargetedExecutionManager.cpp | 18 +- lib/Core/TargetedExecutionManager.h | 5 +- lib/Module/SarifReport.cpp | 32 ++ ...lingUnreachableBranchesInForkErrorGuided.c | 3 +- ...nreachableBranchesInForkErrorGuided.c.json | 8 +- test/Industry/BadCase01_SecB_ForwardNull.c | 6 +- test/Industry/if2.c | 2 +- test/Industry/while_true.c | 4 +- test/InteractiveMode/interactive_mode.c | 93 ----- tools/klee/main.cpp | 358 ++++++++++++------ 13 files changed, 317 insertions(+), 286 deletions(-) delete mode 100644 test/InteractiveMode/interactive_mode.c diff --git a/include/klee/Module/SarifReport.h b/include/klee/Module/SarifReport.h index 834809504d..72d846c90f 100644 --- a/include/klee/Module/SarifReport.h +++ b/include/klee/Module/SarifReport.h @@ -17,6 +17,7 @@ #include #include "klee/ADT/Ref.h" +#include "llvm/IR/Function.h" #include using json = nlohmann::json; @@ -213,6 +214,8 @@ struct Location { bool isInside(KBlock *block, const Instructions &origInsts) const; + bool isInside(const llvm::Function *f, const Instructions &origInsts) const; + std::string toString() const; private: diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index 6cad5cd367..de6a5bef3f 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -4441,17 +4441,15 @@ void Executor::reportProgressTowardsTargets() const { reportProgressTowardsTargets("", states); } -void Executor::run(std::vector initialStates) { +void Executor::run(ExecutionState *initialState) { // Delay init till now so that ticks don't accrue during optimization and // such. if (guidanceKind != GuidanceKind::ErrorGuidance) timers.reset(); - states.insert(initialStates.begin(), initialStates.end()); + states.insert(initialState); if (usingSeeds) { - assert(initialStates.size() == 1); - ExecutionState *initialState = initialStates.back(); seed(*initialState); } @@ -6869,16 +6867,14 @@ void Executor::runFunctionAsMain(Function *f, int argc, char **argv, ExecutionState *state = formState(f, argc, argv, envp); bindModuleConstants(llvm::APFloat::rmNearestTiesToEven); - std::vector states; + KFunction *kEntryFunction = kmodule->functionMap.at(f); if (guidanceKind == GuidanceKind::ErrorGuidance) { - std::map, - klee::KFunctionCompare> - prepTargets; + ref forest; if (FunctionCallReproduce == "") { auto &paths = interpreterOpts.Paths.value(); - prepTargets = targetedExecutionManager->prepareTargets(kmodule.get(), - std::move(paths)); + forest = targetedExecutionManager->prepareTargets( + kmodule.get(), kEntryFunction, std::move(paths)); } else { /* Find all calls to function specified in .prp file * and combine them to single target forest */ @@ -6888,49 +6884,23 @@ void Executor::runFunctionAsMain(Function *f, int argc, char **argv, FunctionCallReproduce.c_str()); } else { auto kCallBlock = kfIt->second->entryKBlock; - KFunction *kEntryFunction = kmodule->functionMap.at(f); - ref forest = new TargetForest(kEntryFunction); + forest = new TargetForest(kEntryFunction); forest->add(ReproduceErrorTarget::create( {ReachWithError::Reachable}, "", ErrorLocation(kCallBlock->getFirstInstruction()), kCallBlock)); - prepTargets.emplace(kEntryFunction, forest); } } - if (prepTargets.empty()) { + if (forest->empty()) { klee_warning( "No targets found in error-guided mode after prepare targets"); delete state; return; } - KInstIterator caller; - if (kmodule->WithPOSIXRuntime()) { - state = prepareStateForPOSIX(caller, state->copy()); - } else { - state->popFrame(); - } - - for (auto &startFunctionAndWhiteList : prepTargets) { - auto kf = - kmodule->functionMap.at(startFunctionAndWhiteList.first->function()); - if (startFunctionAndWhiteList.second->empty()) { - klee_warning("No targets found for %s", - kf->function()->getName().str().c_str()); - continue; - } - auto whitelist = startFunctionAndWhiteList.second; - targets.emplace(kf, TargetedHaltsOnTraces(whitelist)); - ExecutionState *initialState = state->withStackFrame(caller, kf); - prepareSymbolicArgs(*initialState); - prepareTargetedExecution(*initialState, whitelist); - states.push_back(initialState); - } - delete state; - } else { - states.push_back(state); + targets.emplace(kEntryFunction, TargetedHaltsOnTraces(forest)); + prepareTargetedExecution(*state, forest); } - state = nullptr; TreeOStream pathOS; TreeOStream symPathOS; @@ -6943,19 +6913,18 @@ void Executor::runFunctionAsMain(Function *f, int argc, char **argv, } processForest = std::make_unique(); - for (auto &state : states) { - if (statsTracker) - statsTracker->framePushed(*state, 0); - if (pathWriter) - state->pathOS = pathOS; - if (symPathWriter) - state->symPathOS = symPathOS; + if (statsTracker) + statsTracker->framePushed(*state, 0); - processForest->addRoot(state); - } + if (pathWriter) + state->pathOS = pathOS; + if (symPathWriter) + state->symPathOS = symPathOS; + + processForest->addRoot(state); - run(states); + run(state); processForest = nullptr; if (statsTracker) diff --git a/lib/Core/Executor.h b/lib/Core/Executor.h index 1ed917040b..006b74eaae 100644 --- a/lib/Core/Executor.h +++ b/lib/Core/Executor.h @@ -262,7 +262,7 @@ class Executor : public Interpreter { ExecutionState **resultState = nullptr); void seed(ExecutionState &initialState); - void run(std::vector initialStates); + void run(ExecutionState *initialState); void runWithTarget(ExecutionState &state, KFunction *kf, KBlock *target); void initializeTypeManager(); diff --git a/lib/Core/TargetedExecutionManager.cpp b/lib/Core/TargetedExecutionManager.cpp index 98862ede39..37961c20f3 100644 --- a/lib/Core/TargetedExecutionManager.cpp +++ b/lib/Core/TargetedExecutionManager.cpp @@ -16,6 +16,7 @@ #include "klee/Core/TerminationTypes.h" #include "klee/Module/CodeGraphInfo.h" #include "klee/Module/KInstruction.h" +#include "klee/Module/KModule.h" #include "klee/Support/ErrorHandling.h" #include @@ -493,13 +494,14 @@ KFunction *TargetedExecutionManager::tryResolveEntryFunction( return resKf; } -std::map, KFunctionCompare> -TargetedExecutionManager::prepareTargets(KModule *kmodule, SarifReport paths) { +ref TargetedExecutionManager::prepareTargets(KModule *kmodule, + KFunction *entry, + SarifReport paths) { + ref forest = new TargetForest(entry); + Locations locations = collectAllLocations(paths); LocationToBlocks locToBlocks = prepareAllLocations(kmodule, locations); - std::map, KFunctionCompare> whitelists; - for (auto &result : paths.results) { bool isFullyResolved = tryResolveLocations(result, locToBlocks); if (!isFullyResolved) { @@ -513,14 +515,10 @@ TargetedExecutionManager::prepareTargets(KModule *kmodule, SarifReport paths) { continue; } - if (whitelists.count(kf) == 0) { - ref whitelist = new TargetForest(kf); - whitelists[kf] = whitelist; - } - whitelists[kf]->addTrace(result, locToBlocks); + forest->addTrace(result, locToBlocks); } - return whitelists; + return forest; } void TargetedExecutionManager::reportFalseNegative(ExecutionState &state, diff --git a/lib/Core/TargetedExecutionManager.h b/lib/Core/TargetedExecutionManager.h index e5f72e935b..edabcee1e8 100644 --- a/lib/Core/TargetedExecutionManager.h +++ b/lib/Core/TargetedExecutionManager.h @@ -119,8 +119,9 @@ class TargetedExecutionManager { TargetManager &targetManager_) : codeGraphInfo(codeGraphInfo_), targetManager(targetManager_) {} ~TargetedExecutionManager() = default; - std::map, KFunctionCompare> - prepareTargets(KModule *kmodule, SarifReport paths); + + ref prepareTargets(KModule *kmodule, KFunction *entry, + SarifReport paths); void reportFalseNegative(ExecutionState &state, ReachWithError error); diff --git a/lib/Module/SarifReport.cpp b/lib/Module/SarifReport.cpp index 58f1e70621..377baf888d 100644 --- a/lib/Module/SarifReport.cpp +++ b/lib/Module/SarifReport.cpp @@ -11,6 +11,7 @@ #include "klee/Module/KInstruction.h" #include "klee/Module/KModule.h" +#include "klee/Module/LocationInfo.h" #include "klee/Support/ErrorHandling.h" #include "klee/Support/CompilerWarning.h" @@ -350,6 +351,37 @@ bool Location::isInside(KBlock *block, const Instructions &origInsts) const { } } +bool Location::isInside(const llvm::Function *f, + const Instructions &origInsts) const { + if (f->empty()) { + return false; + } + auto first = &f->front().front(); + auto last = &f->back().back(); + auto firstLoc = getLocationInfo(first); + auto lastLoc = getLocationInfo(last); + if (!startColumn.has_value()) { + if (firstLoc.line > endLine) { + return false; + } + return startLine <= lastLoc.line; + } + for (const auto &block : *f) { + for (const auto &inst : block) { + auto locInfo = getLocationInfo(&inst); + if (!isa(&inst) && locInfo.line <= endLine && + locInfo.line >= startLine && locInfo.column <= *endColumn && + locInfo.column >= *startColumn && + origInsts.at(locInfo.line) + .at(locInfo.column) + .count(inst.getOpcode()) != 0) { + return true; + } + } + } + return false; +} + std::string Location::toString() const { return filename + ":" + std::to_string(startLine); } diff --git a/test/Feature/NotCallingUnreachableBranchesInForkErrorGuided.c b/test/Feature/NotCallingUnreachableBranchesInForkErrorGuided.c index 784c0151e2..87b66e23c7 100644 --- a/test/Feature/NotCallingUnreachableBranchesInForkErrorGuided.c +++ b/test/Feature/NotCallingUnreachableBranchesInForkErrorGuided.c @@ -2,7 +2,8 @@ // RUN: rm -rf %t.klee-out // RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --analysis-reproduce=%s.json %t1.bc // RUN: FileCheck -input-file=%t.klee-out/info %s -// CHECK: KLEE: done: total queries = 1 +// 3 = 2 for entrypoint multiplex + 1 for fork +// CHECK: KLEE: done: total queries = 3 #include "assert.h" #include "klee/klee.h" diff --git a/test/Feature/NotCallingUnreachableBranchesInForkErrorGuided.c.json b/test/Feature/NotCallingUnreachableBranchesInForkErrorGuided.c.json index ec8403ab45..b34cb11366 100644 --- a/test/Feature/NotCallingUnreachableBranchesInForkErrorGuided.c.json +++ b/test/Feature/NotCallingUnreachableBranchesInForkErrorGuided.c.json @@ -20,7 +20,7 @@ "uri": "/tmp/NotCallingUnreachableBranchesInForkErrorGuided.c" }, "region": { - "startLine": 9, + "startLine": 10, "startColumn": 14 } } @@ -33,7 +33,7 @@ "uri": "/tmp/NotCallingUnreachableBranchesInForkErrorGuided.c" }, "region": { - "startLine": 13, + "startLine": 14, "startColumn": 5 } } @@ -52,7 +52,7 @@ "uri": "/tmp/NotCallingUnreachableBranchesInForkErrorGuided.c" }, "region": { - "startLine": 13, + "startLine": 14, "startColumn": 5 } } @@ -62,4 +62,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/test/Industry/BadCase01_SecB_ForwardNull.c b/test/Industry/BadCase01_SecB_ForwardNull.c index f72959d73c..d554a1535b 100644 --- a/test/Industry/BadCase01_SecB_ForwardNull.c +++ b/test/Industry/BadCase01_SecB_ForwardNull.c @@ -142,6 +142,6 @@ void badbad(char *ptr) // 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 -// RUN: FileCheck -input-file=%t.klee-out/warnings.txt %s -// CHECK: KLEE: WARNING: No targets found in error-guided mode \ No newline at end of file +// 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 > %t1.log 2>&1 +// RUN: FileCheck -input-file=%t1.log %s +// CHECK: KLEE: WARNING: No paths were given to trace verify diff --git a/test/Industry/if2.c b/test/Industry/if2.c index b35cb487bf..57422bf2d5 100644 --- a/test/Industry/if2.c +++ b/test/Industry/if2.c @@ -10,7 +10,7 @@ int main(int x) { // 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 +// 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-instructions=45 --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 diff --git a/test/Industry/while_true.c b/test/Industry/while_true.c index f0566cce12..72aac7f704 100644 --- a/test/Industry/while_true.c +++ b/test/Industry/while_true.c @@ -10,14 +10,14 @@ int main() { // 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 +// 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=20 --max-cycles-before-stuck=0 --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc // RUN: FileCheck -input-file=%t.klee-out-1/warnings.txt %s -check-prefix=CHECK-NONE // CHECK-NONE: KLEE: WARNING: 0.00% NullPointerException False Positive at trace 1 // RUN: FileCheck -input-file=%t.klee-out-1/messages.txt %s -check-prefix=CHECK-REACH-1 // CHECK-REACH-1: (0, 1, 4) for Target 1: error in function main (lines 8 to 8) // RUN: rm -rf %t.klee-out-2 -// RUN: %klee --output-dir=%t.klee-out-2 --use-guided-search=error --mock-external-calls --skip-not-symbolic-objects --skip-not-lazy-initialized --check-out-of-memory --max-stepped-instructions=50000 --max-cycles-before-stuck=0 --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc +// RUN: %klee --output-dir=%t.klee-out-2 --use-guided-search=error --mock-external-calls --skip-not-symbolic-objects --skip-not-lazy-initialized --check-out-of-memory --max-stepped-instructions=4980 --max-cycles-before-stuck=0 --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc // RUN: FileCheck -input-file=%t.klee-out-2/warnings.txt %s -check-prefix=CHECK-ALL // CHECK-ALL: KLEE: WARNING: 99.00% NullPointerException False Positive at trace 1 // RUN: FileCheck -input-file=%t.klee-out-2/messages.txt %s -check-prefix=CHECK-REACH-2 diff --git a/test/InteractiveMode/interactive_mode.c b/test/InteractiveMode/interactive_mode.c deleted file mode 100644 index 8ae3cb75c1..0000000000 --- a/test/InteractiveMode/interactive_mode.c +++ /dev/null @@ -1,93 +0,0 @@ -/* 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 -// RUN: echo comparison >> %t.entrypoints -// RUN: echo segment_intersection >> %t.entrypoints -// RUN: echo main >> %t.entrypoints -// RUN: %klee --output-dir=%t.klee-out --entry-point=main --interactive --entrypoints-file=%t.entrypoints %t.bc - -// RUN: test -f %t.klee-out/sign_sum/test000001.ktest -// RUN: test -f %t.klee-out/sign_sum/test000002.ktest -// RUN: test -f %t.klee-out/sign_sum/test000003.ktest -// RUN: not test -f %t.klee-out/sign_sum/test000004.ktest - -// RUN: test -f %t.klee-out/comparison/test000001.ktest -// RUN: test -f %t.klee-out/comparison/test000002.ktest -// RUN: not test -f %t.klee-out/comparison/test000003.ktest - -// RUN: test -f %t.klee-out/segment_intersection/test000001.ktest -// RUN: test -f %t.klee-out/segment_intersection/test000002.ktest -// RUN: test -f %t.klee-out/segment_intersection/test000003.ktest -// RUN: test -f %t.klee-out/segment_intersection/test000004.ktest -// RUN: test -f %t.klee-out/segment_intersection/test000005.ktest -// RUN: test -f %t.klee-out/segment_intersection/test000006.ktest -// RUN: test -f %t.klee-out/segment_intersection/test000007.ktest -// RUN: test -f %t.klee-out/segment_intersection/test000008.ktest -// RUN: test -f %t.klee-out/segment_intersection/test000009.ktest -// RUN: not test -f %t.klee-out/segment_intersection/test000010.ktest - -// RUN: test -f %t.klee-out/main/test000001.ktest -// RUN: not test -f %t.klee-out/main/test000002.ktest - -#include "klee/klee.h" -#include - -int sign_sum() { - int x, y; - klee_make_symbolic(&x, sizeof(int), "x"); - klee_make_symbolic(&y, sizeof(int), "y"); - - int c = 0; - if (x + y > 0) { - c = 1; - } else if (x + y < 0) { - c = -1; - } else { - c = 0; - } - return 0; -} - -int comparison() { - int x, y; - klee_make_symbolic(&x, sizeof(int), "x"); - klee_make_symbolic(&y, sizeof(int), "y"); - - if (x < y) { - return 1; - } else { - return 0; - } -} - -int segment_intersection() { - int l, r, A, B; - klee_make_symbolic(&l, sizeof(int), "l"); - klee_make_symbolic(&r, sizeof(int), "r"); - klee_make_symbolic(&A, sizeof(int), "A"); - klee_make_symbolic(&B, sizeof(int), "B"); - - if (l > r || A > B) { - return -1; - } - - if (l > B || r < A) { - return 0; - } - - if (A <= l && r <= B) { - return r - l; - } - - if (l <= A && B <= r) { - return B - A; - } - - return (r <= B ? r : B) - (l >= A ? l : A); -} - -int main() { - return 0; -} diff --git a/tools/klee/main.cpp b/tools/klee/main.cpp index d6c5cca118..60391b7c1b 100644 --- a/tools/klee/main.cpp +++ b/tools/klee/main.cpp @@ -29,6 +29,7 @@ #include "klee/System/Time.h" #include "klee/Support/CompilerWarning.h" +#include "llvm/Analysis/CallGraph.h" DISABLE_WARNING_PUSH DISABLE_WARNING_DEPRECATED_DECLARATIONS #include "llvm/Bitcode/BitcodeReader.h" @@ -149,28 +150,10 @@ cl::opt cl::desc("Function in which to start execution (default=main)"), cl::init("main"), cl::cat(StartCat)); -cl::opt UTBotMode("utbot", cl::desc("Klee was launched by utbot"), - cl::init(false), cl::cat(StartCat)); - -cl::opt InteractiveMode("interactive", - cl::desc("Launch klee in interactive mode."), - cl::init(false), cl::cat(StartCat)); - cl::opt TimeoutPerFunction("timeout-per-function", cl::desc("Timeout per function in klee."), cl::init(0), cl::cat(StartCat)); -cl::opt - EntryPointsFile("entrypoints-file", - cl::desc("Path to file with entrypoints name."), - cl::init("entrypoints.txt"), cl::cat(StartCat)); - -const int MAX_PROCESS_NUMBER = 50; -cl::opt ProcessNumber("process-number", - cl::desc("Number of parallel process in klee, must " - "lie in [1, 50] (default = 1)."), - cl::init(1), cl::cat(StartCat)); - cl::opt AnalysisReproduce("analysis-reproduce", cl::desc("Path of JSON file containing static analysis " @@ -1363,13 +1346,8 @@ static int run_klee_on_function(int pArgc, char **pArgv, char **pEnvp, std::unique_ptr &interpreter, llvm::Module *finalModule, std::vector &replayPath) { - Function *mainFn = finalModule->getFunction(EntryPoint); - if ((UseGuidedSearch != Interpreter::GuidanceKind::ErrorGuidance) && - !mainFn) { // in error guided mode we do not need main function - klee_error("Entry function '%s' not found in module.", EntryPoint.c_str()); - } - externalsAndGlobalsCheck(finalModule); + Function *mainFn = finalModule->getFunction(EntryPoint); if (ReplayPathFile != "") { interpreter->setReplayPath(&replayPath); @@ -1581,6 +1559,201 @@ void wait_until_any_child_dies( } } +llvm::Value *createStringArray(LLVMContext &ctx, const char *str) { + auto type = llvm::ArrayType::get(llvm::Type::getInt8Ty(ctx), strlen(str) + 1); + std::vector chars; + for (size_t i = 0; i < strlen(str) + 1; ++i) { + chars.push_back(llvm::ConstantInt::get(llvm::Type::getInt8Ty(ctx), str[i])); + } + return llvm::ConstantArray::get(type, chars); +} + +void multiplexEntryPoint(llvm::Module *m, LLVMContext &ctx, + std::vector entryFns) { + + klee_message("Multiplexing entry point for the following functions:"); + for (auto fn : entryFns) { + klee_message("%s", fn->getName().data()); + } + klee_message("entry-point parameter is ignored. " + "Initial source can't be used for test replay."); + + llvm::IRBuilder<> builder(ctx); + + // todo 32 and 64 bit + std::vector kleeMakeSymbolicArgsType = { + llvm::Type::getInt8PtrTy(ctx), llvm::Type::getInt64Ty(ctx), + llvm::Type::getInt8PtrTy(ctx)}; + auto kleeMakeSymbolicFnType = llvm::FunctionType::get( + llvm::Type::getVoidTy(ctx), kleeMakeSymbolicArgsType, false); + + auto kleeMakeSymbolicFn = + m->getOrInsertFunction("klee_make_symbolic", kleeMakeSymbolicFnType); + + std::string multiplexedEntryName = "__klee_multiplexed_entry"; + auto type = llvm::FunctionType::get(llvm::Type::getVoidTy(ctx), {}, false); + auto multiplexedEntry = llvm::Function::Create( + type, GlobalVariable::ExternalLinkage, multiplexedEntryName, m); + + auto entryBB = llvm::BasicBlock::Create(ctx, "entry", multiplexedEntry); + auto exitBB = llvm::BasicBlock::Create(ctx, "exit", multiplexedEntry); + + std::vector FnBlocks; + for (size_t i = 0; i < entryFns.size(); ++i) { + auto block = llvm::BasicBlock::Create(ctx, "func_" + llvm::utostr(i + 1), + multiplexedEntry); + FnBlocks.push_back(block); + } + + auto sizeType = llvm::Type::getInt64Ty(ctx); + size_t sizeByteWidth = 8; + + // populate entry + builder.SetInsertPoint(entryBB); + auto alloca = builder.CreateAlloca(sizeType); + auto bitcast = builder.CreateBitCast(alloca, llvm::Type::getInt8PtrTy(ctx)); + auto name = createStringArray(ctx, "__klee_multiplex_switch"); + auto nameAlloca = builder.CreateAlloca(name->getType()); + builder.CreateStore(name, nameAlloca); + auto nameBitcast = + builder.CreateBitCast(nameAlloca, llvm::Type::getInt8PtrTy(ctx)); + std::vector args; + args.push_back(bitcast); + args.push_back(llvm::ConstantInt::get(sizeType, sizeByteWidth)); + args.push_back(nameBitcast); + builder.CreateCall(kleeMakeSymbolicFn, args); + auto load = builder.CreateLoad(llvm::Type::getInt64Ty(ctx), alloca); + auto swtch = builder.CreateSwitch(load, exitBB, entryFns.size()); + + for (size_t i = 0; i < entryFns.size(); ++i) { + swtch->addCase(llvm::ConstantInt::get(sizeType, i + 1), FnBlocks[i]); + } + + // populate exit + builder.SetInsertPoint(exitBB); + builder.CreateRetVoid(); + + // populate funcs + for (size_t i = 0; i < entryFns.size(); ++i) { + builder.SetInsertPoint(FnBlocks[i]); + + // symbolize function arguments + std::vector args; + for (size_t arg_i = 0; arg_i < entryFns[i]->arg_size(); ++arg_i) { + std::string argName = "__klee_arg" + llvm::utostr(arg_i); + auto type = (entryFns[i]->arg_begin() + arg_i)->getType(); + auto byteWidth = + m->getDataLayout().getTypeSizeInBits(type) / 8; // check that + auto alloca = builder.CreateAlloca(type); + auto bitcast = + builder.CreateBitCast(alloca, llvm::Type::getInt8PtrTy(ctx)); + auto name = createStringArray(ctx, argName.c_str()); + auto nameAlloca = builder.CreateAlloca(name->getType()); + builder.CreateStore(name, nameAlloca); + auto nameBitcast = + builder.CreateBitCast(nameAlloca, llvm::Type::getInt8PtrTy(ctx)); + std::vector makeSymbolicArgs; + makeSymbolicArgs.push_back(bitcast); + makeSymbolicArgs.push_back(llvm::ConstantInt::get(sizeType, byteWidth)); + makeSymbolicArgs.push_back(nameBitcast); + builder.CreateCall(kleeMakeSymbolicFn, makeSymbolicArgs); + auto load = builder.CreateLoad(type, alloca); + args.push_back(load); + } + + builder.CreateCall(entryFns[i], args); + builder.CreateBr(exitBB); + } + + EntryPoint = multiplexedEntryName; + return; +} + +struct FunctionReachability { +public: + bool isReachableFrom(llvm::Module *m, llvm::Function *from, + llvm::Function *to) { + if (reachable.count(from) && reachable[from].count(to)) { + return true; + } + + std::unordered_set visited; + auto result = checkReachability(m, from, to, visited); + + for (auto f : visited) { + reachable[from].insert(f); + } + + return result; + } + +private: + bool checkReachability(llvm::Module *m, llvm::Function *from, + llvm::Function *to, + std::unordered_set &visited) { + if (from == to) { + visited.insert(from); + return true; + } + bool reachable = false; + llvm::CallGraph callGraph(*m); + auto node = callGraph[from]; + for (auto child : *node) { + auto f = child.second->getFunction(); + if (f && !visited.count(f)) { + visited.insert(f); + reachable = reachable || checkReachability(m, f, to, visited); + if (reachable) { + break; + } + } + } + return reachable; + } + + std::unordered_map> + reachable; +}; + +llvm::Function * +tryResolveEntryFunction(llvm::Module *mod, + std::vector> &trace) { + + llvm::Function *resKF = nullptr; + + FunctionReachability reachability; + + for (size_t i = 0; i < trace.size() && !resKF; ++i) { + for (size_t k = 0; k < trace[i].size(); ++k) { + resKF = trace[i][k]; + for (size_t j = i; j < trace.size(); ++j) { + if (i == j) { + continue; + } + + llvm::Function *curKf = nullptr; + for (size_t m = 0; m < trace[j].size() && !curKf; ++m) { + curKf = trace[j][m]; + if (!reachability.isReachableFrom(mod, resKF, curKf)) { + if (!reachability.isReachableFrom(mod, curKf, resKF)) { + curKf = nullptr; + } else { + i = j; + resKF = curKf; + } + } + } + if (!curKf) { + resKF = nullptr; + break; + } + } + } + } + + return resKF; +} + int main(int argc, char **argv, char **envp) { if (theInterpreter) { theInterpreter = nullptr; @@ -1704,23 +1877,45 @@ int main(int argc, char **argv, char **envp) { } } - std::vector args; - args.push_back(llvm::Type::getInt32Ty(ctx)); // argc - args.push_back(llvm::PointerType::get( - Type::getInt8PtrTy(ctx), - mainModule->getDataLayout().getAllocaAddrSpace())); // argv - args.push_back(llvm::PointerType::get( - Type::getInt8PtrTy(ctx), - mainModule->getDataLayout().getAllocaAddrSpace())); // envp - std::string stubEntryPoint = "__klee_entry_point_main"; - Function *stub = Function::Create( - llvm::FunctionType::get(llvm::Type::getInt32Ty(ctx), args, false), - GlobalVariable::ExternalLinkage, stubEntryPoint, mainModule); - BasicBlock *bb = BasicBlock::Create(ctx, "entry", stub); - - llvm::IRBuilder<> Builder(bb); - Builder.CreateRet(ConstantInt::get(Type::getInt32Ty(ctx), 0)); - EntryPoint = stubEntryPoint; + std::vector entryFns; + + auto paths = parseStaticAnalysisInput(); + + if (paths->empty()) { + klee_warning("No paths were given to trace verify"); + return 0; + } + + for (const auto &path : paths->results) { + std::vector> trace; + for (const auto &loc : path.locations) { + std::vector funcs; + for (auto &f : *mainModule) { + if (loc->isInside(&f, origInstructions[getLocationInfo(&f).file])) { + funcs.push_back(&f); + } + } + if (!funcs.empty()) { + trace.push_back(funcs); + } else { + klee_warning("weird trace"); + } + } + auto entryFn = tryResolveEntryFunction(mainModule, trace); + if (entryFn) { + if (std::find(entryFns.begin(), entryFns.end(), entryFn) == + entryFns.end()) { + entryFns.push_back(entryFn); + } + } else { + klee_warning("Broken trace (entry fn not resolved)."); + } + } + + if (entryFns.empty()) { + klee_error("Entry function resolved for no trace"); + } + multiplexEntryPoint(mainModule, ctx, entryFns); } std::set mainModuleFunctions; @@ -1808,9 +2003,7 @@ int main(int argc, char **argv, char **envp) { errorMsg.c_str()); } - if (!UTBotMode) { - preparePOSIX(loadedUserModules); - } + preparePOSIX(loadedUserModules); } if (WithFPRuntime) { @@ -1975,82 +2168,9 @@ int main(int argc, char **argv, char **envp) { std::move(origInstructions)); externalsAndGlobalsCheck(finalModule); - if (InteractiveMode) { - klee_message("KLEE finish preprocessing."); - std::ifstream entrypoints(EntryPointsFile); - if (!entrypoints.good()) { - klee_error("Opening %s failed.", EntryPointsFile.c_str()); - } - - if (ProcessNumber < 1 || ProcessNumber > MAX_PROCESS_NUMBER) { - klee_error("Incorrect number of process, your value is %d, but it must " - "lie in [1, %d].", - ProcessNumber.getValue(), MAX_PROCESS_NUMBER); - } - klee_message("Start %d processes.", ProcessNumber.getValue()); - - SmallString<128> outputDirectory = handler->getOutputDirectory(); - const size_t PROCESS = ProcessNumber; - using time_point = std::chrono::time_point; - std::vector> child_processes; - signal(SIGCHLD, SIG_IGN); - while (true) { - std::string entrypoint; - if (!(entrypoints >> entrypoint)) { - break; - } - - if (child_processes.size() == PROCESS) { - if (TimeoutPerFunction != 0) { - wait_until_any_child_dies(child_processes); - } else { - wait(NULL); - } - } - std::vector> alive_child; - for (const auto &child_process : child_processes) { - if (kill(child_process.first, 0) == 0) { - alive_child.push_back(child_process); - } - } - child_processes = alive_child; - - pid_t pid = fork(); - if (pid < 0) { - klee_error("%s", "Cannot create child process."); - } else if (pid == 0) { - signal(SIGCHLD, SIG_DFL); - EntryPoint = entrypoint; - SmallString<128> newOutputDirectory = outputDirectory; - sys::path::append(newOutputDirectory, entrypoint); - handler->setOutputDirectory(newOutputDirectory.c_str()); - run_klee_on_function(pArgc, pArgv, pEnvp, handler, interpreter, - finalModule, replayPath); - exit(0); - } else { - child_processes.emplace_back(pid, std::chrono::steady_clock::now()); - } - } - if (TimeoutPerFunction != 0) { - while (!child_processes.empty()) { - wait_until_any_child_dies(child_processes); - std::vector> alive_child; - for (const auto &child_process : child_processes) { - if (kill(child_process.first, 0) == 0) { - alive_child.push_back(child_process); - } - } - child_processes = alive_child; - } - } else { - while (wait(NULL) > 0) - ; - } - } else { - run_klee_on_function(pArgc, pArgv, pEnvp, handler, interpreter, finalModule, - replayPath); - } + run_klee_on_function(pArgc, pArgv, pEnvp, handler, interpreter, finalModule, + replayPath); paths.reset(); From 36fb45ca3098ba73f39da7af1bbd54b451ce8ca1 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhik Date: Sun, 31 Dec 2023 02:09:40 +0400 Subject: [PATCH 105/120] [fix] Fix the template argument --- include/klee/ADT/Incremental.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/klee/ADT/Incremental.h b/include/klee/ADT/Incremental.h index 6f16fd0867..d5a77defa8 100644 --- a/include/klee/ADT/Incremental.h +++ b/include/klee/ADT/Incremental.h @@ -192,7 +192,7 @@ class inc_uset { } }; - using idMap = std::unordered_map<_Value, MinFrameIds, _Hash, _Pred, _Alloc>; + using idMap = std::unordered_map<_Value, MinFrameIds, _Hash, _Pred>; using citerator = typename idMap::const_iterator; idMap ids; FrameId current_frame = 0; @@ -302,7 +302,7 @@ template , class inc_umap { private: std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc> map; - using idMap = std::unordered_map<_Key, FrameIds, _Hash, _Pred, _Alloc>; + using idMap = std::unordered_map<_Key, FrameIds, _Hash, _Pred>; idMap ids; FrameId current_frame = 0; From 219233c70b558aa43090c72e6bfb1a58ccf52ce7 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhik Date: Sun, 31 Dec 2023 02:12:57 +0400 Subject: [PATCH 106/120] [fix] Add arm float constants --- runtime/klee-fp/fenv.c | 19 ------------------- runtime/klee-fp/fenv.h | 29 ++++++++++++++++++++++++++++- runtime/klee-fp/log.c | 3 +-- 3 files changed, 29 insertions(+), 22 deletions(-) diff --git a/runtime/klee-fp/fenv.c b/runtime/klee-fp/fenv.c index 0a70f90f34..c5dda37789 100644 --- a/runtime/klee-fp/fenv.c +++ b/runtime/klee-fp/fenv.c @@ -9,25 +9,6 @@ #include "fenv.h" #include "klee/klee.h" -// Define the constants. Don't include `fenv.h` here to avoid -// polluting the Intrinsic module. -#if defined(__x86_64__) || defined(__i386__) -// These are the constants used by glibc and musl for x86_64 and i386 -enum { - FE_TONEAREST = 0, - FE_DOWNWARD = 0x400, - FE_UPWARD = 0x800, - FE_TOWARDZERO = 0xc00, - - // Our own implementation defined values. - // Do we want this? Although it's allowed by - // the standard it won't be replayable on native - // binaries. -}; -#else -#error Architecture not supported -#endif - int fegetround(void) { enum KleeRoundingMode rm = klee_get_rounding_mode(); switch (rm) { diff --git a/runtime/klee-fp/fenv.h b/runtime/klee-fp/fenv.h index 3cb7728f20..a833ac75c1 100644 --- a/runtime/klee-fp/fenv.h +++ b/runtime/klee-fp/fenv.h @@ -9,7 +9,34 @@ #ifndef KLEE_FENV_H #define KLEE_FENV_H -#include "klee/klee.h" + +#if defined(__x86_64__) || defined(__i386__) +#include +#elif defined(__arm64__) || defined(__arm__) +enum { + FE_TONEAREST = 0x0, + FE_UPWARD = 0x1, + FE_DOWNWARD = 0x2, + FE_TOWARDZERO = 0x3, + + // Our own implementation defined values. + // Do we want this? Although it's allowed by + // the standard it won't be replayable on native + // binaries. +}; +enum { + FE_INVALID = 0x01, + FE_DIVBYZERO = 0x02, + FE_OVERFLOW = 0x04, + FE_UNDERFLOW = 0x08, + FE_INEXACT = 0x10, + FE_DENORMAL = 0x80, + FE_ALL_EXCEPT = FE_DIVBYZERO | FE_INEXACT | FE_INVALID | FE_OVERFLOW | + FE_UNDERFLOW | FE_DENORMAL +}; +#else +#error Architecture not supported +#endif int fegetround(void); int fesetround(int rm); diff --git a/runtime/klee-fp/log.c b/runtime/klee-fp/log.c index 77f3d3a12f..62d54db47b 100644 --- a/runtime/klee-fp/log.c +++ b/runtime/klee-fp/log.c @@ -8,9 +8,8 @@ //===----------------------------------------------------------------------===*/ #include "fenv.h" -#include "math.h" -#include +#include #define LOG_CORNER_CASE(suffix, type, isnan_function) \ int log_corner_case_##suffix(type *x) { \ From 8f9fb7e29aa494ab8c2095e5370c314e28de6039 Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhik Date: Sun, 31 Dec 2023 17:20:39 +0400 Subject: [PATCH 107/120] [chore] Disable tests with uint128 type on not-x86_64 targets --- test/Feature/uint128.c | 1 + test/Industry/CoverageErrorCall/btor2c-lazyMod.mul6.c | 1 + test/lit.cfg | 1 + 3 files changed, 3 insertions(+) diff --git a/test/Feature/uint128.c b/test/Feature/uint128.c index efa5915beb..98676474c7 100644 --- a/test/Feature/uint128.c +++ b/test/Feature/uint128.c @@ -1,3 +1,4 @@ +// REQUIRES: target-x86_64 // 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 diff --git a/test/Industry/CoverageErrorCall/btor2c-lazyMod.mul6.c b/test/Industry/CoverageErrorCall/btor2c-lazyMod.mul6.c index f0261d2008..4b2d6b79fc 100644 --- a/test/Industry/CoverageErrorCall/btor2c-lazyMod.mul6.c +++ b/test/Industry/CoverageErrorCall/btor2c-lazyMod.mul6.c @@ -1,5 +1,6 @@ // It requires bitwuzla because the script currently runs with bitwuzla solver backend // REQUIRES: bitwuzla +// REQUIRES: target-x86_64 // 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 diff --git a/test/lit.cfg b/test/lit.cfg index d2af70f065..8ccd841160 100644 --- a/test/lit.cfg +++ b/test/lit.cfg @@ -260,6 +260,7 @@ else: # m32 support config.available_features.add('{}target-x86'.format('' if config.target_triple.find("i386") != -1 else 'not-')) +config.available_features.add('{}target-x86_64'.format('' if config.target_triple.find("x86_64") != -1 else 'not-')) config.available_features.add('{}32bit-support'.format('' if config.have_32bit_support else 'not-')) From 8451cc53cf331f9056f969dcebc3d0e4e22ad83f Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhik Date: Wed, 3 Jan 2024 17:35:11 +0400 Subject: [PATCH 108/120] [fix] Disable test on darwin due to stack overflow --- test/ArrayOpt/test_nier.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/ArrayOpt/test_nier.c b/test/ArrayOpt/test_nier.c index 154f72d854..55ecac126f 100644 --- a/test/ArrayOpt/test_nier.c +++ b/test/ArrayOpt/test_nier.c @@ -1,5 +1,6 @@ // REQUIRES: not-asan // REQUIRES: not-msan +// REQUIRES: not-darwin // Ignore msan: Generates a large stack trace > 8k but not a stack overflow for larger stacks // RUN: %clang %s -emit-llvm %O0opt -c -o %t.bc // RUN: rm -rf %t.klee-out @@ -18,8 +19,8 @@ // RUN: %klee --write-kqueries --output-dir=%t.klee-out --optimize-array=all %t.bc 2>&1 | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-OPT_I // RUN: test -f %t.klee-out/test000001.kquery // RUN: test -f %t.klee-out/test000002.kquery -// RUN: not FileCheck %s -input-file=%t.klee-out/test000001.kquery -check-prefix=CHECK-CONST_ARR // RUN: not FileCheck %s -input-file=%t.klee-out/test000002.kquery -check-prefix=CHECK-CONST_ARR +// RUN: not FileCheck %s -input-file=%t.klee-out/test000001.kquery -check-prefix=CHECK-CONST_ARR // CHECK-OPT_I: KLEE: WARNING: OPT_I: successful // CHECK-OPT_V: KLEE: WARNING: OPT_V: successful From 55f7438a61bddee362de48572bf6d1d7600b55fc Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhik Date: Thu, 4 Jan 2024 19:27:33 +0400 Subject: [PATCH 109/120] [ci] Update `.cirrus.yml` --- .cirrus.yml | 8 ++++---- include/klee-test-comp.c | 12 ++++++++++++ lib/Core/Executor.cpp | 2 +- runtime/POSIX/input_output.c | 18 ++++++++++++++++++ scripts/build/p-klee-linux-ubuntu.inc | 1 + scripts/build/p-klee-osx.inc | 1 + scripts/replay.sh | 13 ++++++++++--- .../ChenFlurMukhopadhyay-2012SAS-Fig1-alloca.c | 7 ++++--- .../Industry/CoverageBranches/CostasArray-17.c | 11 ++++++----- .../CoverageBranches/egcd3-ll_valuebound10.c | 11 ++++++----- test/Industry/CoverageBranches/lit.local.cfg | 2 +- test/Industry/CoverageBranches/matrix-2-2.c | 10 +++++----- ...cr.3.ufo.UNBOUNDED.pals+Problem12_label00.c | 12 ++++++------ test/Industry/egcd3-ll_valuebound10.c | 10 +++++----- test/Solver/CallComputeValue.c | 4 ++-- test/lit.cfg | 9 +++++++++ test/regression/2023-03-27-lib-function.c | 8 ++++++-- 17 files changed, 97 insertions(+), 42 deletions(-) diff --git a/.cirrus.yml b/.cirrus.yml index 828f667364..c0c113987c 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -1,16 +1,16 @@ task: freebsd_instance: matrix: - - image_family: freebsd-12-3-snap - - image_family: freebsd-13-1-snap + - image_family: freebsd-13-2-snap + - image_family: freebsd-14-0-snap deps_script: - sed -i.bak -e 's/quarterly/latest/' /etc/pkg/FreeBSD.conf - env ASSUME_ALWAYS_YES=yes pkg update -f - - env ASSUME_ALWAYS_YES=yes pkg install -y llvm11 gmake z3 cmake pkgconf google-perftools python3 py39-sqlite3 py39-tabulate + - env ASSUME_ALWAYS_YES=yes pkg install -y llvm11 gmake z3 cmake pkgconf google-perftools python3 py39-sqlite3 py39-tabulate nlohmann-json bash coreutils build_script: - mkdir build - cd build - - cmake -DLLVM_DIR=/usr/local/llvm11 -DMAKE_BINARY=/usr/local/bin/gmake -DENABLE_TCMALLOC:BOOL=true -DENABLE_POSIX_RUNTIME:BOOL=ON -DENABLE_SOLVER_Z3:BOOL=true -DENABLE_SYSTEM_TESTS:BOOL=ON .. + - cmake -DLLVM_DIR=/usr/local/llvm11 -DMAKE_BINARY=/usr/local/bin/gmake -DJSON_SRC_DIR=/usr/local -DENABLE_TCMALLOC:BOOL=true -DENABLE_POSIX_RUNTIME:BOOL=ON -DENABLE_SOLVER_Z3:BOOL=true -DENABLE_SYSTEM_TESTS:BOOL=ON .. - gmake test_script: - sed -i.bak -e 's/lit\./lit11\./' test/lit.cfg diff --git a/include/klee-test-comp.c b/include/klee-test-comp.c index 34e805e588..3013b7d669 100644 --- a/include/klee-test-comp.c +++ b/include/klee-test-comp.c @@ -22,6 +22,18 @@ void __assert_fail(const char *assertion, const char *file, unsigned int line, void klee_prefer_cex(void *, uintptr_t); #endif +#if defined(__APPLE__) || defined(__FreeBSD__) +#include + +extern void abort(void); +void __assert_fail(const char *failedexpr, const char *file, unsigned int line, + const char *fn) { + warnx("assertion \"%s\" failed: file \"%s\", line %u%s%s%s", failedexpr, file, + line, fn ? ", function: \"" : "", fn ? fn : "", fn ? "\"" : ""); + abort(); +} +#endif + int __VERIFIER_nondet_int(void) { int x; klee_make_symbolic(&x, sizeof(x), "int"); diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index de6a5bef3f..575e8299cd 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -161,7 +161,7 @@ cl::opt UseTypeBasedAliasAnalysis( cl::opt AlignSymbolicPointers("align-symbolic-pointers", cl::desc("Makes symbolic pointers aligned according" - "to the used type system (default=true)"), + "to the used type system (default=false)"), cl::init(false), cl::cat(ExecCat)); cl::opt diff --git a/runtime/POSIX/input_output.c b/runtime/POSIX/input_output.c index afed9e3d0d..14daa68af8 100644 --- a/runtime/POSIX/input_output.c +++ b/runtime/POSIX/input_output.c @@ -2,6 +2,7 @@ #include #include #include +#include /* * Return the (stdio) flags for a given mode. Store the flags @@ -53,8 +54,13 @@ FILE *fopen(const char *file, const char *mode) { if ((f = open(file, oflags)) < 0) return NULL; } +#ifndef __FreeBSD__ fp->_fileno = f; fp->_mode = oflags; +#else + fp->_file = f; + fp->_flags = oflags; +#endif return fp; } @@ -68,7 +74,11 @@ int get_file_descriptor(FILE *stream) { if (stream == stderr) { return 2; } +#ifndef __FreeBSD__ return stream->_fileno; +#else + return stream->_file; +#endif } int fgetc(FILE *stream) { @@ -86,6 +96,7 @@ int fgetc(FILE *stream) { } } +#ifndef __FreeBSD__ int getc(FILE *stream) { if (stream == NULL) { return 0; @@ -100,6 +111,7 @@ int getc(FILE *stream) { return EOF; } } +#endif size_t fread(void *buffer, size_t size, size_t count, FILE *stream) { if (stream == NULL) { @@ -137,7 +149,9 @@ char *fgets(char *s, int n, FILE *stream) { return s; } +#ifndef __FreeBSD__ int getchar(void) { return getc(stdin); } +#endif char *gets(char *s) { char *p = s; @@ -174,6 +188,7 @@ int fputc(int c, FILE *stream) { } } +#ifndef __FreeBSD__ int putc(int c, FILE *stream) { if (stream == NULL) { return 0; @@ -188,6 +203,7 @@ int putc(int c, FILE *stream) { return EOF; } } +#endif size_t fwrite(const void *buffer, size_t size, size_t count, FILE *stream) { if (stream == NULL) { @@ -221,7 +237,9 @@ int fputs(const char *str, FILE *stream) { return 1; } +#ifndef __FreeBSD__ int putchar(int c) { return putc(c, stdout); } +#endif int puts(const char *str) { int write_code = fputs(str, stdout); diff --git a/scripts/build/p-klee-linux-ubuntu.inc b/scripts/build/p-klee-linux-ubuntu.inc index a67a061615..70af8dc110 100644 --- a/scripts/build/p-klee-linux-ubuntu.inc +++ b/scripts/build/p-klee-linux-ubuntu.inc @@ -12,6 +12,7 @@ install_build_dependencies_klee() { python3-wheel pkg-config cmake-data + coreutils ) if [[ "${SOLVERS:-}" == "metaSMT" ]]; then diff --git a/scripts/build/p-klee-osx.inc b/scripts/build/p-klee-osx.inc index 4f5b063599..12893fbbb4 100644 --- a/scripts/build/p-klee-osx.inc +++ b/scripts/build/p-klee-osx.inc @@ -10,6 +10,7 @@ install_build_dependencies_klee() { pip3 install --user --upgrade lit tabulate brew install pkg-config + brew install coreutils # Get path of package location base_path=$(python3 -m site --user-base) export PATH="${base_path}/bin:$PATH" diff --git a/scripts/replay.sh b/scripts/replay.sh index 2673c91e4a..4b1f4b8cc4 100755 --- a/scripts/replay.sh +++ b/scripts/replay.sh @@ -9,6 +9,13 @@ # # ===----------------------------------------------------------------------===## -for f in `find $1 -name "*.ktest" -type f`; do - KLEE_RUN_TEST_ERRORS_NON_FATAL=STOP KTEST_FILE=$f timeout 1 $2 -done +if [[ "$OSTYPE" == "linux-gnu"* ]]; then + for f in `find $1 -name "*.ktest" -type f`; do + KLEE_RUN_TEST_ERRORS_NON_FATAL=STOP KTEST_FILE=$f timeout 1 $2 + done +else + for f in `find $1 -name "*.ktest" -type f`; do + KLEE_RUN_TEST_ERRORS_NON_FATAL=STOP KTEST_FILE=$f gtimeout 1 $2 + done +fi +exit 0 diff --git a/test/Industry/CoverageBranches/ChenFlurMukhopadhyay-2012SAS-Fig1-alloca.c b/test/Industry/CoverageBranches/ChenFlurMukhopadhyay-2012SAS-Fig1-alloca.c index fff21e4d2b..fe61b84c59 100644 --- a/test/Industry/CoverageBranches/ChenFlurMukhopadhyay-2012SAS-Fig1-alloca.c +++ b/test/Industry/CoverageBranches/ChenFlurMukhopadhyay-2012SAS-Fig1-alloca.c @@ -2,20 +2,21 @@ // 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=all %t1.bc 2>&1 | FileCheck -check-prefix=CHECK %s -// RUN: rm -f %t*.gcda %t*.gcno %t*.gcov +// RUN: rm -f ./%gcov-files-path*.gcda ./%gcov-files-path*.gcno ./%gcov-files-path*.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: gcov -b %gcov-files-path > %t.cov.log // RUN: FileCheck --input-file=%t.cov.log --check-prefix=CHECK-COV %s // Branch coverage 100%, the number of branches is 2: -// CHECK-COV: Lines executed:100.00% of 11 +// CHECK-COV: Lines executed:100.00% of 1{{1|2}} // 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" +#define alloca(size) __builtin_alloca (size) extern int __VERIFIER_nondet_int(void); int main() { diff --git a/test/Industry/CoverageBranches/CostasArray-17.c b/test/Industry/CoverageBranches/CostasArray-17.c index 6f2bcea325..7fc3bafe93 100644 --- a/test/Industry/CoverageBranches/CostasArray-17.c +++ b/test/Industry/CoverageBranches/CostasArray-17.c @@ -2,25 +2,25 @@ // 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=all --search=dfs %t1.bc -// RUN: rm -f %t*.gcda %t*.gcno %t*.gcov +// RUN: rm -f ./%gcov-files-path*.gcda ./%gcov-files-path*.gcno ./%gcov-files-path*.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: gcov -b %gcov-files-path > %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=all --search=dfs %t1.bc -// RUN: rm -f %t*.gcda %t*.gcno %t*.gcov +// RUN: rm -f ./%gcov-files-path*.gcda ./%gcov-files-path*.gcno ./%gcov-files-path*.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: gcov -b %gcov-files-path > %t.cov.log // RUN: FileCheck --input-file=%t.cov.log --check-prefix=CHECK %s // Branch coverage 100%, the number of branches is 2: -// CHECK: Lines executed:{{(0\.7[0-9])}}% of 1545 +// CHECK: Lines executed:{{(0\.7[0-9])|(99\.94)}}% of 1545 // CHECK-NEXT: Branches executed:100.00% of 2 // CHECK-NEXT: Taken at least once:100.00% of 2 @@ -44,6 +44,7 @@ int __VERIFIER_nondet_int(); #ifdef GCOV extern void __gcov_dump(void); +extern void exit(int exit_code) __attribute__((noreturn)); #endif void abort_prog() { diff --git a/test/Industry/CoverageBranches/egcd3-ll_valuebound10.c b/test/Industry/CoverageBranches/egcd3-ll_valuebound10.c index 9d433194b3..a3846f9ec0 100644 --- a/test/Industry/CoverageBranches/egcd3-ll_valuebound10.c +++ b/test/Industry/CoverageBranches/egcd3-ll_valuebound10.c @@ -2,22 +2,23 @@ // 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=all --search=dfs --search=random-state %t1.bc -// RUN: rm -f %t*.gcda %t*.gcno %t*.gcov +// RUN: rm -f ./%gcov-files-path*.gcda ./%gcov-files-path*.gcno ./%gcov-files-path*.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: gcov -b %gcov-files-path > %t.cov.log // RUN: FileCheck --input-file=%t.cov.log --check-prefix=CHECK %s -// 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 +// CHECK: Lines executed:{{87\.93|89\.83}}% of 5{{8|9}} +// CHECK-NEXT: Branches executed:100.00% of 1{{8|4}} +// CHECK-NEXT: Taken at least once:{{83\.33|85\.71}}% of 1{{8|4}} #include "klee-test-comp.c" /* extended Euclid's algorithm */ extern void abort(void); #ifdef GCOV extern void __gcov_dump(void); +extern void exit( int exit_code ) __attribute__((noreturn)); #endif void dump() { diff --git a/test/Industry/CoverageBranches/lit.local.cfg b/test/Industry/CoverageBranches/lit.local.cfg index ad131f8f64..95cecce749 100644 --- a/test/Industry/CoverageBranches/lit.local.cfg +++ b/test/Industry/CoverageBranches/lit.local.cfg @@ -4,5 +4,5 @@ def getRoot(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: +if config.have_asan or config.have_ubsan or config.have_msan: config.unsupported = True diff --git a/test/Industry/CoverageBranches/matrix-2-2.c b/test/Industry/CoverageBranches/matrix-2-2.c index 6170da72fe..879b4560ac 100644 --- a/test/Industry/CoverageBranches/matrix-2-2.c +++ b/test/Industry/CoverageBranches/matrix-2-2.c @@ -2,24 +2,24 @@ // 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=all --use-sym-size-alloc=true --symbolic-allocation-threshold=8192 %t1.bc 2>&1 -// RUN: rm -f %t*.gcda %t*.gcno %t*.gcov +// RUN: rm -f ./%gcov-files-path*.gcda ./%gcov-files-path*.gcno ./%gcov-files-path*.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: gcov -b %gcov-files-path > %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: Lines executed:{{(9[0-9]\.[0-9][0-9])|(100\.00)}}% of 2{{4|5}} // 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 +// CHECK-COV-NEXT: Taken at least once:{{([8-9][0-9]\.[0-9][0-9])|(100\.00)}}% of 16 #include "klee-test-comp.c" -extern void exit(int); extern void abort(void); #ifdef GCOV extern void __gcov_dump(void); +extern void exit(int); #endif void dump() { diff --git a/test/Industry/CoverageBranches/pals_lcr.3.ufo.UNBOUNDED.pals+Problem12_label00.c b/test/Industry/CoverageBranches/pals_lcr.3.ufo.UNBOUNDED.pals+Problem12_label00.c index c1fc602469..5e7399e6ee 100644 --- a/test/Industry/CoverageBranches/pals_lcr.3.ufo.UNBOUNDED.pals+Problem12_label00.c +++ b/test/Industry/CoverageBranches/pals_lcr.3.ufo.UNBOUNDED.pals+Problem12_label00.c @@ -1,18 +1,17 @@ -// 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=all --search=dfs --search=random-state --use-iterative-deepening-search=max-cycles --max-cycles=4 %t1.bc -// RUN: rm -f %t*.gcda %t*.gcno %t*.gcov +// RUN: rm -f ./%gcov-files-path*.gcda ./%gcov-files-path*.gcno ./%gcov-files-path*.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: gcov -b %gcov-files-path > %t.cov.log // RUN: FileCheck --input-file=%t.cov.log --check-prefix=CHECK %s -// 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 +// CHECK: Lines executed:{{(9[0-9]\.[0-9][0-9])}}% of 41{{(1|5)(3|4)}} +// CHECK-NEXT: Branches executed:{{(9[0-9]\.[0-9][0-9])}}% of {{13404|11628}} +// CHECK-NEXT: Taken at least once:{{([8-9][0-9]\.[0-9][0-9])}}% of {{13404|11628}} // This file is part of the SV-Benchmarks collection of verification tasks: // https://gitlab.com/sosy-lab/benchmarking/sv-benchmarks @@ -35,6 +34,7 @@ extern void exit(int); extern void abort(void); #ifdef GCOV extern void __gcov_dump(void); +extern void exit(int exit_code) __attribute__((noreturn)); #endif void dump() { diff --git a/test/Industry/egcd3-ll_valuebound10.c b/test/Industry/egcd3-ll_valuebound10.c index 5811f1f44d..bc6c06f982 100644 --- a/test/Industry/egcd3-ll_valuebound10.c +++ b/test/Industry/egcd3-ll_valuebound10.c @@ -3,17 +3,17 @@ // 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=all --search=dfs --search=random-state %t1.bc -// RUN: rm -f %t*.gcda %t*.gcno %t*.gcov +// RUN: rm -f ./%gcov-files-path*.gcda ./%gcov-files-path*.gcno ./%gcov-files-path*.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: gcov -b %gcov-files-path > %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 +// CHECK: Lines executed:{{(8[0-9]\.[0-9][0-9])}}% of 5{{8|9}} +// CHECK-NEXT: Branches executed:100.00% of 1{{8|4}} +// CHECK-NEXT: Taken at least once:{{(8[0-9]\.[0-9][0-9])}}% of 1{{8|4}} #include "klee-test-comp.c" /* extended Euclid's algorithm */ diff --git a/test/Solver/CallComputeValue.c b/test/Solver/CallComputeValue.c index 3e0dbe408f..36ca85cf1e 100644 --- a/test/Solver/CallComputeValue.c +++ b/test/Solver/CallComputeValue.c @@ -1,7 +1,7 @@ // 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-lazy-initialization=only %t1.bc 2>&1 | FileCheck %s #include "klee/klee.h" @@ -17,5 +17,5 @@ int main() { return 2; } -// CHECK: KLEE: done: completed paths = 17 +// CHECK: KLEE: done: completed paths = {{3|5}} // CHECK: KLEE: done: partially completed paths = 0 diff --git a/test/lit.cfg b/test/lit.cfg index 8ccd841160..55adadf5cc 100644 --- a/test/lit.cfg +++ b/test/lit.cfg @@ -173,6 +173,15 @@ config.substitutions.append( config.substitutions.append( ('%libcxx_include', getattr(config, 'libcxx_include_dir', None))) +if config.target_triple.find("darwin") != -1: + config.substitutions.append( + ('%gcov-files-path', '%basename_t') + ) +else: + config.substitutions.append( + ('%gcov-files-path', '%t_runner-%basename_t') + ) + # Add feature for the LLVM version in use, so it can be tested in REQUIRES and # XFAIL checks. We also add "not-XXX" variants, for the same reason. known_llvm_versions = { "9.0", "10.0", "11.0", "11.1", "12.0", "13.0", "14.0" } diff --git a/test/regression/2023-03-27-lib-function.c b/test/regression/2023-03-27-lib-function.c index 4754267431..90df4b41a4 100644 --- a/test/regression/2023-03-27-lib-function.c +++ b/test/regression/2023-03-27-lib-function.c @@ -11,6 +11,10 @@ #include #include +#ifdef __FreeBSD__ +#include +#endif + #ifdef INET_NTOP const char *inet_ntop(int af, const void *restrict src, char *restrict dst, socklen_t size) { @@ -22,8 +26,8 @@ const char *inet_ntop(int af, const void *restrict src, int main(int argc, char **argv) { inet_ntop(0, 0, 0, 0); - // CHECK_INTERNAL-NOT: calling external: inet_ntop - // CHECK_EXTERNAL: calling external: inet_ntop + // CHECK_INTERNAL-NOT: calling external: {{inet_ntop|__inet_ntop}} + // CHECK_EXTERNAL: calling external: {{inet_ntop|__inet_ntop}} #ifdef INET_PTON struct in_addr inaddr; inet_pton(AF_INET, "10.1.0.29", &inaddr); From cf5178a99574670e66669678f766172b247b5efe Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhik Date: Thu, 18 Jan 2024 01:40:56 +0400 Subject: [PATCH 110/120] [fix] Use `find -exec` --- scripts/replay.sh | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/scripts/replay.sh b/scripts/replay.sh index 4b1f4b8cc4..8a4a426efb 100755 --- a/scripts/replay.sh +++ b/scripts/replay.sh @@ -10,12 +10,9 @@ # ===----------------------------------------------------------------------===## if [[ "$OSTYPE" == "linux-gnu"* ]]; then - for f in `find $1 -name "*.ktest" -type f`; do - KLEE_RUN_TEST_ERRORS_NON_FATAL=STOP KTEST_FILE=$f timeout 1 $2 - done + TIMEOUT="timeout" else - for f in `find $1 -name "*.ktest" -type f`; do - KLEE_RUN_TEST_ERRORS_NON_FATAL=STOP KTEST_FILE=$f gtimeout 1 $2 - done + TIMEOUT="gtimeout" fi +find $1 -name "*.ktest" -type f -exec bash -c 'KLEE_RUN_TEST_ERRORS_NON_FATAL=STOP KTEST_FILE=$1 $3 1 $2' bash {} $2 $TIMEOUT \; exit 0 From c6a4198e769fd21ee1254fce6f1007e8b285d84d Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhik Date: Fri, 19 Jan 2024 15:25:25 +0400 Subject: [PATCH 111/120] [fix] Initialize local variables --- lib/Core/Executor.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index 575e8299cd..feb34f4470 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -48,6 +48,7 @@ #include "klee/Expr/ExprPPrinter.h" #include "klee/Expr/ExprSMTLIBPrinter.h" #include "klee/Expr/ExprUtil.h" +#include "klee/Expr/IndependentConstraintSetUnion.h" #include "klee/Expr/IndependentSet.h" #include "klee/Expr/Symcrete.h" #include "klee/Module/Cell.h" @@ -1884,9 +1885,9 @@ void Executor::unwindToNextLandingpad(ExecutionState &state) { UnwindingInformation *ui = state.unwindingInformation.get(); assert(ui && "unwinding without unwinding information"); - std::size_t startIndex; - std::size_t lowestStackIndex; - bool popFrames; + std::size_t startIndex = 0; + std::size_t lowestStackIndex = 0; + bool popFrames = false; if (auto *sui = dyn_cast(ui)) { startIndex = sui->unwindingProgress; From 8d17abfbd3389e26a946aa7cb6eb7d32eb50312f Mon Sep 17 00:00:00 2001 From: Aleksandr Misonizhik Date: Fri, 19 Jan 2024 15:46:20 +0400 Subject: [PATCH 112/120] [fix] Fix assertion fail --- include/klee/Expr/Constraints.h | 1 - include/klee/Expr/IndependentSet.h | 7 ++- lib/Expr/Constraints.cpp | 1 + lib/Expr/IndependentConstraintSetUnion.cpp | 18 +++++-- lib/Expr/IndependentSet.cpp | 61 +++++----------------- lib/Solver/ConcretizingSolver.cpp | 1 + 6 files changed, 33 insertions(+), 56 deletions(-) diff --git a/include/klee/Expr/Constraints.h b/include/klee/Expr/Constraints.h index f4c0e22db8..3809238a1b 100644 --- a/include/klee/Expr/Constraints.h +++ b/include/klee/Expr/Constraints.h @@ -17,7 +17,6 @@ #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" diff --git a/include/klee/Expr/IndependentSet.h b/include/klee/Expr/IndependentSet.h index cbcf9ec752..c2aeb7173f 100644 --- a/include/klee/Expr/IndependentSet.h +++ b/include/klee/Expr/IndependentSet.h @@ -23,6 +23,7 @@ DISABLE_WARNING_POP namespace klee { using ExprOrSymcrete = either; +class IndependentConstraintSetUnion; struct ExprOrSymcreteHash { unsigned operator()(const ref &e) const { return e->hash(); } @@ -97,9 +98,7 @@ inline llvm::raw_ostream &operator<<(llvm::raw_ostream &os, class IndependentConstraintSet { private: - using InnerSetUnion = - DisjointSetUnion, IndependentConstraintSet, - ExprOrSymcreteHash, ExprOrSymcreteCmp>; + using InnerSetUnion = IndependentConstraintSetUnion; void initIndependentConstraintSet(ref e); void initIndependentConstraintSet(ref s); @@ -119,7 +118,7 @@ class IndependentConstraintSet { Assignment concretization; - InnerSetUnion concretizedSets; + std::shared_ptr concretizedSets; ref addExpr(ref e) const; ref diff --git a/lib/Expr/Constraints.cpp b/lib/Expr/Constraints.cpp index b88c204555..7669baad7d 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/IndependentConstraintSetUnion.h" #include "klee/Expr/IndependentSet.h" #include "klee/Expr/Path.h" #include "klee/Expr/Symcrete.h" diff --git a/lib/Expr/IndependentConstraintSetUnion.cpp b/lib/Expr/IndependentConstraintSetUnion.cpp index b2c67e5a14..ba0b57026c 100644 --- a/lib/Expr/IndependentConstraintSetUnion.cpp +++ b/lib/Expr/IndependentConstraintSetUnion.cpp @@ -1,5 +1,8 @@ #include "klee/Expr/IndependentConstraintSetUnion.h" +#include "klee/ADT/DisjointSetUnion.h" +#include "klee/Expr/IndependentSet.h" + namespace klee { IndependentConstraintSetUnion::IndependentConstraintSetUnion() {} @@ -152,10 +155,11 @@ IndependentConstraintSetUnion::getConcretizedVersion() { ref root = disjointSets.at(i); if (root->concretization.bindings.empty()) { for (ref expr : root->exprs) { - icsu.addValue(new ExprOrSymcrete::left(expr)); + icsu.addExpr(expr); } } else { - icsu.add(root->concretizedSets); + root->concretizedSets->calculateQueue(); + icsu.add(*root->concretizedSets.get()); } icsu.concretization.addIndependentAssignment(root->concretization); } @@ -178,7 +182,15 @@ void IndependentConstraintSetUnion::calculateQueue() { calculateUpdateConcretizationQueue(); calculateRemoveConcretizationQueue(); while (!constraintQueue.empty()) { - addValue(constraintQueue[constraintQueue.size() - 1]); + auto constraint = constraintQueue[constraintQueue.size() - 1]; + if (auto expr = dyn_cast(constraint)) { + if (auto ce = dyn_cast(expr->value())) { + assert(ce->isTrue() && "Attempt to add invalid constraint"); + constraintQueue.pop_back(); + continue; + } + } + addValue(constraint); constraintQueue.pop_back(); } calculateUpdateConcretizationQueue(); diff --git a/lib/Expr/IndependentSet.cpp b/lib/Expr/IndependentSet.cpp index 888dc52fdd..79e3fad63e 100644 --- a/lib/Expr/IndependentSet.cpp +++ b/lib/Expr/IndependentSet.cpp @@ -5,6 +5,7 @@ #include "klee/Expr/Constraints.h" #include "klee/Expr/ExprHashMap.h" #include "klee/Expr/ExprUtil.h" +#include "klee/Expr/IndependentConstraintSetUnion.h" #include "klee/Expr/SymbolicSource.h" #include "klee/Expr/Symcrete.h" #include "klee/Solver/Solver.h" @@ -29,32 +30,20 @@ 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(new ExprOrSymcrete::left(e)); + DSU.addExpr(e); } for (ref s : symcretes) { 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 ExprOrSymcrete::left(e)); + DSU.addExpr(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 ExprOrSymcrete::left(e)); + DSU.addExpr(e); } - ics->concretizedSets = DSU; + ics->concretizedSets.reset(new InnerSetUnion(DSU)); return ics; } @@ -71,33 +60,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(new ExprOrSymcrete::left(e)); + DSU.addExpr(e); } for (ref s : symcretes) { 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 ExprOrSymcrete::left(e)); + DSU.addExpr(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 ExprOrSymcrete::left(e)); + DSU.addExpr(e); } - ics->concretizedSets = DSU; + ics->concretizedSets.reset(new InnerSetUnion(DSU)); return ics; } @@ -346,32 +323,20 @@ IndependentConstraintSet::merge(ref A, 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 ExprOrSymcrete::left(e)); + DSU.addExpr(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 ExprOrSymcrete::left(e)); + DSU.addExpr(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 ExprOrSymcrete::left(e)); + DSU.addExpr(e); } - a->concretizedSets = DSU; + a->concretizedSets.reset(new InnerSetUnion(DSU)); } return a; diff --git a/lib/Solver/ConcretizingSolver.cpp b/lib/Solver/ConcretizingSolver.cpp index 6f0327a226..645d1863f4 100644 --- a/lib/Solver/ConcretizingSolver.cpp +++ b/lib/Solver/ConcretizingSolver.cpp @@ -3,6 +3,7 @@ #include "klee/Expr/Constraints.h" #include "klee/Expr/Expr.h" #include "klee/Expr/ExprUtil.h" +#include "klee/Expr/IndependentConstraintSetUnion.h" #include "klee/Expr/IndependentSet.h" #include "klee/Expr/SymbolicSource.h" #include "klee/Expr/Symcrete.h" From cac9566c8a44eafa92caf1569c8a6a77971a7cda Mon Sep 17 00:00:00 2001 From: Vladislav Kalugin Date: Tue, 23 Jan 2024 16:19:53 +0300 Subject: [PATCH 113/120] Remove unnecessary field from the ImmutableList --- include/klee/ADT/ImmutableList.h | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/include/klee/ADT/ImmutableList.h b/include/klee/ADT/ImmutableList.h index 425036979e..73ce89f448 100644 --- a/include/klee/ADT/ImmutableList.h +++ b/include/klee/ADT/ImmutableList.h @@ -47,16 +47,10 @@ template class ImmutableList { 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()); - } - } + explicit iterator(const ImmutableListNode *p) : rootNode(p), get(0) {} bool operator==(const iterator &b) const { return rootNode == b.rootNode && get == b.get; @@ -66,17 +60,16 @@ template class ImmutableList { iterator &operator++() { ++get; - if (get < rootNode->prev_len) { - it->operator++(); - } return *this; } const T &operator*() const { - if (get < rootNode->prev_len) { - return **it; + assert(get < rootNode->size() && "Out of bound"); + const ImmutableListNode *curNode = rootNode; + while (get < curNode->prev_len) { + curNode = curNode->prev.get(); } - return rootNode->values[get - rootNode->prev_len]; + return curNode->values[get - curNode->prev_len]; } const T &operator->() const { return **this; } From 4fd12f0a2a83ed07e702545f83cfc86e656736be Mon Sep 17 00:00:00 2001 From: Aleksei Babushkin Date: Mon, 29 Jan 2024 16:40:15 +0500 Subject: [PATCH 114/120] [fix] fix bitwuzla build version fix --- .github/workflows/build.yaml | 3 +-- build.sh | 5 ++--- scripts/build/common-functions | 6 ------ scripts/build/p-bitwuzla.inc | 2 +- scripts/build/v-bitwuzla.inc | 1 - 5 files changed, 4 insertions(+), 13 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 91e11e7431..2e531d15da 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -29,8 +29,7 @@ env: USE_LIBCXX: 1 Z3_VERSION: 4.8.15 SQLITE_VERSION: 3400100 - BITWUZLA_VERSION: main - BITWUZLA_COMMIT: 80ef7cd803e1c71b5939c3eb951f1736388f7090 + BITWUZLA_VERSION: 0.3.1 JSON_VERSION: v3.11.3 jobs: diff --git a/build.sh b/build.sh index 2bd37ea984..6878b06a10 100755 --- a/build.sh +++ b/build.sh @@ -53,7 +53,6 @@ Z3_VERSION=4.8.15 STP_VERSION=2.3.3 MINISAT_VERSION=master -BITWUZLA_VERSION=main -BITWUZLA_COMMIT=80ef7cd803e1c71b5939c3eb951f1736388f7090 +BITWUZLA_VERSION=0.3.1 -BASE="$BASE" KLEE_RUNTIME_BUILD=$KLEE_RUNTIME_BUILD COVERAGE=$COVERAGE ENABLE_DOXYGEN=$ENABLE_DOXYGEN USE_TCMALLOC=$USE_TCMALLOC USE_LIBCXX=$USE_LIBCXX LLVM_VERSION=$LLVM_VERSION ENABLE_OPTIMIZED=$ENABLE_OPTIMIZED ENABLE_DEBUG=$ENABLE_DEBUG DISABLE_ASSERTIONS=$DISABLE_ASSERTIONS REQUIRES_RTTI=$REQUIRES_RTTI SOLVERS=$SOLVERS GTEST_VERSION=$GTEST_VERSION UCLIBC_VERSION=$UCLIBC_VERSION STP_VERSION=$STP_VERSION MINISAT_VERSION=$MINISAT_VERSION Z3_VERSION=$Z3_VERSION BITWUZLA_VERSION=$BITWUZLA_VERSION BITWUZLA_COMMIT=$BITWUZLA_COMMIT SQLITE_VERSION=$SQLITE_VERSION JSON_VERSION=$JSON_VERSION ./scripts/build/build.sh klee --install-system-deps +BASE="$BASE" KLEE_RUNTIME_BUILD=$KLEE_RUNTIME_BUILD COVERAGE=$COVERAGE ENABLE_DOXYGEN=$ENABLE_DOXYGEN USE_TCMALLOC=$USE_TCMALLOC USE_LIBCXX=$USE_LIBCXX LLVM_VERSION=$LLVM_VERSION ENABLE_OPTIMIZED=$ENABLE_OPTIMIZED ENABLE_DEBUG=$ENABLE_DEBUG DISABLE_ASSERTIONS=$DISABLE_ASSERTIONS REQUIRES_RTTI=$REQUIRES_RTTI SOLVERS=$SOLVERS GTEST_VERSION=$GTEST_VERSION UCLIBC_VERSION=$UCLIBC_VERSION STP_VERSION=$STP_VERSION MINISAT_VERSION=$MINISAT_VERSION Z3_VERSION=$Z3_VERSION BITWUZLA_VERSION=$BITWUZLA_VERSION SQLITE_VERSION=$SQLITE_VERSION JSON_VERSION=$JSON_VERSION ./scripts/build/build.sh klee --install-system-deps diff --git a/scripts/build/common-functions b/scripts/build/common-functions index 65027f0bd3..d7ae4654c4 100644 --- a/scripts/build/common-functions +++ b/scripts/build/common-functions @@ -15,12 +15,6 @@ function git_clone_or_update() { fi popd fi - - if [[ $# -ge 4 ]]; then - pushd "$destination" - git checkout $4 - popd - fi } function get_git_hash() { diff --git a/scripts/build/p-bitwuzla.inc b/scripts/build/p-bitwuzla.inc index 87a28ea827..fb518ab1f8 100644 --- a/scripts/build/p-bitwuzla.inc +++ b/scripts/build/p-bitwuzla.inc @@ -13,7 +13,7 @@ setup_build_variables_bitwuzla() { download_bitwuzla() { source "${DIR}/common-functions" # Download Bitwuzla - git_clone_or_update "${bitwuzla_url}" "${BASE}/bitwuzla-${BITWUZLA_VERSION}" "${BITWUZLA_VERSION}" "${BITWUZLA_COMMIT}" + git_clone_or_update "${bitwuzla_url}" "${BASE}/bitwuzla-${BITWUZLA_VERSION}" "${BITWUZLA_VERSION}" } build_bitwuzla() { diff --git a/scripts/build/v-bitwuzla.inc b/scripts/build/v-bitwuzla.inc index bccd375853..752e9e64d8 100644 --- a/scripts/build/v-bitwuzla.inc +++ b/scripts/build/v-bitwuzla.inc @@ -1,7 +1,6 @@ # Build information for Bitwuzla solver required_variables_bitwuzla=( "BITWUZLA_VERSION" - "BITWUZLA_COMMIT" ) artifact_dependency_bitwuzla=("sanitizer") From 79aedb617897e6a489c44b59b3b33f4758556203 Mon Sep 17 00:00:00 2001 From: Lana243 Date: Fri, 16 Jun 2023 14:15:47 +0300 Subject: [PATCH 115/120] Add mocks: - Generation in two modes: naive and determinitic - Mocks are reproducible - Special mocks for allocators: malloc, calloc, realloc --- .github/workflows/build.yaml | 1 + include/klee/Core/Interpreter.h | 34 +++-- include/klee/Core/MockBuilder.h | 39 ++++++ include/klee/Expr/SourceBuilder.h | 8 ++ include/klee/Expr/SymbolicSource.h | 56 ++++++++ include/klee/klee.h | 1 + lib/Core/CMakeLists.txt | 1 + lib/Core/ExecutionState.cpp | 1 + lib/Core/Executor.cpp | 135 +++++++++++++++++- lib/Core/Executor.h | 9 +- lib/Core/MockBuilder.cpp | 152 +++++++++++++++++++++ lib/Core/SpecialFunctionHandler.cpp | 23 ++++ lib/Core/SpecialFunctionHandler.h | 1 + lib/Expr/ExprPPrinter.cpp | 12 ++ lib/Expr/ExprUtil.cpp | 10 ++ lib/Expr/IndependentSet.cpp | 13 ++ lib/Expr/Parser.cpp | 36 +++++ lib/Expr/SourceBuilder.cpp | 18 +++ lib/Expr/SymbolicSource.cpp | 63 ++++++++- lib/Solver/Z3Builder.cpp | 39 +++++- lib/Solver/Z3Builder.h | 7 + runtime/CMakeLists.txt | 2 + runtime/Mocks/CMakeLists.txt | 19 +++ runtime/Mocks/models.c | 36 +++++ runtime/Runtest/CMakeLists.txt | 2 + runtime/Runtest/intrinsics.c | 11 +- scripts/run_tests_with_mocks.py | 26 ++++ test/Feature/MockPointersDeterministic.c | 23 ++++ test/Feature/MockStrategies.c | 37 +++++ test/Replay/libkleeruntest/replay_mocks.c | 19 +++ test/lit.cfg | 9 ++ tools/klee/main.cpp | 159 ++++++++++++++++++---- 32 files changed, 957 insertions(+), 45 deletions(-) create mode 100644 include/klee/Core/MockBuilder.h create mode 100644 lib/Core/MockBuilder.cpp create mode 100644 runtime/Mocks/CMakeLists.txt create mode 100644 runtime/Mocks/models.c create mode 100755 scripts/run_tests_with_mocks.py create mode 100644 test/Feature/MockPointersDeterministic.c create mode 100644 test/Feature/MockStrategies.c create mode 100644 test/Replay/libkleeruntest/replay_mocks.c diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 2e531d15da..9932e4de62 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -146,6 +146,7 @@ jobs: runs-on: macos-latest env: BASE: /tmp + LLVM_VERSION: 11 SOLVERS: STP UCLIBC_VERSION: 0 USE_TCMALLOC: 0 diff --git a/include/klee/Core/Interpreter.h b/include/klee/Core/Interpreter.h index 0a15abc56d..942c678c2f 100644 --- a/include/klee/Core/Interpreter.h +++ b/include/klee/Core/Interpreter.h @@ -29,6 +29,7 @@ class BasicBlock; class Function; class LLVMContext; class Module; +class Type; class raw_ostream; class raw_fd_ostream; } // namespace llvm @@ -63,6 +64,13 @@ using FLCtoOpcode = std::unordered_map< std::unordered_map< unsigned, std::unordered_map>>>; +enum class MockStrategy { + None, // No mocks are generated + Naive, // For each function call new symbolic value is generated + Deterministic, // Each function is treated as uninterpreted function in SMT. + // Compatible with Z3 solver only +}; + class Interpreter { public: enum class GuidanceKind { @@ -79,6 +87,8 @@ class Interpreter { std::string LibraryDir; std::string EntryPoint; std::string OptSuffix; + std::string MainCurrentName; + std::string MainNameAfterMock; bool Optimize; bool Simplify; bool CheckDivZero; @@ -88,13 +98,16 @@ class Interpreter { ModuleOptions(const std::string &_LibraryDir, const std::string &_EntryPoint, const std::string &_OptSuffix, - bool _Optimize, bool _Simplify, bool _CheckDivZero, - bool _CheckOvershift, bool _WithFPRuntime, - bool _WithPOSIXRuntime) + const std::string &_MainCurrentName, + const std::string &_MainNameAfterMock, bool _Optimize, + bool _Simplify, bool _CheckDivZero, bool _CheckOvershift, + bool _WithFPRuntime, bool _WithPOSIXRuntime) : LibraryDir(_LibraryDir), EntryPoint(_EntryPoint), - OptSuffix(_OptSuffix), Optimize(_Optimize), Simplify(_Simplify), - CheckDivZero(_CheckDivZero), CheckOvershift(_CheckOvershift), - WithFPRuntime(_WithFPRuntime), WithPOSIXRuntime(_WithPOSIXRuntime) {} + OptSuffix(_OptSuffix), MainCurrentName(_MainCurrentName), + MainNameAfterMock(_MainNameAfterMock), Optimize(_Optimize), + Simplify(_Simplify), CheckDivZero(_CheckDivZero), + CheckOvershift(_CheckOvershift), WithFPRuntime(_WithFPRuntime), + WithPOSIXRuntime(_WithPOSIXRuntime) {} }; enum LogType { @@ -112,10 +125,11 @@ class Interpreter { unsigned MakeConcreteSymbolic; GuidanceKind Guidance; std::optional Paths; + enum MockStrategy MockStrategy; InterpreterOptions(std::optional Paths) : MakeConcreteSymbolic(false), Guidance(GuidanceKind::NoGuidance), - Paths(std::move(Paths)) {} + Paths(std::move(Paths)), MockStrategy(MockStrategy::None) {} }; protected: @@ -144,7 +158,11 @@ class Interpreter { const ModuleOptions &opts, std::set &&mainModuleFunctions, std::set &&mainModuleGlobals, - FLCtoOpcode &&origInstructions) = 0; + FLCtoOpcode &&origInstructions, + const std::set &ignoredExternals) = 0; + + virtual std::map + getAllExternals(const std::set &ignoredExternals) = 0; // supply a tree stream writer which the interpreter will use // to record the concrete path (as a stream of '0' and '1' bytes). diff --git a/include/klee/Core/MockBuilder.h b/include/klee/Core/MockBuilder.h new file mode 100644 index 0000000000..70949b10a7 --- /dev/null +++ b/include/klee/Core/MockBuilder.h @@ -0,0 +1,39 @@ +#ifndef KLEE_MOCKBUILDER_H +#define KLEE_MOCKBUILDER_H + +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/Module.h" + +#include +#include + +namespace klee { + +class MockBuilder { +private: + const llvm::Module *userModule; + std::unique_ptr mockModule; + std::unique_ptr> builder; + std::map externals; + + const std::string mockEntrypoint, userEntrypoint; + + void initMockModule(); + void buildMockMain(); + void buildExternalGlobalsDefinitions(); + void buildExternalFunctionsDefinitions(); + void buildCallKleeMakeSymbol(const std::string &klee_function_name, + llvm::Value *source, llvm::Type *type, + const std::string &symbol_name); + +public: + MockBuilder(const llvm::Module *initModule, std::string mockEntrypoint, + std::string userEntrypoint, + std::map externals); + + std::unique_ptr build(); +}; + +} // namespace klee + +#endif // KLEE_MOCKBUILDER_H diff --git a/include/klee/Expr/SourceBuilder.h b/include/klee/Expr/SourceBuilder.h index f922a29861..20eea0b49a 100644 --- a/include/klee/Expr/SourceBuilder.h +++ b/include/klee/Expr/SourceBuilder.h @@ -3,6 +3,8 @@ #include "klee/Expr/SymbolicSource.h" +#include "llvm/IR/Function.h" + namespace klee { class KInstruction; @@ -39,6 +41,12 @@ class SourceBuilder { static ref value(const llvm::Value &_allocSite, int _index, KModule *km); static ref irreproducible(const std::string &name); + static ref mockNaive(const KModule *kModule, + const llvm::Function &kFunction, + unsigned version); + static ref + mockDeterministic(const KModule *kModule, const llvm::Function &kFunction, + const std::vector> &args); static ref alpha(int _index); }; diff --git a/include/klee/Expr/SymbolicSource.h b/include/klee/Expr/SymbolicSource.h index 6853e4715d..6707ebd31c 100644 --- a/include/klee/Expr/SymbolicSource.h +++ b/include/klee/Expr/SymbolicSource.h @@ -20,11 +20,13 @@ DISABLE_WARNING_POP namespace klee { +class Expr; class Array; class Expr; class ConstantExpr; struct KGlobalVariable; class KModule; +struct KFunction; struct KValue; struct KInstruction; @@ -48,6 +50,8 @@ class SymbolicSource { Instruction, Argument, Irreproducible, + MockNaive, + MockDeterministic, Alpha }; @@ -383,6 +387,58 @@ class AlphaSource : public SymbolicSource { } }; +class MockSource : public SymbolicSource { +public: + const KModule *km; + const llvm::Function &function; + MockSource(const KModule *_km, const llvm::Function &_function) + : km(_km), function(_function) {} + + static bool classof(const SymbolicSource *S) { + return S->getKind() == Kind::MockNaive || + S->getKind() == Kind::MockDeterministic; + } +}; + +class MockNaiveSource : public MockSource { +public: + const unsigned version; + + MockNaiveSource(const KModule *km, const llvm::Function &function, + unsigned _version) + : MockSource(km, function), version(_version) {} + + Kind getKind() const override { return Kind::MockNaive; } + std::string getName() const override { return "mockNaive"; } + + static bool classof(const SymbolicSource *S) { + return S->getKind() == Kind::MockNaive; + } + + unsigned computeHash() override; + + int internalCompare(const SymbolicSource &b) const override; +}; + +class MockDeterministicSource : public MockSource { +public: + const std::vector> args; + + MockDeterministicSource(const KModule *_km, const llvm::Function &_function, + const std::vector> &_args); + + Kind getKind() const override { return Kind::MockDeterministic; } + std::string getName() const override { return "mockDeterministic"; } + + static bool classof(const SymbolicSource *S) { + return S->getKind() == Kind::MockDeterministic; + } + + unsigned computeHash() override; + + int internalCompare(const SymbolicSource &b) const override; +}; + } // namespace klee #endif /* KLEE_SYMBOLICSOURCE_H */ diff --git a/include/klee/klee.h b/include/klee/klee.h index 9c40ef335c..5995ff2e24 100644 --- a/include/klee/klee.h +++ b/include/klee/klee.h @@ -201,5 +201,6 @@ long double klee_rintl(long double d); // stdin/stdout void klee_init_env(int *argcPtr, char ***argvPtr); void check_stdin_read(); +void *__klee_wrapped_malloc(size_t size); #endif /* KLEE_H */ diff --git a/lib/Core/CMakeLists.txt b/lib/Core/CMakeLists.txt index 9d94da9169..9e0dbb715c 100644 --- a/lib/Core/CMakeLists.txt +++ b/lib/Core/CMakeLists.txt @@ -22,6 +22,7 @@ add_library(kleeCore Memory.cpp MemoryManager.cpp PForest.cpp + MockBuilder.cpp PTree.cpp Searcher.cpp SeedInfo.cpp diff --git a/lib/Core/ExecutionState.cpp b/lib/Core/ExecutionState.cpp index 1d4d06f927..bf843031da 100644 --- a/lib/Core/ExecutionState.cpp +++ b/lib/Core/ExecutionState.cpp @@ -25,6 +25,7 @@ DISABLE_WARNING_DEPRECATED_DECLARATIONS #include "llvm/IR/Function.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/raw_ostream.h" +#include "klee/Support/ErrorHandling.h" DISABLE_WARNING_POP #include diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index feb34f4470..182836cca4 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -40,6 +40,7 @@ #include "klee/Config/Version.h" #include "klee/Config/config.h" #include "klee/Core/Interpreter.h" +#include "klee/Core/MockBuilder.h" #include "klee/Expr/ArrayExprOptimizer.h" #include "klee/Expr/ArrayExprVisitor.h" #include "klee/Expr/Assignment.h" @@ -508,9 +509,9 @@ Executor::Executor(LLVMContext &ctx, const InterpreterOptions &opts, InterpreterHandler *ih) : Interpreter(opts), interpreterHandler(ih), searcher(nullptr), externalDispatcher(new ExternalDispatcher(ctx)), statsTracker(0), - pathWriter(0), symPathWriter(0), - specialFunctionHandler(0), timers{time::Span(TimerInterval)}, - guidanceKind(opts.Guidance), codeGraphInfo(new CodeGraphInfo()), + pathWriter(0), symPathWriter(0), specialFunctionHandler(0), + timers{time::Span(TimerInterval)}, guidanceKind(opts.Guidance), + codeGraphInfo(new CodeGraphInfo()), distanceCalculator(new DistanceCalculator(*codeGraphInfo)), targetCalculator(new TargetCalculator(*codeGraphInfo)), targetManager(new TargetManager(guidanceKind, *distanceCalculator, @@ -521,6 +522,11 @@ Executor::Executor(LLVMContext &ctx, const InterpreterOptions &opts, inhibitForking(false), coverOnTheFly(false), haltExecution(HaltExecution::NotHalt), ivcEnabled(false), debugLogBuffer(debugBufferString) { + if (CoreSolverToUse != Z3_SOLVER && + interpreterOpts.MockStrategy == MockStrategy::Deterministic) { + klee_error("Deterministic mocks can be generated with Z3 solver only.\n"); + } + const time::Span maxTime{MaxTime}; if (maxTime) timers.add(std::make_unique(maxTime, [&] { @@ -587,10 +593,22 @@ llvm::Module *Executor::setModule( std::vector> &userModules, std::vector> &libsModules, const ModuleOptions &opts, std::set &&mainModuleFunctions, - std::set &&mainModuleGlobals, FLCtoOpcode &&origInstructions) { + std::set &&mainModuleGlobals, FLCtoOpcode &&origInstructions, + const std::set &ignoredExternals) { assert(!kmodule && !userModules.empty() && "can only register one module"); // XXX gross + if (ExternalCalls == ExternalCallPolicy::All && + interpreterOpts.MockStrategy != MockStrategy::None) { + llvm::Function *mainFn = + userModules.front()->getFunction(opts.MainCurrentName); + if (!mainFn) { + klee_error("Entry function '%s' not found in module.", + opts.MainCurrentName.c_str()); + } + mainFn->setName(opts.MainNameAfterMock); + } + kmodule = std::make_unique(); // 1.) Link the modules together && 2.) Apply different instrumentation @@ -615,6 +633,42 @@ llvm::Module *Executor::setModule( kmodule->instrument(opts); } + if (ExternalCalls == ExternalCallPolicy::All && + interpreterOpts.MockStrategy != MockStrategy::None) { + // TODO: move this to function + std::map externals = + getAllExternals(ignoredExternals); + MockBuilder builder(kmodule->module.get(), opts.MainCurrentName, + opts.MainNameAfterMock, externals); + std::unique_ptr mockModule = builder.build(); + if (!mockModule) { + klee_error("Unable to generate mocks"); + } + // TODO: change this to bc file + std::unique_ptr f( + interpreterHandler->openOutputFile("externals.ll")); + auto mainFn = mockModule->getFunction(opts.MainCurrentName); + mainFn->setName(opts.EntryPoint); + *f << *mockModule; + mainFn->setName(opts.MainCurrentName); + + std::vector> mockModules; + mockModules.push_back(std::move(mockModule)); + kmodule->link(mockModules, 0); + + for (auto &global : kmodule->module->globals()) { + if (global.isDeclaration()) { + llvm::Constant *zeroInitializer = + llvm::Constant::getNullValue(global.getValueType()); + if (!zeroInitializer) { + klee_error("Unable to get zero initializer for '%s'", + global.getName().str().c_str()); + } + global.setInitializer(zeroInitializer); + } + } + } + // 3.) Optimise and prepare for KLEE // Create a list of functions that should be preserved if used @@ -677,6 +731,37 @@ llvm::Module *Executor::setModule( return kmodule->module.get(); } +std::map +Executor::getAllExternals(const std::set &ignoredExternals) { + std::map externals; + for (const auto &f : kmodule->module->functions()) { + if (f.isDeclaration() && !f.use_empty() && + !ignoredExternals.count(f.getName().str())) + // NOTE: here we detect all the externals, even linked. + externals.insert(std::make_pair(f.getName(), f.getFunctionType())); + } + + for (const auto &global : kmodule->module->globals()) { + if (global.isDeclaration() && + !ignoredExternals.count(global.getName().str())) + externals.insert(std::make_pair(global.getName(), global.getValueType())); + } + + for (const auto &alias : kmodule->module->aliases()) { + auto it = externals.find(alias.getName().str()); + if (it != externals.end()) { + externals.erase(it); + } + } + + for (const auto &e : externals) { + klee_message("Mocking external %s %s", + e.second->isFunctionTy() ? "function" : "variable", + e.first.c_str()); + } + return externals; +} + Executor::~Executor() { delete typeSystemManager; delete externalDispatcher; @@ -6745,6 +6830,48 @@ void Executor::executeMakeSymbolic(ExecutionState &state, } } +void Executor::executeMakeMock(ExecutionState &state, KInstruction *target, + std::vector> &arguments) { + KFunction *kf = target->parent->parent; + std::string name = "@call_" + kf->getName().str(); + uint64_t width = + kmodule->targetData->getTypeSizeInBits(kf->function->getReturnType()); + KType *type = typeSystemManager->getWrappedType( + llvm::PointerType::get(kf->function->getReturnType(), + kmodule->targetData->getAllocaAddrSpace())); + + IDType moID; + bool success = state.addressSpace.resolveOne(cast(arguments[0]), + type, moID); + assert(success && "memory object for mock should already be allocated"); + const MemoryObject *mo = state.addressSpace.findObject(moID).first; + assert(mo && "memory object for mock should already be allocated"); + mo->setName(name); + + ref source; + switch (interpreterOpts.MockStrategy) { + case MockStrategy::None: + klee_error("klee_make_mock is not allowed when mock strategy is none"); + break; + case MockStrategy::Naive: + source = SourceBuilder::mockNaive(kmodule.get(), *kf->function, + updateNameVersion(state, name)); + break; + case MockStrategy::Deterministic: + std::vector> args(kf->numArgs); + for (size_t i = 0; i < kf->numArgs; i++) { + args[i] = getArgumentCell(state, kf, i).value; + } + source = + SourceBuilder::mockDeterministic(kmodule.get(), *kf->function, args); + break; + } + executeMakeSymbolic(state, mo, type, source, false); + const ObjectState *os = state.addressSpace.findObject(mo->id).second; + auto result = os->read(0, width); + bindLocal(target, state, result); +} + /***/ ExecutionState *Executor::formState(Function *f) { diff --git a/lib/Core/Executor.h b/lib/Core/Executor.h index 006b74eaae..1dfe2ddc5b 100644 --- a/lib/Core/Executor.h +++ b/lib/Core/Executor.h @@ -428,6 +428,9 @@ class Executor : public Interpreter { KType *type, const ref source, bool isLocal); + void executeMakeMock(ExecutionState &state, KInstruction *target, + std::vector> &arguments); + void updateStateWithSymcretes(ExecutionState &state, const Assignment &assignment); @@ -735,7 +738,11 @@ class Executor : public Interpreter { const ModuleOptions &opts, std::set &&mainModuleFunctions, std::set &&mainModuleGlobals, - FLCtoOpcode &&origInstructions) override; + FLCtoOpcode &&origInstructions, + const std::set &ignoredExternals) override; + + std::map + getAllExternals(const std::set &ignoredExternals) override; void useSeeds(const std::vector *seeds) override { usingSeeds = seeds; diff --git a/lib/Core/MockBuilder.cpp b/lib/Core/MockBuilder.cpp new file mode 100644 index 0000000000..2392458241 --- /dev/null +++ b/lib/Core/MockBuilder.cpp @@ -0,0 +1,152 @@ +#include "klee/Core/MockBuilder.h" + +#include "klee/Support/ErrorHandling.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/Module.h" + +#include + +namespace klee { + +MockBuilder::MockBuilder(const llvm::Module *initModule, + std::string mockEntrypoint, std::string userEntrypoint, + std::map externals) + : userModule(initModule), externals(std::move(externals)), + mockEntrypoint(std::move(mockEntrypoint)), + userEntrypoint(std::move(userEntrypoint)) {} + +std::unique_ptr MockBuilder::build() { + initMockModule(); + buildMockMain(); + buildExternalFunctionsDefinitions(); + return std::move(mockModule); +} + +void MockBuilder::initMockModule() { + mockModule = std::make_unique(userModule->getName().str() + + "__klee_externals", + userModule->getContext()); + mockModule->setTargetTriple(userModule->getTargetTriple()); + mockModule->setDataLayout(userModule->getDataLayout()); + builder = std::make_unique>(mockModule->getContext()); +} + +// Set up entrypoint in new module. Here we'll define external globals and then +// call user's entrypoint. +void MockBuilder::buildMockMain() { + llvm::Function *userMainFn = userModule->getFunction(userEntrypoint); + if (!userMainFn) { + klee_error("Entry function '%s' not found in module.", + userEntrypoint.c_str()); + } + mockModule->getOrInsertFunction(mockEntrypoint, userMainFn->getFunctionType(), + userMainFn->getAttributes()); + llvm::Function *mockMainFn = mockModule->getFunction(mockEntrypoint); + if (!mockMainFn) { + klee_error("Entry function '%s' not found in module.", + mockEntrypoint.c_str()); + } + auto globalsInitBlock = + llvm::BasicBlock::Create(mockModule->getContext(), "entry", mockMainFn); + builder->SetInsertPoint(globalsInitBlock); + // Define all the external globals + buildExternalGlobalsDefinitions(); + + auto userMainCallee = mockModule->getOrInsertFunction( + userEntrypoint, userMainFn->getFunctionType()); + std::vector args; + args.reserve(userMainFn->arg_size()); + for (auto it = mockMainFn->arg_begin(); it != mockMainFn->arg_end(); it++) { + args.push_back(it); + } + auto callUserMain = builder->CreateCall(userMainCallee, args); + builder->CreateRet(callUserMain); +} + +void MockBuilder::buildExternalGlobalsDefinitions() { + for (const auto &it : externals) { + if (it.second->isFunctionTy()) { + continue; + } + const std::string &extName = it.first; + llvm::Type *type = it.second; + mockModule->getOrInsertGlobal(extName, type); + auto *global = mockModule->getGlobalVariable(extName); + if (!global) { + klee_error("Unable to add global variable '%s' to module", + extName.c_str()); + } + global->setLinkage(llvm::GlobalValue::ExternalLinkage); + if (!type->isSized()) { + continue; + } + + auto *zeroInitializer = llvm::Constant::getNullValue(it.second); + if (!zeroInitializer) { + klee_error("Unable to get zero initializer for '%s'", extName.c_str()); + } + global->setInitializer(zeroInitializer); + buildCallKleeMakeSymbol("klee_make_symbolic", global, type, + "@obj_" + extName); + } +} + +void MockBuilder::buildExternalFunctionsDefinitions() { + for (const auto &it : externals) { + if (!it.second->isFunctionTy()) { + continue; + } + std::string extName = it.first; + auto *type = llvm::cast(it.second); + mockModule->getOrInsertFunction(extName, type); + llvm::Function *func = mockModule->getFunction(extName); + if (!func) { + klee_error("Unable to find function '%s' in module", extName.c_str()); + } + if (!func->empty()) { + continue; + } + auto *BB = + llvm::BasicBlock::Create(mockModule->getContext(), "entry", func); + builder->SetInsertPoint(BB); + + if (!func->getReturnType()->isSized()) { + builder->CreateRet(nullptr); + continue; + } + + auto *mockReturnValue = + builder->CreateAlloca(func->getReturnType(), nullptr); + buildCallKleeMakeSymbol("klee_make_mock", mockReturnValue, + func->getReturnType(), "@call_" + extName); + auto *loadInst = builder->CreateLoad(mockReturnValue, "klee_var"); + builder->CreateRet(loadInst); + } +} + +void MockBuilder::buildCallKleeMakeSymbol(const std::string &klee_function_name, + llvm::Value *source, llvm::Type *type, + const std::string &symbol_name) { + auto *klee_mk_symb_type = llvm::FunctionType::get( + llvm::Type::getVoidTy(mockModule->getContext()), + {llvm::Type::getInt8PtrTy(mockModule->getContext()), + llvm::Type::getInt64Ty(mockModule->getContext()), + llvm::Type::getInt8PtrTy(mockModule->getContext())}, + false); + auto kleeMakeSymbolCallee = + mockModule->getOrInsertFunction(klee_function_name, klee_mk_symb_type); + auto bitcastInst = builder->CreateBitCast( + source, llvm::Type::getInt8PtrTy(mockModule->getContext())); + auto str_name = builder->CreateGlobalString(symbol_name); + auto gep = builder->CreateConstInBoundsGEP2_64(str_name, 0, 0); + builder->CreateCall( + kleeMakeSymbolCallee, + {bitcastInst, + llvm::ConstantInt::get( + mockModule->getContext(), + llvm::APInt(64, mockModule->getDataLayout().getTypeStoreSize(type), + false)), + gep}); +} + +} // namespace klee diff --git a/lib/Core/SpecialFunctionHandler.cpp b/lib/Core/SpecialFunctionHandler.cpp index 82dc7f5388..4690a1d1e1 100644 --- a/lib/Core/SpecialFunctionHandler.cpp +++ b/lib/Core/SpecialFunctionHandler.cpp @@ -112,6 +112,7 @@ static SpecialFunctionHandler::HandlerInfo handlerInfo[] = { #endif add("klee_is_symbolic", handleIsSymbolic, true), add("klee_make_symbolic", handleMakeSymbolic, false), + add("klee_make_mock", handleMakeMock, false), add("klee_mark_global", handleMarkGlobal, false), add("klee_prefer_cex", handlePreferCex, false), add("klee_posix_prefer_cex", handlePosixPreferCex, false), @@ -937,6 +938,28 @@ void SpecialFunctionHandler::handleMakeSymbolic( } } +void SpecialFunctionHandler::handleMakeMock(ExecutionState &state, + KInstruction *target, + std::vector> &arguments) { + std::string name; + + if (arguments.size() != 3) { + executor.terminateStateOnUserError(state, + "Incorrect number of arguments to " + "klee_make_mock(void*, size_t, char*)"); + return; + } + + name = arguments[2]->isZero() ? "" : readStringAtAddress(state, arguments[2]); + + if (name.length() == 0) { + executor.terminateStateOnUserError( + state, "Empty name of function in klee_make_mock"); + return; + } + executor.executeMakeMock(state, target, arguments); +} + void SpecialFunctionHandler::handleMarkGlobal( ExecutionState &state, KInstruction *target, std::vector> &arguments) { diff --git a/lib/Core/SpecialFunctionHandler.h b/lib/Core/SpecialFunctionHandler.h index 78f920450e..6528b98c36 100644 --- a/lib/Core/SpecialFunctionHandler.h +++ b/lib/Core/SpecialFunctionHandler.h @@ -127,6 +127,7 @@ class SpecialFunctionHandler { HANDLER(handleGetValue); HANDLER(handleIsSymbolic); HANDLER(handleMakeSymbolic); + HANDLER(handleMakeMock); HANDLER(handleMalloc); HANDLER(handleMemalign); HANDLER(handleMarkGlobal); diff --git a/lib/Expr/ExprPPrinter.cpp b/lib/Expr/ExprPPrinter.cpp index 4d5fdc2554..83c6e0b782 100644 --- a/lib/Expr/ExprPPrinter.cpp +++ b/lib/Expr/ExprPPrinter.cpp @@ -423,6 +423,18 @@ 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->km->functionMap.at(&s->function)->getName() << ' ' << s->version; + } else if (auto s = dyn_cast(source)) { + PC << s->km->functionMap.at(&s->function)->getName() << ' '; + PC << "("; + for (unsigned i = 0; i < s->args.size(); i++) { + print(s->args[i], PC); + if (i != s->args.size() - 1) { + PC << " "; + } + } + PC << ')'; } else if (auto s = dyn_cast(source)) { PC << s->index; } else { diff --git a/lib/Expr/ExprUtil.cpp b/lib/Expr/ExprUtil.cpp index 87bed5d731..518e922dc8 100644 --- a/lib/Expr/ExprUtil.cpp +++ b/lib/Expr/ExprUtil.cpp @@ -54,6 +54,16 @@ void klee::findReads(ref e, bool visitUpdates, cast(re->updates.root->source)->pointer); } + if (ref mockSource = + dyn_cast_or_null( + re->updates.root->source)) { + for (auto arg : mockSource->args) { + if (visited.insert(arg).second) { + stack.push_back(arg); + } + } + } + if (visitUpdates) { // XXX this is probably suboptimal. We want to avoid a potential // explosion traversing update lists which can be quite diff --git a/lib/Expr/IndependentSet.cpp b/lib/Expr/IndependentSet.cpp index 79e3fad63e..50ac99942c 100644 --- a/lib/Expr/IndependentSet.cpp +++ b/lib/Expr/IndependentSet.cpp @@ -8,6 +8,7 @@ #include "klee/Expr/IndependentConstraintSetUnion.h" #include "klee/Expr/SymbolicSource.h" #include "klee/Expr/Symcrete.h" +#include "klee/Module/KModule.h" #include "klee/Solver/Solver.h" #include @@ -125,6 +126,11 @@ void IndependentConstraintSet::initIndependentConstraintSet(ref e) { if (re->updates.root->isConstantArray() && !re->updates.head) continue; + if (ref mockSource = + dyn_cast_or_null(array->source)) { + uninterpretedFunctions.insert(mockSource->function.getName().str()); + } + if (!wholeObjects.count(array)) { if (ConstantExpr *CE = dyn_cast(re->index)) { // if index constant, then add to set of constraints operating @@ -264,6 +270,13 @@ bool IndependentConstraintSet::intersects( if (it2 != b->elements.end()) { if (it->second.intersects(it2->second)) { return true; + } + } + for (std::set::iterator it = uninterpretedFunctions.begin(), + ie = uninterpretedFunctions.end(); + it != ie; ++it) { + if (b.uninterpretedFunctions.count(*it)) { + return true; } } } diff --git a/lib/Expr/Parser.cpp b/lib/Expr/Parser.cpp index 95c2d09a38..616d7a7f4a 100644 --- a/lib/Expr/Parser.cpp +++ b/lib/Expr/Parser.cpp @@ -331,6 +331,8 @@ class ParserImpl : public Parser { SourceResult ParseLazyInitializationSizeSource(); SourceResult ParseInstructionSource(); SourceResult ParseArgumentSource(); + SourceResult ParseMockNaiveSource(); + SourceResult ParseMockDeterministicSource(); SourceResult ParseAlphaSource(); /*** Diagnostics ***/ @@ -501,6 +503,12 @@ SourceResult ParserImpl::ParseSource() { } else if (type == "argument") { assert(km); source = ParseArgumentSource(); + } else if (type == "mockNaive") { + assert(km); + source = ParseMockNaiveSource(); + } else if (type == "mockDeterministic") { + assert(km); + source = ParseMockDeterministicSource(); } else if (type == "alpha") { source = ParseAlphaSource(); } else { @@ -631,6 +639,34 @@ SourceResult ParserImpl::ParseInstructionSource() { return SourceBuilder::instruction(*KI->inst(), index, km); } +SourceResult ParserImpl::ParseMockNaiveSource() { + auto name = Tok.getString(); + auto kf = km->functionNameMap[name]; + ConsumeExpectedToken(Token::Identifier); + auto versionExpr = ParseNumber(64).get(); + auto version = dyn_cast(versionExpr); + assert(version); + return SourceBuilder::mockNaive(km, *kf->function, version->getZExtValue()); +} + +SourceResult ParserImpl::ParseMockDeterministicSource() { + auto name = Tok.getString(); + auto kf = km->functionNameMap[name]; + ConsumeExpectedToken(Token::Identifier); + ConsumeLParen(); + std::vector> args; + args.reserve(kf->numArgs); + for (unsigned i = 0; i < kf->numArgs; i++) { + auto expr = ParseExpr(TypeResult()); + if (!expr.isValid()) { + return {false, nullptr}; + } + args.push_back(expr.get()); + } + ConsumeRParen(); + return SourceBuilder::mockDeterministic(km, *kf->function, args); +} + SourceResult ParserImpl::ParseAlphaSource() { auto indexExpr = ParseNumber(64).get(); auto index = dyn_cast(indexExpr)->getZExtValue(); diff --git a/lib/Expr/SourceBuilder.cpp b/lib/Expr/SourceBuilder.cpp index b49111e4f6..36193d3433 100644 --- a/lib/Expr/SourceBuilder.cpp +++ b/lib/Expr/SourceBuilder.cpp @@ -99,6 +99,24 @@ ref SourceBuilder::irreproducible(const std::string &name) { return r; } +ref SourceBuilder::mockNaive(const KModule *km, + const llvm::Function &function, + unsigned int version) { + ref r(new MockNaiveSource(km, function, version)); + r->computeHash(); + return r; +} + +ref +SourceBuilder::mockDeterministic(const KModule *km, + const llvm::Function &function, + const std::vector> &args) { + ref r(new MockDeterministicSource(km, function, args)); + r->computeHash(); + return r; +} + + ref SourceBuilder::alpha(int _index) { ref r(new AlphaSource(_index)); r->computeHash(); diff --git a/lib/Expr/SymbolicSource.cpp b/lib/Expr/SymbolicSource.cpp index 2dc798d32d..a32287784d 100644 --- a/lib/Expr/SymbolicSource.cpp +++ b/lib/Expr/SymbolicSource.cpp @@ -1,6 +1,6 @@ #include "klee/Expr/SymbolicSource.h" - #include "klee/Expr/Expr.h" + #include "klee/Expr/ExprPPrinter.h" #include "klee/Expr/ExprUtil.h" #include "klee/Module/KInstruction.h" @@ -202,4 +202,65 @@ unsigned InstructionSource::computeHash() { return hashValue; } +unsigned MockNaiveSource::computeHash() { + unsigned res = (getKind() * SymbolicSource::MAGIC_HASH_CONSTANT) + version; + unsigned funcID = km->functionIDMap.at(&function); + res = (res * SymbolicSource::MAGIC_HASH_CONSTANT) + funcID; + hashValue = res; + return res; +} + +int MockNaiveSource::internalCompare(const SymbolicSource &b) const { + if (getKind() != b.getKind()) { + return getKind() < b.getKind() ? -1 : 1; + } + const MockNaiveSource &mnb = static_cast(b); + if (version != mnb.version) { + return version < mnb.version ? -1 : 1; + } + unsigned funcID = km->functionIDMap.at(&function); + unsigned bFuncID = mnb.km->functionIDMap.at(&mnb.function); + if (funcID != bFuncID) { + return funcID < bFuncID ? -1 : 1; + } + return 0; +} + +MockDeterministicSource::MockDeterministicSource( + const KModule *km, const llvm::Function &function, + const std::vector> &_args) + : MockSource(km, function), args(_args) {} + +unsigned MockDeterministicSource::computeHash() { + unsigned res = getKind(); + res = (res * SymbolicSource::MAGIC_HASH_CONSTANT) + + km->functionIDMap.at(&function); + for (const auto &arg : args) { + res = (res * SymbolicSource::MAGIC_HASH_CONSTANT) + arg->hash(); + } + hashValue = res; + return res; +} + +int MockDeterministicSource::internalCompare(const SymbolicSource &b) const { + if (getKind() != b.getKind()) { + return getKind() < b.getKind() ? -1 : 1; + } + const MockDeterministicSource &mdb = + static_cast(b); + unsigned funcID = km->functionIDMap.at(&function); + unsigned bFuncID = mdb.km->functionIDMap.at(&mdb.function); + if (funcID != bFuncID) { + return funcID < bFuncID ? -1 : 1; + } + assert(args.size() == mdb.args.size() && + "the same functions should have the same arguments number"); + for (unsigned i = 0; i < args.size(); i++) { + if (args[i] != mdb.args[i]) { + return args[i] < mdb.args[i] ? -1 : 1; + } + } + return 0; +} + } // namespace klee diff --git a/lib/Solver/Z3Builder.cpp b/lib/Solver/Z3Builder.cpp index b26ec1e75c..d97b70eb76 100644 --- a/lib/Solver/Z3Builder.cpp +++ b/lib/Solver/Z3Builder.cpp @@ -13,6 +13,7 @@ #include "klee/ADT/Bits.h" #include "klee/Expr/Expr.h" #include "klee/Expr/SymbolicSource.h" +#include "klee/Module/KModule.h" #include "klee/Solver/Solver.h" #include "klee/Solver/SolverStats.h" #include "klee/Support/ErrorHandling.h" @@ -262,7 +263,38 @@ Z3ASTHandle Z3Builder::getInitialArray(const Array *root) { if (source && !isa(root->size)) { array_expr = buildConstantArray(unique_name.c_str(), root->getDomain(), root->getRange(), value->getZExtValue(8)); - } else { + } else if (ref mockDeterministicSource = + dyn_cast(root->source)) { + size_t num_args = mockDeterministicSource->args.size(); + std::vector argsHandled(num_args); + std::vector argsSortHandled(num_args); + std::vector args(num_args); + std::vector argsSort(num_args); + for (size_t i = 0; i < num_args; i++) { + ref kid = mockDeterministicSource->args[i]; + int kidWidth = kid->getWidth(); + argsHandled[i] = construct(kid, &kidWidth); + args[i] = argsHandled[i]; + argsSortHandled[i] = Z3SortHandle(Z3_get_sort(ctx, args[i]), ctx); + argsSort[i] = argsSortHandled[i]; + } + + Z3SortHandle domainSort = getBvSort(root->getDomain()); + Z3SortHandle rangeSort = getBvSort(root->getRange()); + Z3SortHandle retValSort = getArraySort(domainSort, rangeSort); + + Z3FuncDeclHandle func; + func = Z3FuncDeclHandle( + Z3_mk_func_decl( + ctx, + Z3_mk_string_symbol( + ctx, + mockDeterministicSource->function.getName().str().c_str()), + num_args, argsSort.data(), retValSort), + ctx); + array_expr = + Z3ASTHandle(Z3_mk_app(ctx, func, num_args, args.data()), ctx); + } else { array_expr = buildArray(unique_name.c_str(), root->getDomain(), root->getRange()); } @@ -309,6 +341,11 @@ Z3ASTHandle Z3Builder::getArrayForUpdate(const Array *root, const UpdateNode *un) { // Iterate over the update nodes, until we find a cached version of the node, // or no more update nodes remain + if (root->source->isMock()) { + klee_error("Updates applied to mock array %s are not allowed", + root->getName().c_str()); + } + // FIXME: This really needs to be non-recursive. Z3ASTHandle un_expr; std::vector update_nodes; for (; un && !_arr_hash.lookupUpdateNodeExpr(un, un_expr); diff --git a/lib/Solver/Z3Builder.h b/lib/Solver/Z3Builder.h index 7b407c6e3d..ef8b5be9f5 100644 --- a/lib/Solver/Z3Builder.h +++ b/lib/Solver/Z3Builder.h @@ -91,6 +91,13 @@ typedef Z3NodeHandle Z3SortHandle; template <> void Z3NodeHandle::dump() const __attribute__((used)); template <> unsigned Z3NodeHandle::hash() __attribute__((used)); +// Specialize for Z3_func_decl +template <> inline ::Z3_ast Z3NodeHandle::as_ast() { + return ::Z3_func_decl_to_ast(context, node); +} +typedef Z3NodeHandle Z3FuncDeclHandle; +template <> void Z3NodeHandle::dump() __attribute__((used)); + // Specialise for Z3_ast template <> inline ::Z3_ast Z3NodeHandle::as_ast() const { return node; diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt index ada82c0f33..d1c8a17d2f 100644 --- a/runtime/CMakeLists.txt +++ b/runtime/CMakeLists.txt @@ -90,12 +90,14 @@ add_subdirectory(Freestanding) add_subdirectory(Intrinsic) add_subdirectory(klee-libc) add_subdirectory(Fortify) +add_subdirectory(Mocks) set(RUNTIME_LIBRARIES RuntimeFreestanding RuntimeIntrinsic RuntimeKLEELibc RuntimeFortify + RuntimeMocks ) if (ENABLE_KLEE_EH_CXX) diff --git a/runtime/Mocks/CMakeLists.txt b/runtime/Mocks/CMakeLists.txt new file mode 100644 index 0000000000..efd6497470 --- /dev/null +++ b/runtime/Mocks/CMakeLists.txt @@ -0,0 +1,19 @@ +#===------------------------------------------------------------------------===# +# +# The KLEE Symbolic Virtual Machine +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +#===------------------------------------------------------------------------===# + +set(LIB_PREFIX "RuntimeMocks") +set(SRC_FILES + models.c + ) + +# Build it +include("${CMAKE_SOURCE_DIR}/cmake/compile_bitcode_library.cmake") +prefix_with_path("${SRC_FILES}" "${CMAKE_CURRENT_SOURCE_DIR}/" runtime_mocks_files) + +add_bitcode_library_targets("${LIB_PREFIX}" "${runtime_mocks_files}" "" "") diff --git a/runtime/Mocks/models.c b/runtime/Mocks/models.c new file mode 100644 index 0000000000..ad95634b47 --- /dev/null +++ b/runtime/Mocks/models.c @@ -0,0 +1,36 @@ +#include "stddef.h" + +extern void klee_make_symbolic(void *array, size_t nbytes, const char *name); +extern void *malloc(size_t size); +extern void *calloc(size_t num, size_t size); +extern void *realloc(void *ptr, size_t new_size); + +void *__klee_wrapped_malloc(size_t size) { + char retNull; + klee_make_symbolic(&retNull, sizeof(retNull), "retNullMalloc"); + if (retNull) { + return 0; + } + void *array = malloc(size); + return array; +} + +void *__klee_wrapped_calloc(size_t num, size_t size) { + char retNull; + klee_make_symbolic(&retNull, sizeof(retNull), "retNullCalloc"); + if (retNull) { + return 0; + } + void *array = calloc(num, size); + return array; +} + +void *__klee_wrapped_realloc(void *ptr, size_t new_size) { + char retNull; + klee_make_symbolic(&retNull, sizeof(retNull), "retNullRealloc"); + if (retNull) { + return 0; + } + void *array = realloc(ptr, new_size); + return array; +} diff --git a/runtime/Runtest/CMakeLists.txt b/runtime/Runtest/CMakeLists.txt index df5f2c23be..33d190a262 100644 --- a/runtime/Runtest/CMakeLists.txt +++ b/runtime/Runtest/CMakeLists.txt @@ -9,6 +9,8 @@ add_library(kleeRuntest SHARED intrinsics.c + # Mocks: + ${CMAKE_SOURCE_DIR}/runtime/Mocks/models.c # HACK: ${CMAKE_SOURCE_DIR}/lib/Basic/KTest.cpp ) diff --git a/runtime/Runtest/intrinsics.c b/runtime/Runtest/intrinsics.c index 7372549b93..5402908de2 100644 --- a/runtime/Runtest/intrinsics.c +++ b/runtime/Runtest/intrinsics.c @@ -75,8 +75,7 @@ void recursively_allocate(KTestObject *obj, size_t index, void *addr, return; } -void klee_make_symbolic(void *array, size_t nbytes, const char *name) { - +static void klee_make_symbol(void *array, size_t nbytes, const char *name) { if (!name) name = "unnamed"; @@ -157,6 +156,14 @@ void klee_make_symbolic(void *array, size_t nbytes, const char *name) { } } +void klee_make_symbolic(void *array, size_t nbytes, const char *name) { + klee_make_symbol(array, nbytes, name); +} + +void klee_make_mock(void *ret_array, size_t ret_nbytes, const char *fname) { + klee_make_symbol(ret_array, ret_nbytes, fname); +} + void klee_silent_exit(int x) { exit(x); } uintptr_t klee_choose(uintptr_t n) { diff --git a/scripts/run_tests_with_mocks.py b/scripts/run_tests_with_mocks.py new file mode 100755 index 0000000000..5843a37ad0 --- /dev/null +++ b/scripts/run_tests_with_mocks.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 + +# This script builds executable file using initial bitcode file and artifacts produced by KLEE. +# To run the script provide all the arguments you want to pass to clang for building executable. +# +# NOTE: Pre-last argument should be a path to KLEE output directory which contains redefinitions.txt and externals.ll. +# NOTE: Last argument is path to initial bitcode. +# +# Example: python3 run_tests_with_mocks.py -I ~/klee/include/ -L ~/klee/build/lib/ -lkleeRuntest klee-last a.bc +# +# You can read more about replaying test cases here: http://klee.github.io/tutorials/testing-function/ + +import subprocess as sp +import sys +import os + +klee_out_dir = sys.argv[-2] +bitcode = sys.argv[-1] + +filename = os.path.splitext(bitcode)[0] +object_file = f'{filename}.o' +sp.run(f'clang -c {bitcode} -o {object_file}', shell=True) +sp.run(f'llvm-objcopy {object_file} --redefine-syms {klee_out_dir}/redefinitions.txt', shell=True) +clang_args = ' '.join(sys.argv[1:len(sys.argv) - 2]) +print(f'clang {clang_args} {klee_out_dir}/externals.ll {object_file}') +sp.run(f'clang {clang_args} {klee_out_dir}/externals.ll {object_file}', shell=True) diff --git a/test/Feature/MockPointersDeterministic.c b/test/Feature/MockPointersDeterministic.c new file mode 100644 index 0000000000..d8c871588d --- /dev/null +++ b/test/Feature/MockPointersDeterministic.c @@ -0,0 +1,23 @@ +// REQUIRES: z3 +// RUN: %clang %s -g -emit-llvm %O0opt -c -o %t.bc + +// RUN: rm -rf %t.klee-out-1 +// RUN: %klee --solver-backend=z3 --output-dir=%t.klee-out-1 --skip-not-lazy-initialized --external-calls=all --mock-strategy=deterministic %t.bc 2>&1 | FileCheck %s -check-prefix=CHECK-1 +// CHECK-1: memory error: null pointer exception +// CHECK-1: KLEE: done: completed paths = 1 +// CHECK-1: KLEE: done: partially completed paths = 2 +// CHECK-1: KLEE: done: generated tests = 3 + +#include + +extern int *age(); + +int main() { + if (age() != age()) { + assert(0 && "age is deterministic"); + } + if (*age() != *age()) { + assert(0 && "age is deterministic"); + } + return *age(); +} \ No newline at end of file diff --git a/test/Feature/MockStrategies.c b/test/Feature/MockStrategies.c new file mode 100644 index 0000000000..524fbba3a2 --- /dev/null +++ b/test/Feature/MockStrategies.c @@ -0,0 +1,37 @@ +// REQUIRES: z3 +// RUN: %clang %s -g -emit-llvm %O0opt -c -o %t.bc + +// RUN: rm -rf %t.klee-out-1 +// RUN: %klee --output-dir=%t.klee-out-1 --external-calls=all --mock-strategy=none %t.bc 2>&1 | FileCheck %s -check-prefix=CHECK-1 +// CHECK-1: failed external call +// CHECK-1: KLEE: done: completed paths = 1 +// CHECK-1: KLEE: done: generated tests = 2 + +// RUN: rm -rf %t.klee-out-2 +// RUN: %klee --output-dir=%t.klee-out-2 --external-calls=all --mock-strategy=naive %t.bc 2>&1 | FileCheck %s -check-prefix=CHECK-2 +// CHECK-2: ASSERTION FAIL: 0 +// CHECK-2: KLEE: done: completed paths = 2 +// CHECK-2: KLEE: done: generated tests = 3 + +// RUN: rm -rf %t.klee-out-3 +// RUN: not %klee --output-dir=%t.klee-out-3 --solver-backend=stp --external-calls=all --mock-strategy=deterministic %t.bc 2>&1 | FileCheck %s -check-prefix=CHECK-3 +// CHECK-3: KLEE: ERROR: Deterministic mocks can be generated with Z3 solver only. + +// RUN: rm -rf %t.klee-out-4 +// RUN: %klee --output-dir=%t.klee-out-4 --solver-backend=z3 --external-calls=all --mock-strategy=deterministic %t.bc 2>&1 | FileCheck %s -check-prefix=CHECK-4 +// CHECK-4: KLEE: done: completed paths = 2 +// CHECK-4: KLEE: done: generated tests = 2 + +#include + +extern int foo(int x, int y); + +int main() { + int a, b; + klee_make_symbolic(&a, sizeof(a), "a"); + klee_make_symbolic(&b, sizeof(b), "b"); + if (a == b && foo(a + b, b) != foo(2 * b, a)) { + assert(0); + } + return 0; +} diff --git a/test/Replay/libkleeruntest/replay_mocks.c b/test/Replay/libkleeruntest/replay_mocks.c new file mode 100644 index 0000000000..cfd151a9e5 --- /dev/null +++ b/test/Replay/libkleeruntest/replay_mocks.c @@ -0,0 +1,19 @@ +// REQUIRES: geq-llvm-11.0 +// RUN: %clang %s -emit-llvm -g %O0opt -c -o %t.bc +// RUN: rm -rf %t.klee-out +// RUN: %klee --output-dir=%t.klee-out --external-calls=all --mock-strategy=naive %t.bc +// RUN: %clang -c %t.bc -o %t.o +// RUN: %llvmobjcopy --redefine-syms %t.klee-out/redefinitions.txt %t.o +// RUN: %clang -o %t.klee-out/a.out %libkleeruntest %t.klee-out/externals.ll %t.o +// RUN: test -f %t.klee-out/test000001.ktest +// RUN: env KTEST_FILE=%t.klee-out/test000001.ktest %t.klee-out/a.out + +extern int variable; + +extern int foo(int); + +int main() { + int a; + klee_make_symbolic(&a, sizeof(a), "a"); + return variable + foo(a); +} diff --git a/test/lit.cfg b/test/lit.cfg index 55adadf5cc..72144bfe1e 100644 --- a/test/lit.cfg +++ b/test/lit.cfg @@ -97,6 +97,10 @@ for name in subs: lit_config.fatal('{0} is not set'.format(name)) config.substitutions.append( ('%' + name, value)) +config.substitutions.append( + ('%runmocks', os.path.join(klee_src_root, 'scripts/run_tests_with_mocks.py')) +) + # Add a substitution for lli. config.substitutions.append( ('%lli', os.path.join(llvm_tools_dir, 'lli')) @@ -118,6 +122,11 @@ config.substitutions.append( ('%llvmcov', os.path.join(llvm_tools_dir, 'llvm-cov')) ) +# Add a substitution for llvm-objcopy +config.substitutions.append( + ('%llvmobjcopy', os.path.join(llvm_tools_dir, 'llvm-objcopy')) +) + # Add a substition for libkleeruntest config.substitutions.append( ('%libkleeruntestdir', os.path.dirname(config.libkleeruntest)) diff --git a/tools/klee/main.cpp b/tools/klee/main.cpp index 60391b7c1b..ce112d1990 100644 --- a/tools/klee/main.cpp +++ b/tools/klee/main.cpp @@ -347,6 +347,33 @@ cl::opt XMLMetadataProgramHash( llvm::cl::desc("Test-Comp hash sum of original file for xml metadata"), llvm::cl::cat(TestCompCat)); + +/*** Mocking options ***/ + +cl::OptionCategory MockCat("Mock category"); + +cl::opt MockLinkedExternals( + "mock-linked-externals", + cl::desc("Mock modelled linked externals (default=false)"), cl::init(false), + cl::cat(MockCat)); + +cl::opt MockUnlinkedStrategy( + "mock-strategy", cl::init(MockStrategy::None), + cl::desc("Specify strategy for mocking external calls"), + cl::values( + clEnumValN(MockStrategy::None, "none", + "External calls are not mocked (default)"), + clEnumValN(MockStrategy::Naive, "naive", + "Every time external function is called, new symbolic value " + "is generated for its return value"), + clEnumValN( + MockStrategy::Deterministic, "deterministic", + "NOTE: this option is compatible with Z3 solver only. Each " + "external function is treated as a deterministic " + "function. Therefore, when function is called many times " + "with equal arguments, every time equal values will be returned.")), + cl::init(MockStrategy::None), cl::cat(MockCat)); + } // namespace namespace klee { @@ -852,7 +879,7 @@ std::string KleeHandler::getRunTimeLibraryPath(const char *argv0) { void KleeHandler::setOutputDirectory(const std::string &directoryName) { // create output directory - if (directoryName == "") { + if (directoryName.empty()) { klee_error("Empty name of new directory"); } SmallString<128> directory(directoryName); @@ -957,7 +984,8 @@ static const char *modelledExternals[] = { "klee_check_memory_access", "klee_define_fixed_object", "klee_get_errno", "klee_get_valuef", "klee_get_valued", "klee_get_valuel", "klee_get_valuell", "klee_get_value_i32", "klee_get_value_i64", "klee_get_obj_size", - "klee_is_symbolic", "klee_make_symbolic", "klee_mark_global", + "klee_is_symbolic", "klee_make_symbolic", "klee_make_mock", + "klee_mark_global", "klee_open_merge", "klee_close_merge", "klee_prefer_cex", "klee_posix_prefer_cex", "klee_print_expr", "klee_print_range", "klee_report_error", "klee_set_forking", "klee_silent_exit", "klee_warning", "klee_warning_once", "klee_stack_trace", @@ -1033,30 +1061,17 @@ static const char *dontCareExternals[] = { #endif // static information, pretty ok to return - "getegid", - "geteuid", - "getgid", - "getuid", - "getpid", - "gethostname", - "getpgrp", - "getppid", - "getpagesize", - "getpriority", - "getgroups", - "getdtablesize", - "getrlimit", - "getrlimit64", - "getcwd", - "getwd", - "gettimeofday", - "uname", + "getegid", "geteuid", "getgid", "getuid", "getpid", "gethostname", + "getpgrp", "getppid", "getpagesize", "getpriority", "getgroups", + "getdtablesize", "getrlimit", "getrlimit64", "getcwd", "getwd", + "gettimeofday", "uname", "ioctl", // fp stuff we just don't worry about yet "frexp", "ldexp", "__isnan", "__signbit", + "llvm.dbg.label", }; // Extra symbols we aren't going to warn about with klee-libc @@ -1559,6 +1574,41 @@ void wait_until_any_child_dies( } } +void mockLinkedExternals( + const Interpreter::ModuleOptions &Opts, llvm::LLVMContext &ctx, + llvm::Module *mainModule, + std::vector> &loadedLibsModules, + llvm::raw_string_ostream *redefineFile) { + std::string errorMsg; + std::vector> mockModules; + SmallString<128> Path(Opts.LibraryDir); + llvm::sys::path::append(Path, + "libkleeRuntimeMocks" + Opts.OptSuffix + ".bca"); + klee_message("NOTE: Using mocks model %s for linked externals", Path.c_str()); + if (!klee::loadFileAsOneModule(Path.c_str(), ctx, mockModules, errorMsg)) { + klee_error("error loading mocks model '%s': %s", Path.c_str(), + errorMsg.c_str()); + } + + for (auto &module : mockModules) { + for (const auto &fmodel : module->functions()) { + if (fmodel.getName().str().substr(0, 15) != "__klee_wrapped_") { + continue; + } + llvm::Function *f = + mainModule->getFunction(fmodel.getName().str().substr(15)); + if (!f) { + continue; + } + klee_message("Renamed symbol %s to %s", f->getName().str().c_str(), + fmodel.getName().str().c_str()); + *redefineFile << f->getName() << ' ' << fmodel.getName() << '\n'; + f->setName(fmodel.getName()); + } + loadedLibsModules.push_back(std::move(module)); + } +} + llvm::Value *createStringArray(LLVMContext &ctx, const char *str) { auto type = llvm::ArrayType::get(llvm::Type::getInt8Ty(ctx), strlen(str) + 1); std::vector chars; @@ -1846,9 +1896,10 @@ int main(int argc, char **argv, char **envp) { sys::SetInterruptFunction(interrupt_handle); - // Load the bytecode... std::string errorMsg; LLVMContext ctx; + + // Load the bytecode... std::vector> loadedUserModules; std::vector> loadedLibsModules; if (!klee::loadFileAsOneModule(InputFile, ctx, loadedUserModules, errorMsg)) { @@ -1937,6 +1988,11 @@ int main(int argc, char **argv, char **envp) { "This may cause unexpected crashes or assertion violations.", module_triple.c_str(), host_triple.c_str()); + llvm::Function *initialMainFn = mainModule->getFunction(EntryPoint); + if (!initialMainFn) { + klee_error("Entry function '%s' not found in module.", EntryPoint.c_str()); + } + // Detect architecture std::string bit_suffix = "64"; // Fall back to 64bit if (module_triple.find("i686") != std::string::npos || @@ -1954,13 +2010,16 @@ int main(int argc, char **argv, char **envp) { } std::string LibraryDir = KleeHandler::getRunTimeLibraryPath(argv[0]); - Interpreter::ModuleOptions Opts(LibraryDir.c_str(), EntryPoint, opt_suffix, - /*Optimize=*/OptimizeModule, - /*Simplify*/ SimplifyModule, - /*CheckDivZero=*/CheckDivZero, - /*CheckOvershift=*/CheckOvershift, - /*WithFPRuntime=*/WithFPRuntime, - /*WithPOSIXRuntime=*/WithPOSIXRuntime); + Interpreter::ModuleOptions Opts( + LibraryDir.c_str(), EntryPoint, opt_suffix, + /*MainCurrentName=*/EntryPoint, + /*MainNameAfterMock=*/"__klee_mock_wrapped_main", + /*Optimize=*/OptimizeModule, + /*Simplify*/ SimplifyModule, + /*CheckDivZero=*/CheckDivZero, + /*CheckOvershift=*/CheckOvershift, + /*WithFPRuntime=*/WithFPRuntime, + /*WithPOSIXRuntime=*/WithPOSIXRuntime); // Get the main function for (auto &module : loadedUserModules) { @@ -1982,6 +2041,17 @@ int main(int argc, char **argv, char **envp) { if (!entryFn) klee_error("Entry function '%s' not found in module.", EntryPoint.c_str()); + std::string redefinitions; + llvm::raw_string_ostream o_redefinitions(redefinitions); + if (MockLinkedExternals) { + mockLinkedExternals(Opts, ctx, mainModule, loadedLibsModules, + &o_redefinitions); + } + + if (MockUnlinkedStrategy != MockStrategy::None) { + o_redefinitions << EntryPoint << ' ' << Opts.MainNameAfterMock << '\n'; + } + if (WithPOSIXRuntime) { SmallString<128> Path(Opts.LibraryDir); llvm::sys::path::append(Path, "libkleeRuntimePOSIX" + opt_suffix + ".bca"); @@ -2148,6 +2218,7 @@ int main(int argc, char **argv, char **envp) { Interpreter::InterpreterOptions IOpts(paths); IOpts.MakeConcreteSymbolic = MakeConcreteSymbolic; IOpts.Guidance = UseGuidedSearch; + IOpts.MockStrategy = MockUnlinkedStrategy; std::unique_ptr interpreter( Interpreter::create(ctx, IOpts, handler.get())); theInterpreter = interpreter.get(); @@ -2159,6 +2230,38 @@ int main(int argc, char **argv, char **envp) { } handler->getInfoStream() << "PID: " << getpid() << "\n"; + std::set ignoredExternals; + ignoredExternals.insert(modelledExternals, + modelledExternals + NELEMS(modelledExternals)); + ignoredExternals.insert(dontCareExternals, + dontCareExternals + NELEMS(dontCareExternals)); + ignoredExternals.insert(unsafeExternals, + unsafeExternals + NELEMS(unsafeExternals)); + + switch (Libc) { + case LibcType::KleeLibc: + ignoredExternals.insert(dontCareKlee, dontCareKlee + NELEMS(dontCareKlee)); + break; + case LibcType::UcLibc: + ignoredExternals.insert(dontCareUclibc, + dontCareUclibc + NELEMS(dontCareUclibc)); + break; + case LibcType::FreestandingLibc: /* silence compiler warning */ + break; + } + + if (WithPOSIXRuntime) { + ignoredExternals.insert("syscall"); + } + + Opts.MainCurrentName = initialMainFn->getName().str(); + + if (MockLinkedExternals || MockUnlinkedStrategy != MockStrategy::None) { + o_redefinitions.flush(); + auto f_redefinitions = handler->openOutputFile("redefinitions.txt"); + *f_redefinitions << redefinitions; + } + // Get the desired main function. klee_main initializes uClibc // locale and other data and then calls main. From f6072e067ae63979d56e8a980bc67dec31ff456c Mon Sep 17 00:00:00 2001 From: Maria Date: Thu, 29 Jun 2023 02:00:53 +0300 Subject: [PATCH 116/120] Add annotations json parser --- include/klee/Core/Interpreter.h | 4 +- include/klee/Core/MockBuilder.h | 10 +- include/klee/Module/Annotation.h | 86 +++++++++++ lib/Core/Executor.cpp | 5 +- lib/Core/Executor.h | 3 +- lib/Core/MockBuilder.cpp | 74 ++++++++- lib/Module/Annotation.cpp | 175 ++++++++++++++++++++++ lib/Module/CMakeLists.txt | 1 + tools/klee/main.cpp | 24 ++- unittests/Annotations/AnnotationsTest.cpp | 108 +++++++++++++ unittests/Annotations/CMakeLists.txt | 3 + unittests/CMakeLists.txt | 1 + 12 files changed, 486 insertions(+), 8 deletions(-) create mode 100644 include/klee/Module/Annotation.h create mode 100644 lib/Module/Annotation.cpp create mode 100644 unittests/Annotations/AnnotationsTest.cpp create mode 100644 unittests/Annotations/CMakeLists.txt diff --git a/include/klee/Core/Interpreter.h b/include/klee/Core/Interpreter.h index 942c678c2f..5a619c6e29 100644 --- a/include/klee/Core/Interpreter.h +++ b/include/klee/Core/Interpreter.h @@ -10,6 +10,7 @@ #define KLEE_INTERPRETER_H #include "TerminationTypes.h" +#include "klee/Module/Annotation.h" #include "klee/Module/SarifReport.h" @@ -159,7 +160,8 @@ class Interpreter { std::set &&mainModuleFunctions, std::set &&mainModuleGlobals, FLCtoOpcode &&origInstructions, - const std::set &ignoredExternals) = 0; + const std::set &ignoredExternals, + const Annotations &annotations) = 0; virtual std::map getAllExternals(const std::set &ignoredExternals) = 0; diff --git a/include/klee/Core/MockBuilder.h b/include/klee/Core/MockBuilder.h index 70949b10a7..0ff22bd890 100644 --- a/include/klee/Core/MockBuilder.h +++ b/include/klee/Core/MockBuilder.h @@ -1,6 +1,8 @@ #ifndef KLEE_MOCKBUILDER_H #define KLEE_MOCKBUILDER_H +#include "klee/Module/Annotation.h" + #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Module.h" @@ -15,6 +17,7 @@ class MockBuilder { std::unique_ptr mockModule; std::unique_ptr> builder; std::map externals; + Annotations annotations; const std::string mockEntrypoint, userEntrypoint; @@ -25,11 +28,16 @@ class MockBuilder { void buildCallKleeMakeSymbol(const std::string &klee_function_name, llvm::Value *source, llvm::Type *type, const std::string &symbol_name); + void buildAnnotationForExternalFunctionParams(llvm::Function *func, + Annotation &annotation); + llvm::Value *goByOffset(llvm::Value *value, + const std::vector &offset); public: MockBuilder(const llvm::Module *initModule, std::string mockEntrypoint, std::string userEntrypoint, - std::map externals); + std::map externals, + Annotations annotations); std::unique_ptr build(); }; diff --git a/include/klee/Module/Annotation.h b/include/klee/Module/Annotation.h new file mode 100644 index 0000000000..6defdd15b3 --- /dev/null +++ b/include/klee/Module/Annotation.h @@ -0,0 +1,86 @@ +#ifndef KLEE_ANNOTATION_H +#define KLEE_ANNOTATION_H + +#include "map" +#include "set" +#include "string" +#include "vector" + +#include "nlohmann/json.hpp" +#include "nonstd/optional.hpp" + +using nonstd::nullopt; +using nonstd::optional; +using json = nlohmann::json; + +namespace klee { + +// Annotation format: https://github.com/UnitTestBot/klee/discussions/92 +struct Annotation { + enum class StatementKind { + Unknown, + + Deref, + InitNull, + }; + + enum class Property { + Unknown, + + Determ, + Noreturn, + }; + + struct StatementUnknown { + explicit StatementUnknown(const std::string &str); + virtual ~StatementUnknown(); + + virtual Annotation::StatementKind getStatementName() const; + virtual bool operator==(const StatementUnknown &other) const; + + std::string statementStr; + std::vector offset; + + protected: + void parseOffset(const std::string &offsetStr); + void parseOnlyOffset(const std::string &str); + }; + + struct StatementDeref final : public StatementUnknown { + explicit StatementDeref(const std::string &str); + + Annotation::StatementKind getStatementName() const override; + }; + + struct StatementInitNull final : public StatementUnknown { + explicit StatementInitNull(const std::string &str); + + Annotation::StatementKind getStatementName() const override; + }; + + using StatementPtr = std::shared_ptr; + using StatementPtrs = std::vector; + + bool operator==(const Annotation &other) const; + + std::string functionName; + std::vector statements; + std::set properties; +}; + +using Annotations = std::map; + +const std::map toProperties{ + {"determ", Annotation::Property::Determ}, + {"noreturn", Annotation::Property::Noreturn}, +}; + +Annotations parseAnnotationsFile(const json &annotationsJson); +Annotations parseAnnotationsFile(const std::string &path); + +bool operator==(const Annotation::StatementPtr &first, + const Annotation::StatementPtr &second); + +} // namespace klee + +#endif // KLEE_ANNOTATION_H diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index 182836cca4..91a06e79ea 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -594,7 +594,8 @@ llvm::Module *Executor::setModule( std::vector> &libsModules, const ModuleOptions &opts, std::set &&mainModuleFunctions, std::set &&mainModuleGlobals, FLCtoOpcode &&origInstructions, - const std::set &ignoredExternals) { + const std::set &ignoredExternals, + const Annotations &annotations) { assert(!kmodule && !userModules.empty() && "can only register one module"); // XXX gross @@ -639,7 +640,7 @@ llvm::Module *Executor::setModule( std::map externals = getAllExternals(ignoredExternals); MockBuilder builder(kmodule->module.get(), opts.MainCurrentName, - opts.MainNameAfterMock, externals); + opts.MainNameAfterMock, externals, annotations); std::unique_ptr mockModule = builder.build(); if (!mockModule) { klee_error("Unable to generate mocks"); diff --git a/lib/Core/Executor.h b/lib/Core/Executor.h index 1dfe2ddc5b..f0c53a8da4 100644 --- a/lib/Core/Executor.h +++ b/lib/Core/Executor.h @@ -739,7 +739,8 @@ class Executor : public Interpreter { std::set &&mainModuleFunctions, std::set &&mainModuleGlobals, FLCtoOpcode &&origInstructions, - const std::set &ignoredExternals) override; + const std::set &ignoredExternals, + const Annotations &annotations) override; std::map getAllExternals(const std::set &ignoredExternals) override; diff --git a/lib/Core/MockBuilder.cpp b/lib/Core/MockBuilder.cpp index 2392458241..0545c34115 100644 --- a/lib/Core/MockBuilder.cpp +++ b/lib/Core/MockBuilder.cpp @@ -1,17 +1,21 @@ #include "klee/Core/MockBuilder.h" +#include "klee/Module/Annotation.h" #include "klee/Support/ErrorHandling.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Module.h" #include +#include namespace klee { MockBuilder::MockBuilder(const llvm::Module *initModule, std::string mockEntrypoint, std::string userEntrypoint, - std::map externals) + std::map externals, + Annotations annotations) : userModule(initModule), externals(std::move(externals)), + annotations(std::move(annotations)), mockEntrypoint(std::move(mockEntrypoint)), userEntrypoint(std::move(userEntrypoint)) {} @@ -115,6 +119,11 @@ void MockBuilder::buildExternalFunctionsDefinitions() { continue; } + const auto annotation = annotations.find(extName); + if (annotation != annotations.end()) { + buildAnnotationForExternalFunctionParams(func, annotation->second); + } + auto *mockReturnValue = builder->CreateAlloca(func->getReturnType(), nullptr); buildCallKleeMakeSymbol("klee_make_mock", mockReturnValue, @@ -149,4 +158,67 @@ void MockBuilder::buildCallKleeMakeSymbol(const std::string &klee_function_name, gep}); } +// TODO: add method for return value of external functions. +void MockBuilder::buildAnnotationForExternalFunctionParams( + llvm::Function *func, Annotation &annotation) { + for (size_t i = 1; i < annotation.statements.size(); i++) { + const auto arg = func->getArg(i - 1); + for (const auto &statement : annotation.statements[i]) { + llvm::Value *elem = goByOffset(arg, statement->offset); + switch (statement->getStatementName()) { + case Annotation::StatementKind::Deref: { + if (!elem->getType()->isPointerTy()) { + klee_error("Incorrect annotation offset."); + } + builder->CreateLoad(elem); + break; + } + case Annotation::StatementKind::InitNull: { + // TODO + } + case Annotation::StatementKind::Unknown: + default: + __builtin_unreachable(); + } + } + } + + for (const auto &property : annotation.properties) { + switch (property) { + case Annotation::Property::Determ: { + // TODO + } + case Annotation::Property::Noreturn: { + // TODO + } + case Annotation::Property::Unknown: + default: + __builtin_unreachable(); + } + } +} + +llvm::Value *MockBuilder::goByOffset(llvm::Value *value, + const std::vector &offset) { + llvm::Value *current = value; + for (const auto &inst : offset) { + if (inst == "*") { + if (!current->getType()->isPointerTy()) { + klee_error("Incorrect annotation offset."); + } + current = builder->CreateLoad(current); + } else if (inst == "&") { + auto addr = builder->CreateAlloca(current->getType()); + current = builder->CreateStore(current, addr); + } else { + const size_t index = std::stol(inst); + if (!(current->getType()->isPointerTy() || current->getType()->isArrayTy())) { + klee_error("Incorrect annotation offset."); + } + current = builder->CreateConstInBoundsGEP1_64(current, index); + } + } + return current; +} + } // namespace klee diff --git a/lib/Module/Annotation.cpp b/lib/Module/Annotation.cpp new file mode 100644 index 0000000000..5c40769054 --- /dev/null +++ b/lib/Module/Annotation.cpp @@ -0,0 +1,175 @@ +#include "klee/Module/Annotation.h" + +#include "klee/Support/ErrorHandling.h" + +#include + +namespace { + +using namespace klee; + +Annotation::StatementPtr toStatement(const std::string &name, + const std::string &str) { + if (name == "Deref") { + return std::make_shared(str); + } else if (name == "InitNull") { + return std::make_shared(str); + } else { + return std::make_shared(str); + } +} + +} // namespace + +namespace klee { + +Annotation::StatementUnknown::StatementUnknown(const std::string &str) + : statementStr(str) { + parseOnlyOffset(str); +} + +Annotation::StatementUnknown::~StatementUnknown() = default; + +Annotation::StatementKind +Annotation::StatementUnknown::getStatementName() const { + return Annotation::StatementKind::Unknown; +} + +bool Annotation::StatementUnknown::operator==( + const Annotation::StatementUnknown &other) const { + return (statementStr == other.statementStr) && (offset == other.offset); +} + +void Annotation::StatementUnknown::parseOffset(const std::string &offsetStr) { + size_t pos = 0; + while (pos < offsetStr.size()) { + if (offsetStr[pos] == '*') { + offset.emplace_back("*"); + pos++; + } else if (offsetStr[pos] == '&') { + offset.emplace_back("&"); + pos++; + } else if (offsetStr[pos] == '[') { + size_t posEndExpr = offsetStr.find(']', pos); + if (posEndExpr == std::string::npos) { + klee_error("Incorrect annotation offset format."); + } + offset.push_back(offsetStr.substr(pos + 1, posEndExpr - 1 - pos)); + pos = posEndExpr + 1; + } else { + klee_error("Incorrect annotation offset format."); + } + } +} + +void Annotation::StatementUnknown::parseOnlyOffset(const std::string &str) { + const size_t delimiterAfterName = str.find(':'); + if (delimiterAfterName == std::string::npos) { + return; + } + const size_t delimiterAfterOffset = str.find(':', delimiterAfterName + 1); + const size_t offsetLength = + (delimiterAfterOffset == std::string::npos) + ? std::string::npos + : delimiterAfterOffset - delimiterAfterName - 1; + parseOffset(str.substr(delimiterAfterName + 1, offsetLength)); +} + +Annotation::StatementDeref::StatementDeref(const std::string &str) + : StatementUnknown(str) {} + +Annotation::StatementKind Annotation::StatementDeref::getStatementName() const { + return Annotation::StatementKind::Deref; +} + +Annotation::StatementInitNull::StatementInitNull(const std::string &str) + : StatementUnknown(str) {} + +Annotation::StatementKind +Annotation::StatementInitNull::getStatementName() const { + return Annotation::StatementKind::InitNull; +} + +bool Annotation::operator==(const Annotation &other) const { + return (functionName == other.functionName) && + (statements == other.statements) && (properties == other.properties); +} + +void from_json(const json &j, Annotation::StatementPtr &statement) { + if (!j.is_string()) { + klee_error("Incorrect annotation format."); + } + const std::string jStr = j.get(); + statement = toStatement(jStr.substr(0, jStr.find(':')), jStr); +} + +void from_json(const json &j, Annotation::Property &property) { + if (!j.is_string()) { + klee_error("Incorrect properties format in annotations file."); + } + const std::string jStr = j.get(); + + property = Annotation::Property::Unknown; + const auto propertyPtr = toProperties.find(jStr); + if (propertyPtr != toProperties.end()) { + property = propertyPtr->second; + } +} + +Annotations parseAnnotationsFile(const json &annotationsJson) { + Annotations annotations; + for (auto &item : annotationsJson.items()) { + Annotation annotation; + annotation.functionName = item.key(); + + const json &j = item.value(); + if (!j.is_object() || !j.contains("annotation") || + !j.contains("properties")) { + klee_error("Incorrect annotations file format."); + } + + annotation.statements = + j.at("annotation").get>(); + annotation.properties = + j.at("properties").get>(); + annotations[item.key()] = annotation; + } + return annotations; +} + +Annotations parseAnnotationsFile(const std::string &path) { + std::ifstream annotationsFile(path); + if (!annotationsFile.good()) { + klee_error("Opening %s failed.", path.c_str()); + } + + json annotationsJson = json::parse(annotationsFile, nullptr, false); + if (annotationsJson.is_discarded()) { + klee_error("Parsing JSON %s failed.", path.c_str()); + } + + return parseAnnotationsFile(annotationsJson); +} + +bool operator==(const Annotation::StatementPtr &first, + const Annotation::StatementPtr &second) { + if (first->getStatementName() != second->getStatementName()) { + return false; + } + + switch (first->getStatementName()) { + case Annotation::StatementKind::Unknown: + return (*dynamic_cast(first.get()) == + *dynamic_cast(second.get())); + case Annotation::StatementKind::Deref: + return (*dynamic_cast(first.get()) == + *dynamic_cast(second.get())); + case Annotation::StatementKind::InitNull: + return (*dynamic_cast(first.get()) == + *dynamic_cast(second.get())); + default: + __builtin_unreachable(); + } +} + +} // namespace klee diff --git a/lib/Module/CMakeLists.txt b/lib/Module/CMakeLists.txt index 19d9c11dbe..d185f53a72 100644 --- a/lib/Module/CMakeLists.txt +++ b/lib/Module/CMakeLists.txt @@ -7,6 +7,7 @@ # #===------------------------------------------------------------------------===# set(KLEE_MODULE_COMPONENT_SRCS + Annotation.cpp CallSplitter.cpp CallRemover.cpp Checks.cpp diff --git a/tools/klee/main.cpp b/tools/klee/main.cpp index ce112d1990..3da77c59f6 100644 --- a/tools/klee/main.cpp +++ b/tools/klee/main.cpp @@ -12,10 +12,13 @@ #include "klee/ADT/KTest.h" #include "klee/ADT/TreeStream.h" #include "klee/Config/Version.h" +#include "klee/Core/Annotation.h" #include "klee/Core/Context.h" #include "klee/Core/Interpreter.h" #include "klee/Core/TargetedExecutionReporter.h" #include "klee/Module/LocationInfo.h" +#include "klee/Core/FunctionAnnotation.h" +#include "klee/Module/Annotation.h" #include "klee/Module/SarifReport.h" #include "klee/Module/TargetForest.h" #include "klee/Solver/SolverCmdLine.h" @@ -374,6 +377,15 @@ cl::opt MockUnlinkedStrategy( "with equal arguments, every time equal values will be returned.")), cl::init(MockStrategy::None), cl::cat(MockCat)); +/*** Annotations options ***/ + +cl::OptionCategory AnnotCat("Annotations category"); + +cl::opt + AnnotationsFile("annotations", cl::desc("Path to the annotation JSON file"), + cl::value_desc("path file"), + cl::cat(AnnotCat)); + } // namespace namespace klee { @@ -1285,7 +1297,7 @@ createLibCWrapper(std::vector> &userModules, args.push_back(llvm::ConstantExpr::getBitCast( cast(inModuleReference.getCallee()), ft->getParamType(0))); - args.push_back(&*(stub->arg_begin())); // argc + args.push_back(&*(stub->arg_begin())); // argc auto arg_it = stub->arg_begin(); args.push_back(&*(++arg_it)); // argv args.push_back(Constant::getNullValue(ft->getParamType(3))); // app_init @@ -2215,6 +2227,10 @@ int main(int argc, char **argv, char **envp) { UseGuidedSearch = Interpreter::GuidanceKind::ErrorGuidance; } + const Annotations annotations = (AnnotationsFile.empty()) + ? Annotations() + : parseAnnotationsFile(AnnotationsFile); + Interpreter::InterpreterOptions IOpts(paths); IOpts.MakeConcreteSymbolic = MakeConcreteSymbolic; IOpts.Guidance = UseGuidedSearch; @@ -2268,7 +2284,11 @@ int main(int argc, char **argv, char **envp) { auto finalModule = interpreter->setModule( loadedUserModules, loadedLibsModules, Opts, std::move(mainModuleFunctions), std::move(mainModuleGlobals), - std::move(origInstructions)); + std::move(origInstructions), ignoredExternals, annotations); + Function *mainFn = finalModule->getFunction(EntryPoint); + if (!mainFn) { + klee_error("Entry function '%s' not found in module.", EntryPoint.c_str()); + } externalsAndGlobalsCheck(finalModule); diff --git a/unittests/Annotations/AnnotationsTest.cpp b/unittests/Annotations/AnnotationsTest.cpp new file mode 100644 index 0000000000..9d67ab9461 --- /dev/null +++ b/unittests/Annotations/AnnotationsTest.cpp @@ -0,0 +1,108 @@ +#include "gtest/gtest.h" + +#include "klee/Module/Annotation.h" + +#include + +using namespace klee; + +TEST(AnnotationsTest, Empty) { + const json j = json::parse(R"( +{ + "foo" : { + "annotation" : [], + "properties" : [] + } +} +)"); + const Annotations expected = Annotations{ + {"foo", Annotation{"foo", std::vector(), + std::set()}}}; + const Annotations actual = parseAnnotationsFile(j); + ASSERT_EQ(expected, actual); +} + +TEST(AnnotationsTest, KnownProperties) { + const json j = json::parse(R"( +{ + "foo" : { + "annotation" : [], + "properties" : ["determ", "noreturn", "determ"] + } +} +)"); + const std::set properties{ + Annotation::Property::Determ, Annotation::Property::Noreturn}; + const Annotations expected = Annotations{ + {"foo", Annotation{"foo", std::vector(), + properties}}}; + const Annotations actual = parseAnnotationsFile(j); + ASSERT_EQ(expected, actual); +} + +TEST(AnnotationsTest, UnknownProperties) { + const json j = json::parse(R"( +{ + "foo" : { + "annotation" : [], + "properties" : ["derm", "noreturn", "determ"] + } +} +)"); + const std::set properties{ + Annotation::Property::Determ, Annotation::Property::Noreturn, + Annotation::Property::Unknown}; + const Annotations expected = Annotations{ + {"foo", Annotation{"foo", std::vector(), + properties}}}; + const Annotations actual = parseAnnotationsFile(j); + ASSERT_EQ(expected, actual); +} + +TEST(AnnotationsTest, UnknownAnnotations) { + const json j = json::parse(R"( +{ + "foo" : { + "annotation" : [[], ["Ooo"]], + "properties" : [] + } +} +)"); + const Annotations actual = parseAnnotationsFile(j); + ASSERT_EQ(actual.at("foo").statements[1][0]->getStatementName(), + Annotation::StatementKind::Unknown); +} + +TEST(AnnotationsTest, KnownAnnotations) { + const json j = json::parse(R"( +{ + "foo" : { + "annotation" : [["InitNull"], ["Deref", "InitNull"]], + "properties" : [] + } +} +)"); + const Annotations actual = parseAnnotationsFile(j); + ASSERT_EQ(actual.at("foo").statements[0][0]->getStatementName(), + Annotation::StatementKind::InitNull); + ASSERT_EQ(actual.at("foo").statements[1][0]->getStatementName(), + Annotation::StatementKind::Deref); + ASSERT_EQ(actual.at("foo").statements[1][1]->getStatementName(), + Annotation::StatementKind::InitNull); +} + +TEST(AnnotationsTest, WithOffsets) { + const json j = json::parse(R"( +{ + "foo" : { + "annotation" : [["InitNull:*[10]*&"]], + "properties" : [] + } +} +)"); + const Annotations actual = parseAnnotationsFile(j); + ASSERT_EQ(actual.at("foo").statements[0][0]->getStatementName(), + Annotation::StatementKind::InitNull); + const std::vector expectedOffset{"*", "10", "*", "&"}; + ASSERT_EQ(actual.at("foo").statements[0][0]->offset, expectedOffset); +} diff --git a/unittests/Annotations/CMakeLists.txt b/unittests/Annotations/CMakeLists.txt new file mode 100644 index 0000000000..cb9a7b1df1 --- /dev/null +++ b/unittests/Annotations/CMakeLists.txt @@ -0,0 +1,3 @@ +add_klee_unit_test(AnnotationsTest + AnnotationsTest.cpp) +target_link_libraries(AnnotationsTest PRIVATE kleaverExpr kleaverSolver) diff --git a/unittests/CMakeLists.txt b/unittests/CMakeLists.txt index d4b4d1f9f7..edb1f46361 100644 --- a/unittests/CMakeLists.txt +++ b/unittests/CMakeLists.txt @@ -272,6 +272,7 @@ function(add_klee_unit_test target_name) endfunction() # Unit Tests +add_subdirectory(Annotations) add_subdirectory(Assignment) add_subdirectory(Expr) add_subdirectory(Ref) From a36439e2d523efba62edb7ec7637bf934b4d9e76 Mon Sep 17 00:00:00 2001 From: Vladislav Kalugin Date: Tue, 25 Jul 2023 17:03:05 +0300 Subject: [PATCH 117/120] Add annotations implementation: - Merge args for external calls - Add config example in config/annotations.json --- .github/workflows/build.yaml | 1 - configs/annotations.json | 2027 +++++++++++++++++ configs/options.json | 5 +- include/klee/Core/Interpreter.h | 63 +- include/klee/Core/MockBuilder.h | 68 +- include/klee/Expr/AlphaBuilder.h | 2 +- include/klee/Expr/IndependentSet.h | 2 + include/klee/Expr/SourceBuilder.h | 2 - include/klee/Expr/SymbolicSource.h | 20 +- include/klee/Module/Annotation.h | 148 +- include/klee/Module/SarifReport.h | 2 +- include/klee/Support/OptionCategories.h | 1 - lib/Core/ExecutionState.cpp | 3 - lib/Core/Executor.cpp | 244 +- lib/Core/Executor.h | 22 +- lib/Core/MockBuilder.cpp | 708 ++++-- lib/Core/SpecialFunctionHandler.cpp | 59 +- lib/Expr/AlphaBuilder.cpp | 19 +- lib/Expr/IndependentSet.cpp | 12 +- lib/Expr/Parser.cpp | 8 +- lib/Expr/SourceBuilder.cpp | 1 - lib/Expr/SymbolicSource.cpp | 19 +- lib/Module/Annotation.cpp | 311 ++- lib/Solver/Z3Builder.cpp | 18 +- lib/Solver/Z3Builder.h | 4 +- runtime/Mocks/models.c | 15 +- scripts/kleef | 2 +- scripts/run_tests_with_mocks.py | 17 +- test/CMakeLists.txt | 1 + test/Feature/Annotation/AllocSource.c | 65 + test/Feature/Annotation/AllocSource.json | 40 + test/Feature/Annotation/BrokenAnnotation.json | 11 + test/Feature/Annotation/Deref.c | 104 + test/Feature/Annotation/Deref.json | 67 + test/Feature/Annotation/EmptyAnnotation.json | 1 + test/Feature/Annotation/Free.c | 45 + test/Feature/Annotation/Free.json | 31 + test/Feature/Annotation/General.c | 43 + test/Feature/Annotation/General.json | 24 + test/Feature/Annotation/InitNull.c | 79 + test/Feature/Annotation/InitNull.json | 49 + test/Feature/Annotation/InitNullEmpty.json | 32 + test/Feature/MockPointersDeterministic.c | 5 +- test/Feature/MockStrategies.c | 10 +- test/Industry/AssignNull_Scene_BadCase02.c | 4 +- test/Industry/AssignNull_Scene_BadCase04.c | 2 +- test/Industry/BadCase01_SecB_ForwardNull.c | 2 +- test/Industry/CheckNull_Scene_BadCase02.c | 2 +- test/Industry/CheckNull_Scene_BadCase04.c | 2 +- .../CoverageBranches/egcd3-ll_valuebound10.c | 2 +- ...r.3.ufo.UNBOUNDED.pals+Problem12_label00.c | 2 +- test/Industry/FN_SecB_ForwardNull_filed.c | 4 +- ...Var_Alloc_in_Loop_Exit_in_Loop_BadCase01.c | 2 +- test/Industry/NullReturn_BadCase_WhiteBox01.c | 4 +- test/Industry/NullReturn_Scene_BadCase01.c | 2 +- test/Industry/NullReturn_Scene_BadCase02.c | 2 +- test/Industry/NullReturn_Scene_BadCase03.c | 2 +- test/Industry/NullReturn_Scene_BadCase04.c | 4 +- test/Industry/NullReturn_Scene_BadCase06.c | 2 +- test/Industry/NullReturn_Scene_BadCase08.cpp | 2 +- test/Industry/SecB_ForwardNull.c | 4 +- .../UseAfterFree/Double_Free_BadCase01.c | 2 +- .../UseAfterFree/Double_Free_BadCase02.c | 2 +- .../Free_Not_Set_Null_BadCase02.cpp | 2 +- .../Prod_Dereference_After_Free_BadCase01.c | 2 +- test/Industry/ZeroDeref_Scene_BadCase02.c | 2 +- test/Industry/ZeroDeref_Scene_BadCase05.c | 4 +- test/Industry/egcd3-ll_valuebound10.c | 2 +- test/Industry/fn_reverse_null.c | 2 +- test/Industry/fp_forward_null_address.c | 2 +- test/Industry/fp_null_returns_self_define.c | 2 +- test/Industry/fp_null_returns_self_define2.c | 2 +- test/Industry/if2.c | 2 +- test/Industry/test.c | 4 +- test/Industry/while_true.c | 4 +- test/Replay/libkleeruntest/replay_mocks.c | 20 +- test/Solver/sina2f.c | 2 +- test/lit.cfg | 12 +- test/lit.site.cfg.in | 1 + .../2023-10-02-test-from-mocked-global.c | 4 +- test/regression/2023-10-13-kbfiltr.i.cil-2.c | 2 +- tools/klee/main.cpp | 162 +- unittests/Annotations/AnnotationsTest.cpp | 92 +- 83 files changed, 3998 insertions(+), 785 deletions(-) create mode 100644 configs/annotations.json create mode 100644 test/Feature/Annotation/AllocSource.c create mode 100644 test/Feature/Annotation/AllocSource.json create mode 100644 test/Feature/Annotation/BrokenAnnotation.json create mode 100644 test/Feature/Annotation/Deref.c create mode 100644 test/Feature/Annotation/Deref.json create mode 100644 test/Feature/Annotation/EmptyAnnotation.json create mode 100644 test/Feature/Annotation/Free.c create mode 100644 test/Feature/Annotation/Free.json create mode 100644 test/Feature/Annotation/General.c create mode 100644 test/Feature/Annotation/General.json create mode 100644 test/Feature/Annotation/InitNull.c create mode 100644 test/Feature/Annotation/InitNull.json create mode 100644 test/Feature/Annotation/InitNullEmpty.json diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 9932e4de62..2e531d15da 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -146,7 +146,6 @@ jobs: runs-on: macos-latest env: BASE: /tmp - LLVM_VERSION: 11 SOLVERS: STP UCLIBC_VERSION: 0 USE_TCMALLOC: 0 diff --git a/configs/annotations.json b/configs/annotations.json new file mode 100644 index 0000000000..685f60c2a6 --- /dev/null +++ b/configs/annotations.json @@ -0,0 +1,2027 @@ +{ + "atof": { + "name": "atof", + "annotation": [ + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "atoi": { + "name": "atoi", + "annotation": [ + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "atol": { + "name": "atol", + "annotation": [ + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "atoll": { + "name": "atoll", + "annotation": [ + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "bcmp": { + "name": "bcmp", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "calloc": { + "name": "calloc", + "annotation": [ + [ + "AllocSource::1", + "InitNull" + ], + [], + [] + ], + "properties": [] + }, + "fclose": { + "name": "fclose", + "annotation": [ + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "fcvt": { + "name": "fcvt", + "annotation": [ + [], + [], + [], + [ + "Deref" + ], + [ + "Deref" + ] + ], + "properties": [] + }, + "feof": { + "name": "feof", + "annotation": [ + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "ferror": { + "name": "ferror", + "annotation": [ + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "fgetc": { + "name": "fgetc", + "annotation": [ + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "fgetpos": { + "name": "fgetpos", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ] + ], + "properties": [] + }, + "fgetpos64": { + "name": "fgetpos64", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ] + ], + "properties": [] + }, + "fgets": { + "name": "fgets", + "annotation": [ + [ + "InitNull" + ], + [ + "Deref" + ], + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "fgetwc": { + "name": "fgetwc", + "annotation": [ + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "fgetws": { + "name": "fgetws", + "annotation": [ + [ + "InitNull" + ], + [ + "Deref" + ], + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "fileno": { + "name": "fileno", + "annotation": [ + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "fopen": { + "name": "fopen", + "annotation": [ + [ + "InitNull" + ], + [], + [] + ], + "properties": [] + }, + "fopen64": { + "name": "fopen64", + "annotation": [ + [ + "InitNull" + ], + [], + [] + ], + "properties": [] + }, + "fopen_s": { + "name": "fopen_s", + "annotation": [ + [], + [ + "InitNull:*:!=0" + ], + [], + [ + "FreeSink::4" + ] + ], + "properties": [] + }, + "fprintf": { + "name": "fprintf", + "annotation": [ + [], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "fputc": { + "name": "fputc", + "annotation": [ + [], + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "fputs": { + "name": "fputs", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ] + ], + "properties": [] + }, + "fputwc": { + "name": "fputwc", + "annotation": [ + [], + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "fputws": { + "name": "fputws", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ] + ], + "properties": [] + }, + "fread": { + "name": "fread", + "annotation": [ + [], + [ + "Deref" + ], + [], + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "free": { + "name": "free", + "annotation": [ + [], + [ + "FreeSink::1" + ] + ], + "properties": [] + }, + "freopen": { + "name": "freopen", + "annotation": [ + [ + "InitNull" + ], + [], + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "freopen64": { + "name": "freopen64", + "annotation": [ + [ + "InitNull" + ], + [], + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "freopen_s": { + "name": "freopen_s", + "annotation": [ + [], + [ + "InitNull:*:!=0" + ], + [], + [], + [ + "FreeSink::4" + ] + ], + "properties": [] + }, + "fscanf": { + "name": "fscanf", + "annotation": [ + [], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "fscanf_s": { + "name": "fscanf_s", + "annotation": [ + [], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "fseek": { + "name": "fseek", + "annotation": [ + [], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "fsetpos": { + "name": "fsetpos", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ] + ], + "properties": [] + }, + "fsetpos64": { + "name": "fsetpos64", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ] + ], + "properties": [] + }, + "ftell": { + "name": "ftell", + "annotation": [ + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "fwide": { + "name": "fwide", + "annotation": [ + [], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "fwprintf": { + "name": "fwprintf", + "annotation": [ + [], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "fwrite": { + "name": "fwrite", + "annotation": [ + [], + [ + "Deref" + ], + [], + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "fwscanf": { + "name": "fwscanf", + "annotation": [ + [], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "getc": { + "name": "getc", + "annotation": [ + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "getenv": { + "name": "getenv", + "annotation": [ + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "getenv_s": { + "name": "getenv_s", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "gets": { + "name": "gets", + "annotation": [ + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "gets_s": { + "name": "gets_s", + "annotation": [ + [], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "getw": { + "name": "getw", + "annotation": [ + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "getwc": { + "name": "getwc", + "annotation": [ + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "itoa": { + "name": "itoa", + "annotation": [ + [], + [], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "localtime": { + "name": "localtime", + "annotation": [ + [ + "InitNull::Must" + ], + [] + ], + "properties": [] + }, + "malloc": { + "name": "malloc", + "annotation": [ + [ + "AllocSource::1", + "InitNull" + ], + [] + ], + "properties": [] + }, + "memccpy": { + "name": "memccpy", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "memchr": { + "name": "memchr", + "annotation": [ + [ + "InitNull" + ], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "memcmp": { + "name": "memcmp", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "memcpy": { + "name": "memcpy", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "memcpy_s": { + "name": "memcpy_s", + "annotation": [ + [], + [ + "Deref" + ], + [], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "memicmp": { + "name": "memicmp", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "memmem": { + "name": "memmem", + "annotation": [ + [ + "InitNull" + ], + [ + "Deref" + ], + [], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "memmove": { + "name": "memmove", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "memmove_s": { + "name": "memmove_s", + "annotation": [ + [], + [ + "Deref" + ], + [], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "mempcpy": { + "name": "mempcpy", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "memset": { + "name": "memset", + "annotation": [ + [], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "memset_s": { + "name": "memset_s", + "annotation": [ + [], + [ + "Deref" + ], + [], + [], + [] + ], + "properties": [] + }, + "pthread_mutex_lock": { + "name": "pthread_mutex_lock", + "annotation": [ + [], + [ + "InitNull::!=0" + ] + ], + "properties": [] + }, + "pthread_mutex_trylock": { + "name": "pthread_mutex_trylock", + "annotation": [ + [], + [ + "InitNull::!=0" + ] + ], + "properties": [] + }, + "putc": { + "name": "putc", + "annotation": [ + [], + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "puts": { + "name": "puts", + "annotation": [ + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "qsort": { + "name": "qsort", + "annotation": [ + [], + [ + "Deref" + ], + [], + [], + [] + ], + "properties": [] + }, + "rawmemchr": { + "name": "rawmemchr", + "annotation": [ + [ + "InitNull" + ], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "realloc": { + "name": "realloc", + "annotation": [ + [ + "AllocSource::1", + "InitNull" + ], + [], + [] + ], + "properties": [] + }, + "setbuf": { + "name": "setbuf", + "annotation": [ + [], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "setlocale": { + "name": "setlocale", + "annotation": [ + [ + "InitNull" + ], + [], + [] + ], + "properties": [] + }, + "snprintf": { + "name": "snprintf", + "annotation": [ + [], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "snprintf_s": { + "name": "snprintf_s", + "annotation": [ + [], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "snwprintf": { + "name": "snwprintf", + "annotation": [ + [], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "sprintf": { + "name": "sprintf", + "annotation": [ + [], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "sprintf_s": { + "name": "sprintf_s", + "annotation": [ + [], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "sscanf": { + "name": "sscanf", + "annotation": [ + [], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "sscanf_s": { + "name": "sscanf_s", + "annotation": [ + [], + [ + "Deref" + ], + [], + [], + [] + ], + "properties": [] + }, + "std::from_chars": { + "name": "std::from_chars", + "annotation": [ + [], + [ + "Deref" + ], + [], + [], + [] + ], + "properties": [] + }, + "std::to_chars": { + "name": "std::to_chars", + "annotation": [ + [], + [ + "Deref" + ], + [], + [], + [] + ], + "properties": [] + }, + "stpcpy": { + "name": "stpcpy", + "annotation": [ + [], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "strcat": { + "name": "strcat", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ] + ], + "properties": [] + }, + "strcat_s": { + "name": "strcat_s", + "annotation": [ + [], + [ + "Deref" + ], + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "strchr": { + "name": "strchr", + "annotation": [ + [ + "InitNull" + ], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "strchrnul": { + "name": "strchrnul", + "annotation": [ + [], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "strcmp": { + "name": "strcmp", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ] + ], + "properties": [] + }, + "strcpy": { + "name": "strcpy", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ] + ], + "properties": [] + }, + "strcpy_s": { + "name": "strcpy_s", + "annotation": [ + [], + [ + "Deref" + ], + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "strdup": { + "name": "strdup", + "annotation": [ + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "strlen": { + "name": "strlen", + "annotation": [ + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "strncasecmp": { + "name": "strncasecmp", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "strncat": { + "name": "strncat", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "strncat_s": { + "name": "strncat_s", + "annotation": [ + [], + [ + "Deref" + ], + [], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "strncmp": { + "name": "strncmp", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "strncpy": { + "name": "strncpy", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "strncpy_s": { + "name": "strncpy_s", + "annotation": [ + [], + [ + "Deref" + ], + [], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "strndup": { + "name": "strndup", + "annotation": [ + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "strnlen": { + "name": "strnlen", + "annotation": [ + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "strnset": { + "name": "strnset", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "strpbrk": { + "name": "strpbrk", + "annotation": [ + [ + "InitNull" + ], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "strrchr": { + "name": "strrchr", + "annotation": [ + [ + "InitNull" + ], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "strset": { + "name": "strset", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ] + ], + "properties": [] + }, + "strspn": { + "name": "strspn", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ] + ], + "properties": [] + }, + "strstr": { + "name": "strstr", + "annotation": [ + [ + "InitNull" + ], + [], + [] + ], + "properties": [] + }, + "strtod": { + "name": "strtod", + "annotation": [ + [], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "strtol": { + "name": "strtol", + "annotation": [ + [], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "strtold": { + "name": "strtold", + "annotation": [ + [], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "strtoll": { + "name": "strtoll", + "annotation": [ + [], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "strtoul": { + "name": "strtoul", + "annotation": [ + [], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "strtoull": { + "name": "strtoull", + "annotation": [ + [], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "strxfrm": { + "name": "strxfrm", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "swprintf": { + "name": "swprintf", + "annotation": [ + [], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "swprintf_s": { + "name": "swprintf_s", + "annotation": [ + [], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "swscanf": { + "name": "swscanf", + "annotation": [ + [], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "swscanf_s": { + "name": "swscanf_s", + "annotation": [ + [], + [ + "Deref" + ], + [], + [], + [] + ], + "properties": [] + }, + "tmpnam": { + "name": "tmpnam", + "annotation": [ + [ + "InitNull" + ], + [] + ], + "properties": [] + }, + "vfprintf_s": { + "name": "vfprintf_s", + "annotation": [ + [], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "vfscanf": { + "name": "vfscanf", + "annotation": [ + [], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "vfwprintf": { + "name": "vfwprintf", + "annotation": [ + [], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "vfwprintf_s": { + "name": "vfwprintf_s", + "annotation": [ + [], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "vfwscanf": { + "name": "vfwscanf", + "annotation": [ + [], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "vsnprintf_s": { + "name": "vsnprintf_s", + "annotation": [ + [], + [ + "Deref" + ], + [], + [], + [] + ], + "properties": [] + }, + "vsnwprintf": { + "name": "vsnwprintf", + "annotation": [ + [], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "vsprintf": { + "name": "vsprintf", + "annotation": [ + [], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "vsprintf_s": { + "name": "vsprintf_s", + "annotation": [ + [], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "vsscanf": { + "name": "vsscanf", + "annotation": [ + [], + [ + "Deref" + ], + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "vswscanf": { + "name": "vswscanf", + "annotation": [ + [], + [ + "Deref" + ], + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "wcscat": { + "name": "wcscat", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ] + ], + "properties": [] + }, + "wcscat_s": { + "name": "wcscat_s", + "annotation": [ + [], + [ + "Deref" + ], + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "wcschr": { + "name": "wcschr", + "annotation": [ + [ + "InitNull" + ], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "wcschrnul": { + "name": "wcschrnul", + "annotation": [ + [ + "InitNull" + ], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "wcscmp": { + "name": "wcscmp", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ] + ], + "properties": [] + }, + "wcscoll": { + "name": "wcscoll", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ] + ], + "properties": [] + }, + "wcscpy": { + "name": "wcscpy", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ] + ], + "properties": [] + }, + "wcscpy_s": { + "name": "wcscpy_s", + "annotation": [ + [], + [ + "Deref" + ], + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "wcscspn": { + "name": "wcscspn", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ] + ], + "properties": [] + }, + "wcsftime": { + "name": "wcsftime", + "annotation": [ + [], + [], + [], + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "wcsncasecmp": { + "name": "wcsncasecmp", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "wcsncat": { + "name": "wcsncat", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "wcsncat_s": { + "name": "wcsncat_s", + "annotation": [ + [], + [ + "Deref" + ], + [], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "wcsncmp": { + "name": "wcsncmp", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "wcsncpy": { + "name": "wcsncpy", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "wcsncpy_s": { + "name": "wcsncpy_s", + "annotation": [ + [], + [ + "Deref" + ], + [], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "wcspbrk": { + "name": "wcspbrk", + "annotation": [ + [ + "InitNull" + ], + [ + "Deref" + ], + [ + "Deref" + ] + ], + "properties": [] + }, + "wcsrchr": { + "name": "wcsrchr", + "annotation": [ + [ + "InitNull" + ], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "wcsspn": { + "name": "wcsspn", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ] + ], + "properties": [] + }, + "wcsstr": { + "name": "wcsstr", + "annotation": [ + [ + "InitNull" + ], + [ + "Deref" + ], + [ + "Deref" + ] + ], + "properties": [] + }, + "wcstol": { + "name": "wcstol", + "annotation": [ + [], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "wcstold": { + "name": "wcstold", + "annotation": [ + [], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "wcstoll": { + "name": "wcstoll", + "annotation": [ + [], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "wcstoul": { + "name": "wcstoul", + "annotation": [ + [], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "wcstoull": { + "name": "wcstoull", + "annotation": [ + [], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "wcsxfrm": { + "name": "wcsxfrm", + "annotation": [ + [], + [], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "wctrans": { + "name": "wctrans", + "annotation": [ + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "wctype": { + "name": "wctype", + "annotation": [ + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "wmemchr": { + "name": "wmemchr", + "annotation": [ + [ + "InitNull" + ], + [ + "Deref" + ], + [], + [] + ], + "properties": [] + }, + "wmemcmp": { + "name": "wmemcmp", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "wmemcpy": { + "name": "wmemcpy", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "wmemcpy_s": { + "name": "wmemcpy_s", + "annotation": [ + [], + [ + "Deref" + ], + [], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "wmemmove": { + "name": "wmemmove", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "wmemmove_s": { + "name": "wmemmove_s", + "annotation": [ + [], + [ + "Deref" + ], + [], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "wmempcpy": { + "name": "wmempcpy", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ], + [] + ], + "properties": [] + } +} diff --git a/configs/options.json b/configs/options.json index 32f20ebbf7..e89988448a 100644 --- a/configs/options.json +++ b/configs/options.json @@ -18,13 +18,13 @@ "program": "${buildPath}/bin/klee", "args": [ "--use-guided-search=error", - "--mock-external-calls", "--posix-runtime", "--check-out-of-memory", "--suppress-external-warnings", "--libc=klee", "--skip-not-lazy-initialized", "--external-calls=all", + "--mock-policy=all", "--output-source=false", "--output-istats=false", "--output-stats=false", @@ -32,7 +32,6 @@ "--max-sym-alloc=${maxSymAlloc}", "--max-forks=${maxForks}", "--max-solver-time=${maxSolverTime}s", - "--mock-all-externals", "--smart-resolve-entry-function", "--extern-calls-can-return-null", "--align-symbolic-pointers=false", @@ -49,4 +48,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/include/klee/Core/Interpreter.h b/include/klee/Core/Interpreter.h index 5a619c6e29..04eec908de 100644 --- a/include/klee/Core/Interpreter.h +++ b/include/klee/Core/Interpreter.h @@ -65,11 +65,21 @@ using FLCtoOpcode = std::unordered_map< std::unordered_map< unsigned, std::unordered_map>>>; -enum class MockStrategy { - None, // No mocks are generated - Naive, // For each function call new symbolic value is generated - Deterministic, // Each function is treated as uninterpreted function in SMT. - // Compatible with Z3 solver only +enum class MockStrategyKind { + Naive, // For each function call new symbolic value is generated + Deterministic // Each function is treated as uninterpreted function in SMT. + // Compatible with Z3 solver only +}; + +enum class MockPolicy { + None, // No mock function generated + Failed, // Generate symbolic value for failed external calls + All // Generate IR module with all external values +}; + +enum class MockMutableGlobalsPolicy { + None, // No mock for globals + All, // Mock globals on module build stage and generate bc module for it }; class Interpreter { @@ -90,25 +100,31 @@ class Interpreter { std::string OptSuffix; std::string MainCurrentName; std::string MainNameAfterMock; + std::string AnnotationsFile; bool Optimize; bool Simplify; bool CheckDivZero; bool CheckOvershift; + bool AnnotateOnlyExternal; bool WithFPRuntime; bool WithPOSIXRuntime; ModuleOptions(const std::string &_LibraryDir, const std::string &_EntryPoint, const std::string &_OptSuffix, const std::string &_MainCurrentName, - const std::string &_MainNameAfterMock, bool _Optimize, + const std::string &_MainNameAfterMock, + const std::string &_AnnotationsFile, bool _Optimize, bool _Simplify, bool _CheckDivZero, bool _CheckOvershift, - bool _WithFPRuntime, bool _WithPOSIXRuntime) + bool _AnnotateOnlyExternal, bool _WithFPRuntime, + bool _WithPOSIXRuntime) : LibraryDir(_LibraryDir), EntryPoint(_EntryPoint), OptSuffix(_OptSuffix), MainCurrentName(_MainCurrentName), - MainNameAfterMock(_MainNameAfterMock), Optimize(_Optimize), + MainNameAfterMock(_MainNameAfterMock), + AnnotationsFile(_AnnotationsFile), Optimize(_Optimize), Simplify(_Simplify), CheckDivZero(_CheckDivZero), - CheckOvershift(_CheckOvershift), WithFPRuntime(_WithFPRuntime), - WithPOSIXRuntime(_WithPOSIXRuntime) {} + CheckOvershift(_CheckOvershift), + AnnotateOnlyExternal(_AnnotateOnlyExternal), + WithFPRuntime(_WithFPRuntime), WithPOSIXRuntime(_WithPOSIXRuntime) {} }; enum LogType { @@ -126,11 +142,15 @@ class Interpreter { unsigned MakeConcreteSymbolic; GuidanceKind Guidance; std::optional Paths; - enum MockStrategy MockStrategy; + MockPolicy Mock; + MockStrategyKind MockStrategy; + MockMutableGlobalsPolicy MockMutableGlobals; InterpreterOptions(std::optional Paths) : MakeConcreteSymbolic(false), Guidance(GuidanceKind::NoGuidance), - Paths(std::move(Paths)), MockStrategy(MockStrategy::None) {} + Paths(std::move(Paths)), Mock(MockPolicy::None), + MockStrategy(MockStrategyKind::Naive), + MockMutableGlobals(MockMutableGlobalsPolicy::None) {} }; protected: @@ -153,18 +173,13 @@ class Interpreter { /// module /// \return The final module after it has been optimized, checks /// inserted, and modified for interpretation. - virtual llvm::Module * - setModule(std::vector> &userModules, - std::vector> &libsModules, - const ModuleOptions &opts, - std::set &&mainModuleFunctions, - std::set &&mainModuleGlobals, - FLCtoOpcode &&origInstructions, - const std::set &ignoredExternals, - const Annotations &annotations) = 0; - - virtual std::map - getAllExternals(const std::set &ignoredExternals) = 0; + virtual llvm::Module *setModule( + std::vector> &userModules, + std::vector> &libsModules, + const ModuleOptions &opts, std::set &&mainModuleFunctions, + std::set &&mainModuleGlobals, FLCtoOpcode &&origInstructions, + const std::set &ignoredExternals, + std::vector> redefinitions) = 0; // supply a tree stream writer which the interpreter will use // to record the concrete path (as a stream of '0' and '1' bytes). diff --git a/include/klee/Core/MockBuilder.h b/include/klee/Core/MockBuilder.h index 0ff22bd890..da5d0ea198 100644 --- a/include/klee/Core/MockBuilder.h +++ b/include/klee/Core/MockBuilder.h @@ -1,6 +1,15 @@ +//===-- MockBuilder.h -------------------------------------------*- C++ -*-===// +// +// The KLEEF Symbolic Virtual Machine +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +//===----------------------------------------------------------------------===// + #ifndef KLEE_MOCKBUILDER_H #define KLEE_MOCKBUILDER_H +#include "klee/Core/Interpreter.h" #include "klee/Module/Annotation.h" #include "llvm/IR/IRBuilder.h" @@ -14,32 +23,63 @@ namespace klee { class MockBuilder { private: const llvm::Module *userModule; + llvm::LLVMContext &ctx; std::unique_ptr mockModule; std::unique_ptr> builder; - std::map externals; - Annotations annotations; - const std::string mockEntrypoint, userEntrypoint; + const Interpreter::ModuleOptions &opts; + const Interpreter::InterpreterOptions &interpreterOptions; + + std::set ignoredExternals; + std::vector> redefinitions; + + InterpreterHandler *interpreterHandler; + + std::set &mainModuleFunctions; + std::set &mainModuleGlobals; + + AnnotationsMap annotations; void initMockModule(); void buildMockMain(); void buildExternalGlobalsDefinitions(); void buildExternalFunctionsDefinitions(); - void buildCallKleeMakeSymbol(const std::string &klee_function_name, - llvm::Value *source, llvm::Type *type, - const std::string &symbol_name); - void buildAnnotationForExternalFunctionParams(llvm::Function *func, - Annotation &annotation); - llvm::Value *goByOffset(llvm::Value *value, - const std::vector &offset); + void + buildCallKleeMakeSymbolic(const std::string &kleeMakeSymbolicFunctionName, + llvm::Value *source, llvm::Type *type, + const std::string &symbolicName); + + void buildAnnotationForExternalFunctionArgs( + llvm::Function *func, + const std::vector> &statementsNotAllign); + void buildAnnotationForExternalFunctionReturn( + llvm::Function *func, const std::vector &statements); + void buildAnnotationForExternalFunctionProperties( + llvm::Function *func, const std::set &properties); + + std::map getExternalFunctions(); + std::map getExternalGlobals(); + + std::pair + goByOffset(llvm::Value *value, const std::vector &offset); public: - MockBuilder(const llvm::Module *initModule, std::string mockEntrypoint, - std::string userEntrypoint, - std::map externals, - Annotations annotations); + MockBuilder(const llvm::Module *initModule, + const Interpreter::ModuleOptions &opts, + const Interpreter::InterpreterOptions &interpreterOptions, + const std::set &ignoredExternals, + std::vector> &redefinitions, + InterpreterHandler *interpreterHandler, + std::set &mainModuleFunctions, + std::set &mainModuleGlobals); std::unique_ptr build(); + void buildAllocSource(llvm::Value *prev, llvm::Type *elemType, + const Statement::Alloc *allocSourcePtr); + void buildFree(llvm::Value *elem, const Statement::Free *freePtr); + void processingValue(llvm::Value *prev, llvm::Type *elemType, + const Statement::Alloc *allocSourcePtr, + bool initNullPtr); }; } // namespace klee diff --git a/include/klee/Expr/AlphaBuilder.h b/include/klee/Expr/AlphaBuilder.h index 6a965c3962..cc481f8f69 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); + constraints_ty visitConstraints(const constraints_ty &cs); ref build(ref v); const Array *buildArray(const Array *arr) { return visitArray(arr); } ref reverseBuild(ref v); diff --git a/include/klee/Expr/IndependentSet.h b/include/klee/Expr/IndependentSet.h index c2aeb7173f..af84a4dd8a 100644 --- a/include/klee/Expr/IndependentSet.h +++ b/include/klee/Expr/IndependentSet.h @@ -120,6 +120,8 @@ class IndependentConstraintSet { std::shared_ptr concretizedSets; + std::set uninterpretedFunctions; + ref addExpr(ref e) const; ref updateConcretization(const Assignment &delta, diff --git a/include/klee/Expr/SourceBuilder.h b/include/klee/Expr/SourceBuilder.h index 20eea0b49a..1a353901e0 100644 --- a/include/klee/Expr/SourceBuilder.h +++ b/include/klee/Expr/SourceBuilder.h @@ -3,8 +3,6 @@ #include "klee/Expr/SymbolicSource.h" -#include "llvm/IR/Function.h" - namespace klee { class KInstruction; diff --git a/include/klee/Expr/SymbolicSource.h b/include/klee/Expr/SymbolicSource.h index 6707ebd31c..7bdea46962 100644 --- a/include/klee/Expr/SymbolicSource.h +++ b/include/klee/Expr/SymbolicSource.h @@ -361,8 +361,8 @@ class AlphaSource : public SymbolicSource { const unsigned index; AlphaSource(unsigned _index) : index(_index) {} - Kind getKind() const override { return Kind::Alpha; } - virtual std::string getName() const override { return "alpha"; } + [[nodiscard]] Kind getKind() const override { return Kind::Alpha; } + [[nodiscard]] virtual std::string getName() const override { return "alpha"; } static bool classof(const SymbolicSource *S) { return S->getKind() == Kind::Alpha; @@ -408,8 +408,8 @@ class MockNaiveSource : public MockSource { unsigned _version) : MockSource(km, function), version(_version) {} - Kind getKind() const override { return Kind::MockNaive; } - std::string getName() const override { return "mockNaive"; } + [[nodiscard]] Kind getKind() const override { return Kind::MockNaive; } + [[nodiscard]] std::string getName() const override { return "mockNaive"; } static bool classof(const SymbolicSource *S) { return S->getKind() == Kind::MockNaive; @@ -417,7 +417,7 @@ class MockNaiveSource : public MockSource { unsigned computeHash() override; - int internalCompare(const SymbolicSource &b) const override; + [[nodiscard]] int internalCompare(const SymbolicSource &b) const override; }; class MockDeterministicSource : public MockSource { @@ -427,8 +427,12 @@ class MockDeterministicSource : public MockSource { MockDeterministicSource(const KModule *_km, const llvm::Function &_function, const std::vector> &_args); - Kind getKind() const override { return Kind::MockDeterministic; } - std::string getName() const override { return "mockDeterministic"; } + [[nodiscard]] Kind getKind() const override { + return Kind::MockDeterministic; + } + [[nodiscard]] std::string getName() const override { + return "mockDeterministic"; + } static bool classof(const SymbolicSource *S) { return S->getKind() == Kind::MockDeterministic; @@ -436,7 +440,7 @@ class MockDeterministicSource : public MockSource { unsigned computeHash() override; - int internalCompare(const SymbolicSource &b) const override; + [[nodiscard]] int internalCompare(const SymbolicSource &b) const override; }; } // namespace klee diff --git a/include/klee/Module/Annotation.h b/include/klee/Module/Annotation.h index 6defdd15b3..d94c591091 100644 --- a/include/klee/Module/Annotation.h +++ b/include/klee/Module/Annotation.h @@ -1,3 +1,11 @@ +//===-- Annotation.h --------------------------------------------*- C++ -*-===// +// +// The KLEEF Symbolic Virtual Machine +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +//===----------------------------------------------------------------------===// + #ifndef KLEE_ANNOTATION_H #define KLEE_ANNOTATION_H @@ -7,80 +15,126 @@ #include "vector" #include "nlohmann/json.hpp" -#include "nonstd/optional.hpp" +#include + +#include "klee/Config/config.h" + +#include "llvm/IR/Module.h" -using nonstd::nullopt; -using nonstd::optional; using json = nlohmann::json; namespace klee { -// Annotation format: https://github.com/UnitTestBot/klee/discussions/92 -struct Annotation { - enum class StatementKind { - Unknown, +namespace Statement { +enum class Kind { + Unknown, - Deref, - InitNull, - }; + Deref, + InitNull, + MaybeInitNull, + // TODO: rename to alloc + AllocSource, + Free +}; - enum class Property { - Unknown, +enum class Property { + Unknown, - Determ, - Noreturn, - }; + Deterministic, + Noreturn, +}; - struct StatementUnknown { - explicit StatementUnknown(const std::string &str); - virtual ~StatementUnknown(); +struct Unknown { +protected: + std::string rawAnnotation; + std::string rawOffset; + std::string rawValue; - virtual Annotation::StatementKind getStatementName() const; - virtual bool operator==(const StatementUnknown &other) const; +public: + std::vector offset; - std::string statementStr; - std::vector offset; + explicit Unknown(const std::string &str = "Unknown"); + virtual ~Unknown(); - protected: - void parseOffset(const std::string &offsetStr); - void parseOnlyOffset(const std::string &str); - }; + virtual bool operator==(const Unknown &other) const; + [[nodiscard]] virtual Kind getKind() const; - struct StatementDeref final : public StatementUnknown { - explicit StatementDeref(const std::string &str); + [[nodiscard]] const std::vector &getOffset() const; + [[nodiscard]] std::string toString() const; +}; - Annotation::StatementKind getStatementName() const override; - }; +struct Deref final : public Unknown { + explicit Deref(const std::string &str = "Deref"); - struct StatementInitNull final : public StatementUnknown { - explicit StatementInitNull(const std::string &str); + [[nodiscard]] Kind getKind() const override; +}; + +struct InitNull final : public Unknown { +public: + explicit InitNull(const std::string &str = "InitNull"); + + [[nodiscard]] Kind getKind() const override; +}; - Annotation::StatementKind getStatementName() const override; +struct MaybeInitNull final : public Unknown { +public: + explicit MaybeInitNull(const std::string &str = "MaybeInitNull"); + + [[nodiscard]] Kind getKind() const override; +}; + +struct Alloc final : public Unknown { +public: + enum Type { + ALLOC = 1, // malloc, calloc, realloc + NEW = 2, // operator new + NEW_BRACKETS = 3, // operator new[] + OPEN_FILE = 4, // open file (fopen, open) + MUTEX_LOCK = 5 // mutex lock (pthread_mutex_lock) }; - using StatementPtr = std::shared_ptr; - using StatementPtrs = std::vector; + Type value = Alloc::Type::ALLOC; - bool operator==(const Annotation &other) const; + explicit Alloc(const std::string &str = "AllocSource::1"); - std::string functionName; - std::vector statements; - std::set properties; + [[nodiscard]] Kind getKind() const override; }; -using Annotations = std::map; +struct Free final : public Unknown { +public: + enum Type { + FREE = 1, // Kind of free function + DELETE = 2, // operator delete + DELETE_BRACKETS = 3, // operator delete[] + CLOSE_FILE = 4, // close file + MUTEX_UNLOCK = 5 // mutex unlock (pthread_mutex_unlock) + }; + + Type value = Free::Type::FREE; + + explicit Free(const std::string &str = "FreeSource::1"); -const std::map toProperties{ - {"determ", Annotation::Property::Determ}, - {"noreturn", Annotation::Property::Noreturn}, + [[nodiscard]] Kind getKind() const override; }; -Annotations parseAnnotationsFile(const json &annotationsJson); -Annotations parseAnnotationsFile(const std::string &path); +using Ptr = std::shared_ptr; +bool operator==(const Ptr &first, const Ptr &second); +} // namespace Statement + +// Annotation format: https://github.com/UnitTestBot/klee/discussions/92 +struct Annotation { + std::string functionName; + std::vector returnStatements; + std::vector> argsStatements; + std::set properties; + + bool operator==(const Annotation &other) const; +}; -bool operator==(const Annotation::StatementPtr &first, - const Annotation::StatementPtr &second); +using AnnotationsMap = std::map; +AnnotationsMap parseAnnotationsJson(const json &annotationsJson); +AnnotationsMap parseAnnotations(const std::string &path); } // namespace klee #endif // KLEE_ANNOTATION_H diff --git a/include/klee/Module/SarifReport.h b/include/klee/Module/SarifReport.h index 72d846c90f..09652206dd 100644 --- a/include/klee/Module/SarifReport.h +++ b/include/klee/Module/SarifReport.h @@ -17,8 +17,8 @@ #include #include "klee/ADT/Ref.h" +#include "nlohmann/json.hpp" #include "llvm/IR/Function.h" -#include using json = nlohmann::json; diff --git a/include/klee/Support/OptionCategories.h b/include/klee/Support/OptionCategories.h index da1d0d4934..ed8c23c880 100644 --- a/include/klee/Support/OptionCategories.h +++ b/include/klee/Support/OptionCategories.h @@ -24,7 +24,6 @@ namespace klee { extern llvm::cl::OptionCategory TestCompCat; extern llvm::cl::OptionCategory ExecCat; extern llvm::cl::OptionCategory DebugCat; -extern llvm::cl::OptionCategory ExecCat; extern llvm::cl::OptionCategory MiscCat; extern llvm::cl::OptionCategory ModuleCat; extern llvm::cl::OptionCategory SeedingCat; diff --git a/lib/Core/ExecutionState.cpp b/lib/Core/ExecutionState.cpp index bf843031da..3fd5a29996 100644 --- a/lib/Core/ExecutionState.cpp +++ b/lib/Core/ExecutionState.cpp @@ -25,16 +25,13 @@ DISABLE_WARNING_DEPRECATED_DECLARATIONS #include "llvm/IR/Function.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/raw_ostream.h" -#include "klee/Support/ErrorHandling.h" DISABLE_WARNING_POP #include #include #include -#include #include #include -#include #include using namespace llvm; diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp index 91a06e79ea..51e2d6f849 100644 --- a/lib/Core/Executor.cpp +++ b/lib/Core/Executor.cpp @@ -36,7 +36,6 @@ #include "klee/Core/Context.h" #include "klee/ADT/KTest.h" -#include "klee/ADT/RNG.h" #include "klee/Config/Version.h" #include "klee/Config/config.h" #include "klee/Core/Interpreter.h" @@ -183,24 +182,9 @@ cl::opt StackCopySizeMemoryCheckThreshold( "copied"), cl::cat(ExecCat)); -enum class MockMutableGlobalsPolicy { - None, - PrimitiveFields, - All, -}; +namespace { -cl::opt MockMutableGlobals( - "mock-mutable-globals", - cl::values(clEnumValN(MockMutableGlobalsPolicy::None, "none", - "No mutable global object are allowed o mock except " - "external (default)"), - clEnumValN(MockMutableGlobalsPolicy::PrimitiveFields, - "primitive-fields", - "Only primitive fileds of mutable global objects are " - "allowed to mock."), - clEnumValN(MockMutableGlobalsPolicy::All, "all", - "All mutable global object are allowed o mock.")), - cl::init(MockMutableGlobalsPolicy::None), cl::cat(ExecCat)); +/*** Lazy initialization options ***/ enum class LazyInitializationPolicy { None, @@ -229,6 +213,7 @@ llvm::cl::opt MinNumberElementsLazyInit( llvm::cl::desc("Minimum number of array elements for one lazy " "initialization (default 4)"), llvm::cl::init(4), llvm::cl::cat(LazyInitCat)); +} // namespace cl::opt FunctionCallReproduce( "function-call-reproduce", cl::init(""), @@ -350,18 +335,6 @@ cl::opt AllExternalWarnings( "as opposed to once per function (default=false)"), cl::cat(ExtCallsCat)); -cl::opt - MockExternalCalls("mock-external-calls", cl::init(false), - cl::desc("If true, failed external calls are mocked, " - "i.e. return values are made symbolic " - "and then added to generated test cases. " - "If false, fails on externall calls."), - cl::cat(ExtCallsCat)); - -cl::opt MockAllExternals("mock-all-externals", cl::init(false), - cl::desc("If true, all externals are mocked."), - cl::cat(ExtCallsCat)); - /*** Seeding options ***/ cl::opt AlwaysOutputSeeds( @@ -509,9 +482,9 @@ Executor::Executor(LLVMContext &ctx, const InterpreterOptions &opts, InterpreterHandler *ih) : Interpreter(opts), interpreterHandler(ih), searcher(nullptr), externalDispatcher(new ExternalDispatcher(ctx)), statsTracker(0), - pathWriter(0), symPathWriter(0), specialFunctionHandler(0), - timers{time::Span(TimerInterval)}, guidanceKind(opts.Guidance), - codeGraphInfo(new CodeGraphInfo()), + pathWriter(0), symPathWriter(0), + specialFunctionHandler(0), timers{time::Span(TimerInterval)}, + guidanceKind(opts.Guidance), codeGraphInfo(new CodeGraphInfo()), distanceCalculator(new DistanceCalculator(*codeGraphInfo)), targetCalculator(new TargetCalculator(*codeGraphInfo)), targetManager(new TargetManager(guidanceKind, *distanceCalculator, @@ -522,10 +495,15 @@ Executor::Executor(LLVMContext &ctx, const InterpreterOptions &opts, inhibitForking(false), coverOnTheFly(false), haltExecution(HaltExecution::NotHalt), ivcEnabled(false), debugLogBuffer(debugBufferString) { - if (CoreSolverToUse != Z3_SOLVER && - interpreterOpts.MockStrategy == MockStrategy::Deterministic) { + if (interpreterOpts.MockStrategy == MockStrategyKind::Deterministic && + CoreSolverToUse != Z3_SOLVER) { klee_error("Deterministic mocks can be generated with Z3 solver only.\n"); } + if (interpreterOpts.MockStrategy == MockStrategyKind::Deterministic && + interpreterOpts.Mock != MockPolicy::All) { + klee_error("Deterministic mocks can be generated only with " + "`--mock-policy=all`.\n"); + } const time::Span maxTime{MaxTime}; if (maxTime) @@ -595,21 +573,10 @@ llvm::Module *Executor::setModule( const ModuleOptions &opts, std::set &&mainModuleFunctions, std::set &&mainModuleGlobals, FLCtoOpcode &&origInstructions, const std::set &ignoredExternals, - const Annotations &annotations) { + std::vector> redefinitions) { assert(!kmodule && !userModules.empty() && "can only register one module"); // XXX gross - if (ExternalCalls == ExternalCallPolicy::All && - interpreterOpts.MockStrategy != MockStrategy::None) { - llvm::Function *mainFn = - userModules.front()->getFunction(opts.MainCurrentName); - if (!mainFn) { - klee_error("Entry function '%s' not found in module.", - opts.MainCurrentName.c_str()); - } - mainFn->setName(opts.MainNameAfterMock); - } - kmodule = std::make_unique(); // 1.) Link the modules together && 2.) Apply different instrumentation @@ -634,28 +601,19 @@ llvm::Module *Executor::setModule( kmodule->instrument(opts); } - if (ExternalCalls == ExternalCallPolicy::All && - interpreterOpts.MockStrategy != MockStrategy::None) { - // TODO: move this to function - std::map externals = - getAllExternals(ignoredExternals); - MockBuilder builder(kmodule->module.get(), opts.MainCurrentName, - opts.MainNameAfterMock, externals, annotations); - std::unique_ptr mockModule = builder.build(); - if (!mockModule) { - klee_error("Unable to generate mocks"); - } - // TODO: change this to bc file - std::unique_ptr f( - interpreterHandler->openOutputFile("externals.ll")); - auto mainFn = mockModule->getFunction(opts.MainCurrentName); - mainFn->setName(opts.EntryPoint); - *f << *mockModule; - mainFn->setName(opts.MainCurrentName); + if (interpreterOpts.Mock == MockPolicy::All || + interpreterOpts.MockMutableGlobals == MockMutableGlobalsPolicy::All || + !opts.AnnotationsFile.empty()) { + MockBuilder mockBuilder(kmodule->module.get(), opts, interpreterOpts, + ignoredExternals, redefinitions, interpreterHandler, + mainModuleFunctions, mainModuleGlobals); + std::unique_ptr mockModule = mockBuilder.build(); std::vector> mockModules; mockModules.push_back(std::move(mockModule)); - kmodule->link(mockModules, 0); + // std::swap(mockModule, kmodule->module); + kmodule->link(mockModules, 1); + klee_message("Mock linkage: done"); for (auto &global : kmodule->module->globals()) { if (global.isDeclaration()) { @@ -732,37 +690,6 @@ llvm::Module *Executor::setModule( return kmodule->module.get(); } -std::map -Executor::getAllExternals(const std::set &ignoredExternals) { - std::map externals; - for (const auto &f : kmodule->module->functions()) { - if (f.isDeclaration() && !f.use_empty() && - !ignoredExternals.count(f.getName().str())) - // NOTE: here we detect all the externals, even linked. - externals.insert(std::make_pair(f.getName(), f.getFunctionType())); - } - - for (const auto &global : kmodule->module->globals()) { - if (global.isDeclaration() && - !ignoredExternals.count(global.getName().str())) - externals.insert(std::make_pair(global.getName(), global.getValueType())); - } - - for (const auto &alias : kmodule->module->aliases()) { - auto it = externals.find(alias.getName().str()); - if (it != externals.end()) { - externals.erase(it); - } - } - - for (const auto &e : externals) { - klee_message("Mocking external %s %s", - e.second->isFunctionTy() ? "function" : "variable", - e.first.c_str()); - } - return externals; -} - Executor::~Executor() { delete typeSystemManager; delete externalDispatcher; @@ -1098,11 +1025,7 @@ void Executor::initializeGlobalObjects(ExecutionState &state) { } else { addr = externalDispatcher->resolveSymbol(v.getName().str()); } - if (MockAllExternals && !addr) { - executeMakeSymbolic( - state, mo, typeSystemManager->getWrappedType(v.getType()), - SourceBuilder::irreproducible("mockExternGlobalObject"), false); - } else if (!addr) { + if (!addr) { klee_error("Unable to load symbol(%.*s) while initializing globals", static_cast(v.getName().size()), v.getName().data()); } else { @@ -1116,18 +1039,11 @@ void Executor::initializeGlobalObjects(ExecutionState &state) { SourceBuilder::irreproducible("unsizedGlobal"), false); } } else if (v.hasInitializer()) { - if (!v.isConstant() && kmodule->inMainModule(v) && - MockMutableGlobals == MockMutableGlobalsPolicy::All) { - executeMakeSymbolic( - state, mo, typeSystemManager->getWrappedType(v.getType()), - SourceBuilder::irreproducible("mockMutableGlobalObject"), false); - } else { - initializeGlobalObject(state, os, v.getInitializer(), 0); - if (v.isConstant()) { - os->setReadOnly(true); - // initialise constant memory that may be used with external calls - state.addressSpace.copyOutConcrete(mo, os, {}); - } + initializeGlobalObject(state, os, v.getInitializer(), 0); + if (v.isConstant()) { + os->setReadOnly(true); + // initialise constant memory that may be used with external calls + state.addressSpace.copyOutConcrete(mo, os, {}); } } } @@ -3091,7 +3007,7 @@ void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) { have already got a value. But in the end the caches should handle it for us, albeit with some overhead. */ do { - if (!first && MockExternalCalls) { + if (!first && interpreterOpts.Mock == MockPolicy::Failed) { free = nullptr; if (ki->inst()->getType()->isSized()) { prepareMockValue(state, "mockExternResult", ki); @@ -5078,28 +4994,6 @@ void Executor::callExternalFunction(ExecutionState &state, KInstruction *target, return; } - if (ExternalCalls == ExternalCallPolicy::All && MockAllExternals) { - std::string TmpStr; - llvm::raw_string_ostream os(TmpStr); - os << "calling external: " << callable->getName().str() << "("; - for (unsigned i = 0; i < arguments.size(); i++) { - os << arguments[i]; - if (i != arguments.size() - 1) - os << ", "; - } - os << ") at " << state.pc->getSourceLocationString(); - - if (AllExternalWarnings) - klee_warning("%s", os.str().c_str()); - else if (!SuppressExternalWarnings) - klee_warning_once(callable->unwrap(), "%s", os.str().c_str()); - - if (target->inst()->getType()->isSized()) { - prepareMockValue(state, "mockExternResult", target); - } - return; - } - // normal external function handling path // allocate 512 bits for each argument (+return value) to support // fp80's and SIMD vectors as parameters for external calls; @@ -5218,7 +5112,7 @@ void Executor::callExternalFunction(ExecutionState &state, KInstruction *target, roundingMode); if (!success) { - if (MockExternalCalls) { + if (interpreterOpts.Mock == MockPolicy::Failed) { if (target->inst()->getType()->isSized()) { prepareMockValue(state, "mockExternResult", target); } @@ -5309,7 +5203,7 @@ ObjectState *Executor::bindObjectInState(ExecutionState &state, // will put multiple copies on this list, but it doesn't really // matter because all we use this list for is to unbind the object // on function return. - if (isLocal && state.stack.size() > 0) { + if (isLocal && !state.stack.empty()) { state.stack.valueStack().back().allocas.push_back(mo->id); } return os; @@ -6163,16 +6057,6 @@ void Executor::collectReads( result = FPToX87FP80Ext(result); } - if (MockMutableGlobals == MockMutableGlobalsPolicy::PrimitiveFields && - mo->isGlobal && !os->readOnly && isa(result) && - !targetType->getRawType()->isPointerTy()) { - result = makeMockValue(state, "mockGlobalValue", result->getWidth()); - ObjectState *wos = state.addressSpace.getWriteable(mo, os); - maxNewWriteableOSSize = - std::max(maxNewWriteableOSSize, wos->getSparseStorageEntries()); - wos->write(mo->getOffsetExpr(address), result); - } - results.push_back(result); } } @@ -6342,16 +6226,6 @@ void Executor::executeMemoryOperation( if (interpreterOpts.MakeConcreteSymbolic) result = replaceReadWithSymbolic(*state, result); - if (MockMutableGlobals == MockMutableGlobalsPolicy::PrimitiveFields && - mo->isGlobal && !os->readOnly && isa(result) && - !targetType->getRawType()->isPointerTy()) { - result = makeMockValue(*state, "mockGlobalValue", result->getWidth()); - ObjectState *wos = state->addressSpace.getWriteable(mo, os); - maxNewWriteableOSSize = - std::max(maxNewWriteableOSSize, wos->getSparseStorageEntries()); - wos->write(mo->getOffsetExpr(address), result); - } - bindLocal(target, *state, result); } @@ -6534,16 +6408,6 @@ void Executor::executeMemoryOperation( result = FPToX87FP80Ext(result); } - if (MockMutableGlobals == MockMutableGlobalsPolicy::PrimitiveFields && - mo->isGlobal && !os->readOnly && isa(result) && - !targetType->getRawType()->isPointerTy()) { - result = makeMockValue(*bound, "mockGlobalValue", result->getWidth()); - ObjectState *wos = bound->addressSpace.getWriteable(mo, os); - maxNewWriteableOSSize = - std::max(maxNewWriteableOSSize, wos->getSparseStorageEntries()); - wos->write(mo->getOffsetExpr(address), result); - } - bindLocal(target, *bound, result); } } @@ -6831,48 +6695,6 @@ void Executor::executeMakeSymbolic(ExecutionState &state, } } -void Executor::executeMakeMock(ExecutionState &state, KInstruction *target, - std::vector> &arguments) { - KFunction *kf = target->parent->parent; - std::string name = "@call_" + kf->getName().str(); - uint64_t width = - kmodule->targetData->getTypeSizeInBits(kf->function->getReturnType()); - KType *type = typeSystemManager->getWrappedType( - llvm::PointerType::get(kf->function->getReturnType(), - kmodule->targetData->getAllocaAddrSpace())); - - IDType moID; - bool success = state.addressSpace.resolveOne(cast(arguments[0]), - type, moID); - assert(success && "memory object for mock should already be allocated"); - const MemoryObject *mo = state.addressSpace.findObject(moID).first; - assert(mo && "memory object for mock should already be allocated"); - mo->setName(name); - - ref source; - switch (interpreterOpts.MockStrategy) { - case MockStrategy::None: - klee_error("klee_make_mock is not allowed when mock strategy is none"); - break; - case MockStrategy::Naive: - source = SourceBuilder::mockNaive(kmodule.get(), *kf->function, - updateNameVersion(state, name)); - break; - case MockStrategy::Deterministic: - std::vector> args(kf->numArgs); - for (size_t i = 0; i < kf->numArgs; i++) { - args[i] = getArgumentCell(state, kf, i).value; - } - source = - SourceBuilder::mockDeterministic(kmodule.get(), *kf->function, args); - break; - } - executeMakeSymbolic(state, mo, type, source, false); - const ObjectState *os = state.addressSpace.findObject(mo->id).second; - auto result = os->read(0, width); - bindLocal(target, state, result); -} - /***/ ExecutionState *Executor::formState(Function *f) { diff --git a/lib/Core/Executor.h b/lib/Core/Executor.h index f0c53a8da4..d6cbb17352 100644 --- a/lib/Core/Executor.h +++ b/lib/Core/Executor.h @@ -428,9 +428,6 @@ class Executor : public Interpreter { KType *type, const ref source, bool isLocal); - void executeMakeMock(ExecutionState &state, KInstruction *target, - std::vector> &arguments); - void updateStateWithSymcretes(ExecutionState &state, const Assignment &assignment); @@ -732,18 +729,13 @@ class Executor : public Interpreter { replayPosition = 0; } - llvm::Module * - setModule(std::vector> &userModules, - std::vector> &libsModules, - const ModuleOptions &opts, - std::set &&mainModuleFunctions, - std::set &&mainModuleGlobals, - FLCtoOpcode &&origInstructions, - const std::set &ignoredExternals, - const Annotations &annotations) override; - - std::map - getAllExternals(const std::set &ignoredExternals) override; + llvm::Module *setModule( + std::vector> &userModules, + std::vector> &libsModules, + const ModuleOptions &opts, std::set &&mainModuleFunctions, + std::set &&mainModuleGlobals, FLCtoOpcode &&origInstructions, + const std::set &ignoredExternals, + std::vector> redefinitions) override; void useSeeds(const std::vector *seeds) override { usingSeeds = seeds; diff --git a/lib/Core/MockBuilder.cpp b/lib/Core/MockBuilder.cpp index 0545c34115..de06f5e463 100644 --- a/lib/Core/MockBuilder.cpp +++ b/lib/Core/MockBuilder.cpp @@ -1,224 +1,672 @@ +//===-- MockBuilder.cpp ---------------------------------------------------===// +// +// The KLEEF Symbolic Virtual Machine +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +//===----------------------------------------------------------------------===// + #include "klee/Core/MockBuilder.h" +#include "klee/Config/Version.h" #include "klee/Module/Annotation.h" #include "klee/Support/ErrorHandling.h" +#include "klee/Support/ModuleUtil.h" + #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Module.h" +#include "llvm/Support/raw_ostream.h" #include #include namespace klee { -MockBuilder::MockBuilder(const llvm::Module *initModule, - std::string mockEntrypoint, std::string userEntrypoint, - std::map externals, - Annotations annotations) - : userModule(initModule), externals(std::move(externals)), - annotations(std::move(annotations)), - mockEntrypoint(std::move(mockEntrypoint)), - userEntrypoint(std::move(userEntrypoint)) {} +template +void inline removeAliases(const llvm::Module *userModule, + std::map &externals) { + for (const auto &alias : userModule->aliases()) { + auto it = externals.find(alias.getName().str()); + if (it != externals.end()) { + externals.erase(it); + } + } +} + +void MockBuilder::buildCallKleeMakeSymbolic( + const std::string &kleeMakeSymbolicFunctionName, llvm::Value *source, + llvm::Type *type, const std::string &symbolicName) { + auto *kleeMakeSymbolicName = llvm::FunctionType::get( + llvm::Type::getVoidTy(ctx), + {llvm::Type::getInt8PtrTy(ctx), llvm::Type::getInt64Ty(ctx), + llvm::Type::getInt8PtrTy(ctx)}, + false); + auto kleeMakeSymbolicCallee = mockModule->getOrInsertFunction( + kleeMakeSymbolicFunctionName, kleeMakeSymbolicName); + auto bitCastInst = + builder->CreateBitCast(source, llvm::Type::getInt8PtrTy(ctx)); + auto globalSymbolicName = builder->CreateGlobalString("@" + symbolicName); + auto gep = builder->CreateConstInBoundsGEP2_64( + globalSymbolicName->getValueType(), globalSymbolicName, 0, 0); + auto sz = llvm::APInt(64, mockModule->getDataLayout().getTypeStoreSize(type), + false); + builder->CreateCall(kleeMakeSymbolicCallee, + {bitCastInst, llvm::ConstantInt::get(ctx, sz), gep}); +} + +std::map +MockBuilder::getExternalFunctions() { + std::map externals; + for (const auto &f : userModule->functions()) { + if (f.isDeclaration() && !f.use_empty() && + !ignoredExternals.count(f.getName().str())) { + // NOTE: here we detect all the externals, even linked. + externals.insert(std::make_pair(f.getName(), f.getFunctionType())); + } + } + removeAliases(userModule, externals); + + return externals; +} + +std::map MockBuilder::getExternalGlobals() { + std::map externals; + for (const auto &global : userModule->globals()) { + if (global.isDeclaration() && + !ignoredExternals.count(global.getName().str())) { + externals.insert(std::make_pair(global.getName(), global.getType())); + } + } + removeAliases(userModule, externals); + return externals; +} + +MockBuilder::MockBuilder( + const llvm::Module *initModule, const Interpreter::ModuleOptions &opts, + const Interpreter::InterpreterOptions &interpreterOptions, + const std::set &ignoredExternals, + std::vector> &redefinitions, + InterpreterHandler *interpreterHandler, + std::set &mainModuleFunctions, + std::set &mainModuleGlobals) + : userModule(initModule), ctx(initModule->getContext()), opts(opts), + interpreterOptions(interpreterOptions), + ignoredExternals(ignoredExternals), redefinitions(redefinitions), + interpreterHandler(interpreterHandler), + mainModuleFunctions(mainModuleFunctions), + mainModuleGlobals(mainModuleGlobals) { + annotations = parseAnnotations(opts.AnnotationsFile); +} std::unique_ptr MockBuilder::build() { initMockModule(); buildMockMain(); buildExternalFunctionsDefinitions(); + + if (!mockModule) { + klee_error("Unable to generate mocks"); + } + + { + const std::string redefinitionsFileName = "redefinitions.txt"; + auto os(interpreterHandler->openOutputFile(redefinitionsFileName)); + if (!os) { + klee_error("Mock: can't open %s file", redefinitionsFileName.c_str()); + } + for (const auto &i : redefinitions) { + *os << i.first << " " << i.second << "\n"; + } + } + + const std::string externalsFileName = "externals.ll"; + std::string extFile = + interpreterHandler->getOutputFilename(externalsFileName); + + { + auto mainFn = mockModule->getFunction(opts.MainCurrentName); + mainFn->setName(opts.EntryPoint); + auto os = interpreterHandler->openOutputFile(externalsFileName); + if (!os) { + klee_error("Mock: can't open '%s' file", externalsFileName.c_str()); + } + *os << *mockModule; + mockModule.reset(); + } + + { + std::string errorMsg; + std::vector> loadedUserModules; + loadFileAsOneModule(extFile, ctx, loadedUserModules, errorMsg); + std::swap(loadedUserModules.front(), mockModule); + + auto mainFn = mockModule->getFunction(opts.MainCurrentName); + mainFn->setName(opts.MainCurrentName); + } + return std::move(mockModule); } void MockBuilder::initMockModule() { - mockModule = std::make_unique(userModule->getName().str() + - "__klee_externals", - userModule->getContext()); + mockModule = std::make_unique( + userModule->getName().str() + "__klee_externals", ctx); mockModule->setTargetTriple(userModule->getTargetTriple()); mockModule->setDataLayout(userModule->getDataLayout()); - builder = std::make_unique>(mockModule->getContext()); + builder = std::make_unique>(ctx); } // Set up entrypoint in new module. Here we'll define external globals and then // call user's entrypoint. void MockBuilder::buildMockMain() { - llvm::Function *userMainFn = userModule->getFunction(userEntrypoint); + mainModuleFunctions.insert(opts.MainNameAfterMock); + llvm::Function *userMainFn = userModule->getFunction(opts.MainCurrentName); if (!userMainFn) { klee_error("Entry function '%s' not found in module.", - userEntrypoint.c_str()); + opts.MainCurrentName.c_str()); } - mockModule->getOrInsertFunction(mockEntrypoint, userMainFn->getFunctionType(), + userMainFn->setName(opts.MainNameAfterMock); + + mockModule->getOrInsertFunction(opts.MainCurrentName, + userMainFn->getFunctionType(), userMainFn->getAttributes()); - llvm::Function *mockMainFn = mockModule->getFunction(mockEntrypoint); + llvm::Function *mockMainFn = mockModule->getFunction(opts.MainCurrentName); if (!mockMainFn) { - klee_error("Entry function '%s' not found in module.", - mockEntrypoint.c_str()); + klee_error("Mock: Entry function '%s' not found in module", + opts.MainCurrentName.c_str()); } - auto globalsInitBlock = - llvm::BasicBlock::Create(mockModule->getContext(), "entry", mockMainFn); + mockMainFn->setDSOLocal(true); + auto globalsInitBlock = llvm::BasicBlock::Create(ctx, "", mockMainFn); builder->SetInsertPoint(globalsInitBlock); // Define all the external globals - buildExternalGlobalsDefinitions(); + if (interpreterOptions.Mock == MockPolicy::All || + interpreterOptions.MockMutableGlobals == MockMutableGlobalsPolicy::All) { + buildExternalGlobalsDefinitions(); + } auto userMainCallee = mockModule->getOrInsertFunction( - userEntrypoint, userMainFn->getFunctionType()); + opts.MainNameAfterMock, userMainFn->getFunctionType()); std::vector args; args.reserve(userMainFn->arg_size()); - for (auto it = mockMainFn->arg_begin(); it != mockMainFn->arg_end(); it++) { - args.push_back(it); + for (auto &arg : mockMainFn->args()) { + args.push_back(&arg); } + auto callUserMain = builder->CreateCall(userMainCallee, args); - builder->CreateRet(callUserMain); + if (!userMainFn->getReturnType()->isSized()) { + builder->CreateRet(nullptr); + return; + } else { + builder->CreateRet(callUserMain); + } } void MockBuilder::buildExternalGlobalsDefinitions() { - for (const auto &it : externals) { - if (it.second->isFunctionTy()) { - continue; - } - const std::string &extName = it.first; - llvm::Type *type = it.second; - mockModule->getOrInsertGlobal(extName, type); - auto *global = mockModule->getGlobalVariable(extName); + auto externalGlobals = getExternalGlobals(); + for (const auto &[extName, type] : externalGlobals) { + auto elementType = type->getPointerElementType(); + klee_message("Mocking external variable %s", extName.c_str()); + llvm::GlobalVariable *global = dyn_cast_or_null( + mockModule->getOrInsertGlobal(extName, elementType)); if (!global) { - klee_error("Unable to add global variable '%s' to module", + klee_error("Mock: Unable to add global variable '%s' to module", extName.c_str()); } - global->setLinkage(llvm::GlobalValue::ExternalLinkage); - if (!type->isSized()) { + + mainModuleGlobals.insert(extName); + if (!elementType->isSized()) { continue; } - auto *zeroInitializer = llvm::Constant::getNullValue(it.second); + auto *zeroInitializer = llvm::GlobalValue::getNullValue(elementType); if (!zeroInitializer) { - klee_error("Unable to get zero initializer for '%s'", extName.c_str()); + klee_error("Mock: Unable to get zero initializer for '%s'", + extName.c_str()); } global->setInitializer(zeroInitializer); - buildCallKleeMakeSymbol("klee_make_symbolic", global, type, - "@obj_" + extName); + global->setDSOLocal(true); + auto *localPointer = builder->CreateAlloca(elementType, nullptr); + buildCallKleeMakeSymbolic("klee_make_symbolic", localPointer, elementType, + "external_" + extName); + llvm::Value *localValue = builder->CreateLoad(elementType, localPointer); + builder->CreateStore(localValue, global); } } +// standard functions that must be ignored +const std::set StandartIgnoredFunctions = { + "_ZNSt8ios_base4InitC1Ev", "_ZNSt8ios_base4InitD1Ev"}; + void MockBuilder::buildExternalFunctionsDefinitions() { - for (const auto &it : externals) { - if (!it.second->isFunctionTy()) { - continue; + std::map externalFunctions; + if (interpreterOptions.Mock == MockPolicy::All) { + externalFunctions = getExternalFunctions(); + } + + if (!opts.AnnotateOnlyExternal) { + for (const auto &annotation : annotations) { + llvm::Function *func = userModule->getFunction(annotation.first); + if (func) { + auto ext = externalFunctions.find(annotation.first); + if (ext == externalFunctions.end()) { + externalFunctions[annotation.first] = func->getFunctionType(); + } + } } - std::string extName = it.first; - auto *type = llvm::cast(it.second); + } + + for (const auto &[extName, type] : externalFunctions) { mockModule->getOrInsertFunction(extName, type); llvm::Function *func = mockModule->getFunction(extName); if (!func) { - klee_error("Unable to find function '%s' in module", extName.c_str()); + klee_error("Mock: Unable to find function '%s' in module", + extName.c_str()); + } + if (func->isIntrinsic()) { + klee_message("Mock: Skip intrinsic function '%s'", extName.c_str()); + continue; + } + if (StandartIgnoredFunctions.count(extName)) { + klee_message("Mock: Skip function '%s'", extName.c_str()); + continue; } + mainModuleFunctions.insert(extName); if (!func->empty()) { continue; } - auto *BB = - llvm::BasicBlock::Create(mockModule->getContext(), "entry", func); + auto *BB = llvm::BasicBlock::Create(ctx, "entry", func); builder->SetInsertPoint(BB); - if (!func->getReturnType()->isSized()) { - builder->CreateRet(nullptr); - continue; + const auto nameToAnnotations = annotations.find(extName); + if (nameToAnnotations != annotations.end()) { + klee_message("Annotation function %s", extName.c_str()); + const auto &annotation = nameToAnnotations->second; + + buildAnnotationForExternalFunctionArgs(func, annotation.argsStatements); + buildAnnotationForExternalFunctionReturn(func, + annotation.returnStatements); + buildAnnotationForExternalFunctionProperties(func, annotation.properties); + } else { + klee_message("Mocking external function %s", extName.c_str()); + // Default annotation for externals return + buildAnnotationForExternalFunctionReturn( + func, {std::make_shared()}); } + } +} - const auto annotation = annotations.find(extName); - if (annotation != annotations.end()) { - buildAnnotationForExternalFunctionParams(func, annotation->second); +std::pair +MockBuilder::goByOffset(llvm::Value *value, + const std::vector &offset) { + llvm::Value *prev = nullptr; + llvm::Value *current = value; + for (const auto &inst : offset) { + if (inst == "*") { + if (!current->getType()->isPointerTy()) { + klee_error("Incorrect annotation offset."); + } + prev = current; + current = builder->CreateLoad(current->getType()->getPointerElementType(), + current); + } else if (inst == "&") { + auto addr = builder->CreateAlloca(current->getType()); + prev = current; + current = builder->CreateStore(current, addr); + } else { + const size_t index = std::stol(inst); + if (!(current->getType()->isPointerTy() || + current->getType()->isArrayTy())) { + klee_error("Incorrect annotation offset."); + } + prev = current; + current = builder->CreateConstInBoundsGEP1_64(current->getType(), current, + index); } + } + return {prev, current}; +} - auto *mockReturnValue = - builder->CreateAlloca(func->getReturnType(), nullptr); - buildCallKleeMakeSymbol("klee_make_mock", mockReturnValue, - func->getReturnType(), "@call_" + extName); - auto *loadInst = builder->CreateLoad(mockReturnValue, "klee_var"); - builder->CreateRet(loadInst); +inline llvm::Type *getTypeByOffset(llvm::Type *value, + const std::vector &offset) { + llvm::Type *current = value; + for (const auto &inst : offset) { + if (inst == "*") { + if (!current->isPointerTy()) { + return nullptr; + } + current = current->getPointerElementType(); + } else if (inst == "&") { + // Not change + } else { + const size_t index = std::stol(inst); + if (current->isArrayTy() || current->isPointerTy()) { + current = current->getContainedType(index); + } else { + return nullptr; + } + } } + return current; } -void MockBuilder::buildCallKleeMakeSymbol(const std::string &klee_function_name, - llvm::Value *source, llvm::Type *type, - const std::string &symbol_name) { - auto *klee_mk_symb_type = llvm::FunctionType::get( - llvm::Type::getVoidTy(mockModule->getContext()), - {llvm::Type::getInt8PtrTy(mockModule->getContext()), - llvm::Type::getInt64Ty(mockModule->getContext()), - llvm::Type::getInt8PtrTy(mockModule->getContext())}, - false); - auto kleeMakeSymbolCallee = - mockModule->getOrInsertFunction(klee_function_name, klee_mk_symb_type); - auto bitcastInst = builder->CreateBitCast( - source, llvm::Type::getInt8PtrTy(mockModule->getContext())); - auto str_name = builder->CreateGlobalString(symbol_name); - auto gep = builder->CreateConstInBoundsGEP2_64(str_name, 0, 0); - builder->CreateCall( - kleeMakeSymbolCallee, - {bitcastInst, - llvm::ConstantInt::get( - mockModule->getContext(), - llvm::APInt(64, mockModule->getDataLayout().getTypeStoreSize(type), - false)), - gep}); -} - -// TODO: add method for return value of external functions. -void MockBuilder::buildAnnotationForExternalFunctionParams( - llvm::Function *func, Annotation &annotation) { - for (size_t i = 1; i < annotation.statements.size(); i++) { - const auto arg = func->getArg(i - 1); - for (const auto &statement : annotation.statements[i]) { - llvm::Value *elem = goByOffset(arg, statement->offset); - switch (statement->getStatementName()) { - case Annotation::StatementKind::Deref: { - if (!elem->getType()->isPointerTy()) { - klee_error("Incorrect annotation offset."); - } - builder->CreateLoad(elem); +inline bool isCorrectStatements(const std::vector &statements, + const llvm::Argument *arg) { + return std::any_of(statements.begin(), statements.end(), + [arg](const Statement::Ptr &statement) { + auto argType = + getTypeByOffset(arg->getType(), statement->offset); + switch (statement->getKind()) { + case Statement::Kind::Deref: + case Statement::Kind::InitNull: + return argType->isPointerTy(); + case Statement::Kind::AllocSource: + assert(false); + case Statement::Kind::Unknown: + default: + return true; + } + }); +} + +bool tryAlign(llvm::Function *func, + const std::vector> &statements, + std::vector> &res) { + if (func->arg_size() == statements.size()) { + res = statements; + return true; + } + + for (size_t i = 0, j = 0; j < func->arg_size() && i < statements.size();) { + while (true) { +#if LLVM_VERSION_CODE >= LLVM_VERSION(10, 0) + auto arg = func->getArg(j); +#else + auto arg = &func->arg_begin()[j]; +#endif + if (isCorrectStatements(statements[i], arg)) { break; } - case Annotation::StatementKind::InitNull: { - // TODO + res.emplace_back(); + j++; + if (j >= func->arg_size()) { + break; } - case Annotation::StatementKind::Unknown: - default: - __builtin_unreachable(); + } + res.push_back(statements[i]); + j++; + i++; + } + if (func->arg_size() == statements.size()) { + return true; + } + return false; +} + +std::map, std::vector> +unifyByOffset(const std::vector &statements) { + std::map, std::vector> res; + for (const auto &i : statements) { + res[i->offset].push_back(i); + } + return res; +} + +void MockBuilder::buildAnnotationForExternalFunctionArgs( + llvm::Function *func, + const std::vector> &statementsNotAlign) { + std::vector> statements; + bool flag = tryAlign(func, statementsNotAlign, statements); + if (!flag) { + klee_warning("Annotation: can't align function arguments %s", + func->getName().str().c_str()); + return; + } + for (size_t i = 0; i < statements.size(); i++) { +#if LLVM_VERSION_CODE >= LLVM_VERSION(10, 0) + const auto arg = func->getArg(i); +#else + const auto arg = &func->arg_begin()[i]; +#endif + auto statementsMap = unifyByOffset(statements[i]); + for (const auto &[offset, statementsOffset] : statementsMap) { + auto [prev, elem] = goByOffset(arg, offset); + + Statement::Alloc *allocSourcePtr = nullptr; + Statement::Free *freePtr = nullptr; + Statement::InitNull *initNullPtr = nullptr; + + for (const auto &statement : statementsOffset) { + switch (statement->getKind()) { + case Statement::Kind::Deref: { + if (!elem->getType()->isPointerTy()) { + klee_error("Annotation: Deref arg not pointer"); + } + + std::string derefCondName = "condition_deref_arg_" + + std::to_string(i) + "_deref_" + + func->getName().str(); + + auto intType = llvm::IntegerType::get(ctx, 1); + auto *derefCond = builder->CreateAlloca(intType, nullptr); + buildCallKleeMakeSymbolic("klee_make_mock", derefCond, intType, + derefCondName); + + llvm::BasicBlock *fromIf = builder->GetInsertBlock(); + llvm::Function *curFunc = fromIf->getParent(); + + llvm::BasicBlock *derefBB = + llvm::BasicBlock::Create(ctx, derefCondName, curFunc); + llvm::BasicBlock *contBB = + llvm::BasicBlock::Create(ctx, "continue_" + derefCondName); + auto brValue = builder->CreateLoad(intType, derefCond); + builder->CreateCondBr(brValue, derefBB, contBB); + + builder->SetInsertPoint(derefBB); + builder->CreateLoad(elem->getType()->getPointerElementType(), elem); + builder->CreateBr(contBB); + + curFunc->getBasicBlockList().push_back(contBB); + builder->SetInsertPoint(contBB); + break; + } + case Statement::Kind::AllocSource: { + if (prev != nullptr) { + allocSourcePtr = (Statement::Alloc *)statement.get(); + } else { + klee_message("Annotation: not valid annotation %s", + statement->toString().c_str()); + } + break; + } + case Statement::Kind::InitNull: { + if (prev != nullptr) { + initNullPtr = (Statement::InitNull *)statement.get(); + } else { + klee_message("Annotation: not valid annotation %s", + statement->toString().c_str()); + } + break; + } + case Statement::Kind::Free: { + if (elem->getType()->isPointerTy()) { + freePtr = (Statement::Free *)statement.get(); + } else { + klee_message("Annotation: not valid annotation %s", + statement->toString().c_str()); + } + break; + } + case Statement::Kind::Unknown: + default: + klee_message("Annotation: not implemented %s", + statement->toString().c_str()); + break; + } } + if (freePtr) { + buildFree(elem, freePtr); + } + processingValue(prev, elem->getType(), allocSourcePtr, initNullPtr); } } +} - for (const auto &property : annotation.properties) { - switch (property) { - case Annotation::Property::Determ: { - // TODO +void MockBuilder::processingValue(llvm::Value *prev, llvm::Type *elemType, + const Statement::Alloc *allocSourcePtr, + bool initNullPtr) { + if (initNullPtr) { + auto intType = llvm::IntegerType::get(ctx, 1); + auto *allocCond = builder->CreateAlloca(intType, nullptr); + buildCallKleeMakeSymbolic("klee_make_mock", allocCond, intType, + "initPtrCond"); + + llvm::BasicBlock *fromIf = builder->GetInsertBlock(); + llvm::Function *curFunc = fromIf->getParent(); + + llvm::BasicBlock *initNullBB = llvm::BasicBlock::Create(ctx, "initNullBR"); + llvm::BasicBlock *contBB = llvm::BasicBlock::Create(ctx, "continueBR"); + auto brValue = builder->CreateLoad(intType, allocCond); + if (allocSourcePtr) { + llvm::BasicBlock *allocBB = + llvm::BasicBlock::Create(ctx, "allocArg", curFunc); + builder->CreateCondBr(brValue, allocBB, initNullBB); + builder->SetInsertPoint(allocBB); + buildAllocSource(prev, elemType, allocSourcePtr); + builder->CreateBr(contBB); + } else { + builder->CreateCondBr(brValue, initNullBB, contBB); + } + curFunc->getBasicBlockList().push_back(initNullBB); + builder->SetInsertPoint(initNullBB); + builder->CreateStore( + llvm::ConstantPointerNull::get(llvm::cast(elemType)), + prev); + builder->CreateBr(contBB); + + curFunc->getBasicBlockList().push_back(contBB); + builder->SetInsertPoint(contBB); + } else if (allocSourcePtr) { + buildAllocSource(prev, elemType, allocSourcePtr); + } +} + +void MockBuilder::buildAllocSource(llvm::Value *prev, llvm::Type *elemType, + const Statement::Alloc *allocSourcePtr) { + if (allocSourcePtr->value != Statement::Alloc::ALLOC) { + klee_warning("Annotation: AllocSource \"%d\" not implemented use alloc", + allocSourcePtr->value); + } + auto valueType = elemType->getPointerElementType(); + auto sizeValue = llvm::ConstantInt::get( + ctx, + llvm::APInt(64, mockModule->getDataLayout().getTypeStoreSize(valueType), + false)); + auto int8PtrTy = llvm::IntegerType::getInt64Ty(ctx); + auto mallocInstr = + llvm::CallInst::CreateMalloc(builder->GetInsertBlock(), int8PtrTy, + valueType, sizeValue, nullptr, nullptr); + auto mallocValue = builder->Insert(mallocInstr, llvm::Twine("MallocValue")); + builder->CreateStore(mallocValue, prev); +} + +void MockBuilder::buildFree(llvm::Value *elem, const Statement::Free *freePtr) { + if (freePtr->value != Statement::Free::FREE) { + klee_warning("Annotation: AllocSource \"%d\" not implemented use free", + freePtr->value); + } + auto freeInstr = llvm::CallInst::CreateFree(elem, builder->GetInsertBlock()); + builder->Insert(freeInstr); +} + +void MockBuilder::buildAnnotationForExternalFunctionReturn( + llvm::Function *func, const std::vector &statements) { + auto returnType = func->getReturnType(); + if (!returnType->isSized()) { // void return type + builder->CreateRet(nullptr); + return; + } + + Statement::Alloc *allocSourcePtr = nullptr; + Statement::InitNull *mustInitNull = nullptr; + Statement::MaybeInitNull *maybeInitNull = nullptr; + + for (const auto &statement : statements) { + switch (statement->getKind()) { + case Statement::Kind::Deref: + klee_warning("Annotation: unused Deref for return function \"%s\"", + func->getName().str().c_str()); + break; + case Statement::Kind::AllocSource: { + allocSourcePtr = returnType->isPointerTy() + ? (Statement::Alloc *)statement.get() + : nullptr; + break; + } + case Statement::Kind::InitNull: { + mustInitNull = returnType->isPointerTy() + ? (Statement::InitNull *)statement.get() + : nullptr; + break; + } + case Statement::Kind::MaybeInitNull: { + maybeInitNull = returnType->isPointerTy() + ? (Statement::MaybeInitNull *)statement.get() + : nullptr; + break; } - case Annotation::Property::Noreturn: { - // TODO + case Statement::Kind::Free: { + klee_warning("Annotation: unused \"Free\" for return"); + break; } - case Annotation::Property::Unknown: + case Statement::Kind::Unknown: default: - __builtin_unreachable(); + klee_message("Annotation: not implemented %s", + statement->toString().c_str()); + break; } } + std::string retName = "ret_" + func->getName().str(); + llvm::Value *retValuePtr = builder->CreateAlloca(returnType, nullptr); + + if (returnType->isPointerTy() && (allocSourcePtr || mustInitNull)) { + processingValue(retValuePtr, returnType, allocSourcePtr, + mustInitNull || maybeInitNull); + } else { + buildCallKleeMakeSymbolic("klee_make_mock", retValuePtr, returnType, + func->getName().str()); + if (returnType->isPointerTy() && !maybeInitNull) { + llvm::Value *retValue = + builder->CreateLoad(returnType, retValuePtr, retName); + auto cmpResult = + builder->CreateICmpNE(retValue, + llvm::ConstantPointerNull::get( + llvm::cast(returnType)), + "condition_init_null" + retName); + + auto *kleeAssumeType = llvm::FunctionType::get( + llvm::Type::getVoidTy(ctx), {llvm::Type::getInt64Ty(ctx)}, false); + + auto kleeAssumeFunc = + mockModule->getOrInsertFunction("klee_assume", kleeAssumeType); + auto cmpResult64 = + builder->CreateZExt(cmpResult, llvm::Type::getInt64Ty(ctx)); + builder->CreateCall(kleeAssumeFunc, {cmpResult64}); + } + } + llvm::Value *retValue = builder->CreateLoad(returnType, retValuePtr, retName); + builder->CreateRet(retValue); } -llvm::Value *MockBuilder::goByOffset(llvm::Value *value, - const std::vector &offset) { - llvm::Value *current = value; - for (const auto &inst : offset) { - if (inst == "*") { - if (!current->getType()->isPointerTy()) { - klee_error("Incorrect annotation offset."); - } - current = builder->CreateLoad(current); - } else if (inst == "&") { - auto addr = builder->CreateAlloca(current->getType()); - current = builder->CreateStore(current, addr); - } else { - const size_t index = std::stol(inst); - if (!(current->getType()->isPointerTy() || current->getType()->isArrayTy())) { - klee_error("Incorrect annotation offset."); - } - current = builder->CreateConstInBoundsGEP1_64(current, index); +void MockBuilder::buildAnnotationForExternalFunctionProperties( + llvm::Function *func, const std::set &properties) { + for (const auto &property : properties) { + switch (property) { + case Statement::Property::Deterministic: + case Statement::Property::Noreturn: + case Statement::Property::Unknown: + default: + klee_message("Property not implemented"); + break; } } - return current; } } // namespace klee diff --git a/lib/Core/SpecialFunctionHandler.cpp b/lib/Core/SpecialFunctionHandler.cpp index 4690a1d1e1..ae4a7b358c 100644 --- a/lib/Core/SpecialFunctionHandler.cpp +++ b/lib/Core/SpecialFunctionHandler.cpp @@ -952,12 +952,67 @@ void SpecialFunctionHandler::handleMakeMock(ExecutionState &state, name = arguments[2]->isZero() ? "" : readStringAtAddress(state, arguments[2]); - if (name.length() == 0) { + if (name.empty()) { executor.terminateStateOnUserError( state, "Empty name of function in klee_make_mock"); return; } - executor.executeMakeMock(state, target, arguments); + + KFunction *kf = target->parent->parent; + + Executor::ExactResolutionList rl; + executor.resolveExact(state, arguments[0], + executor.typeSystemManager->getUnknownType(), rl, + "make_symbolic"); + + for (auto &it : rl) { + ObjectPair op = it.second->addressSpace.findObject(it.first); + const MemoryObject *mo = op.first; + mo->setName(name); + mo->updateTimestamp(); + + const ObjectState *old = op.second; + ExecutionState *s = it.second; + + if (old->readOnly) { + executor.terminateStateOnUserError( + *s, "cannot make readonly object symbolic"); + return; + } + + bool res; + bool success __attribute__((unused)) = executor.solver->mustBeTrue( + s->constraints.cs(), + EqExpr::create( + ZExtExpr::create(arguments[1], Context::get().getPointerWidth()), + mo->getSizeExpr()), + res, s->queryMetaData); + assert(success && "FIXME: Unhandled solver failure"); + + if (res) { + ref source; + switch (executor.interpreterOpts.MockStrategy) { + case MockStrategyKind::Naive: + source = + SourceBuilder::mockNaive(executor.kmodule.get(), *kf->function(), + executor.updateNameVersion(state, name)); + break; + case MockStrategyKind::Deterministic: + std::vector> args(kf->getNumArgs()); + for (size_t i = 0; i < kf->getNumArgs(); i++) { + args[i] = executor.getArgumentCell(state, kf, i).value; + } + source = SourceBuilder::mockDeterministic(executor.kmodule.get(), + *kf->function(), args); + break; + } + executor.executeMakeSymbolic(state, mo, old->getDynamicType(), source, + false); + } else { + executor.terminateStateOnUserError(*s, + "Wrong size given to klee_make_mock"); + } + } } void SpecialFunctionHandler::handleMarkGlobal( diff --git a/lib/Expr/AlphaBuilder.cpp b/lib/Expr/AlphaBuilder.cpp index 13fb00073f..3056503669 100644 --- a/lib/Expr/AlphaBuilder.cpp +++ b/lib/Expr/AlphaBuilder.cpp @@ -19,8 +19,18 @@ const Array *AlphaBuilder::visitArray(const Array *arr) { if (!reverse && alphaArrayMap.find(arr) == alphaArrayMap.end()) { ref source = arr->source; ref size = visit(arr->getSize()); - - if (!arr->isConstantArray()) { + if (ref mockSource = + dyn_cast_or_null(source)) { + std::vector> args; + for (const auto &it : mockSource->args) { + args.push_back(visit(it)); + } + source = SourceBuilder::mockDeterministic(mockSource->km, + mockSource->function, args); + alphaArrayMap[arr] = arrayCache.CreateArray( + size, source, arr->getDomain(), arr->getRange()); + reverseAlphaArrayMap[alphaArrayMap[arr]] = arr; + } else if (!arr->isConstantArray()) { source = SourceBuilder::alpha(index); index++; alphaArrayMap[arr] = arrayCache.CreateArray( @@ -69,9 +79,9 @@ ExprVisitor::Action AlphaBuilder::visitRead(const ReadExpr &re) { AlphaBuilder::AlphaBuilder(ArrayCache &_arrayCache) : arrayCache(_arrayCache) {} -constraints_ty AlphaBuilder::visitConstraints(constraints_ty cs) { +constraints_ty AlphaBuilder::visitConstraints(const constraints_ty &cs) { constraints_ty result; - for (auto arg : cs) { + for (const auto &arg : cs) { ref v = visit(arg); reverseExprMap[v] = arg; reverseExprMap[Expr::createIsZero(v)] = Expr::createIsZero(arg); @@ -79,6 +89,7 @@ constraints_ty AlphaBuilder::visitConstraints(constraints_ty cs) { } return result; } + ref AlphaBuilder::build(ref v) { ref e = visit(v); reverseExprMap[e] = v; diff --git a/lib/Expr/IndependentSet.cpp b/lib/Expr/IndependentSet.cpp index 50ac99942c..9ff427baf7 100644 --- a/lib/Expr/IndependentSet.cpp +++ b/lib/Expr/IndependentSet.cpp @@ -9,10 +9,8 @@ #include "klee/Expr/SymbolicSource.h" #include "klee/Expr/Symcrete.h" #include "klee/Module/KModule.h" -#include "klee/Solver/Solver.h" #include -#include #include #include #include @@ -270,13 +268,11 @@ bool IndependentConstraintSet::intersects( if (it2 != b->elements.end()) { if (it->second.intersects(it2->second)) { return true; + } } - } - for (std::set::iterator it = uninterpretedFunctions.begin(), - ie = uninterpretedFunctions.end(); - it != ie; ++it) { - if (b.uninterpretedFunctions.count(*it)) { - return true; + for (const auto &uFn : a->uninterpretedFunctions) { + if (b->uninterpretedFunctions.count(uFn)) { + return true; } } } diff --git a/lib/Expr/Parser.cpp b/lib/Expr/Parser.cpp index 616d7a7f4a..956f1fb876 100644 --- a/lib/Expr/Parser.cpp +++ b/lib/Expr/Parser.cpp @@ -646,7 +646,7 @@ SourceResult ParserImpl::ParseMockNaiveSource() { auto versionExpr = ParseNumber(64).get(); auto version = dyn_cast(versionExpr); assert(version); - return SourceBuilder::mockNaive(km, *kf->function, version->getZExtValue()); + return SourceBuilder::mockNaive(km, *kf->function(), version->getZExtValue()); } SourceResult ParserImpl::ParseMockDeterministicSource() { @@ -655,8 +655,8 @@ SourceResult ParserImpl::ParseMockDeterministicSource() { ConsumeExpectedToken(Token::Identifier); ConsumeLParen(); std::vector> args; - args.reserve(kf->numArgs); - for (unsigned i = 0; i < kf->numArgs; i++) { + args.reserve(kf->getNumArgs()); + for (unsigned i = 0; i < kf->getNumArgs(); i++) { auto expr = ParseExpr(TypeResult()); if (!expr.isValid()) { return {false, nullptr}; @@ -664,7 +664,7 @@ SourceResult ParserImpl::ParseMockDeterministicSource() { args.push_back(expr.get()); } ConsumeRParen(); - return SourceBuilder::mockDeterministic(km, *kf->function, args); + return SourceBuilder::mockDeterministic(km, *kf->function(), args); } SourceResult ParserImpl::ParseAlphaSource() { diff --git a/lib/Expr/SourceBuilder.cpp b/lib/Expr/SourceBuilder.cpp index 36193d3433..47f5fdd823 100644 --- a/lib/Expr/SourceBuilder.cpp +++ b/lib/Expr/SourceBuilder.cpp @@ -116,7 +116,6 @@ SourceBuilder::mockDeterministic(const KModule *km, return r; } - ref SourceBuilder::alpha(int _index) { ref r(new AlphaSource(_index)); r->computeHash(); diff --git a/lib/Expr/SymbolicSource.cpp b/lib/Expr/SymbolicSource.cpp index a32287784d..a1ea9a0de0 100644 --- a/lib/Expr/SymbolicSource.cpp +++ b/lib/Expr/SymbolicSource.cpp @@ -1,6 +1,5 @@ #include "klee/Expr/SymbolicSource.h" #include "klee/Expr/Expr.h" - #include "klee/Expr/ExprPPrinter.h" #include "klee/Expr/ExprUtil.h" #include "klee/Module/KInstruction.h" @@ -204,7 +203,7 @@ unsigned InstructionSource::computeHash() { unsigned MockNaiveSource::computeHash() { unsigned res = (getKind() * SymbolicSource::MAGIC_HASH_CONSTANT) + version; - unsigned funcID = km->functionIDMap.at(&function); + unsigned funcID = km->getFunctionId(&function); res = (res * SymbolicSource::MAGIC_HASH_CONSTANT) + funcID; hashValue = res; return res; @@ -215,14 +214,14 @@ int MockNaiveSource::internalCompare(const SymbolicSource &b) const { return getKind() < b.getKind() ? -1 : 1; } const MockNaiveSource &mnb = static_cast(b); - if (version != mnb.version) { - return version < mnb.version ? -1 : 1; - } - unsigned funcID = km->functionIDMap.at(&function); - unsigned bFuncID = mnb.km->functionIDMap.at(&mnb.function); + unsigned funcID = km->getFunctionId(&function); + unsigned bFuncID = mnb.km->getFunctionId(&mnb.function); if (funcID != bFuncID) { return funcID < bFuncID ? -1 : 1; } + if (version != mnb.version) { + return version < mnb.version ? -1 : 1; + } return 0; } @@ -234,7 +233,7 @@ MockDeterministicSource::MockDeterministicSource( unsigned MockDeterministicSource::computeHash() { unsigned res = getKind(); res = (res * SymbolicSource::MAGIC_HASH_CONSTANT) + - km->functionIDMap.at(&function); + km->getFunctionId(&function); for (const auto &arg : args) { res = (res * SymbolicSource::MAGIC_HASH_CONSTANT) + arg->hash(); } @@ -248,8 +247,8 @@ int MockDeterministicSource::internalCompare(const SymbolicSource &b) const { } const MockDeterministicSource &mdb = static_cast(b); - unsigned funcID = km->functionIDMap.at(&function); - unsigned bFuncID = mdb.km->functionIDMap.at(&mdb.function); + unsigned funcID = km->getFunctionId(&function); + unsigned bFuncID = mdb.km->getFunctionId(&mdb.function); if (funcID != bFuncID) { return funcID < bFuncID ? -1 : 1; } diff --git a/lib/Module/Annotation.cpp b/lib/Module/Annotation.cpp index 5c40769054..bfc4b2abf4 100644 --- a/lib/Module/Annotation.cpp +++ b/lib/Module/Annotation.cpp @@ -1,123 +1,220 @@ -#include "klee/Module/Annotation.h" +//===-- Annotation.cpp ----------------------------------------------------===// +// +// The KLEEF Symbolic Virtual Machine +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +//===----------------------------------------------------------------------===// +#include "klee/Module/Annotation.h" #include "klee/Support/ErrorHandling.h" #include - -namespace { - -using namespace klee; - -Annotation::StatementPtr toStatement(const std::string &name, - const std::string &str) { - if (name == "Deref") { - return std::make_shared(str); - } else if (name == "InitNull") { - return std::make_shared(str); - } else { - return std::make_shared(str); - } -} - -} // namespace +#include namespace klee { -Annotation::StatementUnknown::StatementUnknown(const std::string &str) - : statementStr(str) { - parseOnlyOffset(str); +static inline std::string toLower(const std::string &str) { + std::string strLower; + strLower.reserve(str.size()); + std::transform(str.begin(), str.end(), std::back_inserter(strLower), tolower); + return strLower; } -Annotation::StatementUnknown::~StatementUnknown() = default; +namespace Statement { -Annotation::StatementKind -Annotation::StatementUnknown::getStatementName() const { - return Annotation::StatementKind::Unknown; -} +Unknown::Unknown(const std::string &str) { + { + const size_t firstColonPos = str.find(':'); + const size_t startOffset = firstColonPos + 1; + const size_t secondColonPos = str.find(':', startOffset); + const size_t offsetLength = (secondColonPos == std::string::npos) + ? std::string::npos + : secondColonPos - startOffset; -bool Annotation::StatementUnknown::operator==( - const Annotation::StatementUnknown &other) const { - return (statementStr == other.statementStr) && (offset == other.offset); -} + rawAnnotation = str.substr(0, firstColonPos); + if (firstColonPos == std::string::npos) { + return; + } + rawOffset = str.substr(startOffset, offsetLength); + if (secondColonPos != std::string::npos) { + rawValue = str.substr(secondColonPos + 1, std::string::npos); + } + } -void Annotation::StatementUnknown::parseOffset(const std::string &offsetStr) { - size_t pos = 0; - while (pos < offsetStr.size()) { - if (offsetStr[pos] == '*') { + for (size_t pos = 0; pos < rawOffset.size(); pos++) { + switch (rawOffset[pos]) { + case '*': { offset.emplace_back("*"); - pos++; - } else if (offsetStr[pos] == '&') { + break; + } + case '&': { offset.emplace_back("&"); - pos++; - } else if (offsetStr[pos] == '[') { - size_t posEndExpr = offsetStr.find(']', pos); + break; + } + case '[': { + size_t posEndExpr = rawOffset.find(']', pos); if (posEndExpr == std::string::npos) { - klee_error("Incorrect annotation offset format."); + klee_error("Annotation: Incorrect offset format \"%s\"", str.c_str()); } - offset.push_back(offsetStr.substr(pos + 1, posEndExpr - 1 - pos)); - pos = posEndExpr + 1; + offset.push_back(rawOffset.substr(pos + 1, posEndExpr - 1 - pos)); + pos = posEndExpr; + break; + } + default: { + klee_warning("Annotation: Incorrect offset format \"%s\"", str.c_str()); + break; + } + } + } +} + +Unknown::~Unknown() = default; + +Kind Unknown::getKind() const { return Kind::Unknown; } + +const std::vector &Unknown::getOffset() const { return offset; } + +std::string Unknown::toString() const { + if (rawValue.empty()) { + if (rawOffset.empty()) { + return rawAnnotation; } else { - klee_error("Incorrect annotation offset format."); + return rawAnnotation + ":" + rawOffset; } } + return rawAnnotation + ":" + rawOffset + ":" + rawValue; } -void Annotation::StatementUnknown::parseOnlyOffset(const std::string &str) { - const size_t delimiterAfterName = str.find(':'); - if (delimiterAfterName == std::string::npos) { - return; - } - const size_t delimiterAfterOffset = str.find(':', delimiterAfterName + 1); - const size_t offsetLength = - (delimiterAfterOffset == std::string::npos) - ? std::string::npos - : delimiterAfterOffset - delimiterAfterName - 1; - parseOffset(str.substr(delimiterAfterName + 1, offsetLength)); +bool Unknown::operator==(const Unknown &other) const { + return this->getKind() == other.getKind() && toString() == other.toString(); } -Annotation::StatementDeref::StatementDeref(const std::string &str) - : StatementUnknown(str) {} +/* + * Format: {kind}:{offset}:{data} + * Example: InitNull:*[5]: + */ + +Deref::Deref(const std::string &str) : Unknown(str) {} + +Kind Deref::getKind() const { return Kind::Deref; } -Annotation::StatementKind Annotation::StatementDeref::getStatementName() const { - return Annotation::StatementKind::Deref; +InitNull::InitNull(const std::string &str) : Unknown(str) {} + +Kind InitNull::getKind() const { return Kind::InitNull; } + +MaybeInitNull::MaybeInitNull(const std::string &str) : Unknown(str) {} + +Kind MaybeInitNull::getKind() const { return Kind::MaybeInitNull; } + +Alloc::Alloc(const std::string &str) : Unknown(str) { + if (!std::all_of(rawValue.begin(), rawValue.end(), isdigit)) { + klee_error("Annotation: Incorrect value format \"%s\"", rawValue.c_str()); + } + if (!rawValue.empty()) { + value = static_cast(std::stoi(rawValue)); + } } -Annotation::StatementInitNull::StatementInitNull(const std::string &str) - : StatementUnknown(str) {} +Kind Alloc::getKind() const { return Kind::AllocSource; } -Annotation::StatementKind -Annotation::StatementInitNull::getStatementName() const { - return Annotation::StatementKind::InitNull; +Free::Free(const std::string &str) : Unknown(str) { + if (!std::all_of(rawValue.begin(), rawValue.end(), isdigit)) { + klee_error("Annotation: Incorrect value format \"%s\"", rawValue.c_str()); + } + if (!rawValue.empty()) { + value = static_cast(std::stoi(rawValue)); + } } -bool Annotation::operator==(const Annotation &other) const { - return (functionName == other.functionName) && - (statements == other.statements) && (properties == other.properties); +Kind Free::getKind() const { return Kind::Free; } + +const std::map StringToKindMap = { + {"deref", Statement::Kind::Deref}, + {"initnull", Statement::Kind::InitNull}, + {"maybeinitnull", Statement::Kind::MaybeInitNull}, + {"allocsource", Statement::Kind::AllocSource}, + {"freesource", Statement::Kind::Free}, + {"freesink", Statement::Kind::Free}}; + +inline Statement::Kind stringToKind(const std::string &str) { + auto it = StringToKindMap.find(toLower(str)); + if (it != StringToKindMap.end()) { + return it->second; + } + return Statement::Kind::Unknown; } -void from_json(const json &j, Annotation::StatementPtr &statement) { +Ptr stringToKindPtr(const std::string &str) { + std::string statementStr = toLower(str.substr(0, str.find(':'))); + switch (stringToKind(statementStr)) { + case Statement::Kind::Unknown: + return std::make_shared(str); + case Statement::Kind::Deref: + return std::make_shared(str); + case Statement::Kind::InitNull: + return std::make_shared(str); + case Statement::Kind::MaybeInitNull: + return std::make_shared(str); + case Statement::Kind::AllocSource: + return std::make_shared(str); + case Statement::Kind::Free: + return std::make_shared(str); + } +} + +const std::map StringToPropertyMap{ + {"deterministic", Property::Deterministic}, + {"noreturn", Property::Noreturn}, +}; + +inline Property stringToProperty(const std::string &str) { + auto it = StringToPropertyMap.find(toLower(str)); + if (it != StringToPropertyMap.end()) { + return it->second; + } + return Property::Unknown; +} + +void from_json(const json &j, Ptr &statement) { if (!j.is_string()) { - klee_error("Incorrect annotation format."); + klee_error("Annotation: Incorrect statement format"); } const std::string jStr = j.get(); - statement = toStatement(jStr.substr(0, jStr.find(':')), jStr); + statement = Statement::stringToKindPtr(jStr); } -void from_json(const json &j, Annotation::Property &property) { +void from_json(const json &j, Property &property) { if (!j.is_string()) { - klee_error("Incorrect properties format in annotations file."); + klee_error("Annotation: Incorrect properties format"); } const std::string jStr = j.get(); - property = Annotation::Property::Unknown; - const auto propertyPtr = toProperties.find(jStr); - if (propertyPtr != toProperties.end()) { + property = Statement::Property::Unknown; + const auto propertyPtr = Statement::StringToPropertyMap.find(jStr); + if (propertyPtr != Statement::StringToPropertyMap.end()) { property = propertyPtr->second; } } -Annotations parseAnnotationsFile(const json &annotationsJson) { - Annotations annotations; +bool operator==(const Statement::Ptr &first, const Statement::Ptr &second) { + if (first->getKind() != second->getKind()) { + return false; + } + + return *first.get() == *second.get(); +} +} // namespace Statement + +bool Annotation::operator==(const Annotation &other) const { + return (functionName == other.functionName) && + (returnStatements == other.returnStatements) && + (argsStatements == other.argsStatements) && + (properties == other.properties); +} + +AnnotationsMap parseAnnotationsJson(const json &annotationsJson) { + AnnotationsMap annotations; for (auto &item : annotationsJson.items()) { Annotation annotation; annotation.functionName = item.key(); @@ -125,51 +222,53 @@ Annotations parseAnnotationsFile(const json &annotationsJson) { const json &j = item.value(); if (!j.is_object() || !j.contains("annotation") || !j.contains("properties")) { - klee_error("Incorrect annotations file format."); + klee_error("Annotation: Incorrect file format"); + } + { + std::vector> allStatements = + j.at("annotation").get>>(); + + if (allStatements.empty()) { + klee_error("Annotation: function \"%s\" should has return", + annotation.functionName.c_str()); + } + annotation.returnStatements = allStatements[0]; + if (std::any_of(allStatements.begin() + 1, allStatements.end(), + [](const std::vector &statements) { + return std::any_of( + statements.begin(), statements.end(), + [](const Statement::Ptr &statement) { + return statement->getKind() == + Statement::Kind::MaybeInitNull; + }); + })) { + klee_error("Annotation: MaybeInitNull can annotate only return value"); + } + annotation.argsStatements = std::vector>( + allStatements.begin() + 1, allStatements.end()); } - annotation.statements = - j.at("annotation").get>(); annotation.properties = - j.at("properties").get>(); + j.at("properties").get>(); annotations[item.key()] = annotation; } return annotations; } -Annotations parseAnnotationsFile(const std::string &path) { +AnnotationsMap parseAnnotations(const std::string &path) { + if (path.empty()) { + return {}; + } std::ifstream annotationsFile(path); if (!annotationsFile.good()) { - klee_error("Opening %s failed.", path.c_str()); + klee_error("Annotation: Opening %s failed.", path.c_str()); } - json annotationsJson = json::parse(annotationsFile, nullptr, false); if (annotationsJson.is_discarded()) { - klee_error("Parsing JSON %s failed.", path.c_str()); - } - - return parseAnnotationsFile(annotationsJson); -} - -bool operator==(const Annotation::StatementPtr &first, - const Annotation::StatementPtr &second) { - if (first->getStatementName() != second->getStatementName()) { - return false; + klee_error("Annotation: Parsing JSON %s failed.", path.c_str()); } - switch (first->getStatementName()) { - case Annotation::StatementKind::Unknown: - return (*dynamic_cast(first.get()) == - *dynamic_cast(second.get())); - case Annotation::StatementKind::Deref: - return (*dynamic_cast(first.get()) == - *dynamic_cast(second.get())); - case Annotation::StatementKind::InitNull: - return (*dynamic_cast(first.get()) == - *dynamic_cast(second.get())); - default: - __builtin_unreachable(); - } + return parseAnnotationsJson(annotationsJson); } } // namespace klee diff --git a/lib/Solver/Z3Builder.cpp b/lib/Solver/Z3Builder.cpp index d97b70eb76..7cc873980c 100644 --- a/lib/Solver/Z3Builder.cpp +++ b/lib/Solver/Z3Builder.cpp @@ -266,17 +266,16 @@ Z3ASTHandle Z3Builder::getInitialArray(const Array *root) { } else if (ref mockDeterministicSource = dyn_cast(root->source)) { size_t num_args = mockDeterministicSource->args.size(); - std::vector argsHandled(num_args); - std::vector argsSortHandled(num_args); std::vector args(num_args); std::vector argsSort(num_args); for (size_t i = 0; i < num_args; i++) { ref kid = mockDeterministicSource->args[i]; int kidWidth = kid->getWidth(); - argsHandled[i] = construct(kid, &kidWidth); - args[i] = argsHandled[i]; - argsSortHandled[i] = Z3SortHandle(Z3_get_sort(ctx, args[i]), ctx); - argsSort[i] = argsSortHandled[i]; + Z3ASTHandle argsHandle = construct(kid, &kidWidth); + args[i] = argsHandle; + Z3SortHandle z3SortHandle = + Z3SortHandle(Z3_get_sort(ctx, args[i]), ctx); + argsSort[i] = z3SortHandle; } Z3SortHandle domainSort = getBvSort(root->getDomain()); @@ -294,7 +293,7 @@ Z3ASTHandle Z3Builder::getInitialArray(const Array *root) { ctx); array_expr = Z3ASTHandle(Z3_mk_app(ctx, func, num_args, args.data()), ctx); - } else { + } else { array_expr = buildArray(unique_name.c_str(), root->getDomain(), root->getRange()); } @@ -341,11 +340,6 @@ Z3ASTHandle Z3Builder::getArrayForUpdate(const Array *root, const UpdateNode *un) { // Iterate over the update nodes, until we find a cached version of the node, // or no more update nodes remain - if (root->source->isMock()) { - klee_error("Updates applied to mock array %s are not allowed", - root->getName().c_str()); - } - // FIXME: This really needs to be non-recursive. Z3ASTHandle un_expr; std::vector update_nodes; for (; un && !_arr_hash.lookupUpdateNodeExpr(un, un_expr); diff --git a/lib/Solver/Z3Builder.h b/lib/Solver/Z3Builder.h index ef8b5be9f5..e6d10fed10 100644 --- a/lib/Solver/Z3Builder.h +++ b/lib/Solver/Z3Builder.h @@ -92,11 +92,11 @@ template <> void Z3NodeHandle::dump() const __attribute__((used)); template <> unsigned Z3NodeHandle::hash() __attribute__((used)); // Specialize for Z3_func_decl -template <> inline ::Z3_ast Z3NodeHandle::as_ast() { +template <> inline ::Z3_ast Z3NodeHandle::as_ast() const { return ::Z3_func_decl_to_ast(context, node); } typedef Z3NodeHandle Z3FuncDeclHandle; -template <> void Z3NodeHandle::dump() __attribute__((used)); +template <> void Z3NodeHandle::dump() const __attribute__((used)); // Specialise for Z3_ast template <> inline ::Z3_ast Z3NodeHandle::as_ast() const { diff --git a/runtime/Mocks/models.c b/runtime/Mocks/models.c index ad95634b47..e40b0cfaa0 100644 --- a/runtime/Mocks/models.c +++ b/runtime/Mocks/models.c @@ -1,3 +1,12 @@ +//===-- models.c ----------------------------------------------------------===// +// +// The KLEEF Symbolic Virtual Machine +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + #include "stddef.h" extern void klee_make_symbolic(void *array, size_t nbytes, const char *name); @@ -6,7 +15,7 @@ extern void *calloc(size_t num, size_t size); extern void *realloc(void *ptr, size_t new_size); void *__klee_wrapped_malloc(size_t size) { - char retNull; + unsigned char retNull; klee_make_symbolic(&retNull, sizeof(retNull), "retNullMalloc"); if (retNull) { return 0; @@ -16,7 +25,7 @@ void *__klee_wrapped_malloc(size_t size) { } void *__klee_wrapped_calloc(size_t num, size_t size) { - char retNull; + unsigned char retNull; klee_make_symbolic(&retNull, sizeof(retNull), "retNullCalloc"); if (retNull) { return 0; @@ -26,7 +35,7 @@ void *__klee_wrapped_calloc(size_t num, size_t size) { } void *__klee_wrapped_realloc(void *ptr, size_t new_size) { - char retNull; + unsigned char retNull; klee_make_symbolic(&retNull, sizeof(retNull), "retNullRealloc"); if (retNull) { return 0; diff --git a/scripts/kleef b/scripts/kleef index 2dd0bd016d..969b6c4460 100755 --- a/scripts/kleef +++ b/scripts/kleef @@ -29,7 +29,7 @@ def klee_options( "--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. + "--mock-policy=all", # 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", diff --git a/scripts/run_tests_with_mocks.py b/scripts/run_tests_with_mocks.py index 5843a37ad0..ef5db2def6 100755 --- a/scripts/run_tests_with_mocks.py +++ b/scripts/run_tests_with_mocks.py @@ -3,10 +3,11 @@ # This script builds executable file using initial bitcode file and artifacts produced by KLEE. # To run the script provide all the arguments you want to pass to clang for building executable. # +# NOTE: First argument is path to compiler # NOTE: Pre-last argument should be a path to KLEE output directory which contains redefinitions.txt and externals.ll. # NOTE: Last argument is path to initial bitcode. # -# Example: python3 run_tests_with_mocks.py -I ~/klee/include/ -L ~/klee/build/lib/ -lkleeRuntest klee-last a.bc +# Example: python3 run_tests_with_mocks.py clang -I ~/klee/include/ -L ~/klee/build/lib/ -lkleeRuntest klee-last a.bc # # You can read more about replaying test cases here: http://klee.github.io/tutorials/testing-function/ @@ -19,8 +20,14 @@ filename = os.path.splitext(bitcode)[0] object_file = f'{filename}.o' -sp.run(f'clang -c {bitcode} -o {object_file}', shell=True) +sp.run(f'llc {bitcode} -filetype=obj -o {object_file}', shell=True) sp.run(f'llvm-objcopy {object_file} --redefine-syms {klee_out_dir}/redefinitions.txt', shell=True) -clang_args = ' '.join(sys.argv[1:len(sys.argv) - 2]) -print(f'clang {clang_args} {klee_out_dir}/externals.ll {object_file}') -sp.run(f'clang {clang_args} {klee_out_dir}/externals.ll {object_file}', shell=True) + +externals = f'{klee_out_dir}/externals.o' +sp.run(f'llc {klee_out_dir}/externals.ll -filetype=obj -o {externals}', shell=True) + +compiler = sys.argv[1] +user_args = ' '.join(sys.argv[2:len(sys.argv) - 2]) +command = f'{compiler} {externals} {object_file} {user_args}' +print(command) +sp.run(command, shell=True) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 17723d865f..c7d14ed87e 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -15,6 +15,7 @@ set(LLVM_TOOLS_DIR "${LLVM_TOOLS_BINARY_DIR}") set(LLVMCC "${LLVMCC} -I${CMAKE_SOURCE_DIR}/include") set(LLVMCXX "${LLVMCXX} -I${CMAKE_SOURCE_DIR}/include") set(NATIVE_CC "${CMAKE_C_COMPILER} ${CMAKE_C_FLAGS} -I ${CMAKE_SOURCE_DIR}/include") +set(NATIVE_OBJCOPY "${CMAKE_OBJCOPY}") set(NATIVE_CXX "${CMAKE_CXX_COMPILER} ${CMAKE_CXX_FLAGS} -I ${CMAKE_SOURCE_DIR}/include") set(TARGET_TRIPLE "${TARGET_TRIPLE}") diff --git a/test/Feature/Annotation/AllocSource.c b/test/Feature/Annotation/AllocSource.c new file mode 100644 index 0000000000..3ac9a1918e --- /dev/null +++ b/test/Feature/Annotation/AllocSource.c @@ -0,0 +1,65 @@ +// REQUIRES: z3 +// RUN: %clang -DAllocSource1 %s -g -emit-llvm %O0opt -c -o %t1.bc +// RUN: rm -rf %t1.klee-out-1 +// RUN: %klee --solver-backend=z3 --output-dir=%t1.klee-out-1 --annotations=%S/AllocSource.json --mock-policy=all --mock-modeled-functions -emit-all-errors=true %t1.bc 2>&1 | FileCheck %s -check-prefix=CHECK-ALLOCSOURCE1 + +// RUN: %clang -DAllocSource2 %s -g -emit-llvm %O0opt -c -o %t2.bc +// RUN: rm -rf %t2.klee-out-1 +// RUN: %klee --solver-backend=z3 --output-dir=%t2.klee-out-1 --annotations=%S/AllocSource.json --mock-policy=all --mock-modeled-functions -emit-all-errors=true %t2.bc 2>&1 | FileCheck %s -check-prefix=CHECK-ALLOCSOURCE2 + +// RUN: %clang -DAllocSource3 %s -g -emit-llvm %O0opt -c -o %t3.bc +// RUN: rm -rf %t3.klee-out-1 +// RUN: %klee --solver-backend=z3 --output-dir=%t3.klee-out-1 --annotations=%S/AllocSource.json --mock-policy=all --mock-modeled-functions -emit-all-errors=true %t3.bc 2>&1 | FileCheck %s -check-prefix=CHECK-ALLOCSOURCE3 + +// RUN: %clang -DAllocSource4 %s -g -emit-llvm %O0opt -c -o %t4.bc +// RUN: rm -rf %t4.klee-out-1 +// RUN: %klee --solver-backend=z3 --output-dir=%t4.klee-out-1 --annotations=%S/AllocSource.json --mock-policy=all --mock-modeled-functions -emit-all-errors=true %t4.bc 2>&1 | FileCheck %s -check-prefix=CHECK-ALLOCSOURCE4 + +#include + +#ifdef AllocSource1 +void maybeAllocSource1(int *a); +#endif +void maybeAllocSource2(int **a); +int *maybeAllocSource3(); +int **maybeAllocSource4(); + +int main() { + int *a = 0; +#ifdef AllocSource1 + // CHECK-ALLOCSOURCE1: not valid annotation + maybeAllocSource1(a); + // CHECK-ALLOCSOURCE1: ASSERTION FAIL + // CHECK-ALLOCSOURCE1: partially completed paths = 1 + // CHECK-ALLOCSOURCE1: generated tests = 1 +#endif + +#ifdef AllocSource2 + maybeAllocSource2(&a); + // CHECK-NOT-ALLOCSOURCE2: memory error + // CHECK-NOT-ALLOCSOURCE2: ASSERTION FAIL + // CHECK-ALLOCSOURCE2: partially completed paths = 0 + // CHECK-ALLOCSOURCE2: generated tests = 1 +#endif + +#ifdef AllocSource3 + a = maybeAllocSource3(); + // CHECK-NOT-ALLOCSOURCE3 : memory error + // CHECK-NOT-ALLOCSOURCE3: Not Allocated + // CHECK-ALLOCSOURCE3: partially completed paths = 0 + // CHECK-ALLOCSOURCE3: generated tests = 1 +#endif + +#ifdef AllocSource4 + a = *maybeAllocSource4(); + // CHECK-NOT-ALLOCSOURCE4: ASSERTION FAIL + // CHECK-ALLOCSOURCE4 : memory error + // CHECK-ALLOCSOURCE4: partially completed paths = {{[1-9][0-9]*}} + // CHECK-ALLOCSOURCE4: generated tests = {{[1-9][0-9]*}} +#endif + + assert(a != 0 && "Not Allocated"); + *a = 42; + + return 0; +} diff --git a/test/Feature/Annotation/AllocSource.json b/test/Feature/Annotation/AllocSource.json new file mode 100644 index 0000000000..a31051c64d --- /dev/null +++ b/test/Feature/Annotation/AllocSource.json @@ -0,0 +1,40 @@ +{ + "maybeAllocSource1": { + "name": "maybeAllocSource1", + "annotation": [ + [], + [ + "AllocSource::1" + ] + ], + "properties": [] + }, + "maybeAllocSource2": { + "name": "maybeAllocSource2", + "annotation": [ + [], + [ + "AllocSource:*:1" + ] + ], + "properties": [] + }, + "maybeAllocSource3": { + "name": "maybeAllocSource3", + "annotation": [ + [ + "AllocSource::1" + ] + ], + "properties": [] + }, + "maybeAllocSource4": { + "name": "maybeAllocSource4", + "annotation": [ + [ + "AllocSource::1" + ] + ], + "properties": [] + } +} diff --git a/test/Feature/Annotation/BrokenAnnotation.json b/test/Feature/Annotation/BrokenAnnotation.json new file mode 100644 index 0000000000..0b5c90598f --- /dev/null +++ b/test/Feature/Annotation/BrokenAnnotation.json @@ -0,0 +1,11 @@ +{ + "maybeDeref1": { + "name": "maybeDeref1", + "annotation": [ + [], + [ + "Deref" + ], + "properties": [] + } +} diff --git a/test/Feature/Annotation/Deref.c b/test/Feature/Annotation/Deref.c new file mode 100644 index 0000000000..7a1048f644 --- /dev/null +++ b/test/Feature/Annotation/Deref.c @@ -0,0 +1,104 @@ +// REQUIRES: z3 +// RUN: %clang -DDeref1 %s -g -emit-llvm %O0opt -c -o %t1.bc +// RUN: rm -rf %t1.klee-out-1 +// RUN: %klee --solver-backend=z3 --output-dir=%t1.klee-out-1 --annotations=%S/Deref.json --mock-policy=all --mock-modeled-functions --emit-all-errors=true %t1.bc 2>&1 | FileCheck %s -check-prefix=CHECK-DEREF1 + +// RUN: %clang -DDeref2 %s -g -emit-llvm %O0opt -c -o %t2.bc +// RUN: rm -rf %t2.klee-out-1 +// RUN: %klee --solver-backend=z3 --output-dir=%t2.klee-out-1 --annotations=%S/Deref.json --mock-policy=all --mock-modeled-functions --emit-all-errors=true %t2.bc 2>&1 | FileCheck %s -check-prefix=CHECK-DEREF2 + +// RUN: %clang -DDeref3 %s -g -emit-llvm %O0opt -c -o %t3.bc +// RUN: rm -rf %t3.klee-out-1 +// RUN: %klee --solver-backend=z3 --output-dir=%t3.klee-out-1 --annotations=%S/Deref.json --mock-policy=all --mock-modeled-functions --emit-all-errors=true %t3.bc 2>&1 | FileCheck %s -check-prefix=CHECK-DEREF3 + +// RUN: %clang -DDeref4 %s -g -emit-llvm %O0opt -c -o %t4.bc +// RUN: rm -rf %t4.klee-out-1 +// RUN: %klee --solver-backend=z3 --output-dir=%t4.klee-out-1 --annotations=%S/Deref.json --mock-policy=all --mock-modeled-functions --emit-all-errors=true %t4.bc 2>&1 | FileCheck %s -check-prefix=CHECK-DEREF4 + +// RUN: %clang -DDeref5 %s -g -emit-llvm %O0opt -c -o %t5.bc +// RUN: rm -rf %t5.klee-out-1 +// RUN: %klee --solver-backend=z3 --output-dir=%t5.klee-out-1 --annotations=%S/Deref.json --mock-policy=all --mock-modeled-functions --emit-all-errors=true %t5.bc 2>&1 | FileCheck %s -check-prefix=CHECK-DEREF5 + +// RUN: %clang -DDeref6 %s -g -emit-llvm %O0opt -c -o %t6.bc +// RUN: rm -rf %t6.klee-out-1 +// RUN: %klee --solver-backend=z3 --output-dir=%t6.klee-out-1 --annotations=%S/Deref.json --mock-policy=all --mock-modeled-functions --emit-all-errors=true %t6.bc 2>&1 | FileCheck %s -check-prefix=CHECK-DEREF6 + +// RUN: %clang -DHASVALUE -DDeref1 -DDeref2 -DDeref3 -DDeref4 -DDeref5 -DDeref6 %s -g -emit-llvm %O0opt -c -o %t7.bc +// RUN: rm -rf %t7.klee-out-1 +// RUN: %klee --solver-backend=z3 --output-dir=%t7.klee-out-1 --annotations=%S/Deref.json --mock-policy=all --mock-modeled-functions --emit-all-errors=true %t7.bc 2>&1 | FileCheck %s -check-prefix=CHECK-NODEREF +// CHECK-NODEREF-NOT: memory error: null pointer exception + +// RUN: %clang -DDeref1 -DDeref2 -DDeref3 -DDeref4 -DDeref5 -DDeref6 %s -g -emit-llvm %O0opt -c -o %t8.bc +// RUN: rm -rf %t8.klee-out-1 +// RUN: %klee --solver-backend=z3 --output-dir=%t8.klee-out-1 --annotations=%S/EmptyAnnotation.json --external-calls=all --mock-policy=all --mock-modeled-functions --emit-all-errors=true %t8.bc 2>&1 | FileCheck %s -check-prefix=CHECK-EMPTY +// CHECK-EMPTY-NOT: memory error: null pointer exception +// CHECK-EMPTY: partially completed paths = 0 +// CHECK-EMPTY: generated tests = 1 + +void maybeDeref1(int *a); +void maybeDeref2(int **a); +void maybeDeref3(int **a); +void maybeDeref4(int b, int *a); +void maybeDeref5(int *a, int b); +void maybeDeref6(int *a, int *b); + +int main() { + int c = 42; +#ifdef HASVALUE + int *a = &c; + int **b = &a; +#else + int *a = 0; + int **b = 0; +#endif + +#ifdef Deref1 + // CHECK-DEREF1: memory error: null pointer exception + maybeDeref1(a); + // CHECK-DEREF1: memory error: out of bound pointer + maybeDeref1((int *)42); + // CHECK-DEREF1: partially completed paths = 2 + // CHECK-DEREF1: generated tests = 3 +#endif + +#ifdef Deref2 + // CHECK-DEREF2: memory error: null pointer exception + maybeDeref2(b); + maybeDeref2(&a); + // CHECK-DEREF2: partially completed paths = 1 + // CHECK-DEREF2: generated tests = 3 +#endif + +#ifdef Deref3 + // CHECK-DEREF3: memory error: null pointer exception + maybeDeref3(&a); + // CHECK-DEREF3: memory error: null pointer exception + maybeDeref3(b); + // CHECK-DEREF3: partially completed paths = 2 + // CHECK-DEREF3: generated tests = 2 +#endif + +#ifdef Deref4 + // CHECK-DEREF4: memory error: null pointer exception + maybeDeref4(0, a); + // CHECK-DEREF4: partially completed paths = 1 + // CHECK-DEREF4: generated tests = 2 +#endif + +#ifdef Deref5 + // CHECK-DEREF5: memory error: null pointer exception + maybeDeref5(a, 0); + // CHECK-DEREF5: partially completed paths = 1 + // CHECK-DEREF5: generated tests = 2 +#endif + +#ifdef Deref6 + // CHECK-DEREF6: memory error: null pointer exception + maybeDeref6(a, &c); + // CHECK-DEREF6: memory error: null pointer exception + maybeDeref6(&c, a); + // CHECK-DEREF6: partially completed paths = 2 + // CHECK-DEREF6: generated tests = 3 +#endif + return 0; +} diff --git a/test/Feature/Annotation/Deref.json b/test/Feature/Annotation/Deref.json new file mode 100644 index 0000000000..02ce7ecbc3 --- /dev/null +++ b/test/Feature/Annotation/Deref.json @@ -0,0 +1,67 @@ +{ + "maybeDeref1": { + "name": "maybeDeref1", + "annotation": [ + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "maybeDeref2": { + "name": "maybeDeref2", + "annotation": [ + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "maybeDeref3": { + "name": "maybeDeref3", + "annotation": [ + [], + [ + "Deref:*" + ] + ], + "properties": [] + }, + "maybeDeref4": { + "name": "maybeDeref4", + "annotation": [ + [], + [], + [ + "Deref" + ] + ], + "properties": [] + }, + "maybeDeref5": { + "name": "maybeDeref5", + "annotation": [ + [], + [ + "Deref" + ], + [] + ], + "properties": [] + }, + "maybeDeref6": { + "name": "maybeDeref6", + "annotation": [ + [], + [ + "Deref" + ], + [ + "Deref" + ] + ], + "properties": [] + } +} diff --git a/test/Feature/Annotation/EmptyAnnotation.json b/test/Feature/Annotation/EmptyAnnotation.json new file mode 100644 index 0000000000..0967ef424b --- /dev/null +++ b/test/Feature/Annotation/EmptyAnnotation.json @@ -0,0 +1 @@ +{} diff --git a/test/Feature/Annotation/Free.c b/test/Feature/Annotation/Free.c new file mode 100644 index 0000000000..22614bf8f5 --- /dev/null +++ b/test/Feature/Annotation/Free.c @@ -0,0 +1,45 @@ +// REQUIRES: z3 +// RUN: %clang -DFree1 %s -g -emit-llvm %O0opt -c -o %t1.bc +// RUN: rm -rf %t1.klee-out-1 +// RUN: %klee --solver-backend=z3 --output-dir=%t1.klee-out-1 --annotations=%S/Free.json --mock-policy=all --mock-modeled-functions --emit-all-errors=true %t1.bc 2>&1 | FileCheck %s -check-prefix=CHECK-FREE1 + +// RUN: %clang %s -g -emit-llvm %O0opt -c -o %t2.bc +// RUN: rm -rf %t2.klee-out-1 +// RUN: %klee --solver-backend=z3 --output-dir=%t2.klee-out-1 --annotations=%S/Free.json --mock-policy=all --mock-modeled-functions --emit-all-errors=true %t2.bc 2>&1 | FileCheck %s -check-prefix=CHECK-FREE2 + +// RUN: %clang -DFree3 %s -g -emit-llvm %O0opt -c -o %t3.bc +// RUN: rm -rf %t3.klee-out-1 +// RUN: %klee --solver-backend=z3 --output-dir=%t3.klee-out-1 --annotations=%S/Free.json --mock-policy=all --mock-modeled-functions --emit-all-errors=true %t3.bc 2>&1 | FileCheck %s -check-prefix=CHECK-FREE3 + +#include + +int *maybeAllocSource1(); +void maybeFree1(int *a); + +int main() { + int *a; +#ifdef Free1 + // CHECK-FREE1: memory error: invalid pointer: free + // CHECK-FREE1: KLEE: done: completed paths = 1 + // CHECK-FREE1: KLEE: done: partially completed paths = 1 + // CHECK-FREE1: KLEE: done: generated tests = 2 + a = malloc(sizeof(int)); + maybeFree1(a); + maybeFree1(a); +#endif + + a = maybeAllocSource1(); + maybeFree1(a); + // CHECK-NOT-FREE2: memory error: invalid pointer: free + // CHECK-FREE2: KLEE: done: completed paths = 1 + // CHECK-FREE2: KLEE: done: partially completed paths = 0 + // CHECK-FREE2: KLEE: done: generated tests = 1 +#ifdef Free3 + // CHECK-FREE3: memory error: invalid pointer: free + // CHECK-FREE3: KLEE: done: completed paths = 0 + // CHECK-FREE3: KLEE: done: partially completed paths = 1 + // CHECK-FREE3: KLEE: done: generated tests = 1 + maybeFree1(a); +#endif + return 0; +} diff --git a/test/Feature/Annotation/Free.json b/test/Feature/Annotation/Free.json new file mode 100644 index 0000000000..d8a9becf9d --- /dev/null +++ b/test/Feature/Annotation/Free.json @@ -0,0 +1,31 @@ +{ + "maybeFree1": { + "name": "maybeFree1", + "annotation": [ + [], + [ + "FreeSink::1" + ] + ], + "properties": [] + }, + "maybeFree2": { + "name": "maybeFree2", + "annotation": [ + [], + [ + "FreeSink:*:1" + ] + ], + "properties": [] + }, + "maybeAllocSource1": { + "name": "maybeAllocSource1", + "annotation": [ + [ + "AllocSource::1" + ] + ], + "properties": [] + } +} diff --git a/test/Feature/Annotation/General.c b/test/Feature/Annotation/General.c new file mode 100644 index 0000000000..a642919f2b --- /dev/null +++ b/test/Feature/Annotation/General.c @@ -0,0 +1,43 @@ +// REQUIRES: z3 +// RUN: %clang %s -g -emit-llvm %O0opt -c -o %t1.bc +// RUN: rm -rf %t1.klee-out-1 +// RUN: %klee --solver-backend=z3 --output-dir=%t1.klee-out-1 --annotations=%S/BrokenAnnotation.json --mock-policy=all -emit-all-errors=true %t1.bc 2>%t.stderr.log || echo "Exit status must be 0" +// RUN: FileCheck -check-prefix=CHECK-JSON --input-file=%t.stderr.log %s +// CHECK-JSON: Annotation: Parsing JSON + +// RUN: %clang -DPTRARG %s -g -emit-llvm %O0opt -c -o %t2.bc +// RUN: rm -rf %t2.klee-out-1 +// RUN: %klee --solver-backend=z3 --output-dir=%t2.klee-out-1 --annotations=%S/General.json --mock-policy=all -emit-all-errors=true %t2.bc 2>&1 | FileCheck %s -check-prefix=CHECK + +// RUN: %clang -DPTRRET %s -g -emit-llvm %O0opt -c -o %t3.bc +// RUN: rm -rf %t3.klee-out-1 +// RUN: %klee --solver-backend=z3 --output-dir=%t3.klee-out-1 --annotations=%S/General.json --mock-policy=all -emit-all-errors=true %t3.bc 2>&1 | FileCheck %s -check-prefix=CHECK + +#include + +struct ST { + int a; + int b; +}; + +void ptrArg(struct ST, int **a); +int *ptrRet(); + +int main() { + int *a = 15; +#ifdef PTRARG + struct ST st; + ptrArg(st, &a); +#endif + +#ifdef PTRRET + a = ptrRet(); +#endif + + // CHECK: memory error: null pointer exception + // CHECK: partially completed paths = 1 + // CHECK: generated tests = 2 + *a = 42; + + return 0; +} diff --git a/test/Feature/Annotation/General.json b/test/Feature/Annotation/General.json new file mode 100644 index 0000000000..65cffd2fbf --- /dev/null +++ b/test/Feature/Annotation/General.json @@ -0,0 +1,24 @@ +{ + "ptrArg": { + "name": "ptrArg", + "annotation": [ + [], + [], + [ + "InitNull:*", + "AllocSource:*:1" + ] + ], + "properties": [] + }, + "ptrRet": { + "name": "ptrRet", + "annotation": [ + [ + "MaybeInitNull", + "AllocSource::1" + ] + ], + "properties": [] + } +} diff --git a/test/Feature/Annotation/InitNull.c b/test/Feature/Annotation/InitNull.c new file mode 100644 index 0000000000..ff7e152c71 --- /dev/null +++ b/test/Feature/Annotation/InitNull.c @@ -0,0 +1,79 @@ +// REQUIRES: z3 +// RUN: %clang -DInitNull1 %s -g -emit-llvm %O0opt -c -o %t1.bc +// RUN: rm -rf %t1.klee-out-1 +// RUN: %klee --solver-backend=z3 --output-dir=%t1.klee-out-1 --annotations=%S/InitNull.json --mock-policy=all -emit-all-errors=true %t1.bc 2>&1 | FileCheck %s -check-prefix=CHECK-INITNULL1 + +// RUN: %clang -DInitNull2 %s -g -emit-llvm %O0opt -c -o %t2.bc +// RUN: rm -rf %t2.klee-out-1 +// RUN: %klee --solver-backend=z3 --output-dir=%t2.klee-out-1 --annotations=%S/InitNull.json --mock-policy=all -emit-all-errors=true %t2.bc 2>&1 | FileCheck %s -check-prefix=CHECK-INITNULL2 + +// RUN: %clang -DInitNull3 %s -g -emit-llvm %O0opt -c -o %t3.bc +// RUN: rm -rf %t3.klee-out-1 +// RUN: %klee --solver-backend=z3 --output-dir=%t3.klee-out-1 --annotations=%S/InitNull.json --mock-policy=all -emit-all-errors=true %t3.bc 2>&1 | FileCheck %s -check-prefix=CHECK-INITNULL3 + +// RUN: %clang -DInitNull4 %s -g -emit-llvm %O0opt -c -o %t4.bc +// RUN: rm -rf %t4.klee-out-1 +// RUN: %klee --solver-backend=z3 --output-dir=%t4.klee-out-1 --annotations=%S/InitNull.json --mock-policy=all -emit-all-errors=true %t4.bc 2>&1 | FileCheck %s -check-prefix=CHECK-INITNULL4 + +// RUN: %clang -DInitNull1 -DInitNull2 -DInitNull3 -DInitNull4 %s -g -emit-llvm %O0opt -c -o %t5.bc +// RUN: rm -rf %t5.klee-out-1 +// RUN: %klee --solver-backend=z3 --output-dir=%t5.klee-out-1 --annotations=%S/InitNullEmpty.json --mock-policy=all -emit-all-errors=true %t5.bc 2>&1 | FileCheck %s -check-prefix=CHECK-EMPTY +// CHECK-EMPTY: ASSERTION FAIL +// CHECK-EMPTY: partially completed paths = {{[1-2]}} + +// RUN: %clang -DMustInitNull5 %s -g -emit-llvm %O0opt -c -o %t6.bc +// RUN: rm -rf %t6.klee-out-1 +// RUN: %klee --solver-backend=z3 --output-dir=%t6.klee-out-1 --annotations=%S/InitNull.json --mock-policy=all -emit-all-errors=true %t6.bc 2>&1 | FileCheck %s -check-prefix=CHECK-INITNULL5 + +#include + +#ifdef InitNull1 +void mustInitNull1(int *a); +#endif +void mustInitNull2(int **a); +int *maybeInitNull1(); +int **maybeInitNull2(); + +int *mustInitNull3(); + +int main() { + int c = 42; + int *a = &c; +#ifdef InitNull1 + // CHECK-INITNULL1: not valid annotation + mustInitNull1(a); + // CHECK-INITNULL1-NOT: A is Null + // CHECK-INITNULL1: partially completed paths = 0 + // CHECK-INITNULL1: generated tests = 1 +#endif + +#ifdef InitNull2 + mustInitNull2(&a); + // CHECK-INITNULL2: ASSERTION FAIL + // CHECK-INITNULL2: partially completed paths = 1 + // CHECK-INITNULL2: generated tests = 2 +#endif + +#ifdef InitNull3 + a = maybeInitNull1(); + // CHECK-INITNULL3: ASSERTION FAIL + // CHECK-INITNULL3: partially completed paths = 1 + // CHECK-INITNULL3: generated tests = 2 +#endif + +#ifdef InitNull4 + a = *maybeInitNull2(); + // CHECK-INITNULL4: ASSERTION FAIL + // CHECK-INITNULL4: partially completed paths = {{[2-3]}} +#endif + +#ifdef MustInitNull5 + a = mustInitNull3(); + // CHECK-INITNULL5: partially completed paths = 0 + // CHECK-INITNULL5: generated tests = 2 +#else + assert(a != 0 && "A is Null"); +#endif + + return 0; +} diff --git a/test/Feature/Annotation/InitNull.json b/test/Feature/Annotation/InitNull.json new file mode 100644 index 0000000000..270c7f01d1 --- /dev/null +++ b/test/Feature/Annotation/InitNull.json @@ -0,0 +1,49 @@ +{ + "mustInitNull1": { + "name": "maybeInitNull1", + "annotation": [ + [], + [ + "InitNull" + ] + ], + "properties": [] + }, + "mustInitNull2": { + "name": "maybeInitNull2", + "annotation": [ + [], + [ + "InitNull:*" + ] + ], + "properties": [] + }, + "maybeInitNull1": { + "name": "maybeInitNull1", + "annotation": [ + [ + "MaybeInitNull" + ] + ], + "properties": [] + }, + "maybeInitNull2": { + "name": "maybeInitNull2", + "annotation": [ + [ + "MaybeInitNull:*" + ] + ], + "properties": [] + }, + "mustInitNull3": { + "name": "mustInitNull3", + "annotation": [ + [ + "InitNull" + ] + ], + "properties": [] + } +} diff --git a/test/Feature/Annotation/InitNullEmpty.json b/test/Feature/Annotation/InitNullEmpty.json new file mode 100644 index 0000000000..535d0a767b --- /dev/null +++ b/test/Feature/Annotation/InitNullEmpty.json @@ -0,0 +1,32 @@ +{ + "maybeInitNull1": { + "name": "maybeInitNull1", + "annotation": [ + [], + [] + ], + "properties": [] + }, + "maybeInitNull2": { + "name": "maybeInitNull2", + "annotation": [ + [], + [] + ], + "properties": [] + }, + "maybeInitNull3": { + "name": "maybeInitNull3", + "annotation": [ + [] + ], + "properties": [] + }, + "maybeInitNull4": { + "name": "maybeInitNull4", + "annotation": [ + [] + ], + "properties": [] + } +} diff --git a/test/Feature/MockPointersDeterministic.c b/test/Feature/MockPointersDeterministic.c index d8c871588d..03a2480850 100644 --- a/test/Feature/MockPointersDeterministic.c +++ b/test/Feature/MockPointersDeterministic.c @@ -2,8 +2,9 @@ // RUN: %clang %s -g -emit-llvm %O0opt -c -o %t.bc // RUN: rm -rf %t.klee-out-1 -// RUN: %klee --solver-backend=z3 --output-dir=%t.klee-out-1 --skip-not-lazy-initialized --external-calls=all --mock-strategy=deterministic %t.bc 2>&1 | FileCheck %s -check-prefix=CHECK-1 +// RUN: %klee --solver-backend=z3 --output-dir=%t.klee-out-1 --min-number-elements-li=0 --use-sym-size-li --skip-not-lazy-initialized --mock-policy=all --mock-strategy=deterministic %t.bc 2>&1 | FileCheck %s -check-prefix=CHECK-1 // CHECK-1: memory error: null pointer exception +// CHECK-1: memory error: out of bound pointer // CHECK-1: KLEE: done: completed paths = 1 // CHECK-1: KLEE: done: partially completed paths = 2 // CHECK-1: KLEE: done: generated tests = 3 @@ -20,4 +21,4 @@ int main() { assert(0 && "age is deterministic"); } return *age(); -} \ No newline at end of file +} diff --git a/test/Feature/MockStrategies.c b/test/Feature/MockStrategies.c index 524fbba3a2..d8998cfe54 100644 --- a/test/Feature/MockStrategies.c +++ b/test/Feature/MockStrategies.c @@ -2,23 +2,23 @@ // RUN: %clang %s -g -emit-llvm %O0opt -c -o %t.bc // RUN: rm -rf %t.klee-out-1 -// RUN: %klee --output-dir=%t.klee-out-1 --external-calls=all --mock-strategy=none %t.bc 2>&1 | FileCheck %s -check-prefix=CHECK-1 +// RUN: %klee --output-dir=%t.klee-out-1 --external-calls=all %t.bc 2>&1 | FileCheck %s -check-prefix=CHECK-1 // CHECK-1: failed external call // CHECK-1: KLEE: done: completed paths = 1 // CHECK-1: KLEE: done: generated tests = 2 // RUN: rm -rf %t.klee-out-2 -// RUN: %klee --output-dir=%t.klee-out-2 --external-calls=all --mock-strategy=naive %t.bc 2>&1 | FileCheck %s -check-prefix=CHECK-2 -// CHECK-2: ASSERTION FAIL: 0 +// RUN: %klee --output-dir=%t.klee-out-2 --mock-policy=all %t.bc 2>&1 | FileCheck %s -check-prefix=CHECK-2 +// CHECK-2: ASSERTION FAIL // CHECK-2: KLEE: done: completed paths = 2 // CHECK-2: KLEE: done: generated tests = 3 // RUN: rm -rf %t.klee-out-3 -// RUN: not %klee --output-dir=%t.klee-out-3 --solver-backend=stp --external-calls=all --mock-strategy=deterministic %t.bc 2>&1 | FileCheck %s -check-prefix=CHECK-3 +// RUN: not %klee --output-dir=%t.klee-out-3 --solver-backend=stp --mock-policy=all --mock-strategy=deterministic %t.bc 2>&1 | FileCheck %s -check-prefix=CHECK-3 // CHECK-3: KLEE: ERROR: Deterministic mocks can be generated with Z3 solver only. // RUN: rm -rf %t.klee-out-4 -// RUN: %klee --output-dir=%t.klee-out-4 --solver-backend=z3 --external-calls=all --mock-strategy=deterministic %t.bc 2>&1 | FileCheck %s -check-prefix=CHECK-4 +// RUN: %klee --output-dir=%t.klee-out-4 --solver-backend=z3 --mock-policy=all --mock-strategy=deterministic %t.bc 2>&1 | FileCheck %s -check-prefix=CHECK-4 // CHECK-4: KLEE: done: completed paths = 2 // CHECK-4: KLEE: done: generated tests = 2 diff --git a/test/Industry/AssignNull_Scene_BadCase02.c b/test/Industry/AssignNull_Scene_BadCase02.c index 55fb4b7989..e8e25bfbe9 100644 --- a/test/Industry/AssignNull_Scene_BadCase02.c +++ b/test/Industry/AssignNull_Scene_BadCase02.c @@ -51,6 +51,6 @@ void TestBad5(struct STU *pdev, const char *buf, unsigned int count) // 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 +// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --location-accuracy --annotations=%annotations --mock-policy=all --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 -// CHECK: KLEE: WARNING: 100.00% NullPointerException False Positive at trace 2 \ No newline at end of file +// CHECK: KLEE: WARNING: 100.00% NullPointerException False Positive at trace 2 diff --git a/test/Industry/AssignNull_Scene_BadCase04.c b/test/Industry/AssignNull_Scene_BadCase04.c index 6a0979278f..272894d73f 100644 --- a/test/Industry/AssignNull_Scene_BadCase04.c +++ b/test/Industry/AssignNull_Scene_BadCase04.c @@ -52,5 +52,5 @@ int TestBad7(char *arg, unsigned int count) // 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 +// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --annotations=%annotations --mock-policy=all --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 // RUN: FileCheck -input-file=%t.klee-out/warnings.txt %s diff --git a/test/Industry/BadCase01_SecB_ForwardNull.c b/test/Industry/BadCase01_SecB_ForwardNull.c index d554a1535b..80b17cbf9b 100644 --- a/test/Industry/BadCase01_SecB_ForwardNull.c +++ b/test/Industry/BadCase01_SecB_ForwardNull.c @@ -142,6 +142,6 @@ void badbad(char *ptr) // 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 > %t1.log 2>&1 +// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --annotations=%annotations --mock-policy=all --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --check-out-of-memory --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc > %t1.log 2>&1 // RUN: FileCheck -input-file=%t1.log %s // CHECK: KLEE: WARNING: No paths were given to trace verify diff --git a/test/Industry/CheckNull_Scene_BadCase02.c b/test/Industry/CheckNull_Scene_BadCase02.c index 3effb46f57..3f19d9b621 100644 --- a/test/Industry/CheckNull_Scene_BadCase02.c +++ b/test/Industry/CheckNull_Scene_BadCase02.c @@ -43,5 +43,5 @@ void TestBad2() // 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 +// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --annotations=%annotations --mock-policy=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 // RUN: FileCheck -input-file=%t.klee-out/warnings.txt %s diff --git a/test/Industry/CheckNull_Scene_BadCase04.c b/test/Industry/CheckNull_Scene_BadCase04.c index 0e9038201d..179fd1419d 100644 --- a/test/Industry/CheckNull_Scene_BadCase04.c +++ b/test/Industry/CheckNull_Scene_BadCase04.c @@ -58,5 +58,5 @@ void TestBad12(int cond1, int cond2) // 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 +// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --annotations=%annotations --mock-policy=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 // RUN: FileCheck -input-file=%t.klee-out/warnings.txt %s diff --git a/test/Industry/CoverageBranches/egcd3-ll_valuebound10.c b/test/Industry/CoverageBranches/egcd3-ll_valuebound10.c index a3846f9ec0..37524f9b99 100644 --- a/test/Industry/CoverageBranches/egcd3-ll_valuebound10.c +++ b/test/Industry/CoverageBranches/egcd3-ll_valuebound10.c @@ -1,6 +1,6 @@ // 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=all --search=dfs --search=random-state %t1.bc +// RUN: %klee --output-dir=%t.klee-out --delete-dead-loops=false --emit-all-errors --mock-policy=all --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=all --search=dfs --search=random-state %t1.bc // RUN: rm -f ./%gcov-files-path*.gcda ./%gcov-files-path*.gcno ./%gcov-files-path*.gcov // RUN: %cc -DGCOV %s %libkleeruntest -Wl,-rpath %libkleeruntestdir -o %t_runner --coverage diff --git a/test/Industry/CoverageBranches/pals_lcr.3.ufo.UNBOUNDED.pals+Problem12_label00.c b/test/Industry/CoverageBranches/pals_lcr.3.ufo.UNBOUNDED.pals+Problem12_label00.c index 5e7399e6ee..104daa6402 100644 --- a/test/Industry/CoverageBranches/pals_lcr.3.ufo.UNBOUNDED.pals+Problem12_label00.c +++ b/test/Industry/CoverageBranches/pals_lcr.3.ufo.UNBOUNDED.pals+Problem12_label00.c @@ -1,6 +1,6 @@ // 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=all --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-policy=all --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=all --search=dfs --search=random-state --use-iterative-deepening-search=max-cycles --max-cycles=4 %t1.bc // RUN: rm -f ./%gcov-files-path*.gcda ./%gcov-files-path*.gcno ./%gcov-files-path*.gcov // RUN: %cc -DGCOV %s %libkleeruntest -Wl,-rpath %libkleeruntestdir -o %t_runner --coverage diff --git a/test/Industry/FN_SecB_ForwardNull_filed.c b/test/Industry/FN_SecB_ForwardNull_filed.c index 6faaf136b9..e4d507692e 100644 --- a/test/Industry/FN_SecB_ForwardNull_filed.c +++ b/test/Industry/FN_SecB_ForwardNull_filed.c @@ -47,5 +47,5 @@ void WB_BadCase_field2(DataInfo *data) // 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 +// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --annotations=%annotations --mock-policy=all --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 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 9a04367627..58a19a6d5c 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 @@ -55,7 +55,7 @@ void call_func(int num) // 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 +// RUN: %klee --output-dir=%t.klee-out --write-kqueries --max-cycles-before-stuck=0 --use-guided-search=error --annotations=%annotations --mock-policy=all --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 // CHECK: KLEE: WARNING: 100.00% Reachable Reachable at trace 1 diff --git a/test/Industry/NullReturn_BadCase_WhiteBox01.c b/test/Industry/NullReturn_BadCase_WhiteBox01.c index 666c470216..0f0ab116e2 100644 --- a/test/Industry/NullReturn_BadCase_WhiteBox01.c +++ b/test/Industry/NullReturn_BadCase_WhiteBox01.c @@ -66,5 +66,5 @@ void NullReturn_BadCase_WhiteBox01(UINT8 index, SchedHarqStru *harqInfo) // 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 +// RUN: %klee --output-dir=%t.klee-out --smart-resolve-entry-function --use-guided-search=error --annotations=%annotations --mock-policy=all --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 diff --git a/test/Industry/NullReturn_Scene_BadCase01.c b/test/Industry/NullReturn_Scene_BadCase01.c index 45b8240318..b31fb67f34 100644 --- a/test/Industry/NullReturn_Scene_BadCase01.c +++ b/test/Industry/NullReturn_Scene_BadCase01.c @@ -41,5 +41,5 @@ void TestBad1() // 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 +// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --annotations=%annotations --mock-policy=all --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 // RUN: FileCheck -input-file=%t.klee-out/warnings.txt %s diff --git a/test/Industry/NullReturn_Scene_BadCase02.c b/test/Industry/NullReturn_Scene_BadCase02.c index d25af79653..c3a9099c04 100644 --- a/test/Industry/NullReturn_Scene_BadCase02.c +++ b/test/Industry/NullReturn_Scene_BadCase02.c @@ -40,5 +40,5 @@ void TestBad2() // 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 +// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --location-accuracy --annotations=%annotations --mock-policy=all --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 diff --git a/test/Industry/NullReturn_Scene_BadCase03.c b/test/Industry/NullReturn_Scene_BadCase03.c index c4190f9bb2..30d8a0d007 100644 --- a/test/Industry/NullReturn_Scene_BadCase03.c +++ b/test/Industry/NullReturn_Scene_BadCase03.c @@ -42,5 +42,5 @@ void TestBad3() // 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 +// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --annotations=%annotations --mock-policy=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 // RUN: FileCheck -input-file=%t.klee-out/warnings.txt %s diff --git a/test/Industry/NullReturn_Scene_BadCase04.c b/test/Industry/NullReturn_Scene_BadCase04.c index 377e4b9e19..f2fca4e757 100644 --- a/test/Industry/NullReturn_Scene_BadCase04.c +++ b/test/Industry/NullReturn_Scene_BadCase04.c @@ -46,6 +46,6 @@ void TestBad4() // 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 +// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --check-out-of-memory --annotations=%annotations --mock-policy=all --libc=klee --external-calls=all --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 -// CHEK: KLEE: WARNING: 100.00% NullPointerException True Positive at trace 1 \ No newline at end of file +// CHEK: KLEE: WARNING: 100.00% NullPointerException True Positive at trace 1 diff --git a/test/Industry/NullReturn_Scene_BadCase06.c b/test/Industry/NullReturn_Scene_BadCase06.c index 19b11d341b..8fbac9c0d7 100644 --- a/test/Industry/NullReturn_Scene_BadCase06.c +++ b/test/Industry/NullReturn_Scene_BadCase06.c @@ -54,7 +54,7 @@ void TestBad6(unsigned int count) // 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 +// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --annotations=%annotations --mock-policy=all --check-out-of-memory --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 // CHECK-DAG: KLEE: WARNING: 100.00% NullPointerException True Positive at trace 1 diff --git a/test/Industry/NullReturn_Scene_BadCase08.cpp b/test/Industry/NullReturn_Scene_BadCase08.cpp index 91e6dccdf8..d066fdc474 100644 --- a/test/Industry/NullReturn_Scene_BadCase08.cpp +++ b/test/Industry/NullReturn_Scene_BadCase08.cpp @@ -39,6 +39,6 @@ void TestBad9() // 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 +// RUN: %klee --output-dir=%t.klee-out --write-kqueries --use-guided-search=error --location-accuracy --annotations=%annotations --mock-policy=failed --check-out-of-memory --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 // CHECK: KLEE: WARNING: 100.00% NullPointerException False Positive at trace 2 \ No newline at end of file diff --git a/test/Industry/SecB_ForwardNull.c b/test/Industry/SecB_ForwardNull.c index e3a8334c82..522e1e6fe4 100644 --- a/test/Industry/SecB_ForwardNull.c +++ b/test/Industry/SecB_ForwardNull.c @@ -131,5 +131,5 @@ void badbad(char *ptr) // 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 +// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --annotations=%annotations --mock-policy=all --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 diff --git a/test/Industry/UseAfterFree/Double_Free_BadCase01.c b/test/Industry/UseAfterFree/Double_Free_BadCase01.c index 57d3600faa..34420ba6ee 100644 --- a/test/Industry/UseAfterFree/Double_Free_BadCase01.c +++ b/test/Industry/UseAfterFree/Double_Free_BadCase01.c @@ -38,5 +38,5 @@ void DoubleFreeBad01() // 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: %klee --output-dir=%t.klee-out --use-guided-search=error --annotations=%annotations --mock-policy=all --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 diff --git a/test/Industry/UseAfterFree/Double_Free_BadCase02.c b/test/Industry/UseAfterFree/Double_Free_BadCase02.c index be8f1c52c1..f048ea3234 100644 --- a/test/Industry/UseAfterFree/Double_Free_BadCase02.c +++ b/test/Industry/UseAfterFree/Double_Free_BadCase02.c @@ -41,5 +41,5 @@ void DoubleFreeBad02(int flag) // 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: %klee --output-dir=%t.klee-out --use-guided-search=error --annotations=%annotations --mock-policy=all --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 diff --git a/test/Industry/UseAfterFree/Free_Not_Set_Null_BadCase02.cpp b/test/Industry/UseAfterFree/Free_Not_Set_Null_BadCase02.cpp index 90a32d9903..9a6d3fdb5b 100644 --- a/test/Industry/UseAfterFree/Free_Not_Set_Null_BadCase02.cpp +++ b/test/Industry/UseAfterFree/Free_Not_Set_Null_BadCase02.cpp @@ -77,7 +77,7 @@ int main() // 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: %klee --output-dir=%t.klee-out --use-guided-search=error --annotations=%annotations --mock-policy=all --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 // CHECK: KLEE: WARNING: 100.00% UseAfterFree False Positive at trace 1 diff --git a/test/Industry/UseAfterFree/Prod_Dereference_After_Free_BadCase01.c b/test/Industry/UseAfterFree/Prod_Dereference_After_Free_BadCase01.c index 7742d31afd..a8e08c302b 100644 --- a/test/Industry/UseAfterFree/Prod_Dereference_After_Free_BadCase01.c +++ b/test/Industry/UseAfterFree/Prod_Dereference_After_Free_BadCase01.c @@ -35,5 +35,5 @@ void UseAfterFree() // 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: %klee --output-dir=%t.klee-out --use-guided-search=error --annotations=%annotations --mock-policy=all --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 diff --git a/test/Industry/ZeroDeref_Scene_BadCase02.c b/test/Industry/ZeroDeref_Scene_BadCase02.c index dd0fe063ac..31ac93948c 100644 --- a/test/Industry/ZeroDeref_Scene_BadCase02.c +++ b/test/Industry/ZeroDeref_Scene_BadCase02.c @@ -40,5 +40,5 @@ void TestBad9() // 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 +// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --annotations=%annotations --mock-policy=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 // RUN: FileCheck -input-file=%t.klee-out/warnings.txt %s diff --git a/test/Industry/ZeroDeref_Scene_BadCase05.c b/test/Industry/ZeroDeref_Scene_BadCase05.c index 3afb67837e..f531cf719c 100644 --- a/test/Industry/ZeroDeref_Scene_BadCase05.c +++ b/test/Industry/ZeroDeref_Scene_BadCase05.c @@ -64,7 +64,7 @@ void TestBad18(struct STU *stu) // 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 +// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --check-out-of-memory --annotations=%annotations --mock-policy=all --libc=klee --external-calls=all --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 // CHECK: KLEE: WARNING: 100.00% NullPointerException True Positive at trace 2 -// CHECK: KLEE: WARNING: 100.00% NullPointerException False Positive at trace 1 \ No newline at end of file +// CHECK: KLEE: WARNING: 100.00% NullPointerException False Positive at trace 1 diff --git a/test/Industry/egcd3-ll_valuebound10.c b/test/Industry/egcd3-ll_valuebound10.c index bc6c06f982..aa563ed00a 100644 --- a/test/Industry/egcd3-ll_valuebound10.c +++ b/test/Industry/egcd3-ll_valuebound10.c @@ -1,7 +1,7 @@ // 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=all --search=dfs --search=random-state %t1.bc +// RUN: %klee --output-dir=%t.klee-out --delete-dead-loops=false --emit-all-errors --mock-policy=all --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=all --search=dfs --search=random-state %t1.bc // RUN: rm -f ./%gcov-files-path*.gcda ./%gcov-files-path*.gcno ./%gcov-files-path*.gcov // RUN: %cc -DGCOV %s %libkleeruntest -Wl,-rpath %libkleeruntestdir -o %t_runner --coverage diff --git a/test/Industry/fn_reverse_null.c b/test/Industry/fn_reverse_null.c index aff52b8f68..630ac76e28 100644 --- a/test/Industry/fn_reverse_null.c +++ b/test/Industry/fn_reverse_null.c @@ -55,5 +55,5 @@ void TestErr4(TreeNode *head) // 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 +// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --external-calls=all --annotations=%annotations --mock-policy=all --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --check-out-of-memory --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc // RUN: FileCheck -input-file=%t.klee-out/warnings.txt %s diff --git a/test/Industry/fp_forward_null_address.c b/test/Industry/fp_forward_null_address.c index e090051722..b875cce44d 100644 --- a/test/Industry/fp_forward_null_address.c +++ b/test/Industry/fp_forward_null_address.c @@ -24,5 +24,5 @@ void foo() // 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 +// RUN: %klee --output-dir=%t.klee-out --max-cycles-before-stuck=150 --use-guided-search=error --annotations=%annotations --mock-policy=all --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 diff --git a/test/Industry/fp_null_returns_self_define.c b/test/Industry/fp_null_returns_self_define.c index fa331108b6..6329a45238 100644 --- a/test/Industry/fp_null_returns_self_define.c +++ b/test/Industry/fp_null_returns_self_define.c @@ -1,6 +1,6 @@ // 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: %klee --output-dir=%t.klee-out --use-guided-search=error --annotations=%annotations --mock-policy=all --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 #include diff --git a/test/Industry/fp_null_returns_self_define2.c b/test/Industry/fp_null_returns_self_define2.c index 6606140676..551e7aed67 100644 --- a/test/Industry/fp_null_returns_self_define2.c +++ b/test/Industry/fp_null_returns_self_define2.c @@ -28,5 +28,5 @@ void TEST_NullReturns004(unsigned short index) // 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: %klee --output-dir=%t.klee-out --use-guided-search=error --annotations=%annotations --mock-policy=all --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 diff --git a/test/Industry/if2.c b/test/Industry/if2.c index 57422bf2d5..b6ef8b0982 100644 --- a/test/Industry/if2.c +++ b/test/Industry/if2.c @@ -10,7 +10,7 @@ int main(int x) { // 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-instructions=45 --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 --annotations=%annotations --mock-policy=all --skip-not-symbolic-objects --skip-not-lazy-initialized --check-out-of-memory --search=bfs --max-instructions=45 --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 diff --git a/test/Industry/test.c b/test/Industry/test.c index 5b08e0cd97..500ab31738 100644 --- a/test/Industry/test.c +++ b/test/Industry/test.c @@ -21,8 +21,8 @@ void TestBad8(int len) // 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 +// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --annotations=%annotations --mock-policy=all --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --check-out-of-memory --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc // RUN: FileCheck -input-file=%t.klee-out/warnings.txt %s -check-prefix=CHECK-NUM // 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.sarif %t1.bc +// RUN: %klee --output-dir=%t.klee-out --use-guided-search=error --annotations=%annotations --mock-policy=all --libc=klee --skip-not-symbolic-objects --skip-not-lazy-initialized --check-out-of-memory --use-lazy-initialization=only --analysis-reproduce=%s.sarif %t1.bc // RUN: FileCheck -input-file=%t.klee-out/warnings.txt %s -check-prefix=CHECK-UID diff --git a/test/Industry/while_true.c b/test/Industry/while_true.c index 72aac7f704..ffbf90e30b 100644 --- a/test/Industry/while_true.c +++ b/test/Industry/while_true.c @@ -10,14 +10,14 @@ int main() { // 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=20 --max-cycles-before-stuck=0 --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc +// RUN: %klee --output-dir=%t.klee-out-1 --use-guided-search=error --mock-policy=failed --skip-not-symbolic-objects --skip-not-lazy-initialized --check-out-of-memory --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-1/warnings.txt %s -check-prefix=CHECK-NONE // CHECK-NONE: KLEE: WARNING: 0.00% NullPointerException False Positive at trace 1 // RUN: FileCheck -input-file=%t.klee-out-1/messages.txt %s -check-prefix=CHECK-REACH-1 // CHECK-REACH-1: (0, 1, 4) for Target 1: error in function main (lines 8 to 8) // RUN: rm -rf %t.klee-out-2 -// RUN: %klee --output-dir=%t.klee-out-2 --use-guided-search=error --mock-external-calls --skip-not-symbolic-objects --skip-not-lazy-initialized --check-out-of-memory --max-stepped-instructions=4980 --max-cycles-before-stuck=0 --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc +// RUN: %klee --output-dir=%t.klee-out-2 --use-guided-search=error --mock-policy=failed --skip-not-symbolic-objects --skip-not-lazy-initialized --check-out-of-memory --max-stepped-instructions=4980 --max-cycles-before-stuck=0 --use-lazy-initialization=only --analysis-reproduce=%s.json %t1.bc // RUN: FileCheck -input-file=%t.klee-out-2/warnings.txt %s -check-prefix=CHECK-ALL // CHECK-ALL: KLEE: WARNING: 99.00% NullPointerException False Positive at trace 1 // RUN: FileCheck -input-file=%t.klee-out-2/messages.txt %s -check-prefix=CHECK-REACH-2 diff --git a/test/Replay/libkleeruntest/replay_mocks.c b/test/Replay/libkleeruntest/replay_mocks.c index cfd151a9e5..615bea931b 100644 --- a/test/Replay/libkleeruntest/replay_mocks.c +++ b/test/Replay/libkleeruntest/replay_mocks.c @@ -1,12 +1,19 @@ // REQUIRES: geq-llvm-11.0 +// REQUIRES: not-darwin // RUN: %clang %s -emit-llvm -g %O0opt -c -o %t.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --external-calls=all --mock-strategy=naive %t.bc -// RUN: %clang -c %t.bc -o %t.o -// RUN: %llvmobjcopy --redefine-syms %t.klee-out/redefinitions.txt %t.o -// RUN: %clang -o %t.klee-out/a.out %libkleeruntest %t.klee-out/externals.ll %t.o +// RUN: %klee --output-dir=%t.klee-out --mock-policy=all %t.bc + +// RUN: %llc %t.bc -filetype=obj -o %t.o +// RUN: %llc %t.klee-out/externals.ll -filetype=obj -o %t_externals.o +// RUN: %objcopy --redefine-syms %t.klee-out/redefinitions.txt %t.o +// RUN: %cc -no-pie %t_externals.o %t.o %libkleeruntest -Wl,-rpath %libkleeruntestdir -o %t_runner +// RUN: test -f %t.klee-out/test000001.ktest +// RUN: env KTEST_FILE=%t.klee-out/test000001.ktest %t_runner + +// RUN: %runmocks %cc -no-pie %libkleeruntest -Wl,-rpath %libkleeruntestdir -o %t_runner2 %t.klee-out %t.bc // RUN: test -f %t.klee-out/test000001.ktest -// RUN: env KTEST_FILE=%t.klee-out/test000001.ktest %t.klee-out/a.out +// RUN: env KTEST_FILE=%t.klee-out/test000001.ktest %t_runner2 extern int variable; @@ -15,5 +22,6 @@ extern int foo(int); int main() { int a; klee_make_symbolic(&a, sizeof(a), "a"); - return variable + foo(a); + a = variable + foo(a); + return 0; } diff --git a/test/Solver/sina2f.c b/test/Solver/sina2f.c index 628a8e0e8b..c732bf2ddb 100644 --- a/test/Solver/sina2f.c +++ b/test/Solver/sina2f.c @@ -3,7 +3,7 @@ // REQUIRES: not-msan // RUN: %clang %s -emit-llvm %O0opt -g -c -o %t1.bc // RUN: rm -rf %t.klee-out -// RUN: %klee --output-dir=%t.klee-out --strip-unwanted-calls --delete-dead-loops=false --emit-all-errors --mock-all-externals --use-forked-solver=false --solver-backend=bitwuzla-tree --max-solvers-approx-tree-inc=16 --max-memory=6008 --optimize --skip-not-lazy-initialized --output-source=false --output-stats=false --output-istats=false --use-sym-size-alloc=true --cex-cache-validity-cores --fp-runtime --x86FP-as-x87FP80 --symbolic-allocation-threshold=8192 --allocate-determ --allocate-determ-size=3072 --allocate-determ-start-address=0x00030000000 --mem-trigger-cof --use-alpha-equivalence=true --track-coverage=all --use-iterative-deepening-search=max-cycles --max-solver-time=5s --max-cycles-before-stuck=15 --only-output-states-covering-new --dump-states-on-halt=all --search=dfs --search=random-state --cover-on-the-fly=true --delay-cover-on-the-fly=27 --max-time=29 %t1.bc 2>&1 | FileCheck %s +// RUN: %klee --output-dir=%t.klee-out --strip-unwanted-calls --delete-dead-loops=false --emit-all-errors --mock-policy=all --use-forked-solver=false --solver-backend=bitwuzla-tree --max-solvers-approx-tree-inc=16 --max-memory=6008 --optimize --skip-not-lazy-initialized --output-source=false --output-stats=false --output-istats=false --use-sym-size-alloc=true --cex-cache-validity-cores --fp-runtime --x86FP-as-x87FP80 --symbolic-allocation-threshold=8192 --allocate-determ --allocate-determ-size=3072 --allocate-determ-start-address=0x00030000000 --mem-trigger-cof --use-alpha-equivalence=true --track-coverage=all --use-iterative-deepening-search=max-cycles --max-solver-time=5s --max-cycles-before-stuck=15 --only-output-states-covering-new --dump-states-on-halt=all --search=dfs --search=random-state --cover-on-the-fly=true --delay-cover-on-the-fly=27 --max-time=29 %t1.bc 2>&1 | FileCheck %s #include "klee-test-comp.c" /* diff --git a/test/lit.cfg b/test/lit.cfg index 72144bfe1e..79f071b5c0 100644 --- a/test/lit.cfg +++ b/test/lit.cfg @@ -90,7 +90,7 @@ if config.test_exec_root is None: # Add substitutions from lit.site.cfg -subs = [ 'clangxx', 'clang', 'cc', 'cxx', 'O0opt', 'c_prefixes_8', 'c_prefixes_10', 'cpp_prefixes_10' ] +subs = [ 'clangxx', 'clang', 'cc', 'objcopy', 'cxx', 'O0opt', 'c_prefixes_8', 'c_prefixes_10', 'cpp_prefixes_10' ] for name in subs: value = getattr(config, name, None) if value == None: @@ -105,6 +105,12 @@ config.substitutions.append( config.substitutions.append( ('%lli', os.path.join(llvm_tools_dir, 'lli')) ) + +# Add a substitution for llc. +config.substitutions.append( + ('%llc', os.path.join(llvm_tools_dir, 'llc')) +) + # Add a substitution for llvm-as config.substitutions.append( ('%llvmas', os.path.join(llvm_tools_dir, 'llvm-as')) @@ -179,6 +185,10 @@ config.substitutions.append( ('%replay', os.path.join(klee_src_root, 'scripts/replay.sh')) ) +config.substitutions.append( + ('%annotations', os.path.join(klee_src_root, 'configs/annotations.json')) +) + config.substitutions.append( ('%libcxx_include', getattr(config, 'libcxx_include_dir', None))) diff --git a/test/lit.site.cfg.in b/test/lit.site.cfg.in index fb4ed1c586..17ad995b8d 100644 --- a/test/lit.site.cfg.in +++ b/test/lit.site.cfg.in @@ -35,6 +35,7 @@ config.clang = "@LLVMCC@" config.clangxx = "@LLVMCXX@" config.cc = "@NATIVE_CC@" +config.objcopy = "@NATIVE_OBJCOPY@" config.cxx = "@NATIVE_CXX@" # NOTE: any changes to compiler flags also have to be applied to diff --git a/test/regression/2023-10-02-test-from-mocked-global.c b/test/regression/2023-10-02-test-from-mocked-global.c index a62eeb9bba..c89bc74ec9 100644 --- a/test/regression/2023-10-02-test-from-mocked-global.c +++ b/test/regression/2023-10-02-test-from-mocked-global.c @@ -2,7 +2,7 @@ // 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: %klee --mock-policy=all --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__)); @@ -13,4 +13,4 @@ int main() { return 0; } -// CHECK-NOT: XMLMetadataProgramHash( llvm::cl::desc("Test-Comp hash sum of original file for xml metadata"), llvm::cl::cat(TestCompCat)); - /*** Mocking options ***/ -cl::OptionCategory MockCat("Mock category"); - -cl::opt MockLinkedExternals( - "mock-linked-externals", - cl::desc("Mock modelled linked externals (default=false)"), cl::init(false), - cl::cat(MockCat)); - -cl::opt MockUnlinkedStrategy( - "mock-strategy", cl::init(MockStrategy::None), - cl::desc("Specify strategy for mocking external calls"), +cl::OptionCategory MockCat("Mocking options"); + +cl::opt MockModeledFunction( + "mock-modeled-functions", + cl::desc("Link modeled mocks from libkleeRuntimeMocks (default=false)"), + cl::init(false), cl::cat(MockCat)); + +cl::opt + Mock("mock-policy", cl::desc("Specify policy for mocking external calls"), + cl::values(clEnumValN(MockPolicy::None, "none", + "No mock function generated (default)"), + clEnumValN(MockPolicy::Failed, "failed", + "Generate symbolic value for failed external " + "calls, test will be irreproducible"), + clEnumValN(MockPolicy::All, "all", + "Generate IR module with all external symbols")), + cl::init(MockPolicy::None), cl::cat(MockCat)); + +cl::opt MockStrategy( + "mock-strategy", cl::desc("Specify strategy for mocking external calls"), cl::values( - clEnumValN(MockStrategy::None, "none", - "External calls are not mocked (default)"), - clEnumValN(MockStrategy::Naive, "naive", + clEnumValN(MockStrategyKind::Naive, "naive", "Every time external function is called, new symbolic value " - "is generated for its return value"), + "is generated for its return value (default)"), clEnumValN( - MockStrategy::Deterministic, "deterministic", + MockStrategyKind::Deterministic, "deterministic", "NOTE: this option is compatible with Z3 solver only. Each " "external function is treated as a deterministic " "function. Therefore, when function is called many times " "with equal arguments, every time equal values will be returned.")), - cl::init(MockStrategy::None), cl::cat(MockCat)); + cl::init(MockStrategyKind::Naive), cl::cat(MockCat)); -/*** Annotations options ***/ +cl::opt MockMutableGlobals( + "mock-mutable-globals", + cl::desc("Specify strategy for mocking global vars"), + cl::values( + clEnumValN(MockMutableGlobalsPolicy::None, "none", + "No mutable global object are allowed o mock except " + "external (default)"), + clEnumValN(MockMutableGlobalsPolicy::All, "all", + "Mock globals on module build stage and generate bicode " + "module for it")), + cl::init(MockMutableGlobalsPolicy::None), cl::cat(MockCat)); -cl::OptionCategory AnnotCat("Annotations category"); +/*** Annotations options ***/ cl::opt AnnotationsFile("annotations", cl::desc("Path to the annotation JSON file"), - cl::value_desc("path file"), - cl::cat(AnnotCat)); + cl::value_desc("path file"), cl::cat(MockCat)); + +cl::opt AnnotateOnlyExternal( + "annotate-only-external", + cl::desc("Ignore annotations for defined function (default=false)"), + cl::init(false), cl::cat(MockCat)); } // namespace @@ -1073,10 +1091,25 @@ static const char *dontCareExternals[] = { #endif // static information, pretty ok to return - "getegid", "geteuid", "getgid", "getuid", "getpid", "gethostname", - "getpgrp", "getppid", "getpagesize", "getpriority", "getgroups", - "getdtablesize", "getrlimit", "getrlimit64", "getcwd", "getwd", - "gettimeofday", "uname", "ioctl", + "getegid", + "geteuid", + "getgid", + "getuid", + "getpid", + "gethostname", + "getpgrp", + "getppid", + "getpagesize", + "getpriority", + "getgroups", + "getdtablesize", + "getrlimit", + "getrlimit64", + "getcwd", + "getwd", + "gettimeofday", + "uname", + "ioctl", // fp stuff we just don't worry about yet "frexp", @@ -1297,7 +1330,7 @@ createLibCWrapper(std::vector> &userModules, args.push_back(llvm::ConstantExpr::getBitCast( cast(inModuleReference.getCallee()), ft->getParamType(0))); - args.push_back(&*(stub->arg_begin())); // argc + args.push_back(&*(stub->arg_begin())); // argc auto arg_it = stub->arg_begin(); args.push_back(&*(++arg_it)); // argv args.push_back(Constant::getNullValue(ft->getParamType(3))); // app_init @@ -1586,38 +1619,34 @@ void wait_until_any_child_dies( } } -void mockLinkedExternals( +void mockModeledFunction( const Interpreter::ModuleOptions &Opts, llvm::LLVMContext &ctx, llvm::Module *mainModule, std::vector> &loadedLibsModules, - llvm::raw_string_ostream *redefineFile) { + std::vector> &redefinitions) { std::string errorMsg; std::vector> mockModules; SmallString<128> Path(Opts.LibraryDir); llvm::sys::path::append(Path, "libkleeRuntimeMocks" + Opts.OptSuffix + ".bca"); klee_message("NOTE: Using mocks model %s for linked externals", Path.c_str()); - if (!klee::loadFileAsOneModule(Path.c_str(), ctx, mockModules, errorMsg)) { + if (!klee::loadFileAsOneModule(Path.c_str(), ctx, loadedLibsModules, + errorMsg)) { klee_error("error loading mocks model '%s': %s", Path.c_str(), errorMsg.c_str()); } - for (auto &module : mockModules) { - for (const auto &fmodel : module->functions()) { - if (fmodel.getName().str().substr(0, 15) != "__klee_wrapped_") { - continue; - } - llvm::Function *f = - mainModule->getFunction(fmodel.getName().str().substr(15)); - if (!f) { - continue; - } + for (const auto &fmodel : loadedLibsModules.back()->functions()) { + if (fmodel.getName().str().substr(0, 15) != "__klee_wrapped_") { + continue; + } + if (llvm::Function *f = + mainModule->getFunction(fmodel.getName().str().substr(15))) { klee_message("Renamed symbol %s to %s", f->getName().str().c_str(), fmodel.getName().str().c_str()); - *redefineFile << f->getName() << ' ' << fmodel.getName() << '\n'; + redefinitions.emplace_back(f->getName(), fmodel.getName()); f->setName(fmodel.getName()); } - loadedLibsModules.push_back(std::move(module)); } } @@ -1999,12 +2028,6 @@ int main(int argc, char **argv, char **envp) { klee_warning("Module and host target triples do not match: '%s' != '%s'\n" "This may cause unexpected crashes or assertion violations.", module_triple.c_str(), host_triple.c_str()); - - llvm::Function *initialMainFn = mainModule->getFunction(EntryPoint); - if (!initialMainFn) { - klee_error("Entry function '%s' not found in module.", EntryPoint.c_str()); - } - // Detect architecture std::string bit_suffix = "64"; // Fall back to 64bit if (module_triple.find("i686") != std::string::npos || @@ -2023,13 +2046,15 @@ int main(int argc, char **argv, char **envp) { std::string LibraryDir = KleeHandler::getRunTimeLibraryPath(argv[0]); Interpreter::ModuleOptions Opts( - LibraryDir.c_str(), EntryPoint, opt_suffix, + LibraryDir, EntryPoint, opt_suffix, /*MainCurrentName=*/EntryPoint, /*MainNameAfterMock=*/"__klee_mock_wrapped_main", + /*AnnotationsFile=*/AnnotationsFile, /*Optimize=*/OptimizeModule, /*Simplify*/ SimplifyModule, /*CheckDivZero=*/CheckDivZero, /*CheckOvershift=*/CheckOvershift, + /*AnnotateOnlyExternal=*/AnnotateOnlyExternal, /*WithFPRuntime=*/WithFPRuntime, /*WithPOSIXRuntime=*/WithPOSIXRuntime); @@ -2053,15 +2078,15 @@ int main(int argc, char **argv, char **envp) { if (!entryFn) klee_error("Entry function '%s' not found in module.", EntryPoint.c_str()); - std::string redefinitions; - llvm::raw_string_ostream o_redefinitions(redefinitions); - if (MockLinkedExternals) { - mockLinkedExternals(Opts, ctx, mainModule, loadedLibsModules, - &o_redefinitions); + std::vector> redefinitions; + if (Mock == MockPolicy::All || + MockMutableGlobals == MockMutableGlobalsPolicy::All || + AnnotationsFile.empty()) { + redefinitions.emplace_back(EntryPoint, Opts.MainNameAfterMock); } - - if (MockUnlinkedStrategy != MockStrategy::None) { - o_redefinitions << EntryPoint << ' ' << Opts.MainNameAfterMock << '\n'; + if (MockModeledFunction) { + mockModeledFunction(Opts, ctx, mainModule, loadedLibsModules, + redefinitions); } if (WithPOSIXRuntime) { @@ -2227,14 +2252,13 @@ int main(int argc, char **argv, char **envp) { UseGuidedSearch = Interpreter::GuidanceKind::ErrorGuidance; } - const Annotations annotations = (AnnotationsFile.empty()) - ? Annotations() - : parseAnnotationsFile(AnnotationsFile); - Interpreter::InterpreterOptions IOpts(paths); IOpts.MakeConcreteSymbolic = MakeConcreteSymbolic; IOpts.Guidance = UseGuidedSearch; - IOpts.MockStrategy = MockUnlinkedStrategy; + IOpts.Mock = Mock; + IOpts.MockStrategy = MockStrategy; + IOpts.MockMutableGlobals = MockMutableGlobals; + std::unique_ptr interpreter( Interpreter::create(ctx, IOpts, handler.get())); theInterpreter = interpreter.get(); @@ -2270,13 +2294,7 @@ int main(int argc, char **argv, char **envp) { ignoredExternals.insert("syscall"); } - Opts.MainCurrentName = initialMainFn->getName().str(); - - if (MockLinkedExternals || MockUnlinkedStrategy != MockStrategy::None) { - o_redefinitions.flush(); - auto f_redefinitions = handler->openOutputFile("redefinitions.txt"); - *f_redefinitions << redefinitions; - } + Opts.MainCurrentName = entryFn->getName().str(); // Get the desired main function. klee_main initializes uClibc // locale and other data and then calls main. @@ -2284,7 +2302,7 @@ int main(int argc, char **argv, char **envp) { auto finalModule = interpreter->setModule( loadedUserModules, loadedLibsModules, Opts, std::move(mainModuleFunctions), std::move(mainModuleGlobals), - std::move(origInstructions), ignoredExternals, annotations); + std::move(origInstructions), ignoredExternals, redefinitions); Function *mainFn = finalModule->getFunction(EntryPoint); if (!mainFn) { klee_error("Entry function '%s' not found in module.", EntryPoint.c_str()); diff --git a/unittests/Annotations/AnnotationsTest.cpp b/unittests/Annotations/AnnotationsTest.cpp index 9d67ab9461..7c3b90de3f 100644 --- a/unittests/Annotations/AnnotationsTest.cpp +++ b/unittests/Annotations/AnnotationsTest.cpp @@ -1,3 +1,12 @@ +//===-- AnnotationTest.cpp ------------------------------------------------===// +// +// The KLEEF Symbolic Virtual Machine +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + #include "gtest/gtest.h" #include "klee/Module/Annotation.h" @@ -10,15 +19,18 @@ TEST(AnnotationsTest, Empty) { const json j = json::parse(R"( { "foo" : { - "annotation" : [], + "annotation" : [[]], "properties" : [] } } )"); - const Annotations expected = Annotations{ - {"foo", Annotation{"foo", std::vector(), - std::set()}}}; - const Annotations actual = parseAnnotationsFile(j); + const AnnotationsMap expected = { + {"foo", + {/*functionName*/ "foo", + /*returnStatements*/ std::vector(), + /*argsStatements*/ std::vector>(), + /*properties*/ std::set()}}}; + const AnnotationsMap actual = parseAnnotationsJson(j); ASSERT_EQ(expected, actual); } @@ -26,17 +38,20 @@ TEST(AnnotationsTest, KnownProperties) { const json j = json::parse(R"( { "foo" : { - "annotation" : [], - "properties" : ["determ", "noreturn", "determ"] + "annotation" : [[]], + "properties" : ["deterministic", "noreturn", "deterministic"] } } )"); - const std::set properties{ - Annotation::Property::Determ, Annotation::Property::Noreturn}; - const Annotations expected = Annotations{ - {"foo", Annotation{"foo", std::vector(), - properties}}}; - const Annotations actual = parseAnnotationsFile(j); + const std::set properties{ + Statement::Property::Deterministic, Statement::Property::Noreturn}; + const AnnotationsMap expected = { + {"foo", + {/*functionName*/ "foo", + /*returnStatements*/ std::vector(), + /*argsStatements*/ std::vector>(), + /*properties*/ properties}}}; + const AnnotationsMap actual = parseAnnotationsJson(j); ASSERT_EQ(expected, actual); } @@ -44,18 +59,21 @@ TEST(AnnotationsTest, UnknownProperties) { const json j = json::parse(R"( { "foo" : { - "annotation" : [], - "properties" : ["derm", "noreturn", "determ"] + "annotation" : [[]], + "properties" : ["noname", "noreturn", "deterministic"] } } )"); - const std::set properties{ - Annotation::Property::Determ, Annotation::Property::Noreturn, - Annotation::Property::Unknown}; - const Annotations expected = Annotations{ - {"foo", Annotation{"foo", std::vector(), - properties}}}; - const Annotations actual = parseAnnotationsFile(j); + const std::set properties{ + Statement::Property::Deterministic, Statement::Property::Noreturn, + Statement::Property::Unknown}; + const AnnotationsMap expected = { + {"foo", + {/*functionName*/ "foo", + /*returnStatements*/ std::vector(), + /*argsStatements*/ std::vector>(), + /*properties*/ properties}}}; + const AnnotationsMap actual = parseAnnotationsJson(j); ASSERT_EQ(expected, actual); } @@ -68,27 +86,27 @@ TEST(AnnotationsTest, UnknownAnnotations) { } } )"); - const Annotations actual = parseAnnotationsFile(j); - ASSERT_EQ(actual.at("foo").statements[1][0]->getStatementName(), - Annotation::StatementKind::Unknown); + const AnnotationsMap actual = parseAnnotationsJson(j); + ASSERT_EQ(actual.at("foo").argsStatements[0][0]->getKind(), + Statement::Kind::Unknown); } TEST(AnnotationsTest, KnownAnnotations) { const json j = json::parse(R"( { "foo" : { - "annotation" : [["InitNull"], ["Deref", "InitNull"]], + "annotation" : [["MaybeInitNull"], ["Deref", "InitNull"]], "properties" : [] } } )"); - const Annotations actual = parseAnnotationsFile(j); - ASSERT_EQ(actual.at("foo").statements[0][0]->getStatementName(), - Annotation::StatementKind::InitNull); - ASSERT_EQ(actual.at("foo").statements[1][0]->getStatementName(), - Annotation::StatementKind::Deref); - ASSERT_EQ(actual.at("foo").statements[1][1]->getStatementName(), - Annotation::StatementKind::InitNull); + const AnnotationsMap actual = parseAnnotationsJson(j); + ASSERT_EQ(actual.at("foo").returnStatements[0]->getKind(), + Statement::Kind::MaybeInitNull); + ASSERT_EQ(actual.at("foo").argsStatements[0][0]->getKind(), + Statement::Kind::Deref); + ASSERT_EQ(actual.at("foo").argsStatements[0][1]->getKind(), + Statement::Kind::InitNull); } TEST(AnnotationsTest, WithOffsets) { @@ -100,9 +118,9 @@ TEST(AnnotationsTest, WithOffsets) { } } )"); - const Annotations actual = parseAnnotationsFile(j); - ASSERT_EQ(actual.at("foo").statements[0][0]->getStatementName(), - Annotation::StatementKind::InitNull); + const AnnotationsMap actual = parseAnnotationsJson(j); + ASSERT_EQ(actual.at("foo").returnStatements[0]->getKind(), + Statement::Kind::InitNull); const std::vector expectedOffset{"*", "10", "*", "&"}; - ASSERT_EQ(actual.at("foo").statements[0][0]->offset, expectedOffset); + ASSERT_EQ(actual.at("foo").returnStatements[0]->offset, expectedOffset); } From edce9292e4e2fd3cedf88ab95012e4754c43df4c Mon Sep 17 00:00:00 2001 From: Sergey Morozov Date: Thu, 22 Feb 2024 19:00:12 +0300 Subject: [PATCH 118/120] [chore] clang-format CI check replaced with pre-commit hook using clang-format. --- .github/workflows/build.yaml | 14 +++++++------- .pre-commit-config.yaml | 7 +++++++ 2 files changed, 14 insertions(+), 7 deletions(-) create mode 100644 .pre-commit-config.yaml diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 2e531d15da..2e911bd10a 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -213,10 +213,10 @@ jobs: clang-format: runs-on: ubuntu-latest steps: - - name: Checkout KLEE Code - uses: actions/checkout@v2 - - name: Run clang-format on KLEE Code - uses: jidicula/clang-format-action@v4.10.2 - with: - clang-format-version: '13' - include-regex: '(^.*\.((((c|C)(c|pp|xx|\+\+)?$)|((h|H)h?(pp|xx|\+\+)?$))|((ino|pde|proto|cu))$)|^(include|lib)\/.*\.inc)$' + - uses: actions/checkout@v3 + - uses: actions/setup-python@v4 + with: + python-version: 3.x + - uses: pre-commit/action@v3.0.1 + - uses: pre-commit-ci/lite-action@v1.0.2 + if: always() diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000000..be6def773b --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,7 @@ +files: '(^.*\.((((c|C)(c|pp|xx|\+\+)?$)|((h|H)h?(pp|xx|\+\+)?$))|((ino|pde|proto|cu))$)|^(include|lib)\/.*\.inc)$' + +repos: +- repo: https://github.com/pre-commit/mirrors-clang-format + rev: v13.0.1 + hooks: + - id: clang-format From 6b24f901b7e1a647e548e21e989d9e610946d621 Mon Sep 17 00:00:00 2001 From: Sergey Morozov Date: Tue, 27 Feb 2024 13:09:22 +0300 Subject: [PATCH 119/120] [chore, git] make entire pipeline dependent on the result of the clang-format check. --- .github/workflows/build-in-base-env.yml | 9 +++++---- .github/workflows/build.yaml | 23 ++++++++--------------- .github/workflows/clang-format.yaml | 20 ++++++++++++++++++++ 3 files changed, 33 insertions(+), 19 deletions(-) create mode 100644 .github/workflows/clang-format.yaml diff --git a/.github/workflows/build-in-base-env.yml b/.github/workflows/build-in-base-env.yml index daf22bff94..04b7da3633 100644 --- a/.github/workflows/build-in-base-env.yml +++ b/.github/workflows/build-in-base-env.yml @@ -1,14 +1,15 @@ name: Build in UTBot base_env on: - pull_request: - branches: [utbot-main] - push: - branches: [utbot-main] + workflow_run: + workflows: ["Clang Format"] + types: + - completed jobs: build: runs-on: ubuntu-latest + if: ${{ github.event.workflow_run.conclusion == 'success' }} container: image: ghcr.io/unittestbot/utbotcpp/base_env:02-02-2022 credentials: diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 2e911bd10a..192af2535f 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -2,10 +2,10 @@ name: CI on: - pull_request: - branches: [main, utbot-main] - push: - branches: [main, utbot-main] + workflow_run: + workflows: ["Clang Format"] + types: + - completed # Defaults for building KLEE env: @@ -35,6 +35,7 @@ env: jobs: Linux: runs-on: ubuntu-latest + if: ${{ github.event.workflow_run.conclusion == 'success' }} strategy: matrix: name: [ @@ -144,6 +145,7 @@ jobs: macOS: runs-on: macos-latest + if: ${{ github.event.workflow_run.conclusion == 'success' }} env: BASE: /tmp SOLVERS: STP @@ -164,6 +166,7 @@ jobs: Docker: runs-on: ubuntu-latest + if: ${{ github.event.workflow_run.conclusion == 'success' }} steps: - name: Checkout KLEE Code uses: actions/checkout@v3 @@ -174,6 +177,7 @@ jobs: Coverage: runs-on: ubuntu-latest + if: ${{ github.event.workflow_run.conclusion == 'success' }} strategy: matrix: name: [ @@ -209,14 +213,3 @@ jobs: - name: Run tests env: ${{ matrix.env }} run: scripts/build/run-tests.sh --coverage --upload-coverage --run-docker --debug - - clang-format: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 - with: - python-version: 3.x - - uses: pre-commit/action@v3.0.1 - - uses: pre-commit-ci/lite-action@v1.0.2 - if: always() diff --git a/.github/workflows/clang-format.yaml b/.github/workflows/clang-format.yaml new file mode 100644 index 0000000000..12d8135906 --- /dev/null +++ b/.github/workflows/clang-format.yaml @@ -0,0 +1,20 @@ +--- +name: Clang Format + +on: + pull_request: + branches: [main, utbot-main] + push: + branches: [main, utbot-main] + +jobs: + clang-format: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v4 + with: + python-version: 3.x + - uses: pre-commit/action@v3.0.1 + - uses: pre-commit-ci/lite-action@v1.0.2 + if: always() From f9918657b2bc971c1c9de3d3f6405132211286ca Mon Sep 17 00:00:00 2001 From: Sergey Morozov Date: Tue, 27 Feb 2024 13:30:41 +0300 Subject: [PATCH 120/120] [test] --- lib/Core/AddressManager.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/Core/AddressManager.cpp b/lib/Core/AddressManager.cpp index b0219fb9ea..c89e0adce4 100644 --- a/lib/Core/AddressManager.cpp +++ b/lib/Core/AddressManager.cpp @@ -21,6 +21,7 @@ void *AddressManager::allocate(ref address, uint64_t size) { newMO = sizeLocation->second; } else { newMO = nullptr; + objects[size] = newMO; } } else {