mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Fix assignment to contract member access
This commit is contained in:
@@ -1061,10 +1061,9 @@ bool SMTEncoder::visit(MemberAccess const& _memberAccess)
|
||||
|
||||
auto const& exprType = _memberAccess.expression().annotation().type;
|
||||
solAssert(exprType, "");
|
||||
auto identifier = dynamic_cast<Identifier const*>(&_memberAccess.expression());
|
||||
if (exprType->category() == Type::Category::Magic)
|
||||
{
|
||||
if (identifier)
|
||||
if (auto const* identifier = dynamic_cast<Identifier const*>(&_memberAccess.expression()))
|
||||
{
|
||||
auto const& name = identifier->name();
|
||||
solAssert(name == "block" || name == "msg" || name == "tx", "");
|
||||
@@ -1109,13 +1108,23 @@ bool SMTEncoder::visit(MemberAccess const& _memberAccess)
|
||||
}
|
||||
else if (exprType->category() == Type::Category::TypeType)
|
||||
{
|
||||
if (identifier && dynamic_cast<EnumDefinition const*>(identifier->annotation().referencedDeclaration))
|
||||
auto const* decl = expressionToDeclaration(_memberAccess.expression());
|
||||
if (dynamic_cast<EnumDefinition const*>(decl))
|
||||
{
|
||||
auto enumType = dynamic_cast<EnumType const*>(accessType);
|
||||
solAssert(enumType, "");
|
||||
defineExpr(_memberAccess, enumType->memberValue(_memberAccess.memberName()));
|
||||
|
||||
return false;
|
||||
}
|
||||
else if (dynamic_cast<ContractDefinition const*>(decl))
|
||||
{
|
||||
if (auto const* var = dynamic_cast<VariableDeclaration const*>(_memberAccess.annotation().referencedDeclaration))
|
||||
{
|
||||
defineExpr(_memberAccess, currentValue(*var));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else if (exprType->category() == Type::Category::Address)
|
||||
{
|
||||
@@ -1245,6 +1254,23 @@ void SMTEncoder::arrayAssignment()
|
||||
|
||||
void SMTEncoder::indexOrMemberAssignment(Expression const& _expr, smtutil::Expression const& _rightHandSide)
|
||||
{
|
||||
if (auto const* memberAccess = dynamic_cast<MemberAccess const*>(&_expr))
|
||||
{
|
||||
if (dynamic_cast<ContractDefinition const*>(expressionToDeclaration(memberAccess->expression())))
|
||||
{
|
||||
if (auto const* var = dynamic_cast<VariableDeclaration const*>(memberAccess->annotation().referencedDeclaration))
|
||||
{
|
||||
if (var->hasReferenceOrMappingType())
|
||||
resetReferences(*var);
|
||||
|
||||
m_context.addAssertion(m_context.newValue(*var) == _rightHandSide);
|
||||
m_context.expression(_expr)->increaseIndex();
|
||||
defineExpr(_expr, currentValue(*var));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto toStore = _rightHandSide;
|
||||
auto const* lastExpr = &_expr;
|
||||
while (true)
|
||||
@@ -1306,7 +1332,7 @@ void SMTEncoder::indexOrMemberAssignment(Expression const& _expr, smtutil::Expre
|
||||
|
||||
m_context.addAssertion(m_context.newValue(*varDecl) == toStore);
|
||||
m_context.expression(*id)->increaseIndex();
|
||||
defineExpr(*id,currentValue(*varDecl));
|
||||
defineExpr(*id, currentValue(*varDecl));
|
||||
break;
|
||||
}
|
||||
else
|
||||
@@ -2287,16 +2313,25 @@ set<VariableDeclaration const*> SMTEncoder::touchedVariables(ASTNode const& _nod
|
||||
return m_variableUsage.touchedVariables(_node, callStack);
|
||||
}
|
||||
|
||||
Declaration const* SMTEncoder::expressionToDeclaration(Expression const& _expr)
|
||||
{
|
||||
if (auto const* identifier = dynamic_cast<Identifier const*>(&_expr))
|
||||
return identifier->annotation().referencedDeclaration;
|
||||
if (auto const* outerMemberAccess = dynamic_cast<MemberAccess const*>(&_expr))
|
||||
return outerMemberAccess->annotation().referencedDeclaration;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
VariableDeclaration const* SMTEncoder::identifierToVariable(Expression const& _expr)
|
||||
{
|
||||
if (auto identifier = dynamic_cast<Identifier const*>(&_expr))
|
||||
{
|
||||
if (auto decl = dynamic_cast<VariableDeclaration const*>(identifier->annotation().referencedDeclaration))
|
||||
// We do not use `expressionToDeclaration` here because we are not interested in
|
||||
// struct.field, for example.
|
||||
if (auto const* identifier = dynamic_cast<Identifier const*>(&_expr))
|
||||
if (auto const* varDecl = dynamic_cast<VariableDeclaration const*>(identifier->annotation().referencedDeclaration))
|
||||
{
|
||||
solAssert(m_context.knownVariable(*decl), "");
|
||||
return decl;
|
||||
solAssert(m_context.knownVariable(*varDecl), "");
|
||||
return varDecl;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
@@ -280,7 +280,11 @@ protected:
|
||||
/// @returns variables that are touched in _node's subtree.
|
||||
std::set<VariableDeclaration const*> touchedVariables(ASTNode const& _node);
|
||||
|
||||
/// @returns the VariableDeclaration referenced by an Identifier or nullptr.
|
||||
/// @returns the declaration referenced by _expr, if any,
|
||||
/// and nullptr otherwise.
|
||||
Declaration const* expressionToDeclaration(Expression const& _expr);
|
||||
|
||||
/// @returns the VariableDeclaration referenced by an Expression or nullptr.
|
||||
VariableDeclaration const* identifierToVariable(Expression const& _expr);
|
||||
|
||||
/// Creates symbolic expressions for the returned values
|
||||
|
||||
Reference in New Issue
Block a user