Skip to content

Commit 5506519

Browse files
committed
host: Reject DELEGATECALL crossing EOF<>legacy boundary
1 parent 2424f3d commit 5506519

File tree

1 file changed

+17
-4
lines changed

1 file changed

+17
-4
lines changed

test/state/host.cpp

+17-4
Original file line numberDiff line numberDiff line change
@@ -76,15 +76,17 @@ uint256be Host::get_balance(const address& addr) const noexcept
7676

7777
namespace
7878
{
79+
bool is_eof(bytes_view code) noexcept
80+
{
81+
return code.size() >= 2 && code[0] == 0xEF && code[1] == 0x00;
82+
}
83+
7984
// For EXTCODE* instructions if the target is an EOF account, then only return EF00.
8085
// While we only do this if the caller is legacy, it is not a problem doing this
8186
// unconditionally, because EOF contracts dot no have EXTCODE* instructions.
8287
bytes_view extcode(bytes_view code) noexcept
8388
{
84-
if (code.size() >= 2 && code[0] == 0xEF && code[1] == 0x00)
85-
return code.substr(2);
86-
87-
return code;
89+
return is_eof(code) ? code.substr(2) : code;
8890
}
8991
} // namespace
9092

@@ -280,6 +282,17 @@ evmc::Result Host::execute_message(const evmc_message& msg) noexcept
280282

281283
// Copy of the code. Revert will invalidate the account.
282284
const auto code = dst_acc != nullptr ? dst_acc->code : bytes{};
285+
286+
if (msg.kind == EVMC_DELEGATECALL)
287+
{
288+
// TODO: does the sender always have code here? or is this function used for EOAs too?
289+
const auto sender = m_state.get(msg.sender);
290+
291+
// DELEGATECALL initiator and destination both must be either legacy or EOF
292+
if (is_eof(code) != is_eof(sender.code))
293+
return evmc::Result{EVMC_FAILURE};
294+
}
295+
283296
return m_vm.execute(*this, m_rev, msg, code.data(), code.size());
284297
}
285298

0 commit comments

Comments
 (0)