mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Add another argument to setimmutable and the AssignImmutable opcode, allowing to modify code at any memory offset.
This commit is contained in:
parent
00fb152316
commit
0dca223b45
@ -674,15 +674,18 @@ LinkerObject const& Assembly::assemble() const
|
|||||||
case AssignImmutable:
|
case AssignImmutable:
|
||||||
for (auto const& offset: immutableReferencesBySub[i.data()].second)
|
for (auto const& offset: immutableReferencesBySub[i.data()].second)
|
||||||
{
|
{
|
||||||
ret.bytecode.push_back(uint8_t(Instruction::DUP1));
|
ret.bytecode.push_back(uint8_t(Instruction::DUP2));
|
||||||
|
ret.bytecode.push_back(uint8_t(Instruction::DUP2));
|
||||||
// TODO: should we make use of the constant optimizer methods for pushing the offsets?
|
// TODO: should we make use of the constant optimizer methods for pushing the offsets?
|
||||||
bytes offsetBytes = toCompactBigEndian(u256(offset));
|
bytes offsetBytes = toCompactBigEndian(u256(offset));
|
||||||
ret.bytecode.push_back(uint8_t(Instruction::PUSH1) - 1 + offsetBytes.size());
|
ret.bytecode.push_back(uint8_t(Instruction::PUSH1) - 1 + offsetBytes.size());
|
||||||
ret.bytecode += offsetBytes;
|
ret.bytecode += offsetBytes;
|
||||||
|
ret.bytecode.push_back(uint8_t(Instruction::ADD));
|
||||||
ret.bytecode.push_back(uint8_t(Instruction::MSTORE));
|
ret.bytecode.push_back(uint8_t(Instruction::MSTORE));
|
||||||
}
|
}
|
||||||
immutableReferencesBySub.erase(i.data());
|
immutableReferencesBySub.erase(i.data());
|
||||||
ret.bytecode.push_back(uint8_t(Instruction::POP));
|
ret.bytecode.push_back(uint8_t(Instruction::POP));
|
||||||
|
ret.bytecode.push_back(uint8_t(Instruction::POP));
|
||||||
break;
|
break;
|
||||||
case PushDeployTimeAddress:
|
case PushDeployTimeAddress:
|
||||||
ret.bytecode.push_back(uint8_t(Instruction::PUSH20));
|
ret.bytecode.push_back(uint8_t(Instruction::PUSH20));
|
||||||
|
@ -102,7 +102,7 @@ size_t AssemblyItem::arguments() const
|
|||||||
if (type() == Operation)
|
if (type() == Operation)
|
||||||
return static_cast<size_t>(instructionInfo(instruction()).args);
|
return static_cast<size_t>(instructionInfo(instruction()).args);
|
||||||
else if (type() == AssignImmutable)
|
else if (type() == AssignImmutable)
|
||||||
return 1;
|
return 2;
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -93,9 +93,13 @@ KnownState::StoreOperation KnownState::feedItem(AssemblyItem const& _item, bool
|
|||||||
// can be ignored
|
// can be ignored
|
||||||
}
|
}
|
||||||
else if (_item.type() == AssignImmutable)
|
else if (_item.type() == AssignImmutable)
|
||||||
|
{
|
||||||
// Since AssignImmutable breaks blocks, it should be fine to only consider its changes to the stack, which
|
// Since AssignImmutable breaks blocks, it should be fine to only consider its changes to the stack, which
|
||||||
// is the same as POP.
|
// is the same as two POPs.
|
||||||
|
// Note that the StoreOperation for POP is generic and _copyItem is ignored.
|
||||||
|
feedItem(AssemblyItem(Instruction::POP), _copyItem);
|
||||||
return feedItem(AssemblyItem(Instruction::POP), _copyItem);
|
return feedItem(AssemblyItem(Instruction::POP), _copyItem);
|
||||||
|
}
|
||||||
else if (_item.type() != Operation)
|
else if (_item.type() != Operation)
|
||||||
{
|
{
|
||||||
assertThrow(_item.deposit() == 1, InvalidDeposit, "");
|
assertThrow(_item.deposit() == 1, InvalidDeposit, "");
|
||||||
|
@ -203,8 +203,11 @@ size_t ContractCompiler::packIntoContractCreator(ContractDefinition const& _cont
|
|||||||
{
|
{
|
||||||
auto slotNames = m_context.immutableVariableSlotNames(*immutable);
|
auto slotNames = m_context.immutableVariableSlotNames(*immutable);
|
||||||
for (auto&& slotName: slotNames | boost::adaptors::reversed)
|
for (auto&& slotName: slotNames | boost::adaptors::reversed)
|
||||||
|
{
|
||||||
|
m_context << u256(0);
|
||||||
m_context.appendImmutableAssignment(slotName);
|
m_context.appendImmutableAssignment(slotName);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (!immutables.empty())
|
if (!immutables.empty())
|
||||||
m_context.pushSubroutineSize(m_context.runtimeSub());
|
m_context.pushSubroutineSize(m_context.runtimeSub());
|
||||||
m_context << u256(0) << Instruction::RETURN;
|
m_context << u256(0) << Instruction::RETURN;
|
||||||
|
@ -558,7 +558,7 @@ string IRGenerator::deployCode(ContractDefinition const& _contract)
|
|||||||
codecopy(0, dataoffset("<object>"), datasize("<object>"))
|
codecopy(0, dataoffset("<object>"), datasize("<object>"))
|
||||||
|
|
||||||
<#storeImmutables>
|
<#storeImmutables>
|
||||||
setimmutable("<immutableName>", <var>)
|
setimmutable(0, "<immutableName>", <var>)
|
||||||
</storeImmutables>
|
</storeImmutables>
|
||||||
|
|
||||||
return(0, datasize("<object>"))
|
return(0, datasize("<object>"))
|
||||||
|
@ -221,21 +221,22 @@ map<YulString, BuiltinFunctionForEVM> createBuiltins(langutil::EVMVersion _evmVe
|
|||||||
));
|
));
|
||||||
builtins.emplace(createFunction(
|
builtins.emplace(createFunction(
|
||||||
"setimmutable",
|
"setimmutable",
|
||||||
2,
|
3,
|
||||||
0,
|
0,
|
||||||
SideEffects{false, false, false, false, true, SideEffects::None, SideEffects::None, SideEffects::Write},
|
SideEffects{false, false, false, false, true, SideEffects::None, SideEffects::None, SideEffects::Write},
|
||||||
{LiteralKind::String, std::nullopt},
|
{std::nullopt, LiteralKind::String, std::nullopt},
|
||||||
[](
|
[](
|
||||||
FunctionCall const& _call,
|
FunctionCall const& _call,
|
||||||
AbstractAssembly& _assembly,
|
AbstractAssembly& _assembly,
|
||||||
BuiltinContext&,
|
BuiltinContext&,
|
||||||
std::function<void(Expression const&)> _visitExpression
|
std::function<void(Expression const&)> _visitExpression
|
||||||
) {
|
) {
|
||||||
yulAssert(_call.arguments.size() == 2, "");
|
yulAssert(_call.arguments.size() == 3, "");
|
||||||
|
|
||||||
_visitExpression(_call.arguments[1]);
|
_visitExpression(_call.arguments[2]);
|
||||||
|
YulString identifier = std::get<Literal>(_call.arguments[1]).value;
|
||||||
|
_visitExpression(_call.arguments[0]);
|
||||||
_assembly.setSourceLocation(_call.location);
|
_assembly.setSourceLocation(_call.location);
|
||||||
YulString identifier = std::get<Literal>(_call.arguments.front()).value;
|
|
||||||
_assembly.appendImmutableAssignment(identifier.str());
|
_assembly.appendImmutableAssignment(identifier.str());
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
|
@ -91,7 +91,7 @@ BOOST_AUTO_TEST_CASE(all_assembly_items)
|
|||||||
// PushDeployTimeAddress
|
// PushDeployTimeAddress
|
||||||
_assembly.append(PushDeployTimeAddress);
|
_assembly.append(PushDeployTimeAddress);
|
||||||
// AssignImmutable.
|
// AssignImmutable.
|
||||||
// Note that since there is no reference to "someOtherImmutable", this will compile to a simple POP in the hex output.
|
// Note that since there is no reference to "someOtherImmutable", this will just compile to two POPs in the hex output.
|
||||||
_assembly.appendImmutableAssignment("someOtherImmutable");
|
_assembly.appendImmutableAssignment("someOtherImmutable");
|
||||||
_assembly.append(u256(2));
|
_assembly.append(u256(2));
|
||||||
_assembly.appendImmutableAssignment("someImmutable");
|
_assembly.appendImmutableAssignment("someImmutable");
|
||||||
@ -104,9 +104,9 @@ BOOST_AUTO_TEST_CASE(all_assembly_items)
|
|||||||
|
|
||||||
BOOST_CHECK_EQUAL(
|
BOOST_CHECK_EQUAL(
|
||||||
_assembly.assemble().toHex(),
|
_assembly.assemble().toHex(),
|
||||||
"5b6001600220606f73__$bf005014d9d0f534b8fcb268bd84c491a2$__"
|
"5b6001600220607373__$bf005014d9d0f534b8fcb268bd84c491a2$__"
|
||||||
"60005660676022604573000000000000000000000000000000000000000050"
|
"600056606b602260497300000000000000000000000000000000000000005050"
|
||||||
"60028060015250"
|
"60028181600101525050"
|
||||||
"00fe"
|
"00fe"
|
||||||
"7f0000000000000000000000000000000000000000000000000000000000000000"
|
"7f0000000000000000000000000000000000000000000000000000000000000000"
|
||||||
"fe010203044266eeaa"
|
"fe010203044266eeaa"
|
||||||
@ -184,8 +184,10 @@ BOOST_AUTO_TEST_CASE(immutable)
|
|||||||
shared_ptr<Assembly> _subAsmPtr = make_shared<Assembly>(_subAsm);
|
shared_ptr<Assembly> _subAsmPtr = make_shared<Assembly>(_subAsm);
|
||||||
|
|
||||||
_assembly.append(u256(42));
|
_assembly.append(u256(42));
|
||||||
|
_assembly.append(u256(0));
|
||||||
_assembly.appendImmutableAssignment("someImmutable");
|
_assembly.appendImmutableAssignment("someImmutable");
|
||||||
_assembly.append(u256(23));
|
_assembly.append(u256(23));
|
||||||
|
_assembly.append(u256(0));
|
||||||
_assembly.appendImmutableAssignment("someOtherImmutable");
|
_assembly.appendImmutableAssignment("someOtherImmutable");
|
||||||
|
|
||||||
auto sub = _assembly.appendSubroutine(_subAsmPtr);
|
auto sub = _assembly.appendSubroutine(_subAsmPtr);
|
||||||
@ -198,21 +200,26 @@ BOOST_AUTO_TEST_CASE(immutable)
|
|||||||
// root.asm
|
// root.asm
|
||||||
// assign "someImmutable"
|
// assign "someImmutable"
|
||||||
"602a" // PUSH1 42 - value for someImmutable
|
"602a" // PUSH1 42 - value for someImmutable
|
||||||
"80" // DUP1
|
"6000" // PUSH1 0 - offset of code into which to insert the immutable
|
||||||
|
"8181" // DUP2 DUP2
|
||||||
"6001" // PUSH1 1 - offset of first someImmutable in sub_0
|
"6001" // PUSH1 1 - offset of first someImmutable in sub_0
|
||||||
|
"01" // ADD - add offset of immutable to offset of code
|
||||||
"52" // MSTORE
|
"52" // MSTORE
|
||||||
"80" // DUP1
|
"8181" // DUP2 DUP2
|
||||||
"6043" // PUSH1 67 - offset of second someImmutable in sub_0
|
"6043" // PUSH1 67 - offset of second someImmutable in sub_0
|
||||||
|
"01" // ADD - add offset of immutable to offset of code
|
||||||
"52" // MSTORE
|
"52" // MSTORE
|
||||||
"50" // POP
|
"5050" // POP POP
|
||||||
// assign "someOtherImmutable"
|
// assign "someOtherImmutable"
|
||||||
"6017" // PUSH1 23 - value for someOtherImmutable
|
"6017" // PUSH1 23 - value for someOtherImmutable
|
||||||
"80" // DUP1
|
"6000" // PUSH1 0 - offset of code into which to insert the immutable
|
||||||
|
"8181" // DUP2 DUP2
|
||||||
"6022" // PUSH1 34 - offset of someOtherImmutable in sub_0
|
"6022" // PUSH1 34 - offset of someOtherImmutable in sub_0
|
||||||
|
"01" // ADD - add offset of immutable to offset of code
|
||||||
"52" // MSTORE
|
"52" // MSTORE
|
||||||
"50" // POP
|
"5050" // POP POP
|
||||||
"6063" // PUSH1 0x63 - dataSize(sub_0)
|
"6063" // PUSH1 0x63 - dataSize(sub_0)
|
||||||
"6017" // PUSH1 0x17 - dataOffset(sub_0)
|
"6023" // PUSH1 0x23 - dataOffset(sub_0)
|
||||||
"fe" // INVALID
|
"fe" // INVALID
|
||||||
// end of root.asm
|
// end of root.asm
|
||||||
// sub.asm
|
// sub.asm
|
||||||
@ -224,8 +231,10 @@ BOOST_AUTO_TEST_CASE(immutable)
|
|||||||
_assembly.assemblyString(),
|
_assembly.assemblyString(),
|
||||||
" /* \"root.asm\":1:3 */\n"
|
" /* \"root.asm\":1:3 */\n"
|
||||||
" 0x2a\n"
|
" 0x2a\n"
|
||||||
|
" 0x00\n"
|
||||||
" assignImmutable(\"0x26f2c0195e9d408feff3abd77d83f2971f3c9a18d1e8a9437c7835ae4211fc9f\")\n"
|
" assignImmutable(\"0x26f2c0195e9d408feff3abd77d83f2971f3c9a18d1e8a9437c7835ae4211fc9f\")\n"
|
||||||
" 0x17\n"
|
" 0x17\n"
|
||||||
|
" 0x00\n"
|
||||||
" assignImmutable(\"0xc3978657661c4d8e32e3d5f42597c009f0d3859e9f9d0d94325268f9799e2bfb\")\n"
|
" assignImmutable(\"0xc3978657661c4d8e32e3d5f42597c009f0d3859e9f9d0d94325268f9799e2bfb\")\n"
|
||||||
" dataSize(sub_0)\n"
|
" dataSize(sub_0)\n"
|
||||||
" dataOffset(sub_0)\n"
|
" dataOffset(sub_0)\n"
|
||||||
@ -242,8 +251,10 @@ BOOST_AUTO_TEST_CASE(immutable)
|
|||||||
util::jsonCompactPrint(_assembly.assemblyJSON(indices)),
|
util::jsonCompactPrint(_assembly.assemblyJSON(indices)),
|
||||||
"{\".code\":["
|
"{\".code\":["
|
||||||
"{\"begin\":1,\"end\":3,\"name\":\"PUSH\",\"source\":0,\"value\":\"2A\"},"
|
"{\"begin\":1,\"end\":3,\"name\":\"PUSH\",\"source\":0,\"value\":\"2A\"},"
|
||||||
|
"{\"begin\":1,\"end\":3,\"name\":\"PUSH\",\"source\":0,\"value\":\"0\"},"
|
||||||
"{\"begin\":1,\"end\":3,\"name\":\"ASSIGNIMMUTABLE\",\"source\":0,\"value\":\"someImmutable\"},"
|
"{\"begin\":1,\"end\":3,\"name\":\"ASSIGNIMMUTABLE\",\"source\":0,\"value\":\"someImmutable\"},"
|
||||||
"{\"begin\":1,\"end\":3,\"name\":\"PUSH\",\"source\":0,\"value\":\"17\"},"
|
"{\"begin\":1,\"end\":3,\"name\":\"PUSH\",\"source\":0,\"value\":\"17\"},"
|
||||||
|
"{\"begin\":1,\"end\":3,\"name\":\"PUSH\",\"source\":0,\"value\":\"0\"},"
|
||||||
"{\"begin\":1,\"end\":3,\"name\":\"ASSIGNIMMUTABLE\",\"source\":0,\"value\":\"someOtherImmutable\"},"
|
"{\"begin\":1,\"end\":3,\"name\":\"ASSIGNIMMUTABLE\",\"source\":0,\"value\":\"someOtherImmutable\"},"
|
||||||
"{\"begin\":1,\"end\":3,\"name\":\"PUSH #[$]\",\"source\":0,\"value\":\"0000000000000000000000000000000000000000000000000000000000000000\"},"
|
"{\"begin\":1,\"end\":3,\"name\":\"PUSH #[$]\",\"source\":0,\"value\":\"0000000000000000000000000000000000000000000000000000000000000000\"},"
|
||||||
"{\"begin\":1,\"end\":3,\"name\":\"PUSH [$]\",\"source\":0,\"value\":\"0000000000000000000000000000000000000000000000000000000000000000\"}"
|
"{\"begin\":1,\"end\":3,\"name\":\"PUSH [$]\",\"source\":0,\"value\":\"0000000000000000000000000000000000000000000000000000000000000000\"}"
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
object "a" {
|
object "a" {
|
||||||
code {
|
code {
|
||||||
setimmutable(
|
setimmutable(
|
||||||
|
0,
|
||||||
"long___name___that___definitely___exceeds___the___thirty___two___byte___limit",
|
"long___name___that___definitely___exceeds___the___thirty___two___byte___limit",
|
||||||
0x1234567890123456789012345678901234567890
|
0x1234567890123456789012345678901234567890
|
||||||
)
|
)
|
||||||
@ -8,10 +9,12 @@ object "a" {
|
|||||||
}
|
}
|
||||||
// ----
|
// ----
|
||||||
// Assembly:
|
// Assembly:
|
||||||
// /* "source":152:194 */
|
// /* "source":167:209 */
|
||||||
// 0x1234567890123456789012345678901234567890
|
// 0x1234567890123456789012345678901234567890
|
||||||
// /* "source":32:204 */
|
// /* "source":58:59 */
|
||||||
|
// 0x00
|
||||||
|
// /* "source":32:219 */
|
||||||
// assignImmutable("0x85a5b1db611c82c46f5fa18e39ae218397536256c451e5de155a86de843a9ad6")
|
// assignImmutable("0x85a5b1db611c82c46f5fa18e39ae218397536256c451e5de155a86de843a9ad6")
|
||||||
// Bytecode: 73123456789012345678901234567890123456789050
|
// Bytecode: 73123456789012345678901234567890123456789060005050
|
||||||
// Opcodes: PUSH20 0x1234567890123456789012345678901234567890 POP
|
// Opcodes: PUSH20 0x1234567890123456789012345678901234567890 PUSH1 0x0 POP POP
|
||||||
// SourceMappings: 152:42:0:-:0;32:172
|
// SourceMappings: 167:42:0:-:0;58:1;32:187
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
setimmutable(loadimmutable("abc"), "abc")
|
setimmutable(0, loadimmutable("abc"), "abc")
|
||||||
}
|
}
|
||||||
// ====
|
// ====
|
||||||
// dialect: evm
|
// dialect: evm
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
setimmutable("address", 0x1234567890123456789012345678901234567890)
|
setimmutable(0, "address", 0x1234567890123456789012345678901234567890)
|
||||||
}
|
}
|
||||||
// ====
|
// ====
|
||||||
// dialect: evm
|
// dialect: evm
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
{
|
{
|
||||||
setimmutable(0, 0x1234567890123456789012345678901234567890)
|
setimmutable(0, 0, 0x1234567890123456789012345678901234567890)
|
||||||
setimmutable(true, 0x1234567890123456789012345678901234567890)
|
setimmutable(0, true, 0x1234567890123456789012345678901234567890)
|
||||||
setimmutable(false, 0x1234567890123456789012345678901234567890)
|
setimmutable(0, false, 0x1234567890123456789012345678901234567890)
|
||||||
}
|
}
|
||||||
// ====
|
// ====
|
||||||
// dialect: evm
|
// dialect: evm
|
||||||
// ----
|
// ----
|
||||||
// TypeError 5859: (19-20): Function expects string literal.
|
// TypeError 5859: (22-23): Function expects string literal.
|
||||||
// TypeError 5859: (83-87): Function expects string literal.
|
// TypeError 5859: (89-93): Function expects string literal.
|
||||||
// TypeError 5859: (150-155): Function expects string literal.
|
// TypeError 5859: (159-164): Function expects string literal.
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
setimmutable(
|
setimmutable(
|
||||||
|
0,
|
||||||
"long___name___that___definitely___exceeds___the___thirty___two___byte___limit",
|
"long___name___that___definitely___exceeds___the___thirty___two___byte___limit",
|
||||||
0x1234567890123456789012345678901234567890
|
0x1234567890123456789012345678901234567890
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user