Skip to content

Commit

Permalink
Merge pull request #748 from wasmx/cap-hard-mem-limit
Browse files Browse the repository at this point in the history
Cap hard memory limit at 4GB
  • Loading branch information
axic authored Mar 10, 2021
2 parents 0b41654 + 207741f commit a1280d6
Show file tree
Hide file tree
Showing 6 changed files with 35 additions and 5 deletions.
7 changes: 7 additions & 0 deletions lib/fizzy/instantiate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,13 @@ std::tuple<bytes_ptr, Limits> allocate_memory(const std::vector<Memory>& 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)
Expand Down
4 changes: 2 additions & 2 deletions lib/fizzy/limits.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
4 changes: 2 additions & 2 deletions lib/fizzy/parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -257,8 +257,8 @@ inline parser_result<Memory> 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};
}
Expand Down
18 changes: 18 additions & 0 deletions test/unittests/execute_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -673,6 +673,7 @@ TEST(execute, memory_grow_custom_hard_limit)
{1, 1},
{15, 1},
{16, -1},
{65535, -1},
{0xffffffff, -1},
};

Expand All @@ -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)
Expand Down Expand Up @@ -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)
Expand Down
5 changes: 5 additions & 0 deletions test/unittests/instantiate_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<uint32_t>::max()),
instantiate_error, "hard memory limit cannot exceed 4294967296 bytes");
}

TEST(instantiate, imported_memory_custom_hard_limit)
Expand Down
2 changes: 1 addition & 1 deletion tools/wasi/wasi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down

0 comments on commit a1280d6

Please sign in to comment.