From eff49e6640841f1ec871abba887fdc8c39e8e501 Mon Sep 17 00:00:00 2001 From: yperbasis Date: Thu, 4 Jul 2024 00:05:57 +0200 Subject: [PATCH 1/2] Avoid potential overflow in num_words --- lib/evmone/instructions.hpp | 2 +- test/state/precompiles.cpp | 2 +- test/state/state.cpp | 2 +- test/unittests/instructions_test.cpp | 15 +++++++++++++++ 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/lib/evmone/instructions.hpp b/lib/evmone/instructions.hpp index 6d16508c9f..66210fe288 100644 --- a/lib/evmone/instructions.hpp +++ b/lib/evmone/instructions.hpp @@ -60,7 +60,7 @@ constexpr auto word_size = 32; /// i.e. it rounds up the number bytes to number of words. inline constexpr int64_t num_words(uint64_t size_in_bytes) noexcept { - return static_cast((size_in_bytes + (word_size - 1)) / word_size); + return static_cast(size_in_bytes / word_size + (size_in_bytes % word_size != 0)); } /// Computes gas cost of copying the given amount of bytes to/from EVM memory. diff --git a/test/state/precompiles.cpp b/test/state/precompiles.cpp index 21b010f81e..22e5f2617a 100644 --- a/test/state/precompiles.cpp +++ b/test/state/precompiles.cpp @@ -32,7 +32,7 @@ constexpr auto GasCostMax = std::numeric_limits::max(); inline constexpr int64_t num_words(size_t size_in_bytes) noexcept { - return static_cast((size_in_bytes + 31) / 32); + return static_cast(size_in_bytes / 32 + (size_in_bytes % 32 != 0)); } template diff --git a/test/state/state.cpp b/test/state/state.cpp index cdf159739d..5429156fd7 100644 --- a/test/state/state.cpp +++ b/test/state/state.cpp @@ -20,7 +20,7 @@ constexpr auto MAX_INITCODE_COUNT = 256; inline constexpr int64_t num_words(size_t size_in_bytes) noexcept { - return static_cast((size_in_bytes + 31) / 32); + return static_cast(size_in_bytes / 32 + (size_in_bytes % 32 != 0)); } int64_t compute_tx_data_cost(evmc_revision rev, bytes_view data) noexcept diff --git a/test/unittests/instructions_test.cpp b/test/unittests/instructions_test.cpp index c0c00e72bb..774be3ae71 100644 --- a/test/unittests/instructions_test.cpp +++ b/test/unittests/instructions_test.cpp @@ -204,3 +204,18 @@ TEST(instructions, compare_with_evmc_instruction_names) EXPECT_STREQ(instr::traits[i].name, evmc_tbl[i]); } } + + +TEST(instructions, num_words) +{ + EXPECT_EQ(num_words(0), 0); + EXPECT_EQ(num_words(1), 1); + EXPECT_EQ(num_words(31), 1); + EXPECT_EQ(num_words(32), 1); + EXPECT_EQ(num_words(33), 2); + EXPECT_EQ(num_words(0xFFFFFFFFFFFFFFDF), 0x7FFFFFFFFFFFFFF); + EXPECT_EQ(num_words(0xFFFFFFFFFFFFFFE0), 0x7FFFFFFFFFFFFFF); + EXPECT_EQ(num_words(0xFFFFFFFFFFFFFFE1), 0x800000000000000); + EXPECT_EQ(num_words(0xFFFFFFFFFFFFFFFE), 0x800000000000000); + EXPECT_EQ(num_words(0xFFFFFFFFFFFFFFFF), 0x800000000000000); +} From 21b14a42cc575ae2eb91d16114cc7ee690030a9e Mon Sep 17 00:00:00 2001 From: yperbasis Date: Thu, 4 Jul 2024 00:12:23 +0200 Subject: [PATCH 2/2] fix lint --- lib/evmone/instructions.hpp | 3 ++- test/state/precompiles.cpp | 2 +- test/state/state.cpp | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/evmone/instructions.hpp b/lib/evmone/instructions.hpp index 66210fe288..07c59a7f3c 100644 --- a/lib/evmone/instructions.hpp +++ b/lib/evmone/instructions.hpp @@ -60,7 +60,8 @@ constexpr auto word_size = 32; /// i.e. it rounds up the number bytes to number of words. inline constexpr int64_t num_words(uint64_t size_in_bytes) noexcept { - return static_cast(size_in_bytes / word_size + (size_in_bytes % word_size != 0)); + return static_cast( + size_in_bytes / word_size + static_cast(size_in_bytes % word_size != 0)); } /// Computes gas cost of copying the given amount of bytes to/from EVM memory. diff --git a/test/state/precompiles.cpp b/test/state/precompiles.cpp index 22e5f2617a..e7e70d069b 100644 --- a/test/state/precompiles.cpp +++ b/test/state/precompiles.cpp @@ -32,7 +32,7 @@ constexpr auto GasCostMax = std::numeric_limits::max(); inline constexpr int64_t num_words(size_t size_in_bytes) noexcept { - return static_cast(size_in_bytes / 32 + (size_in_bytes % 32 != 0)); + return static_cast(size_in_bytes / 32 + static_cast(size_in_bytes % 32 != 0)); } template diff --git a/test/state/state.cpp b/test/state/state.cpp index 5429156fd7..26c9e0a86e 100644 --- a/test/state/state.cpp +++ b/test/state/state.cpp @@ -20,7 +20,7 @@ constexpr auto MAX_INITCODE_COUNT = 256; inline constexpr int64_t num_words(size_t size_in_bytes) noexcept { - return static_cast(size_in_bytes / 32 + (size_in_bytes % 32 != 0)); + return static_cast(size_in_bytes / 32 + static_cast(size_in_bytes % 32 != 0)); } int64_t compute_tx_data_cost(evmc_revision rev, bytes_view data) noexcept