mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #10836 from ethereum/smt_fix_cex_inheritance
Fix inheritance bug in CHC cex
This commit is contained in:
commit
7405dc5b7f
@ -936,9 +936,9 @@ SortPointer CHC::sort(ASTNode const* _node)
|
|||||||
return functionBodySort(*m_currentFunction, m_currentContract, state());
|
return functionBodySort(*m_currentFunction, m_currentContract, state());
|
||||||
}
|
}
|
||||||
|
|
||||||
Predicate const* CHC::createSymbolicBlock(SortPointer _sort, string const& _name, PredicateType _predType, ASTNode const* _node)
|
Predicate const* CHC::createSymbolicBlock(SortPointer _sort, string const& _name, PredicateType _predType, ASTNode const* _node, ContractDefinition const* _contractContext)
|
||||||
{
|
{
|
||||||
auto const* block = Predicate::create(_sort, _name, _predType, m_context, _node);
|
auto const* block = Predicate::create(_sort, _name, _predType, m_context, _node, _contractContext);
|
||||||
m_interface->registerRelation(block->functor());
|
m_interface->registerRelation(block->functor());
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
@ -1081,7 +1081,8 @@ Predicate const* CHC::createBlock(ASTNode const* _node, PredicateType _predType,
|
|||||||
sort(_node),
|
sort(_node),
|
||||||
"block_" + uniquePrefix() + "_" + _prefix + predicateName(_node),
|
"block_" + uniquePrefix() + "_" + _prefix + predicateName(_node),
|
||||||
_predType,
|
_predType,
|
||||||
_node
|
_node,
|
||||||
|
m_currentContract
|
||||||
);
|
);
|
||||||
|
|
||||||
solAssert(m_currentFunction, "");
|
solAssert(m_currentFunction, "");
|
||||||
@ -1094,7 +1095,8 @@ Predicate const* CHC::createSummaryBlock(FunctionDefinition const& _function, Co
|
|||||||
functionSort(_function, &_contract, state()),
|
functionSort(_function, &_contract, state()),
|
||||||
"summary_" + uniquePrefix() + "_" + predicateName(&_function, &_contract),
|
"summary_" + uniquePrefix() + "_" + predicateName(&_function, &_contract),
|
||||||
_type,
|
_type,
|
||||||
&_function
|
&_function,
|
||||||
|
&_contract
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1104,6 +1106,7 @@ Predicate const* CHC::createConstructorBlock(ContractDefinition const& _contract
|
|||||||
constructorSort(_contract, state()),
|
constructorSort(_contract, state()),
|
||||||
_prefix + "_" + contractSuffix(_contract) + "_" + uniquePrefix(),
|
_prefix + "_" + contractSuffix(_contract) + "_" + uniquePrefix(),
|
||||||
PredicateType::ConstructorSummary,
|
PredicateType::ConstructorSummary,
|
||||||
|
&_contract,
|
||||||
&_contract
|
&_contract
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -126,7 +126,7 @@ private:
|
|||||||
/// Predicate helpers.
|
/// Predicate helpers.
|
||||||
//@{
|
//@{
|
||||||
/// @returns a new block of given _sort and _name.
|
/// @returns a new block of given _sort and _name.
|
||||||
Predicate const* createSymbolicBlock(smtutil::SortPointer _sort, std::string const& _name, PredicateType _predType, ASTNode const* _node = nullptr);
|
Predicate const* createSymbolicBlock(smtutil::SortPointer _sort, std::string const& _name, PredicateType _predType, ASTNode const* _node = nullptr, ContractDefinition const* _contractContext = nullptr);
|
||||||
|
|
||||||
/// Creates summary predicates for all functions of all contracts
|
/// Creates summary predicates for all functions of all contracts
|
||||||
/// in a given _source.
|
/// in a given _source.
|
||||||
|
@ -40,7 +40,8 @@ Predicate const* Predicate::create(
|
|||||||
string _name,
|
string _name,
|
||||||
PredicateType _type,
|
PredicateType _type,
|
||||||
EncodingContext& _context,
|
EncodingContext& _context,
|
||||||
ASTNode const* _node
|
ASTNode const* _node,
|
||||||
|
ContractDefinition const* _contractContext
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
smt::SymbolicFunctionVariable predicate{_sort, move(_name), _context};
|
smt::SymbolicFunctionVariable predicate{_sort, move(_name), _context};
|
||||||
@ -49,18 +50,20 @@ Predicate const* Predicate::create(
|
|||||||
return &m_predicates.emplace(
|
return &m_predicates.emplace(
|
||||||
std::piecewise_construct,
|
std::piecewise_construct,
|
||||||
std::forward_as_tuple(functorName),
|
std::forward_as_tuple(functorName),
|
||||||
std::forward_as_tuple(move(predicate), _type, _node)
|
std::forward_as_tuple(move(predicate), _type, _node, _contractContext)
|
||||||
).first->second;
|
).first->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
Predicate::Predicate(
|
Predicate::Predicate(
|
||||||
smt::SymbolicFunctionVariable&& _predicate,
|
smt::SymbolicFunctionVariable&& _predicate,
|
||||||
PredicateType _type,
|
PredicateType _type,
|
||||||
ASTNode const* _node
|
ASTNode const* _node,
|
||||||
|
ContractDefinition const* _contractContext
|
||||||
):
|
):
|
||||||
m_predicate(move(_predicate)),
|
m_predicate(move(_predicate)),
|
||||||
m_type(_type),
|
m_type(_type),
|
||||||
m_node(_node)
|
m_node(_node),
|
||||||
|
m_contractContext(_contractContext)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,18 +133,8 @@ FunctionCall const* Predicate::programFunctionCall() const
|
|||||||
|
|
||||||
optional<vector<VariableDeclaration const*>> Predicate::stateVariables() const
|
optional<vector<VariableDeclaration const*>> Predicate::stateVariables() const
|
||||||
{
|
{
|
||||||
if (auto const* fun = programFunction())
|
if (m_contractContext)
|
||||||
return SMTEncoder::stateVariablesIncludingInheritedAndPrivate(*fun);
|
return SMTEncoder::stateVariablesIncludingInheritedAndPrivate(*m_contractContext);
|
||||||
if (auto const* contract = programContract())
|
|
||||||
return SMTEncoder::stateVariablesIncludingInheritedAndPrivate(*contract);
|
|
||||||
|
|
||||||
auto const* node = m_node;
|
|
||||||
while (auto const* scopable = dynamic_cast<Scopable const*>(node))
|
|
||||||
{
|
|
||||||
node = scopable->scope();
|
|
||||||
if (auto const* fun = dynamic_cast<FunctionDefinition const*>(node))
|
|
||||||
return SMTEncoder::stateVariablesIncludingInheritedAndPrivate(*fun);
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullopt;
|
return nullopt;
|
||||||
}
|
}
|
||||||
|
@ -55,13 +55,15 @@ public:
|
|||||||
std::string _name,
|
std::string _name,
|
||||||
PredicateType _type,
|
PredicateType _type,
|
||||||
smt::EncodingContext& _context,
|
smt::EncodingContext& _context,
|
||||||
ASTNode const* _node = nullptr
|
ASTNode const* _node = nullptr,
|
||||||
|
ContractDefinition const* _contractContext = nullptr
|
||||||
);
|
);
|
||||||
|
|
||||||
Predicate(
|
Predicate(
|
||||||
smt::SymbolicFunctionVariable&& _predicate,
|
smt::SymbolicFunctionVariable&& _predicate,
|
||||||
PredicateType _type,
|
PredicateType _type,
|
||||||
ASTNode const* _node = nullptr
|
ASTNode const* _node = nullptr,
|
||||||
|
ContractDefinition const* _contractContext = nullptr
|
||||||
);
|
);
|
||||||
|
|
||||||
/// Predicate should not be copiable.
|
/// Predicate should not be copiable.
|
||||||
@ -166,6 +168,12 @@ private:
|
|||||||
/// nullptr if this predicate is not associated with a specific program AST node.
|
/// nullptr if this predicate is not associated with a specific program AST node.
|
||||||
ASTNode const* m_node = nullptr;
|
ASTNode const* m_node = nullptr;
|
||||||
|
|
||||||
|
/// The ContractDefinition that contains this predicate.
|
||||||
|
/// nullptr if this predicate is not associated with a specific contract.
|
||||||
|
/// This is unfortunately necessary because of virtual resolution for
|
||||||
|
/// function nodes.
|
||||||
|
ContractDefinition const* m_contractContext = nullptr;
|
||||||
|
|
||||||
/// Maps the name of the predicate to the actual Predicate.
|
/// Maps the name of the predicate to the actual Predicate.
|
||||||
/// Used in counterexample generation.
|
/// Used in counterexample generation.
|
||||||
static std::map<std::string, Predicate> m_predicates;
|
static std::map<std::string, Predicate> m_predicates;
|
||||||
|
@ -0,0 +1,18 @@
|
|||||||
|
pragma experimental SMTChecker;
|
||||||
|
|
||||||
|
contract B {
|
||||||
|
uint x;
|
||||||
|
function f() public view {
|
||||||
|
assert(x == 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
contract C is B {
|
||||||
|
uint y;
|
||||||
|
function g() public {
|
||||||
|
x = 1;
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// Warning 6328: (85-99): CHC: Assertion violation happens here.\nCounterexample:\ny = 0, x = 1\n\nTransaction trace:\nC.constructor()\nState: y = 0, x = 0\nC.g()\n B.f() -- internal call\nState: y = 0, x = 1\nB.f()
|
@ -0,0 +1,25 @@
|
|||||||
|
pragma experimental SMTChecker;
|
||||||
|
|
||||||
|
contract A {
|
||||||
|
uint x;
|
||||||
|
function f() internal view {
|
||||||
|
assert(x == 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
contract B is A {
|
||||||
|
uint a;
|
||||||
|
uint b;
|
||||||
|
}
|
||||||
|
|
||||||
|
contract C is B {
|
||||||
|
uint y;
|
||||||
|
uint z;
|
||||||
|
uint w;
|
||||||
|
function g() public {
|
||||||
|
x = 1;
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// Warning 6328: (87-101): CHC: Assertion violation happens here.\nCounterexample:\ny = 0, z = 0, w = 0, a = 0, b = 0, x = 1\n\nTransaction trace:\nC.constructor()\nState: y = 0, z = 0, w = 0, a = 0, b = 0, x = 0\nC.g()\n A.f() -- internal call
|
Loading…
Reference in New Issue
Block a user