diff --git a/lib/evmone/instructions.cpp b/lib/evmone/instructions.cpp index dc11f728b6..d27c507b21 100644 --- a/lib/evmone/instructions.cpp +++ b/lib/evmone/instructions.cpp @@ -697,7 +697,10 @@ void op_log(execution_state& state, instr_argument arg) noexcept const auto cost = int64_t(s) * 8; if ((state.gas_left -= cost) < 0) + { state.exit(EVMC_OUT_OF_GAS); + return; + } std::array topics; for (auto i = 0; i < arg.p.number; ++i) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index ab45a30cca..0a6a0d587c 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -11,9 +11,10 @@ add_subdirectory(bench) add_subdirectory(internal_benchmarks) add_subdirectory(unittests) +set(targets evm-test evmone-bench evmone-bench-internal evmone-unittests testutils) + set_target_properties( - evm-test evmone-bench evmone-bench-internal evmone-unittests testutils - PROPERTIES + ${targets} PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR} LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR} RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR} diff --git a/test/unittests/bytecode_test.cpp b/test/unittests/bytecode_test.cpp index 74f1cf7780..47e2aa6e30 100644 --- a/test/unittests/bytecode_test.cpp +++ b/test/unittests/bytecode_test.cpp @@ -49,6 +49,12 @@ TEST(bytecode, repeat) EXPECT_EQ(0 * OP_STOP, ""); } +TEST(bytecode, to_name) +{ + EXPECT_EQ(to_name(OP_SAR), "SAR"); + EXPECT_EQ(to_name(OP_SAR, EVMC_HOMESTEAD), "UNDEFINED_INSTRUCTION:1d"); +} + TEST(bytecode, decode) { const auto code = push(0x01e240) + OP_DUP1 + OP_GAS + "cc" + OP_REVERT; diff --git a/test/unittests/evm_test.cpp b/test/unittests/evm_test.cpp index e1218ed86f..5478d550fe 100644 --- a/test/unittests/evm_test.cpp +++ b/test/unittests/evm_test.cpp @@ -735,11 +735,17 @@ TEST_F(evm, log_data_cost) auto num_topics = op - OP_LOG0; auto code = push(0) + (4 * OP_DUP1) + push(1) + push(0) + op; auto cost = 407 + num_topics * 375; + EXPECT_EQ(recorded_logs.size(), 0); execute(cost, code); EXPECT_EQ(result.status_code, EVMC_SUCCESS); + EXPECT_EQ(recorded_logs.size(), 1); + recorded_logs.clear(); + EXPECT_EQ(recorded_logs.size(), 0); execute(cost - 1, code); EXPECT_EQ(result.status_code, EVMC_OUT_OF_GAS); + EXPECT_EQ(recorded_logs.size(), 0) << to_name(op); + recorded_logs.clear(); } } diff --git a/test/utils/bytecode.hpp b/test/utils/bytecode.hpp index 316aed66c8..2b613774c1 100644 --- a/test/utils/bytecode.hpp +++ b/test/utils/bytecode.hpp @@ -4,6 +4,7 @@ #pragma once #include +#include struct bytecode; @@ -180,6 +181,19 @@ inline bytecode sload(bytecode index) return index + OP_SLOAD; } +inline std::string hex(evmc_opcode opcode) noexcept +{ + return hex(static_cast(opcode)); +} + +inline std::string to_name(evmc_opcode opcode, evmc_revision rev = EVMC_MAX_REVISION) noexcept +{ + const auto names = evmc_get_instruction_names_table(rev); + if (const auto name = names[opcode]; name) + return name; + + return "UNDEFINED_INSTRUCTION:" + hex(opcode); +} inline std::string decode(bytes_view bytecode, evmc_revision rev) { @@ -206,7 +220,7 @@ inline std::string decode(bytes_view bytecode, evmc_revision rev) } } else - s += " + \"" + to_hex({&opcode, 1}) + '"'; + s += " + \"" + hex(opcode) + '"'; } return s; diff --git a/test/utils/host_mock.hpp b/test/utils/host_mock.hpp index 4bcdcd1ded..ae661646d9 100644 --- a/test/utils/host_mock.hpp +++ b/test/utils/host_mock.hpp @@ -90,7 +90,7 @@ class MockedHost : public evmc::Host std::vector recorded_logs; std::vector recorded_selfdestructs; -private: +protected: std::vector m_recorded_calls_inputs; void record_account_access(const evmc_address& addr) diff --git a/test/utils/utils.hpp b/test/utils/utils.hpp index 41cffb12ca..325b9000ef 100644 --- a/test/utils/utils.hpp +++ b/test/utils/utils.hpp @@ -18,11 +18,6 @@ inline std::string hex(uint8_t b) noexcept return {hex_chars[b >> 4], hex_chars[b & 0xf]}; } -inline std::string hex(evmc_opcode opcode) noexcept -{ - return hex(static_cast(opcode)); -} - bytes from_hex(std::string_view hex); std::string to_hex(bytes_view bytes);