summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2022-10-03 12:41:35 -0700
committerGitHub <noreply@github.com>2022-10-03 12:41:35 -0700
commitd9a57f8bac6e8dfd366a12f5ff97f58ceb242b91 (patch)
tree6bd23c6ebb06936dbf820250d7a2e6dba3e5edd0
parent50b0b6da61c1ac4c2b4f27256a038a70a200c3df (diff)
downloadbinaryen-d9a57f8bac6e8dfd366a12f5ff97f58ceb242b91.tar.gz
binaryen-d9a57f8bac6e8dfd366a12f5ff97f58ceb242b91.tar.bz2
binaryen-d9a57f8bac6e8dfd366a12f5ff97f58ceb242b91.zip
Fix ordering of visit() in MemoryGrow interpretation (#5108)
This is a pretty subtle point that was missed in #4811 - we need to first visit the child, then compute the size, as the child may alter that size. Found by the fuzzer.
-rw-r--r--src/wasm-interpreter.h8
-rw-r--r--test/lit/exec/memory.grow.wast26
2 files changed, 30 insertions, 4 deletions
diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h
index 56336b237..69434a297 100644
--- a/src/wasm-interpreter.h
+++ b/src/wasm-interpreter.h
@@ -3322,15 +3322,15 @@ public:
}
Flow visitMemoryGrow(MemoryGrow* curr) {
NOTE_ENTER("MemoryGrow");
+ Flow flow = self()->visit(curr->delta);
+ if (flow.breaking()) {
+ return flow;
+ }
auto info = getMemoryInstanceInfo(curr->memory);
auto memorySize = info.instance->getMemorySize(info.name);
auto* memory = info.instance->wasm.getMemory(info.name);
auto indexType = memory->indexType;
auto fail = Literal::makeFromInt64(-1, memory->indexType);
- Flow flow = self()->visit(curr->delta);
- if (flow.breaking()) {
- return flow;
- }
Flow ret = Literal::makeFromInt64(memorySize, indexType);
uint64_t delta = flow.getSingleValue().getUnsigned();
if (delta > uint32_t(-1) / Memory::kPageSize && indexType == Type::i32) {
diff --git a/test/lit/exec/memory.grow.wast b/test/lit/exec/memory.grow.wast
new file mode 100644
index 000000000..64d88bfc7
--- /dev/null
+++ b/test/lit/exec/memory.grow.wast
@@ -0,0 +1,26 @@
+;; 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
+
+(module
+ (memory $0 1)
+
+ ;; CHECK: [fuzz-exec] calling grow_twice
+ ;; CHECK-NEXT: [fuzz-exec] note result: grow_twice => 3
+ (func "grow_twice" (result i32)
+ ;; The nested grow will increase the size from 1 to 3, and return the old
+ ;; size, 1. Then the outer grow will grow by that amount 1, from 3 to 4.
+ (memory.grow
+ (memory.grow
+ (i32.const 2)
+ )
+ )
+ )
+
+ ;; CHECK: [fuzz-exec] calling measure
+ ;; CHECK-NEXT: [fuzz-exec] note result: measure => 4
+ (func "measure" (export "measure") (result i32)
+ ;; This should return the final size, 4.
+ (memory.size)
+ )
+)