diff --git a/lib/evmone/eof.cpp b/lib/evmone/eof.cpp index 95e6e68659..3cddf54956 100644 --- a/lib/evmone/eof.cpp +++ b/lib/evmone/eof.cpp @@ -214,10 +214,8 @@ EOFValidationError validate_instructions(evmc_revision rev, bytes_view code) noe if (i + 1 >= code.size()) return EOFValidationError::truncated_instruction; - 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 */); } else i += instr::traits[op].immediate_size; @@ -264,8 +262,8 @@ bool validate_rjump_destinations(bytes_view code) noexcept } else if (op == OP_RJUMPV) { - const auto count = code[i + 1]; - imm_size += size_t{1} /* count */ + count * REL_OFFSET_SIZE /* tbl */; + const auto count = static_cast(code[i + 1] + 1); + imm_size += size_t{1} /* max_index */ + count * REL_OFFSET_SIZE /* tbl */; const size_t post_pos = i + 1 + imm_size; for (size_t k = 0; k < count * REL_OFFSET_SIZE; k += REL_OFFSET_SIZE) @@ -337,7 +335,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. @@ -378,10 +376,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; @@ -577,8 +575,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 dea647c163..fe149dfa70 100644 --- a/lib/evmone/eof.hpp +++ b/lib/evmone/eof.hpp @@ -75,7 +75,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 1d82e6d3a6..0a359df0a2 100644 --- a/lib/evmone/instructions.hpp +++ b/lib/evmone/instructions.hpp @@ -728,10 +728,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 39a5dcf41d..b4b0055358 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 030000 00 00000001 60005E010000600100"), + EXPECT_EQ(validate_eof("EF0001 010004 0200010009 030000 00 00000001 60005E000000600100"), EOFValidationError::success); // table = [0,3] case = 0 EXPECT_EQ( - validate_eof("EF0001 010004 020001000E 030000 00 00000001 60005E0200000003600100600200"), + validate_eof("EF0001 010004 020001000E 030000 00 00000001 60005E0100000003600100600200"), EOFValidationError::success); // table = [0,3] case = 2 EXPECT_EQ( - validate_eof("EF0001 010004 020001000E 030000 00 00000001 60025E0200000003600100600200"), + validate_eof("EF0001 010004 020001000E 030000 00 00000001 60025E0100000003600100600200"), EOFValidationError::success); // table = [0,3,-10] case = 2 EXPECT_EQ(validate_eof( - "EF0001 010004 0200010010 030000 00 00000001 60025E0300000003FFF6600100600200"), + "EF0001 010004 0200010010 030000 00 00000001 60025E0200000003FFF6600100600200"), 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 030000 00 00000000 60005E0100"), + EXPECT_EQ(validate_eof("EF0001 010004 0200010005 030000 00 00000000 60005E0000"), EOFValidationError::truncated_instruction); // table = [0,3] case = 0 - EXPECT_EQ(validate_eof("EF0001 010004 0200010007 030000 00 00000000 60005E02000000"), + EXPECT_EQ(validate_eof("EF0001 010004 0200010007 030000 00 00000000 60005E01000000"), EOFValidationError::truncated_instruction); // table = [0,3] case = 2 - EXPECT_EQ(validate_eof("EF0001 010004 0200010006 030000 00 00000000 60025E020000"), + EXPECT_EQ(validate_eof("EF0001 010004 0200010006 030000 00 00000000 60025E010000"), EOFValidationError::truncated_instruction); // table = [0,3,-10] case = 2 - EXPECT_EQ(validate_eof("EF0001 010004 0200010009 030000 00 00000000 60025E0300000003FF"), + EXPECT_EQ(validate_eof("EF0001 010004 0200010009 030000 00 00000000 60025E0200000003FF"), 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 030000 00 00000000 60005E01FFE96001"), + EXPECT_EQ(validate_eof("EF0001 010004 0200010008 030000 00 00000000 60005E00FFE96001"), EOFValidationError::invalid_rjump_destination); // table = [-8] case = 0 - EXPECT_EQ(validate_eof("EF0001 010004 0200010008 030000 00 00000000 60005E01FFF86001"), + EXPECT_EQ(validate_eof("EF0001 010004 0200010008 030000 00 00000000 60005E00FFF86001"), EOFValidationError::invalid_rjump_destination); // table = [-1] case = 0 - EXPECT_EQ(validate_eof("EF0001 010004 0200010008 030000 00 00000000 60005E01FFFF6001"), + EXPECT_EQ(validate_eof("EF0001 010004 0200010008 030000 00 00000000 60005E00FFFF6001"), EOFValidationError::invalid_rjump_destination); // table = [2] case = 0 - EXPECT_EQ(validate_eof("EF0001 010004 0200010008 030000 00 00000000 60005E0100026001"), + EXPECT_EQ(validate_eof("EF0001 010004 0200010008 030000 00 00000000 60005E0000026001"), EOFValidationError::invalid_rjump_destination); // table = [3] case = 0 - EXPECT_EQ(validate_eof("EF0001 010004 0200010008 030000 00 00000000 60005E0100036001"), + EXPECT_EQ(validate_eof("EF0001 010004 0200010008 030000 00 00000000 60005E0000036001"), EOFValidationError::invalid_rjump_destination); // table = [0,3,-27] case = 2 EXPECT_EQ( - validate_eof("EF0001 010004 020001000F 030000 00 00000000 60025E0300000003FFE56001006002"), + validate_eof("EF0001 010004 020001000F 030000 00 00000000 60025E0200000003FFE56001006002"), EOFValidationError::invalid_rjump_destination); // table = [0,3,-12] case = 2 EXPECT_EQ( - validate_eof("EF0001 010004 020001000F 030000 00 00000000 60025E0300000003FFF46001006002"), + validate_eof("EF0001 010004 020001000F 030000 00 00000000 60025E0200000003FFF46001006002"), EOFValidationError::invalid_rjump_destination); // table = [0,3,-1] case = 2 EXPECT_EQ( - validate_eof("EF0001 010004 020001000F 030000 00 00000000 60025E0300000003FFFF6001006002"), + validate_eof("EF0001 010004 020001000F 030000 00 00000000 60025E0200000003FFFF6001006002"), EOFValidationError::invalid_rjump_destination); // table = [0,3,5] case = 2 EXPECT_EQ( - validate_eof("EF0001 010004 020001000F 030000 00 00000000 60025E030000000300056001006002"), + validate_eof("EF0001 010004 020001000F 030000 00 00000000 60025E020000000300056001006002"), EOFValidationError::invalid_rjump_destination); // table = [0,3,6] case = 2 EXPECT_EQ( - validate_eof("EF0001 010004 020001000F 030000 00 00000000 60025E030000000300066001006002"), + validate_eof("EF0001 010004 020001000F 030000 00 00000000 60025E020000000300066001006002"), EOFValidationError::invalid_rjump_destination); } @@ -662,7 +655,7 @@ TEST(eof_valication, max_arguments_count) } } -TEST(eof_valication, max_stack_heigh) +TEST(eof_valication, max_stack_height) { { auto code = "EF0001 010008 02000200010BFE 030000 00 00000000 000003FF B1" + diff --git a/test/utils/bytecode.hpp b/test/utils/bytecode.hpp index cab98883b5..0012cd4132 100644 --- a/test/utils/bytecode.hpp +++ b/test/utils/bytecode.hpp @@ -256,7 +256,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;