mirror of
				https://github.com/ethereum/solidity
				synced 2023-10-03 13:03:40 +00:00 
			
		
		
		
	Merge pull request #3753 from ethereum/whoSupportsPackedEncoding
Prevent encoding of weird types and support packed encoding of extenal function types.
This commit is contained in:
		
						commit
						58c57e446b
					
				| @ -10,11 +10,13 @@ Bugfixes: | ||||
|  * Code Generator: Do not include internal functions in the runtime bytecode which are only referenced in the constructor. | ||||
|  * Code Generator: Properly skip unneeded storage array cleanup when not reducing length. | ||||
|  * Code Generator: Bugfix in modifier lookup in libraries. | ||||
|  * Code Generator: Implement packed encoding of external function types. | ||||
|  * Commandline interface: Support ``--evm-version constantinople`` properly. | ||||
|  * DocString Parser: Fix error message for empty descriptions. | ||||
|  * Standard JSON: Support ``constantinople`` as ``evmVersion`` properly. | ||||
|  * Type System: Improve error message when attempting to shift by a fractional amount. | ||||
|  * Type System: Make external library functions accessible. | ||||
|  * Type System: Prevent encoding of weird types. | ||||
| 
 | ||||
| ### 0.4.21 (2018-03-07) | ||||
| 
 | ||||
