Adjust data section size during creation.

This commit is contained in:
Daniel Kirchner 2022-12-21 21:25:08 +01:00
parent b8f74c968e
commit b73d082809
5 changed files with 48 additions and 4 deletions

View File

@ -71,6 +71,7 @@ public:
IRGenerationContext(
langutil::EVMVersion _evmVersion,
std::optional<uint8_t> _eofVersion,
ExecutionContext _executionContext,
RevertStrings _revertStrings,
OptimiserSettings _optimiserSettings,
@ -79,6 +80,7 @@ public:
langutil::CharStreamProvider const* _soliditySourceProvider
):
m_evmVersion(_evmVersion),
m_eofVersion(_eofVersion),
m_executionContext(_executionContext),
m_revertStrings(_revertStrings),
m_optimiserSettings(std::move(_optimiserSettings)),
@ -149,6 +151,7 @@ public:
YulUtilFunctions utils();
langutil::EVMVersion evmVersion() const { return m_evmVersion; }
std::optional<uint8_t> eofVersion() const { return m_eofVersion; }
ExecutionContext executionContext() const { return m_executionContext; }
void setArithmetic(Arithmetic _value) { m_arithmetic = _value; }
@ -182,6 +185,7 @@ public:
private:
langutil::EVMVersion m_evmVersion;
std::optional<uint8_t> m_eofVersion;
ExecutionContext m_executionContext;
RevertStrings m_revertStrings;
OptimiserSettings m_optimiserSettings;

View File

@ -1110,6 +1110,7 @@ void IRGenerator::resetContext(ContractDefinition const& _contract, ExecutionCon
);
IRGenerationContext newContext(
m_evmVersion,
m_eofVersion,
_context,
m_context.revertStrings(),
m_optimiserSettings,

View File

@ -58,6 +58,7 @@ public:
m_optimiserSettings(_optimiserSettings),
m_context(
_evmVersion,
_eofVersion,
ExecutionContext::Creation,
_revertStrings,
std::move(_optimiserSettings),

View File

@ -1483,10 +1483,21 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
m_context.subObjectsCreated().insert(contract);
Whiskers t(R"(let <memPos> := <allocateUnbounded>()
let <memEnd> := add(<memPos>, datasize("<object>"))
if or(gt(<memEnd>, 0xffffffffffffffff), lt(<memEnd>, <memPos>)) { <panic>() }
let <argPos> := add(<memPos>, datasize("<object>"))
if or(gt(<argPos>, 0xffffffffffffffff), lt(<argPos>, <memPos>)) { <panic>() }
datacopy(<memPos>, dataoffset("<object>"), datasize("<object>"))
<memEnd> := <abiEncode>(<memEnd><constructorParams>)
let <memEnd> := <abiEncode>(<argPos><constructorParams>)
<?eof>
// TODO: this is horrible and hopefully avoided at the spec level
let <argSize> := sub(<memEnd>, <argPos>)
let <numCodeSections> := shr(240, mload(add(<memPos>, 7)))
let <dataSectionOffset> := add(<memPos>, add(10, mul(<numCodeSections>, 2)))
let <tmp> := mload(<dataSectionOffset>)
let <dataSectionSize> := shr(240, <tmp>)
<dataSectionSize> := add(<dataSectionSize>, <argSize>)
if gt(<dataSectionSize>, 0xFFFF) { <panic>() }
mstore(<dataSectionOffset>, or(shr(16, shl(16, <tmp>)), shl(240, <dataSectionSize>)))
</eof>
<?saltSet>
let <address> := create2(<value>, <memPos>, sub(<memEnd>, <memPos>), <salt>)
<!saltSet>
@ -1498,7 +1509,17 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
if iszero(<address>) { <forwardingRevert>() }
</isTryCall>
)");
t("eof", m_context.eofVersion().has_value());
if (m_context.eofVersion().has_value())
{
t("argSize", m_context.newYulVariable());
t("numCodeSections", m_context.newYulVariable());
t("dataSectionOffset", m_context.newYulVariable());
t("dataSectionSize", m_context.newYulVariable());
t("tmp", m_context.newYulVariable());
}
t("memPos", m_context.newYulVariable());
t("argPos", m_context.newYulVariable());
t("memEnd", m_context.newYulVariable());
t("allocateUnbounded", m_utils.allocateUnboundedFunction());
t("object", IRNames::creationObject(*contract));

View File

@ -5,14 +5,31 @@ contract D {
}
}
// TODO: this is horrible and hopefully avoided at the spec level
function adjustContractCodeForArgSize(bytes memory x, uint16 argSize)
{
assembly {
let memPos := add(x, 32)
let numCodeSections := shr(240, mload(add(memPos, 7)))
let dataSectionSizeOffset := add(memPos, add(10, mul(numCodeSections, 2)))
let tmp := mload(dataSectionSizeOffset)
let dataSectionSize := shr(240, tmp)
dataSectionSize := add(dataSectionSize, argSize)
if gt(dataSectionSize, 0xFFFF) { revert(0,0) }
mstore(dataSectionSizeOffset, or(shr(16, shl(16, tmp)), shl(240, dataSectionSize)))
}
}
contract C {
function createDSalted(bytes32 salt, uint arg) public {
bytes memory creationCode = type(D).creationCode;
adjustContractCodeForArgSize(creationCode, 32);
address predictedAddress = address(uint160(uint(keccak256(abi.encodePacked(
bytes1(0xff),
address(this),
salt,
keccak256(abi.encodePacked(
type(D).creationCode,
creationCode,
arg
))
)))));