aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorchriseth <chris@ethereum.org>2017-12-18 22:10:28 +0800
committerGitHub <noreply@github.com>2017-12-18 22:10:28 +0800
commit2e2f819fd6e62ec757a5eba75556d2890d5a2ad3 (patch)
tree6b932b5574ddb6fccdbe038dcb59c733417b7735
parentdbad74ac1b8974884fc6c60a6cb9ed054aabc139 (diff)
parenta1e296e3928b90c9a575e5e816abc566bba35493 (diff)
downloaddexon-solidity-2e2f819fd6e62ec757a5eba75556d2890d5a2ad3.tar
dexon-solidity-2e2f819fd6e62ec757a5eba75556d2890d5a2ad3.tar.gz
dexon-solidity-2e2f819fd6e62ec757a5eba75556d2890d5a2ad3.tar.bz2
dexon-solidity-2e2f819fd6e62ec757a5eba75556d2890d5a2ad3.tar.lz
dexon-solidity-2e2f819fd6e62ec757a5eba75556d2890d5a2ad3.tar.xz
dexon-solidity-2e2f819fd6e62ec757a5eba75556d2890d5a2ad3.tar.zst
dexon-solidity-2e2f819fd6e62ec757a5eba75556d2890d5a2ad3.zip
Merge pull request #3304 from leonardoalt/smt_checker
[SMTChecker] Keep track of current path conditions
-rw-r--r--libsolidity/formal/SMTChecker.cpp45
-rw-r--r--libsolidity/formal/SMTChecker.h13
-rw-r--r--libsolidity/formal/SolverInterface.h5
3 files changed, 55 insertions, 8 deletions
diff --git a/libsolidity/formal/SMTChecker.cpp b/libsolidity/formal/SMTChecker.cpp
index a22e35d6..d4887a3d 100644
--- a/libsolidity/formal/SMTChecker.cpp
+++ b/libsolidity/formal/SMTChecker.cpp
@@ -71,6 +71,7 @@ bool SMTChecker::visit(FunctionDefinition const& _function)
m_interface->reset();
m_currentSequenceCounter.clear();
m_nextFreeSequenceCounter.clear();
+ m_pathConditions.clear();
m_conditionalExecutionHappened = false;
initializeLocalVariables(_function);
return true;
@@ -344,14 +345,14 @@ void SMTChecker::endVisit(FunctionCall const& _funCall)
solAssert(args.size() == 1, "");
solAssert(args[0]->annotation().type->category() == Type::Category::Bool, "");
checkCondition(!(expr(*args[0])), _funCall.location(), "Assertion violation");
- m_interface->addAssertion(expr(*args[0]));
+ addPathImpliedExpression(expr(*args[0]));
}
else if (funType.kind() == FunctionType::Kind::Require)
{
solAssert(args.size() == 1, "");
solAssert(args[0]->annotation().type->category() == Type::Category::Bool, "");
checkBooleanNotConstant(*args[0], "Condition is always $VALUE.");
- m_interface->addAssertion(expr(*args[0]));
+ addPathImpliedExpression(expr(*args[0]));
}
}
@@ -514,11 +515,11 @@ void SMTChecker::visitBranch(Statement const& _statement, smt::Expression const*
{
VariableSequenceCounters sequenceCountersStart = m_currentSequenceCounter;
- m_interface->push();
if (_condition)
- m_interface->addAssertion(*_condition);
+ pushPathCondition(*_condition);
_statement.accept(*this);
- m_interface->pop();
+ if (_condition)
+ popPathCondition();
m_conditionalExecutionHappened = true;
m_currentSequenceCounter = sequenceCountersStart;
@@ -533,7 +534,7 @@ void SMTChecker::checkCondition(
)
{
m_interface->push();
- m_interface->addAssertion(_condition);
+ addPathConjoinedExpression(_condition);
vector<smt::Expression> expressionsToEvaluate;
vector<string> expressionNames;
@@ -605,12 +606,12 @@ void SMTChecker::checkBooleanNotConstant(Expression const& _condition, string co
return;
m_interface->push();
- m_interface->addAssertion(expr(_condition));
+ addPathConjoinedExpression(expr(_condition));
auto positiveResult = checkSatisifable();
m_interface->pop();
m_interface->push();
- m_interface->addAssertion(!expr(_condition));
+ addPathConjoinedExpression(!expr(_condition));
auto negatedResult = checkSatisifable();
m_interface->pop();
@@ -828,3 +829,31 @@ smt::Expression SMTChecker::var(Declaration const& _decl)
solAssert(m_variables.count(&_decl), "");
return m_variables.at(&_decl);
}
+
+void SMTChecker::popPathCondition()
+{
+ solAssert(m_pathConditions.size() > 0, "Cannot pop path condition, empty.");
+ m_pathConditions.pop_back();
+}
+
+void SMTChecker::pushPathCondition(smt::Expression const& _e)
+{
+ m_pathConditions.push_back(currentPathConditions() && _e);
+}
+
+smt::Expression SMTChecker::currentPathConditions()
+{
+ if (m_pathConditions.size() == 0)
+ return smt::Expression(true);
+ return m_pathConditions.back();
+}
+
+void SMTChecker::addPathConjoinedExpression(smt::Expression const& _e)
+{
+ m_interface->addAssertion(currentPathConditions() && _e);
+}
+
+void SMTChecker::addPathImpliedExpression(smt::Expression const& _e)
+{
+ m_interface->addAssertion(smt::Expression::implies(currentPathConditions(), _e));
+}
diff --git a/libsolidity/formal/SMTChecker.h b/libsolidity/formal/SMTChecker.h
index e7481cca..539221cc 100644
--- a/libsolidity/formal/SMTChecker.h
+++ b/libsolidity/formal/SMTChecker.h
@@ -26,6 +26,7 @@
#include <map>
#include <string>
+#include <vector>
namespace dev
{
@@ -145,6 +146,17 @@ private:
/// The function takes one argument which is the "sequence number".
smt::Expression var(Declaration const& _decl);
+ /// Adds a new path condition
+ void pushPathCondition(smt::Expression const& _e);
+ /// Remove the last path condition
+ void popPathCondition();
+ /// Returns the conjunction of all path conditions or True if empty
+ smt::Expression currentPathConditions();
+ /// Conjoin the current path conditions with the given parameter and add to the solver
+ void addPathConjoinedExpression(smt::Expression const& _e);
+ /// Add to the solver: the given expression implied by the current path conditions
+ void addPathImpliedExpression(smt::Expression const& _e);
+
std::shared_ptr<smt::SolverInterface> m_interface;
std::shared_ptr<VariableUsage> m_variableUsage;
bool m_conditionalExecutionHappened = false;
@@ -152,6 +164,7 @@ private:
std::map<Declaration const*, int> m_nextFreeSequenceCounter;
std::map<Expression const*, smt::Expression> m_expressions;
std::map<Declaration const*, smt::Expression> m_variables;
+ std::vector<smt::Expression> m_pathConditions;
ErrorReporter& m_errorReporter;
FunctionDefinition const* m_currentFunction = nullptr;
diff --git a/libsolidity/formal/SolverInterface.h b/libsolidity/formal/SolverInterface.h
index 74c993e8..88487310 100644
--- a/libsolidity/formal/SolverInterface.h
+++ b/libsolidity/formal/SolverInterface.h
@@ -72,6 +72,11 @@ public:
}, _trueValue.sort);
}
+ static Expression implies(Expression _a, Expression _b)
+ {
+ return !std::move(_a) || std::move(_b);
+ }
+
friend Expression operator!(Expression _a)
{
return Expression("not", std::move(_a), Sort::Bool);