[SMTChecker] Zero-initialize arrays

This commit is contained in:
Leonardo Alt
2019-09-02 22:37:30 +02:00
parent 9a6357ab09
commit a774b2d905
23 changed files with 130 additions and 49 deletions
+8
View File
@@ -137,6 +137,8 @@ CVC4::Expr CVC4Interface::toCVC4Expr(Expression const& _expr)
return m_context.mkConst(true);
else if (n == "false")
return m_context.mkConst(false);
else if (auto sortSort = dynamic_pointer_cast<SortSort>(_expr.sort))
return m_context.mkVar(n, cvc4Sort(*sortSort->inner));
else
try
{
@@ -187,6 +189,12 @@ CVC4::Expr CVC4Interface::toCVC4Expr(Expression const& _expr)
return m_context.mkExpr(CVC4::kind::SELECT, arguments[0], arguments[1]);
else if (n == "store")
return m_context.mkExpr(CVC4::kind::STORE, arguments[0], arguments[1], arguments[2]);
else if (n == "const_array")
{
shared_ptr<SortSort> sortSort = std::dynamic_pointer_cast<SortSort>(_expr.arguments[0].sort);
solAssert(sortSort, "");
return m_context.mkConst(CVC4::ArrayStoreAll(cvc4Sort(*sortSort->inner), arguments[1]));
}
solAssert(false, "");
}
-3
View File
@@ -17,8 +17,6 @@
#include <libsolidity/formal/SMTLib2Interface.h>
#include <libsolidity/interface/ReadFile.h>
#include <liblangutil/Exceptions.h>
#include <libdevcore/Keccak256.h>
#include <boost/algorithm/string/join.hpp>
@@ -30,7 +28,6 @@
#include <iostream>
#include <memory>
#include <stdexcept>
#include <string>
using namespace std;
using namespace dev;
+41 -2
View File
@@ -17,6 +17,7 @@
#pragma once
#include <libsolidity/ast/Types.h>
#include <libsolidity/interface/ReadFile.h>
#include <liblangutil/Exceptions.h>
#include <libdevcore/Common.h>
@@ -45,7 +46,8 @@ enum class Kind
Int,
Bool,
Function,
Array
Array,
Sort
};
struct Sort
@@ -110,12 +112,33 @@ struct ArraySort: public Sort
SortPointer range;
};
struct SortSort: public Sort
{
SortSort(SortPointer _inner): Sort(Kind::Sort), inner(std::move(_inner)) {}
bool operator==(Sort const& _other) const override
{
if (!Sort::operator==(_other))
return false;
auto _otherSort = dynamic_cast<SortSort const*>(&_other);
solAssert(_otherSort, "");
solAssert(_otherSort->inner, "");
solAssert(inner, "");
return *inner == *_otherSort->inner;
}
SortPointer inner;
};
// Forward declaration.
SortPointer smtSort(solidity::Type const& _type);
/// C++ representation of an SMTLIB2 expression.
class Expression
{
friend class SolverInterface;
public:
explicit Expression(bool _v): Expression(_v ? "true" : "false", Kind::Bool) {}
explicit Expression(solidity::TypePointer _type): Expression(_type->toString(), {}, std::make_shared<SortSort>(smtSort(*_type))) {}
Expression(size_t _number): Expression(std::to_string(_number), Kind::Int) {}
Expression(u256 const& _number): Expression(_number.str(), Kind::Int) {}
Expression(s256 const& _number): Expression(_number.str(), Kind::Int) {}
@@ -145,7 +168,8 @@ public:
{"/", 2},
{"mod", 2},
{"select", 2},
{"store", 3}
{"store", 3},
{"const_array", 2}
};
return operatorsArity.count(name) && operatorsArity.at(name) == arguments.size();
}
@@ -202,6 +226,21 @@ public:
);
}
static Expression const_array(Expression _sort, Expression _value)
{
solAssert(_sort.sort->kind == Kind::Sort, "");
auto sortSort = std::dynamic_pointer_cast<SortSort>(_sort.sort);
auto arraySort = std::dynamic_pointer_cast<ArraySort>(sortSort->inner);
solAssert(sortSort && arraySort, "");
solAssert(_value.sort, "");
solAssert(*arraySort->range == *_value.sort, "");
return Expression(
"const_array",
std::vector<Expression>{std::move(_sort), std::move(_value)},
arraySort
);
}
friend Expression operator!(Expression _a)
{
return Expression("not", std::move(_a), Kind::Bool);
+25 -4
View File
@@ -276,10 +276,31 @@ void setSymbolicZeroValue(SymbolicVariable const& _variable, EncodingContext& _c
void setSymbolicZeroValue(Expression _expr, solidity::TypePointer const& _type, EncodingContext& _context)
{
solAssert(_type, "");
if (isNumber(_type->category()))
_context.addAssertion(_expr == 0);
else if (isBool(_type->category()))
_context.addAssertion(_expr == Expression(false));
_context.addAssertion(_expr == zeroValue(_type));
}
Expression zeroValue(solidity::TypePointer const& _type)
{
solAssert(_type, "");
if (isSupportedType(_type->category()))
{
if (isNumber(_type->category()))
return 0;
if (isBool(_type->category()))
return Expression(false);
if (isArray(_type->category()) || isMapping(_type->category()))
{
if (auto arrayType = dynamic_cast<ArrayType const*>(_type))
return Expression::const_array(Expression(arrayType), zeroValue(arrayType->baseType()));
auto mappingType = dynamic_cast<MappingType const*>(_type);
solAssert(mappingType, "");
return Expression::const_array(Expression(mappingType), zeroValue(mappingType->valueType()));
}
solAssert(false, "");
}
// Unsupported types are abstracted as Int.
return 0;
}
void setSymbolicUnknownValue(SymbolicVariable const& _variable, EncodingContext& _context)
+1
View File
@@ -63,6 +63,7 @@ std::pair<bool, std::shared_ptr<SymbolicVariable>> newSymbolicVariable(solidity:
Expression minValue(solidity::IntegerType const& _type);
Expression maxValue(solidity::IntegerType const& _type);
Expression zeroValue(solidity::TypePointer const& _type);
void setSymbolicZeroValue(SymbolicVariable const& _variable, EncodingContext& _context);
void setSymbolicZeroValue(Expression _expr, solidity::TypePointer const& _type, EncodingContext& _context);
+13
View File
@@ -33,6 +33,17 @@ Z3CHCInterface::Z3CHCInterface():
z3::set_param("rewriter.pull_cheap_ite", true);
// This needs to be set in the context.
m_context->set("timeout", queryTimeout);
// Spacer options.
// These needs to be set in the solver.
// https://github.com/Z3Prover/z3/blob/master/src/muz/base/fp_params.pyg
z3::params p(*m_context);
// These are useful for solving problems with arrays and loops.
// Use quantified lemma generalizer.
p.set("fp.spacer.q3.use_qgen", true);
// Ground pobs by using values from a model.
p.set("fp.spacer.ground_pobs", false);
m_solver.set(p);
}
void Z3CHCInterface::declareVariable(string const& _name, Sort const& _sort)
@@ -82,9 +93,11 @@ pair<CheckResult, vector<string>> Z3CHCInterface::query(Expression const& _expr)
break;
}
case z3::check_result::unknown:
{
result = CheckResult::UNKNOWN;
break;
}
}
// TODO retrieve model / invariants
}
catch (z3::exception const& _e)
+14
View File
@@ -132,6 +132,12 @@ z3::expr Z3Interface::toZ3Expr(Expression const& _expr)
return m_context.bool_val(true);
else if (n == "false")
return m_context.bool_val(false);
else if (_expr.sort->kind == Kind::Sort)
{
auto sortSort = dynamic_pointer_cast<SortSort>(_expr.sort);
solAssert(sortSort, "");
return m_context.constant(n.c_str(), z3Sort(*sortSort->inner));
}
else
try
{
@@ -178,6 +184,14 @@ z3::expr Z3Interface::toZ3Expr(Expression const& _expr)
return z3::select(arguments[0], arguments[1]);
else if (n == "store")
return z3::store(arguments[0], arguments[1], arguments[2]);
else if (n == "const_array")
{
shared_ptr<SortSort> sortSort = std::dynamic_pointer_cast<SortSort>(_expr.arguments[0].sort);
solAssert(sortSort, "");
auto arraySort = dynamic_pointer_cast<ArraySort>(sortSort->inner);
solAssert(arraySort && arraySort->domain, "");
return z3::const_array(z3Sort(*arraySort->domain), arguments[1]);
}
solAssert(false, "");
}