diff --git a/lib/evmone/eof.cpp b/lib/evmone/eof.cpp index 52e300c658..11e64407e0 100644 --- a/lib/evmone/eof.cpp +++ b/lib/evmone/eof.cpp @@ -229,10 +229,8 @@ EOFValidationError validate_instructions( if (op == OP_RJUMPV) { - const auto count = code[i + 1]; - if (count < 1) - return EOFValidationError::invalid_rjumpv_count; - i += static_cast(1 /* count */ + count * 2 /* tbl */); + const auto count = code[i + 1] + 1; + i += static_cast(1 /* max_index */ + count * 2 /* tbl */); if (i >= code.size()) return EOFValidationError::truncated_instruction; } @@ -292,7 +290,7 @@ bool validate_rjump_destinations(bytes_view code) noexcept } else if (op == OP_RJUMPV) { - const auto count = code[i + 1]; + const auto count = size_t{code[i + 1]} + 1; imm_size += count * REL_OFFSET_SIZE /* tbl */; const size_t post_pos = i + 1 + imm_size; @@ -362,7 +360,7 @@ std::variant validate_max_stack_height( // Determine size of immediate, including the special case of RJUMPV. const size_t imm_size = (opcode == OP_RJUMPV) ? - (1 + /*count*/ size_t{code[i + 1]} * REL_OFFSET_SIZE) : + (1 + /*count*/ (size_t{code[i + 1]} + 1) * REL_OFFSET_SIZE) : instr::traits[opcode].immediate_size; // Mark immediate locations. @@ -403,10 +401,10 @@ std::variant validate_max_stack_height( } else if (opcode == OP_RJUMPV) { - const auto count = code[i + 1]; + const auto max_index = code[i + 1]; // Insert all jump targets. - for (size_t k = 0; k < count; ++k) + for (size_t k = 0; k <= max_index; ++k) { const auto target_rel_offset = read_int16_be(&code[i + k * REL_OFFSET_SIZE + 2]); const auto target = static_cast(next) + target_rel_offset; @@ -602,8 +600,6 @@ std::string_view get_error_message(EOFValidationError err) noexcept return "undefined_instruction"; case EOFValidationError::truncated_instruction: return "truncated_instruction"; - case EOFValidationError::invalid_rjumpv_count: - return "invalid_rjumpv_count"; case EOFValidationError::invalid_rjump_destination: return "invalid_rjump_destination"; case EOFValidationError::too_many_code_sections: diff --git a/lib/evmone/eof.hpp b/lib/evmone/eof.hpp index e67e1904f9..d29ca4e526 100644 --- a/lib/evmone/eof.hpp +++ b/lib/evmone/eof.hpp @@ -84,7 +84,6 @@ enum class EOFValidationError invalid_section_bodies_size, undefined_instruction, truncated_instruction, - invalid_rjumpv_count, invalid_rjump_destination, too_many_code_sections, invalid_type_section_size, diff --git a/lib/evmone/instructions.hpp b/lib/evmone/instructions.hpp index a0208d3e7d..846c0edbeb 100644 --- a/lib/evmone/instructions.hpp +++ b/lib/evmone/instructions.hpp @@ -731,10 +731,10 @@ inline code_iterator rjumpv(StackTop stack, ExecutionState& /*state*/, code_iter constexpr auto REL_OFFSET_SIZE = sizeof(int16_t); const auto case_ = stack.pop(); - const auto count = pc[1]; - const auto pc_post = pc + 1 + 1 /* count */ + count * REL_OFFSET_SIZE /* tbl */; + const auto max_index = pc[1]; + const auto pc_post = pc + 1 + 1 /* max_index */ + (max_index + 1) * REL_OFFSET_SIZE /* tbl */; - if (case_ >= count) + if (case_ > max_index) { return pc_post; } diff --git a/test/unittests/eof_validation_test.cpp b/test/unittests/eof_validation_test.cpp index 5a67bc2018..a0dbf9f541 100644 --- a/test/unittests/eof_validation_test.cpp +++ b/test/unittests/eof_validation_test.cpp @@ -424,22 +424,22 @@ TEST(eof_validation, EOF1_valid_rjumpi) TEST(eof_validation, EOF1_valid_rjumpv) { // table = [0] case = 0 - EXPECT_EQ(validate_eof("EF0001 010004 0200010009 040000 00 00000001 6000E2010000600100"), + EXPECT_EQ(validate_eof("EF0001 010004 0200010009 040000 00 00000001 6000E2000000600100"), EOFValidationError::success); // table = [0,3] case = 0 EXPECT_EQ( - validate_eof("EF0001 010004 020001000E 040000 00 00000001 6000E20200000003600100600200"), + validate_eof("EF0001 010004 020001000E 040000 00 00000001 6000E20100000003600100600200"), EOFValidationError::success); // table = [0,3] case = 2 EXPECT_EQ( - validate_eof("EF0001 010004 020001000E 040000 00 00000001 6002E20200000003600100600200"), + validate_eof("EF0001 010004 020001000E 040000 00 00000001 6002E20100000003600100600200"), EOFValidationError::success); // table = [0,3,-10] case = 2 EXPECT_EQ(validate_eof( - "EF0001 010004 0200010010 040000 00 00000001 6002E20300000003FFF6600100600200"), + "EF0001 010004 0200010010 040000 00 00000001 6002E20200000003FFF6600100600200"), EOFValidationError::success); } @@ -464,29 +464,22 @@ TEST(eof_validation, EOF1_rjumpi_truncated) TEST(eof_validation, EOF1_rjumpv_truncated) { // table = [0] case = 0 - EXPECT_EQ(validate_eof("EF0001 010004 0200010005 040000 00 00000000 6000E20100"), + EXPECT_EQ(validate_eof("EF0001 010004 0200010005 040000 00 00000000 6000E20000"), EOFValidationError::truncated_instruction); // table = [0,3] case = 0 - EXPECT_EQ(validate_eof("EF0001 010004 0200010007 040000 00 00000000 6000E202000000"), + EXPECT_EQ(validate_eof("EF0001 010004 0200010007 040000 00 00000000 6000E201000000"), EOFValidationError::truncated_instruction); // table = [0,3] case = 2 - EXPECT_EQ(validate_eof("EF0001 010004 0200010006 040000 00 00000000 6002E2020000"), + EXPECT_EQ(validate_eof("EF0001 010004 0200010006 040000 00 00000000 6002E2010000"), EOFValidationError::truncated_instruction); // table = [0,3,-10] case = 2 - EXPECT_EQ(validate_eof("EF0001 010004 0200010009 040000 00 00000000 6002E20300000003FF"), + EXPECT_EQ(validate_eof("EF0001 010004 0200010009 040000 00 00000000 6002E20200000003FF"), EOFValidationError::truncated_instruction); } -TEST(eof_validation, EOF1_rjumpv_0_count) -{ - auto code = eof1_bytecode(rjumpv({}, 0) + OP_STOP, 1); - - EXPECT_EQ(validate_eof(code), EOFValidationError::invalid_rjumpv_count); -} - TEST(eof_validation, EOF1_rjump_invalid_destination) { // Into header (offset = -5) @@ -544,49 +537,49 @@ TEST(eof_validation, EOF1_rjumpi_invalid_destination) TEST(eof_validation, EOF1_rjumpv_invalid_destination) { // table = [-23] case = 0 - EXPECT_EQ(validate_eof("EF0001 010004 0200010008 040000 00 00000000 6000E201FFE96001"), + EXPECT_EQ(validate_eof("EF0001 010004 0200010008 040000 00 00000000 6000E200FFE96001"), EOFValidationError::invalid_rjump_destination); // table = [-8] case = 0 - EXPECT_EQ(validate_eof("EF0001 010004 0200010008 040000 00 00000000 6000E201FFF86001"), + EXPECT_EQ(validate_eof("EF0001 010004 0200010008 040000 00 00000000 6000E200FFF86001"), EOFValidationError::invalid_rjump_destination); // table = [-1] case = 0 - EXPECT_EQ(validate_eof("EF0001 010004 0200010008 040000 00 00000000 6000E201FFFF6001"), + EXPECT_EQ(validate_eof("EF0001 010004 0200010008 040000 00 00000000 6000E200FFFF6001"), EOFValidationError::invalid_rjump_destination); // table = [2] case = 0 - EXPECT_EQ(validate_eof("EF0001 010004 0200010008 040000 00 00000000 6000E20100026001"), + EXPECT_EQ(validate_eof("EF0001 010004 0200010008 040000 00 00000000 6000E20000026001"), EOFValidationError::invalid_rjump_destination); // table = [3] case = 0 - EXPECT_EQ(validate_eof("EF0001 010004 0200010008 040000 00 00000000 6000E20100036001"), + EXPECT_EQ(validate_eof("EF0001 010004 0200010008 040000 00 00000000 6000E20000036001"), EOFValidationError::invalid_rjump_destination); // table = [0,3,-27] case = 2 EXPECT_EQ( - validate_eof("EF0001 010004 020001000F 040000 00 00000000 6002E20300000003FFE56001006002"), + validate_eof("EF0001 010004 020001000F 040000 00 00000000 6002E20200000003FFE56001006002"), EOFValidationError::invalid_rjump_destination); // table = [0,3,-12] case = 2 EXPECT_EQ( - validate_eof("EF0001 010004 020001000F 040000 00 00000000 6002E20300000003FFF46001006002"), + validate_eof("EF0001 010004 020001000F 040000 00 00000000 6002E20200000003FFF46001006002"), EOFValidationError::invalid_rjump_destination); // table = [0,3,-1] case = 2 EXPECT_EQ( - validate_eof("EF0001 010004 020001000F 040000 00 00000000 6002E20300000003FFFF6001006002"), + validate_eof("EF0001 010004 020001000F 040000 00 00000000 6002E20200000003FFFF6001006002"), EOFValidationError::invalid_rjump_destination); // table = [0,3,5] case = 2 EXPECT_EQ( - validate_eof("EF0001 010004 020001000F 040000 00 00000000 6002E2030000000300056001006002"), + validate_eof("EF0001 010004 020001000F 040000 00 00000000 6002E2020000000300056001006002"), EOFValidationError::invalid_rjump_destination); // table = [0,3,6] case = 2 EXPECT_EQ( - validate_eof("EF0001 010004 020001000F 040000 00 00000000 6002E2030000000300066001006002"), + validate_eof("EF0001 010004 020001000F 040000 00 00000000 6002E2020000000300066001006002"), EOFValidationError::invalid_rjump_destination); } @@ -662,7 +655,7 @@ TEST(eof_validation, max_arguments_count) } } -TEST(eof_validation, max_stack_heigh) +TEST(eof_validation, max_stack_height) { { auto code = bytecode{"EF0001 010008 02000200010BFE 040000 00 00000000 000003FF"} + OP_RETF + diff --git a/test/utils/bytecode.hpp b/test/utils/bytecode.hpp index 8bebf7603b..2743fbefb4 100644 --- a/test/utils/bytecode.hpp +++ b/test/utils/bytecode.hpp @@ -261,7 +261,8 @@ inline bytecode rjumpi(int16_t offset, bytecode condition) inline bytecode rjumpv(const std::initializer_list offsets, bytecode condition) { - bytecode ret = condition + OP_RJUMPV + static_cast(offsets.size()); + assert(offsets.size() > 0); + bytecode ret = condition + OP_RJUMPV + static_cast(offsets.size() - 1); for (const auto offset : offsets) ret += bytecode{big_endian(offset)}; return ret;