diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index 15926c65b64..2e0562f21b8 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -1589,6 +1589,10 @@ struct OptimizeInstructions // Given the large amount of potential benefit we can get from a successful // optimization in GUFA, any reduction there may be a bad idea, so we // should be very careful and probably *not* remove such casts. + // + // The only case where we are always ok to remove such casts is when lastOpts + // is true, because nothing significant runs after us that can be harmed. That + // logic is in the StripRefiningCasts pass. // If an instruction traps on a null input, there is no need for a // ref.as_non_null on that input: we will trap either way (and the binaryen diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index d5e358a081d..733381f958f 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -4616,14 +4616,19 @@ class ModuleRunnerBase : public ExpressionRunner { if (newSize > memory->max) { return fail; } - if (!info.interface()->growMemory( - info.name, (memorySize << pageSizeLog2), (newSize << pageSizeLog2))) { - // We failed to grow the memory in practice, even though it was valid - // to try to do so. - return fail; + // Only grow if we are actually changing the size (otherwise it is wasted + // work, and may OOM unnecessarily). + if (delta != 0) { + if (!info.interface()->growMemory(info.name, + (memorySize << pageSizeLog2), + (newSize << pageSizeLog2))) { + // We failed to grow the memory in practice, even though it was valid + // to try to do so. + return fail; + } + memorySize = newSize; + info.instance->setMemorySize(info.name, memorySize); } - memorySize = newSize; - info.instance->setMemorySize(info.name, memorySize); return ret; } Flow visitMemoryInit(MemoryInit* curr) { diff --git a/test/lit/exec/memory.grow-huge.wast b/test/lit/exec/memory.grow-huge.wast new file mode 100644 index 00000000000..a14b5c3e14a --- /dev/null +++ b/test/lit/exec/memory.grow-huge.wast @@ -0,0 +1,19 @@ +;; 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 + +;; The memory here is over 2GB in size. We grow it by size 0, that is, just +;; retrieve the size without changing it. We should not error on an OOM here. + +(module + (memory i64 32769) + + ;; CHECK: [fuzz-exec] export measure + ;; CHECK-NEXT: [fuzz-exec] note result: measure => 32769 + (func $measure (export "measure") (result i64) + ;; This will return the size, 32769, and not -1 to indicate an OOM. + (memory.grow + (i64.const 0) + ) + ) +)