diff --git a/src/shell-interface.h b/src/shell-interface.h index 6a8763c9c3f..1d8cf5e9d9e 100644 --- a/src/shell-interface.h +++ b/src/shell-interface.h @@ -90,8 +90,24 @@ struct ShellExternalInterface : ModuleRunner::ExternalInterface { void init(Module& wasm, ModuleRunner& instance) override { ModuleUtils::iterDefinedMemories(wasm, [&](wasm::Memory* memory) { + // Compute the initial size in bytes carefully: the byte size of a + // maximal memory64 (2^48 pages of 64KiB) does not fit in 64 bits. If + // we let it wrap, instantiation would "succeed" with an empty buffer + // and every later access would spuriously trap as out of bounds. + uint64_t bytes = uint64_t(memory->initial) << memory->pageSizeLog2; + if ((bytes >> memory->pageSizeLog2) != uint64_t(memory->initial)) { + // The byte size is not even representable; we certainly cannot + // allocate it, just like a real VM could not. + hostLimit("memory too large"); + } auto shellMemory = Memory(); - shellMemory.resize(memory->initial << memory->pageSizeLog2); + try { + shellMemory.resize(bytes); + } catch (const std::exception&) { + // bad_alloc or length_error from the underlying vector: the memory + // is representable but too large to actually allocate. + hostLimit("memory too large"); + } memories[memory->name] = shellMemory; }); } diff --git a/test/lit/exec/memory64-max-size.wast b/test/lit/exec/memory64-max-size.wast new file mode 100644 index 00000000000..f1b5dc82dd7 --- /dev/null +++ b/test/lit/exec/memory64-max-size.wast @@ -0,0 +1,14 @@ +;; NOTE: Assertions have been generated by update_lit_checks.py --output=fuzz-exec and should not be edited. + +;; RUN: wasm-opt %s -all --fuzz-exec-before -q -o /dev/null 2>&1 | filecheck %s + +;; A maximal memory64 declares 2^48 pages, exactly 2^64 bytes, which cannot be +;; allocated (and whose byte size does not even fit in 64 bits). Instantiation +;; must fail as a host limit, not wrap the size to zero and then spuriously +;; trap on the active segment (which optimizations may legitimately remove, +;; changing the spurious behavior). +(module + ;; CHECK: [host limit memory too large] + (memory $0 i64 281474976710656 281474976710656 shared) + (data $0 (i64.const 0) "\00") +)