diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index 2b98c12af31..f6fc5586a94 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -4861,9 +4861,17 @@ class ModuleRunnerBase : public ExpressionRunner { // There was a return call, so we need to call the next function before // returning to the caller. The flow carries the function arguments and a // function reference. - name = flow.values.back().getFunc(); + auto nextData = flow.values.back().getFuncData(); + name = nextData->name; flow.values.pop_back(); arguments = flow.values; + + if (nextData->self != this) { + // This function is in another module. Call from there. + auto other = (decltype(this))nextData->self; + flow = other->callFunction(name, arguments); + break; + } } if (flow.breaking() && flow.breakTo == NONCONSTANT_FLOW) { diff --git a/test/lit/exec/second_retcall.wast b/test/lit/exec/second_retcall.wast new file mode 100644 index 00000000000..842d2e446b7 --- /dev/null +++ b/test/lit/exec/second_retcall.wast @@ -0,0 +1,23 @@ + +;; RUN: wasm-opt %s -all --fuzz-exec-before --fuzz-exec-second=%s.second -q -o /dev/null 2>&1 | filecheck %s + +(module + (import "fuzzing-support" "log-i32" (func $log-i32 (param i32))) + + (global $global funcref (ref.func $func)) + + (export "global" (global $global)) + + (func $func + (call $log-i32 + (i32.const 42) + ) + ) +) + +;; Export a funcref through a global, and return_call it from the other module. +;; It must be called ok, print 42, and not error. + +;; CHECK: [fuzz-exec] calling caller +;; CHECK-NEXT: [LoggingExternalInterface logging 42] + diff --git a/test/lit/exec/second_retcall.wast.second b/test/lit/exec/second_retcall.wast.second new file mode 100644 index 00000000000..6a7184c4241 --- /dev/null +++ b/test/lit/exec/second_retcall.wast.second @@ -0,0 +1,19 @@ +(module + (type $func (func)) + + (import "primary" "global" (global $gimport funcref)) + + (table $table 10 funcref) + + (func $caller (export "caller") + ;; Do an indirect call from the table, writing the imported funcref first. + (table.set $table + (i32.const 1) + (global.get $gimport) + ) + (return_call_indirect (type $func) + (i32.const 1) + ) + ) +) +