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) | ||||
| { | ||||
| 	solAssert(_type.dataStoredIn(DataLocation::CallData), ""); | ||||
| 	solAssert(_type.isDynamicallyEncoded(), ""); | ||||
| 
 | ||||
| 	unsigned int tailSize = _type.calldataEncodedTailSize(); | ||||
| 	solAssert(tailSize > 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>
 | ||||
| 	} | ||||
| 	m_context << Instruction::SWAP1; | ||||
| 	m_context.callYulFunction( | ||||
| 		m_context.utilFunctions().accessCalldataTailFunction(_type), | ||||
| 		2, | ||||
| 		_type.isDynamicallySized() ? 2 : 1 | ||||
| 	); | ||||
| } | ||||
| 
 | ||||
| unsigned CompilerUtils::loadFromMemory( | ||||
|  | ||||
| @ -942,13 +942,13 @@ string YulUtilFunctions::accessCalldataTailFunction(Type const& _type) | ||||
| 		return Whiskers(R"( | ||||
| 			function <functionName>(base_ref, ptr_to_tail) -> addr<?dynamicallySized>, length</dynamicallySized> { | ||||
| 				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) | ||||
| 				<?dynamicallySized> | ||||
| 					length := calldataload(addr) | ||||
| 					if gt(length, 0xffffffffffffffff) { revert(0, 0) } | ||||
| 					if sgt(base_ref, sub(calldatasize(), mul(length, <calldataStride>))) { revert(0, 0) } | ||||
| 					if gt(length, 0xffffffffffffffff) { <invalidCalldataTailLength> } | ||||
| 					addr := add(addr, 32) | ||||
| 					if sgt(addr, sub(calldatasize(), mul(length, <calldataStride>))) { <shortCalldataTail> } | ||||
| 				</dynamicallySized> | ||||
| 			} | ||||
| 		)") | ||||
| @ -956,6 +956,9 @@ string YulUtilFunctions::accessCalldataTailFunction(Type const& _type) | ||||
| 		("dynamicallySized", _type.isDynamicallySized()) | ||||
| 		("neededLength", toCompactHexWithPrefix(_type.calldataEncodedTailSize())) | ||||
| 		("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(); | ||||
| 	}); | ||||
| } | ||||
|  | ||||
| @ -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