From c0a169ca90b780d102442aca98d1c510dac47464 Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Fri, 3 Aug 2018 14:32:37 +0200 Subject: Disallow assignments to mappings within tuple assignments. --- libsolidity/analysis/TypeChecker.cpp | 25 ++++++++++++++++++++----- libsolidity/analysis/TypeChecker.h | 3 +++ 2 files changed, 23 insertions(+), 5 deletions(-) (limited to 'libsolidity') diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 8c84e4dc..f9604794 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -1318,11 +1318,31 @@ bool TypeChecker::visit(Conditional const& _conditional) return false; } +void TypeChecker::checkExpressionAssignment(Type const& _type, Expression const& _expression) +{ + if (auto const* tupleExpression = dynamic_cast(&_expression)) + { + if (auto const* tupleType = dynamic_cast(&_type)) + { + for (size_t i = 0; i < min(tupleExpression->components().size(), tupleType->components().size()); i++) + if (tupleType->components()[i] && tupleExpression->components()[i]) + checkExpressionAssignment(*tupleType->components()[i], *tupleExpression->components()[i]); + } + else if (!tupleExpression->components().empty()) + checkExpressionAssignment(_type, *tupleExpression->components().front()); + } + else if (_type.category() == Type::Category::Mapping) + m_errorReporter.typeError(_expression.location(), "Mappings cannot be assigned to."); +} + bool TypeChecker::visit(Assignment const& _assignment) { requireLValue(_assignment.leftHandSide()); TypePointer t = type(_assignment.leftHandSide()); _assignment.annotation().type = t; + + checkExpressionAssignment(*t, _assignment.leftHandSide()); + if (TupleType const* tupleType = dynamic_cast(t.get())) { if (_assignment.assignmentOperator() != Token::Assign) @@ -1339,11 +1359,6 @@ bool TypeChecker::visit(Assignment const& _assignment) if (dynamic_cast(type(_assignment.rightHandSide()).get())) checkDoubleStorageAssignment(_assignment); } - else if (t->category() == Type::Category::Mapping) - { - m_errorReporter.typeError(_assignment.location(), "Mappings cannot be assigned to."); - _assignment.rightHandSide().accept(*this); - } else if (_assignment.assignmentOperator() == Token::Assign) expectType(_assignment.rightHandSide(), *t); else diff --git a/libsolidity/analysis/TypeChecker.h b/libsolidity/analysis/TypeChecker.h index 8dc6b376..47892a3f 100644 --- a/libsolidity/analysis/TypeChecker.h +++ b/libsolidity/analysis/TypeChecker.h @@ -87,6 +87,9 @@ private: /// Checks (and warns) if a tuple assignment might cause unexpected overwrites in storage. /// Should only be called if the left hand side is tuple-typed. void checkDoubleStorageAssignment(Assignment const& _assignment); + // Checks whether the expression @arg _expression can be assigned from type @arg _type + // and reports an error, if not. + void checkExpressionAssignment(Type const& _type, Expression const& _expression); virtual void endVisit(InheritanceSpecifier const& _inheritance) override; virtual void endVisit(UsingForDirective const& _usingFor) override; -- cgit v1.2.3