mirror of
				https://github.com/ethereum/solidity
				synced 2023-10-03 13:03:40 +00:00 
			
		
		
		
	Merge pull request #4501 from ethereum/recursiveStructsWithFixedArrays
Consider fixed-size arrays when checking for recursive structs.
This commit is contained in:
		
						commit
						bab4a3975f
					
				| @ -65,6 +65,7 @@ Bugfixes: | ||||
|  * Tests: Fix chain parameters to make ipc tests work with newer versions of cpp-ethereum. | ||||
|  * Code Generator: Fix allocation of byte arrays (zeroed out too much memory). | ||||
|  * Fix NatSpec json output for `@notice` and `@dev` tags on contract definitions. | ||||
|  * Type Checker: Consider fixed size arrays when checking for recursive structs. | ||||
|  * Type System: Allow arbitrary exponents for literals with a mantissa of zero. | ||||
| 
 | ||||
| ### 0.4.24 (2018-05-16) | ||||
|  | ||||
| @ -30,6 +30,7 @@ | ||||
| #include <libsolidity/inlineasm/AsmAnalysisInfo.h> | ||||
| #include <libsolidity/inlineasm/AsmData.h> | ||||
| #include <libsolidity/interface/ErrorReporter.h> | ||||
| #include <libdevcore/Algorithms.h> | ||||
| 
 | ||||
| using namespace std; | ||||
| using namespace dev; | ||||
| @ -593,22 +594,24 @@ bool TypeChecker::visit(StructDefinition const& _struct) | ||||
| 			m_errorReporter.typeError(member->location(), "Type cannot be used in struct."); | ||||
| 
 | ||||
| 	// Check recursion, fatal error if detected.
 | ||||
| 	using StructPointer = StructDefinition const*; | ||||
| 	using StructPointersSet = set<StructPointer>; | ||||
| 	function<void(StructPointer,StructPointersSet const&)> check = [&](StructPointer _struct, StructPointersSet const& _parents) | ||||
| 	auto visitor = [&](StructDefinition const& _struct, CycleDetector<StructDefinition>& _cycleDetector) | ||||
| 	{ | ||||
| 		if (_parents.count(_struct)) | ||||
| 			m_errorReporter.fatalTypeError(_struct->location(), "Recursive struct definition."); | ||||
| 		StructPointersSet parents = _parents; | ||||
| 		parents.insert(_struct); | ||||
| 		for (ASTPointer<VariableDeclaration> const& member: _struct->members()) | ||||
| 			if (type(*member)->category() == Type::Category::Struct) | ||||
| 		for (ASTPointer<VariableDeclaration> const& member: _struct.members()) | ||||
| 		{ | ||||
| 			Type const* memberType = type(*member).get(); | ||||
| 			while (auto arrayType = dynamic_cast<ArrayType const*>(memberType)) | ||||
| 			{ | ||||
| 				auto const& typeName = dynamic_cast<UserDefinedTypeName const&>(*member->typeName()); | ||||
| 				check(&dynamic_cast<StructDefinition const&>(*typeName.annotation().referencedDeclaration), parents); | ||||
| 				if (arrayType->isDynamicallySized()) | ||||
| 					break; | ||||
| 				memberType = arrayType->baseType().get(); | ||||
| 			} | ||||
| 			if (auto structType = dynamic_cast<StructType const*>(memberType)) | ||||
| 				if (_cycleDetector.run(structType->structDefinition())) | ||||
| 					return; | ||||
| 		} | ||||
| 	}; | ||||
| 	check(&_struct, StructPointersSet{}); | ||||
| 	if (CycleDetector<StructDefinition>(visitor).run(_struct) != nullptr) | ||||
| 		m_errorReporter.fatalTypeError(_struct.location(), "Recursive struct definition."); | ||||
| 
 | ||||
| 	ASTNode::listAccept(_struct.members(), *this); | ||||
| 
 | ||||
