From c7b257acde69e42ca2448bd0cb535470e5992db8 Mon Sep 17 00:00:00 2001 From: chriseth Date: Thu, 18 Jun 2015 16:35:25 +0200 Subject: [PATCH] Fix and test for not really recursive structs. Fixes #2223. --- libsolidity/AST.cpp | 33 +++++++++++-------- .../SolidityNameAndTypeResolution.cpp | 11 +++++++ 2 files changed, 31 insertions(+), 13 deletions(-) diff --git a/libsolidity/AST.cpp b/libsolidity/AST.cpp index 6d6a13cff..7333c024a 100644 --- a/libsolidity/AST.cpp +++ b/libsolidity/AST.cpp @@ -21,6 +21,7 @@ */ #include +#include #include #include #include @@ -434,23 +435,29 @@ void StructDefinition::checkMemberTypes() const void StructDefinition::checkRecursion() const { - set definitionsSeen; - vector queue = {this}; - while (!queue.empty()) + using StructPointer = StructDefinition const*; + using StructPointersSet = set; + function check = [&](StructPointer _struct, StructPointersSet const& _parents) { - StructDefinition const* def = queue.back(); - queue.pop_back(); - if (definitionsSeen.count(def)) - BOOST_THROW_EXCEPTION(ParserError() << errinfo_sourceLocation(def->getLocation()) - << errinfo_comment("Recursive struct definition.")); - definitionsSeen.insert(def); - for (ASTPointer const& member: def->getMembers()) + if (_parents.count(_struct)) + BOOST_THROW_EXCEPTION( + ParserError() << + errinfo_sourceLocation(_struct->getLocation()) << + errinfo_comment("Recursive struct definition.") + ); + set parents = _parents; + parents.insert(_struct); + for (ASTPointer const& member: _struct->getMembers()) if (member->getType()->getCategory() == Type::Category::Struct) { - UserDefinedTypeName const& typeName = dynamic_cast(*member->getTypeName()); - queue.push_back(&dynamic_cast(*typeName.getReferencedDeclaration())); + auto const& typeName = dynamic_cast(*member->getTypeName()); + check( + &dynamic_cast(*typeName.getReferencedDeclaration()), + parents + ); } - } + }; + check(this, {}); } TypePointer EnumDefinition::getType(ContractDefinition const*) const diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index fced12848..afa8b727f 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -190,6 +190,17 @@ BOOST_AUTO_TEST_CASE(struct_definition_indirectly_recursive) BOOST_CHECK_THROW(parseTextAndResolveNames(text), ParserError); } +BOOST_AUTO_TEST_CASE(struct_definition_not_really_recursive) +{ + char const* text = R"( + contract test { + struct s1 { uint a; } + struct s2 { s1 x; s1 y; } + } + )"; + BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); +} + BOOST_AUTO_TEST_CASE(struct_definition_recursion_via_mapping) { char const* text = "contract test {\n"