From 1a41241d6cf112b5426ffe8ed308479cfaebe5cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 14 Jun 2022 13:45:25 +0200 Subject: [PATCH] advanced: Fix JUMPI followed by stack underflow Fix stack height check for the basic block following a JUMPI instruction. Before the stack height was 1 too big because the implementation incorrectly did not remove the JUMPI condition from the stack. The bug was introduced in https://github.com/ethereum/evmone/pull/457. --- lib/evmone/advanced_instructions.cpp | 16 +++++++--------- test/unittests/evm_control_flow_test.cpp | 6 ++++++ 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/lib/evmone/advanced_instructions.cpp b/lib/evmone/advanced_instructions.cpp index 2775065678..951c759052 100644 --- a/lib/evmone/advanced_instructions.cpp +++ b/lib/evmone/advanced_instructions.cpp @@ -141,18 +141,16 @@ const Instruction* op_jump(const Instruction*, AdvancedExecutionState& state) no const Instruction* op_jumpi(const Instruction* instr, AdvancedExecutionState& state) noexcept { if (state.stack[1] != 0) - instr = op_jump(instr, state); + { + instr = op_jump(instr, state); // target + state.stack.pop(); // condition + } else { - state.stack.pop(); - - instr = opx_beginblock(instr, state); + state.stack.pop(); // target + state.stack.pop(); // condition + instr = opx_beginblock(instr, state); // follow-by block } - - // OPT: The pc must be the BEGINBLOCK (even in fallback case), - // so we can execute it straight away. - - state.stack.pop(); return instr; } diff --git a/test/unittests/evm_control_flow_test.cpp b/test/unittests/evm_control_flow_test.cpp index 3b99252ee2..6265e73eb8 100644 --- a/test/unittests/evm_control_flow_test.cpp +++ b/test/unittests/evm_control_flow_test.cpp @@ -134,6 +134,12 @@ TEST_P(evm, jumpi_jumpdest) EXPECT_GAS_USED(EVMC_SUCCESS, 20); } +TEST_P(evm, jumpi_followed_by_stack_underflow) +{ + execute(push(0) + OP_DUP1 + OP_JUMPI + OP_POP); + EXPECT_STATUS(EVMC_STACK_UNDERFLOW); +} + TEST_P(evm, pc_sum) { const auto code = 4 * OP_PC + 3 * OP_ADD + ret_top();