|  | ||||
| @ -0,0 +1,7 @@ | ||||
| contract Test { | ||||
|     struct MyStructName { | ||||
|         address addr; | ||||
|         MyStructName[] x; | ||||
|     } | ||||
| } | ||||
| // ---- | ||||
| @ -0,0 +1,8 @@ | ||||
| contract Test { | ||||
|     struct MyStructName { | ||||
|         address addr; | ||||
|         MyStructName[1] x; | ||||
|     } | ||||
| } | ||||
| // ---- | ||||
| // TypeError: (20-96): Recursive struct definition. | ||||
| @ -0,0 +1,18 @@ | ||||
| contract Test { | ||||
|     struct MyStructName1 { | ||||
|         address addr; | ||||
|         uint256 count; | ||||
|         MyStructName4[1] x; | ||||
|     } | ||||
|     struct MyStructName2 { | ||||
|         MyStructName1 x; | ||||
|     } | ||||
|     struct MyStructName3 { | ||||
|         MyStructName2[1] x; | ||||
|     } | ||||
|     struct MyStructName4 { | ||||
|         MyStructName3 x; | ||||
|     } | ||||
| } | ||||
| // ---- | ||||
| // TypeError: (20-121): Recursive struct definition. | ||||
| @ -0,0 +1,11 @@ | ||||
| contract Test { | ||||
|     struct MyStructName1 { | ||||
|         address addr; | ||||
|         uint256 count; | ||||
|         MyStructName2[] x; | ||||
|     } | ||||
|     struct MyStructName2 { | ||||
|         MyStructName1 x; | ||||
|     } | ||||
| } | ||||
| // ---- | ||||
| @ -0,0 +1,11 @@ | ||||
| contract Test { | ||||
|     struct MyStructName1 { | ||||
|         address addr; | ||||
|         uint256 count; | ||||
|         MyStructName2 x; | ||||
|     } | ||||
|     struct MyStructName2 { | ||||
|         MyStructName1[] x; | ||||
|     } | ||||
| } | ||||
| // ---- | ||||
| @ -0,0 +1,11 @@ | ||||
| contract Test { | ||||
|     struct MyStructName1 { | ||||
|         address addr; | ||||
|         uint256 count; | ||||
|         MyStructName2[] x; | ||||
|     } | ||||
|     struct MyStructName2 { | ||||
|         MyStructName1[] x; | ||||
|     } | ||||
| } | ||||
| // ---- | ||||
| @ -0,0 +1,21 @@ | ||||
| contract Test { | ||||
|     struct S1 { | ||||
|         S2[1][] x; | ||||
|     } | ||||
|     struct S2 { | ||||
|         S1 x; | ||||
|     } | ||||
|     struct T1 { | ||||
|         T2[][1] x; | ||||
|     } | ||||
|     struct T2 { | ||||
|         T1 x; | ||||
|     } | ||||
|     struct R1 { | ||||
|         R2[][] x; | ||||
|     } | ||||
|     struct R2 { | ||||
|         R1 x; | ||||
|     } | ||||
| } | ||||
| // ---- | ||||
| @ -0,0 +1,12 @@ | ||||
| contract Test { | ||||
|     struct MyStructName1 { | ||||
|         address addr; | ||||
|         uint256 count; | ||||
|         MyStructName2[1] x; | ||||
|     } | ||||
|     struct MyStructName2 { | ||||
|         MyStructName1 x; | ||||
|     } | ||||
| } | ||||
| // ---- | ||||
| // TypeError: (20-121): Recursive struct definition. | ||||
| @ -0,0 +1,12 @@ | ||||
| contract Test { | ||||
|     struct MyStructName1 { | ||||
|         address addr; | ||||
|         uint256 count; | ||||
|         MyStructName2 x; | ||||
|     } | ||||
|     struct MyStructName2 { | ||||
|         MyStructName1[1] x; | ||||
|     } | ||||
| } | ||||
| // ---- | ||||
| // TypeError: (20-118): Recursive struct definition. | ||||
| @ -0,0 +1,12 @@ | ||||
| contract Test { | ||||
|     struct MyStructName1 { | ||||
|         address addr; | ||||
|         uint256 count; | ||||
|         MyStructName2[1] x; | ||||
|     } | ||||
|     struct MyStructName2 { | ||||
|         MyStructName1[1] x; | ||||
|     } | ||||
| } | ||||
| // ---- | ||||
| // TypeError: (20-121): Recursive struct definition. | ||||
| @ -0,0 +1,12 @@ | ||||
| contract Test { | ||||
|     struct MyStructName1 { | ||||
|         address addr; | ||||
|         uint256 count; | ||||
|         MyStructName2[1][1] x; | ||||
|     } | ||||
|     struct MyStructName2 { | ||||
|         MyStructName1 x; | ||||
|     } | ||||
| } | ||||
| // ---- | ||||
| // TypeError: (20-124): Recursive struct definition. | ||||
| @ -0,0 +1,4 @@ | ||||
| contract Test { | ||||
|     struct S1 { uint a; } | ||||
|     struct S2 { S1[1] x; S1[1] y; } | ||||
| } | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user