|  | ||||
| @ -1644,9 +1644,20 @@ bool TypeChecker::visit(FunctionCall const& _functionCall) | ||||
| 			auto const& argType = type(*arguments[i]); | ||||
| 			if (functionType->takesArbitraryParameters()) | ||||
| 			{ | ||||
| 				bool errored = false; | ||||
| 				if (auto t = dynamic_cast<RationalNumberType const*>(argType.get())) | ||||
| 					if (!t->mobileType()) | ||||
| 					{ | ||||
| 						m_errorReporter.typeError(arguments[i]->location(), "Invalid rational number (too large or division by zero)."); | ||||
| 						errored = true; | ||||
| 					} | ||||
| 				if (!errored && !( | ||||
| 					argType->mobileType() && | ||||
| 					argType->mobileType()->interfaceType(false) && | ||||
| 					argType->mobileType()->interfaceType(false)->encodingType() && | ||||
| 					!(dynamic_cast<StructType const*>(argType->mobileType()->interfaceType(false)->encodingType().get())) | ||||
| 				)) | ||||
| 					m_errorReporter.typeError(arguments[i]->location(), "This type cannot be encoded."); | ||||
| 			} | ||||
| 			else if (!type(*arguments[i])->isImplicitlyConvertibleTo(*parameterTypes[i])) | ||||
| 				m_errorReporter.typeError( | ||||
|  | ||||
| @ -1262,6 +1262,8 @@ bool ContractType::isPayable() const | ||||
| 
 | ||||
| TypePointer ContractType::unaryOperatorResult(Token::Value _operator) const | ||||
| { | ||||
| 	if (isSuper()) | ||||
| 		return TypePointer{}; | ||||
| 	return _operator == Token::Delete ? make_shared<TupleType>() : TypePointer(); | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -692,22 +692,27 @@ public: | ||||
| 	virtual bool operator==(Type const& _other) const override; | ||||
| 	virtual unsigned calldataEncodedSize(bool _padded ) const override | ||||
| 	{ | ||||
| 		solAssert(!isSuper(), ""); | ||||
| 		return encodingType()->calldataEncodedSize(_padded); | ||||
| 	} | ||||
| 	virtual unsigned storageBytes() const override { return 20; } | ||||
| 	virtual bool canLiveOutsideStorage() const override { return true; } | ||||
| 	virtual unsigned storageBytes() const override { solAssert(!isSuper(), ""); return 20; } | ||||
| 	virtual bool canLiveOutsideStorage() const override { return !isSuper(); } | ||||
| 	virtual unsigned sizeOnStack() const override { return m_super ? 0 : 1; } | ||||
| 	virtual bool isValueType() const override { return true; } | ||||
| 	virtual bool isValueType() const override { return !isSuper(); } | ||||
| 	virtual std::string toString(bool _short) const override; | ||||
| 	virtual std::string canonicalName() const override; | ||||
| 
 | ||||
| 	virtual MemberList::MemberMap nativeMembers(ContractDefinition const* _currentScope) const override; | ||||
| 	virtual TypePointer encodingType() const override | ||||
| 	{ | ||||
| 		if (isSuper()) | ||||
| 			return TypePointer{}; | ||||
| 		return std::make_shared<IntegerType>(160, IntegerType::Modifier::Address); | ||||
| 	} | ||||
| 	virtual TypePointer interfaceType(bool _inLibrary) const override | ||||
| 	{ | ||||
| 		if (isSuper()) | ||||
| 			return TypePointer{}; | ||||
| 		return _inLibrary ? shared_from_this() : encodingType(); | ||||
| 	} | ||||
| 
 | ||||
|  | ||||
| @ -142,7 +142,6 @@ void CompilerUtils::storeInMemoryDynamic(Type const& _type, bool _padToWordBound | ||||
| 		dynamic_cast<FunctionType const&>(_type).kind() == FunctionType::Kind::External | ||||
| 	) | ||||
| 	{ | ||||
| 		solUnimplementedAssert(_padToWordBoundaries, "Non-padded store for function not implemented."); | ||||
| 		combineExternalFunctionType(true); | ||||
| 		m_context << Instruction::DUP2 << Instruction::MSTORE; | ||||
| 		m_context << u256(_padToWordBoundaries ? 32 : 24) << Instruction::ADD; | ||||
|  | ||||
| @ -2077,6 +2077,31 @@ BOOST_AUTO_TEST_CASE(packed_keccak256) | ||||
| 	testContractAgainstCpp("a(bytes32)", f, u256(-1)); | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(packed_keccak256_complex_types) | ||||
| { | ||||
| 	char const* sourceCode = R"( | ||||
| 		contract test { | ||||
| 			uint120[3] x; | ||||
| 			function f() view returns (bytes32 hash1, bytes32 hash2, bytes32 hash3) { | ||||
| 				uint120[] memory y = new uint120[](3); | ||||
| 				x[0] = y[0] = uint120(-2); | ||||
| 				x[1] = y[1] = uint120(-3); | ||||
| 				x[2] = y[2] = uint120(-4); | ||||
| 				hash1 = keccak256(x); | ||||
| 				hash2 = keccak256(y); | ||||
| 				hash3 = keccak256(this.f); | ||||
| 			} | ||||
| 		} | ||||
| 	)"; | ||||
| 	compileAndRun(sourceCode); | ||||
| 	// Strangely, arrays are encoded with intra-element padding.
 | ||||
| 	ABI_CHECK(callContractFunction("f()"), encodeArgs( | ||||
| 		dev::keccak256(encodeArgs(u256("0xfffffffffffffffffffffffffffffe"), u256("0xfffffffffffffffffffffffffffffd"), u256("0xfffffffffffffffffffffffffffffc"))), | ||||
| 		dev::keccak256(encodeArgs(u256("0xfffffffffffffffffffffffffffffe"), u256("0xfffffffffffffffffffffffffffffd"), u256("0xfffffffffffffffffffffffffffffc"))), | ||||
| 		dev::keccak256(fromHex(m_contractAddress.hex() + "26121ff0")) | ||||
| 	)); | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(packed_sha256) | ||||
| { | ||||
| 	char const* sourceCode = R"( | ||||
|  | ||||
| @ -0,0 +1,11 @@ | ||||
| contract C { | ||||
|     function f() public pure { | ||||
|         bytes32 h = keccak256(keccak256, f, this.f.gas, block.blockhash); | ||||
|         h; | ||||
|     } | ||||
| } | ||||
| // ---- | ||||
| // TypeError: This type cannot be encoded. | ||||
| // TypeError: This type cannot be encoded. | ||||
| // TypeError: This type cannot be encoded. | ||||
| // TypeError: This type cannot be encoded. | ||||
| @ -0,0 +1,13 @@ | ||||
| contract C { | ||||
|     function f() public pure { | ||||
|         bool a = address(this).call(address(this).delegatecall, super); | ||||
|         bool b = address(this).delegatecall(log0, tx, mulmod); | ||||
|         a; b; | ||||
|     } | ||||
| } | ||||
| // ---- | ||||
| // TypeError: This type cannot be encoded. | ||||
| // TypeError: This type cannot be encoded. | ||||
| // TypeError: This type cannot be encoded. | ||||
| // TypeError: This type cannot be encoded. | ||||
| // TypeError: This type cannot be encoded. | ||||
| @ -0,0 +1,13 @@ | ||||
| contract C { | ||||
|     struct S { uint x; } | ||||
|     S s; | ||||
|     struct T { } | ||||
|     T t; | ||||
|     function f() public pure { | ||||
|         bytes32 a = sha256(s, t); | ||||
|         a; | ||||
|     } | ||||
| } | ||||
| // ---- | ||||
| // TypeError: This type cannot be encoded. | ||||
| // TypeError: This type cannot be encoded. | ||||
| @ -0,0 +1,16 @@ | ||||
| contract C { | ||||
|     struct S { uint x; } | ||||
|     S s; | ||||
|     struct T { } | ||||
|     T t; | ||||
|     enum A { X, Y } | ||||
|     function f() public pure { | ||||
|         bool a = address(this).delegatecall(S, A, A.X, T, uint, uint[]); | ||||
|     } | ||||
| } | ||||
| // ---- | ||||
| // TypeError: This type cannot be encoded. | ||||
| // TypeError: This type cannot be encoded. | ||||
| // TypeError: This type cannot be encoded. | ||||
| // TypeError: This type cannot be encoded. | ||||
| // TypeError: This type cannot be encoded. | ||||
| @ -0,0 +1,9 @@ | ||||
| contract C { | ||||
|     uint[3] sarr; | ||||
|     function f() view public { | ||||
|         uint[3] memory arr; | ||||
|         bytes32 h = keccak256(this.f, arr, sarr); | ||||
|         h; | ||||
|     } | ||||
| } | ||||
| // ---- | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user