diff --git a/lib/fizzy/instantiate.cpp b/lib/fizzy/instantiate.cpp index 9ec4cbe68..8d339c475 100644 --- a/lib/fizzy/instantiate.cpp +++ b/lib/fizzy/instantiate.cpp @@ -177,6 +177,13 @@ std::tuple allocate_memory(const std::vector& module_ static const auto bytes_delete = [](bytes* b) noexcept { delete b; }; static const auto null_delete = [](bytes*) noexcept {}; + if (memory_pages_limit > MaxMemoryPagesLimit) + { + throw instantiate_error{"hard memory limit cannot exceed " + + std::to_string(uint64_t{MaxMemoryPagesLimit} * PageSize) + + " bytes"}; + } + assert(module_memories.size() + imported_memories.size() <= 1); if (module_memories.size() == 1) diff --git a/lib/fizzy/limits.hpp b/lib/fizzy/limits.hpp index f5c497c05..c60f632bb 100644 --- a/lib/fizzy/limits.hpp +++ b/lib/fizzy/limits.hpp @@ -13,8 +13,8 @@ constexpr uint32_t PageSize = 65536; /// The maximum memory page limit as defined by the specification. /// It is only possible to address 4 GB (32-bit) of memory. -constexpr uint32_t MemoryPagesValidationLimit = (4 * 1024 * 1024 * 1024ULL) / PageSize; -static_assert(MemoryPagesValidationLimit == 65536); +constexpr uint32_t MaxMemoryPagesLimit = (4 * 1024 * 1024 * 1024ULL) / PageSize; +static_assert(MaxMemoryPagesLimit == 65536); /// The default hard limit of the memory size (256MB) as number of pages. constexpr uint32_t DefaultMemoryPagesLimit = (256 * 1024 * 1024ULL) / PageSize; diff --git a/lib/fizzy/parser.cpp b/lib/fizzy/parser.cpp index b360c55f1..20413d0dd 100644 --- a/lib/fizzy/parser.cpp +++ b/lib/fizzy/parser.cpp @@ -257,8 +257,8 @@ inline parser_result parse(const uint8_t* pos, const uint8_t* end) { Limits limits; std::tie(limits, pos) = parse_limits(pos, end); - if ((limits.min > MemoryPagesValidationLimit) || - (limits.max.has_value() && *limits.max > MemoryPagesValidationLimit)) + if ((limits.min > MaxMemoryPagesLimit) || + (limits.max.has_value() && *limits.max > MaxMemoryPagesLimit)) throw validation_error{"maximum memory page limit exceeded"}; return {{limits}, pos}; } diff --git a/test/unittests/execute_test.cpp b/test/unittests/execute_test.cpp index 8d54f7ceb..1de405e2d 100644 --- a/test/unittests/execute_test.cpp +++ b/test/unittests/execute_test.cpp @@ -673,6 +673,7 @@ TEST(execute, memory_grow_custom_hard_limit) {1, 1}, {15, 1}, {16, -1}, + {65535, -1}, {0xffffffff, -1}, }; @@ -693,6 +694,15 @@ TEST(execute, memory_grow_custom_hard_limit) EXPECT_THAT(execute(*instance, 0, {input}), Result(expected)); } + { + const auto instance_huge_hard_limit = instantiate(*module, {}, {}, {}, {}, 65536); + // For huge hard limit we test only failure cases, because allocating 4GB of memory would + // be too slow for unit tests. + // EXPECT_THAT(execute(*instance_huge_hard_limit, 0, {65535}), Result(1)); + EXPECT_THAT(execute(*instance_huge_hard_limit, 0, {65536}), Result(-1)); + EXPECT_THAT(execute(*instance_huge_hard_limit, 0, {0xffffffff}), Result(-1)); + } + /* wat2wasm (memory 1 16) (func (param i32) (result i32) @@ -734,6 +744,14 @@ TEST(execute, memory_grow_custom_hard_limit) EXPECT_THAT(execute(*instance_max_limit, 0, {input}), Result(expected)); } + { + bytes memory(PageSize, 0); + const auto instance_huge_hard_limit = + instantiate(*module_imported, {}, {}, {{&memory, {1, std::nullopt}}}, {}, 65536); + EXPECT_THAT(execute(*instance_huge_hard_limit, 0, {65536}), Result(-1)); + EXPECT_THAT(execute(*instance_huge_hard_limit, 0, {0xffffffff}), Result(-1)); + } + /* wat2wasm (memory (import "mod" "mem") 1 16) (func (param i32) (result i32) diff --git a/test/unittests/instantiate_test.cpp b/test/unittests/instantiate_test.cpp index 2b7123c6c..1dca21c61 100644 --- a/test/unittests/instantiate_test.cpp +++ b/test/unittests/instantiate_test.cpp @@ -518,6 +518,11 @@ TEST(instantiate, memory_single_custom_hard_limit) EXPECT_NO_THROW(instantiate(*module, {}, {}, {}, {}, 4)); EXPECT_NO_THROW(instantiate(*module, {}, {}, {}, {}, 8)); + EXPECT_NO_THROW(instantiate(*module, {}, {}, {}, {}, 65536)); + EXPECT_THROW_MESSAGE(instantiate(*module, {}, {}, {}, {}, 65537), instantiate_error, + "hard memory limit cannot exceed 4294967296 bytes"); + EXPECT_THROW_MESSAGE(instantiate(*module, {}, {}, {}, {}, std::numeric_limits::max()), + instantiate_error, "hard memory limit cannot exceed 4294967296 bytes"); } TEST(instantiate, imported_memory_custom_hard_limit) diff --git a/tools/wasi/wasi.cpp b/tools/wasi/wasi.cpp index b7e2606e7..3e67a89ba 100644 --- a/tools/wasi/wasi.cpp +++ b/tools/wasi/wasi.cpp @@ -155,7 +155,7 @@ bool run(int argc, const char** argv) auto module = fizzy::parse(wasm_binary); auto imports = fizzy::resolve_imported_functions(*module, wasi_functions); auto instance = fizzy::instantiate( - std::move(module), std::move(imports), {}, {}, {}, fizzy::MemoryPagesValidationLimit); + std::move(module), std::move(imports), {}, {}, {}, fizzy::MaxMemoryPagesLimit); assert(instance != nullptr); const auto start_function = fizzy::find_exported_function(*instance->module, "_start");