mirror of
				https://github.com/ethereum/solidity
				synced 2023-10-03 13:03:40 +00:00 
			
		
		
		
	Merge pull request #8416 from ethereum/reuseYulCalldataTailAccess
Fix yul calldata tail access functions and reuse them for old codegen.
This commit is contained in:
		
						commit
						b7c001eb7f
					
				| @ -121,56 +121,12 @@ void CompilerUtils::returnDataToArray() | |||||||
| 
 | 
 | ||||||
| void CompilerUtils::accessCalldataTail(Type const& _type) | void CompilerUtils::accessCalldataTail(Type const& _type) | ||||||
| { | { | ||||||
| 	solAssert(_type.dataStoredIn(DataLocation::CallData), ""); | 	m_context << Instruction::SWAP1; | ||||||
| 	solAssert(_type.isDynamicallyEncoded(), ""); | 	m_context.callYulFunction( | ||||||
| 
 | 		m_context.utilFunctions().accessCalldataTailFunction(_type), | ||||||
| 	unsigned int tailSize = _type.calldataEncodedTailSize(); | 		2, | ||||||
| 	solAssert(tailSize > 1, ""); | 		_type.isDynamicallySized() ? 2 : 1 | ||||||
| 
 | 	); | ||||||
| 	// returns the absolute offset of the tail in "base_ref"
 |  | ||||||
| 	m_context.appendInlineAssembly(Whiskers(R"({ |  | ||||||
| 		let rel_offset_of_tail := calldataload(ptr_to_tail) |  | ||||||
| 		if iszero(slt(rel_offset_of_tail, sub(sub(calldatasize(), base_ref), sub(<neededLength>, 1)))) { <revertString> } |  | ||||||
| 		base_ref := add(base_ref, rel_offset_of_tail) |  | ||||||
| 	})") |  | ||||||
| 	("neededLength", toCompactHexWithPrefix(tailSize)) |  | ||||||
| 	("revertString", m_context.revertReasonIfDebug("Invalid calldata tail offset")) |  | ||||||
| 	.render(), {"base_ref", "ptr_to_tail"}); |  | ||||||
| 	// stack layout: <absolute_offset_of_tail> <garbage>
 |  | ||||||
| 
 |  | ||||||
| 	if (!_type.isDynamicallySized()) |  | ||||||
| 	{ |  | ||||||
| 		m_context << Instruction::POP; |  | ||||||
| 		// stack layout: <absolute_offset_of_tail>
 |  | ||||||
| 		solAssert( |  | ||||||
| 			_type.category() == Type::Category::Struct || |  | ||||||
| 			_type.category() == Type::Category::Array, |  | ||||||
| 			"Invalid dynamically encoded base type on tail access." |  | ||||||
| 		); |  | ||||||
| 	} |  | ||||||
| 	else |  | ||||||
| 	{ |  | ||||||
| 		auto const* arrayType = dynamic_cast<ArrayType const*>(&_type); |  | ||||||
| 		solAssert(!!arrayType, "Invalid dynamically sized type."); |  | ||||||
| 		unsigned int calldataStride = arrayType->calldataStride(); |  | ||||||
| 		solAssert(calldataStride > 0, ""); |  | ||||||
| 
 |  | ||||||
| 		// returns the absolute offset of the tail in "base_ref"
 |  | ||||||
| 		// and the length of the tail in "length"
 |  | ||||||
| 		m_context.appendInlineAssembly( |  | ||||||
| 			Whiskers(R"({ |  | ||||||
| 				length := calldataload(base_ref) |  | ||||||
| 				base_ref := add(base_ref, 0x20) |  | ||||||
| 				if gt(length, 0xffffffffffffffff) { <revertString> } |  | ||||||
| 				if sgt(base_ref, sub(calldatasize(), mul(length, <calldataStride>))) { revert(0, 0) } |  | ||||||
| 			})") |  | ||||||
| 			("calldataStride", toCompactHexWithPrefix(calldataStride)) |  | ||||||
| 			("revertString", m_context.revertReasonIfDebug("Invalid calldata tail length")) |  | ||||||
| 			.render(), |  | ||||||
| 			{"base_ref", "length"} |  | ||||||
| 		); |  | ||||||
| 		// stack layout: <absolute_offset_of_tail> <length>
 |  | ||||||
| 	} |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| unsigned CompilerUtils::loadFromMemory( | unsigned CompilerUtils::loadFromMemory( | ||||||
|  | |||||||
| @ -942,13 +942,13 @@ string YulUtilFunctions::accessCalldataTailFunction(Type const& _type) | |||||||
| 		return Whiskers(R"( | 		return Whiskers(R"( | ||||||
| 			function <functionName>(base_ref, ptr_to_tail) -> addr<?dynamicallySized>, length</dynamicallySized> { | 			function <functionName>(base_ref, ptr_to_tail) -> addr<?dynamicallySized>, length</dynamicallySized> { | ||||||
| 				let rel_offset_of_tail := calldataload(ptr_to_tail) | 				let rel_offset_of_tail := calldataload(ptr_to_tail) | ||||||
| 				if iszero(slt(rel_offset_of_tail, sub(sub(calldatasize(), base_ref), sub(<neededLength>, 1)))) { revert(0, 0) } | 				if iszero(slt(rel_offset_of_tail, sub(sub(calldatasize(), base_ref), sub(<neededLength>, 1)))) { <invalidCalldataTailOffset> } | ||||||
| 				addr := add(base_ref, rel_offset_of_tail) | 				addr := add(base_ref, rel_offset_of_tail) | ||||||
| 				<?dynamicallySized> | 				<?dynamicallySized> | ||||||
| 					length := calldataload(addr) | 					length := calldataload(addr) | ||||||
| 					if gt(length, 0xffffffffffffffff) { revert(0, 0) } | 					if gt(length, 0xffffffffffffffff) { <invalidCalldataTailLength> } | ||||||
| 					if sgt(base_ref, sub(calldatasize(), mul(length, <calldataStride>))) { revert(0, 0) } |  | ||||||
| 					addr := add(addr, 32) | 					addr := add(addr, 32) | ||||||
|  | 					if sgt(addr, sub(calldatasize(), mul(length, <calldataStride>))) { <shortCalldataTail> } | ||||||
| 				</dynamicallySized> | 				</dynamicallySized> | ||||||
| 			} | 			} | ||||||
| 		)") | 		)") | ||||||
| @ -956,6 +956,9 @@ string YulUtilFunctions::accessCalldataTailFunction(Type const& _type) | |||||||
| 		("dynamicallySized", _type.isDynamicallySized()) | 		("dynamicallySized", _type.isDynamicallySized()) | ||||||
| 		("neededLength", toCompactHexWithPrefix(_type.calldataEncodedTailSize())) | 		("neededLength", toCompactHexWithPrefix(_type.calldataEncodedTailSize())) | ||||||
| 		("calldataStride", toCompactHexWithPrefix(_type.isDynamicallySized() ? dynamic_cast<ArrayType const&>(_type).calldataStride() : 0)) | 		("calldataStride", toCompactHexWithPrefix(_type.isDynamicallySized() ? dynamic_cast<ArrayType const&>(_type).calldataStride() : 0)) | ||||||
|  | 		("invalidCalldataTailOffset", revertReasonIfDebug("Invalid calldata tail offset")) | ||||||
|  | 		("invalidCalldataTailLength", revertReasonIfDebug("Invalid calldata tail length")) | ||||||
|  | 		("shortCalldataTail", revertReasonIfDebug("Calldata tail too short")) | ||||||
| 		.render(); | 		.render(); | ||||||
| 	}); | 	}); | ||||||
| } | } | ||||||
|  | |||||||
| @ -0,0 +1,9 @@ | |||||||
|  | pragma experimental ABIEncoderV2; | ||||||
|  | contract C { | ||||||
|  |     function f(uint256[][] calldata x) external { x[0]; } | ||||||
|  | } | ||||||
|  | // ==== | ||||||
|  | // EVMVersion: >=byzantium | ||||||
|  | // revertStrings: debug | ||||||
|  | // ---- | ||||||
|  | // f(uint256[][]): 0x20, 1, 0x20, 2, 0x42 -> FAILURE, hex"08c379a0", 0x20, 23, "Calldata tail too short" | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user