From f7d23a8becabdefabd083f7c59ab58c36efe2a8e Mon Sep 17 00:00:00 2001 From: Gabor Greif Date: Wed, 6 May 2026 14:25:37 +0200 Subject: [PATCH] Validator: thread table limits through OnReturnCallIndirect `SharedValidator::OnCallIndirect` passes `table_type.limits` to `TypeChecker::OnCallIndirect`, which uses `is_64` to expect i64 vs i32 for the table-index operand. `OnReturnCallIndirect` doesn't, so under table64 plain `call_indirect` with an i64 index validates while the matching `return_call_indirect` rejects it with `expected [i32] but got [i64]`. Fix: mirror the signature. Co-Authored-By: Claude Opus 4.7 (1M context) --- include/wabt/type-checker.h | 3 ++- src/shared-validator.cc | 4 ++-- src/type-checker.cc | 6 ++++-- ...-returncallindirect-table64-type-mismatch.txt | 16 ++++++++++++++++ 4 files changed, 24 insertions(+), 5 deletions(-) create mode 100644 test/typecheck/bad-returncallindirect-table64-type-mismatch.txt diff --git a/include/wabt/type-checker.h b/include/wabt/type-checker.h index 25b2a421f..1033b5bdd 100644 --- a/include/wabt/type-checker.h +++ b/include/wabt/type-checker.h @@ -106,7 +106,8 @@ class TypeChecker { Result OnReturnCall(const TypeVector& param_types, const TypeVector& result_types); Result OnReturnCallIndirect(const TypeVector& param_types, - const TypeVector& result_types); + const TypeVector& result_types, + const Limits& table_limits); Result OnReturnCallRef(Type type, const TypeVector& param_types, const TypeVector& result_types); diff --git a/src/shared-validator.cc b/src/shared-validator.cc index b7b748e73..243b65343 100644 --- a/src/shared-validator.cc +++ b/src/shared-validator.cc @@ -1225,8 +1225,8 @@ Result SharedValidator::OnReturnCallIndirect(const Location& loc, "type mismatch: return_call_indirect must reference " "table of funcref type"); } - result |= - typechecker_.OnReturnCallIndirect(func_type.params, func_type.results); + result |= typechecker_.OnReturnCallIndirect( + func_type.params, func_type.results, table_type.limits); IgnoreLocalRefs(); return result; } diff --git a/src/type-checker.cc b/src/type-checker.cc index bb0e4d7f3..e309190e7 100644 --- a/src/type-checker.cc +++ b/src/type-checker.cc @@ -722,8 +722,10 @@ Result TypeChecker::OnReturnCall(const TypeVector& param_types, } Result TypeChecker::OnReturnCallIndirect(const TypeVector& param_types, - const TypeVector& result_types) { - Result result = PopAndCheck1Type(Type::I32, "return_call_indirect"); + const TypeVector& result_types, + const Limits& table_limits) { + Result result = PopAndCheck1Type(table_limits.is_64 ? Type::I64 : Type::I32, + "return_call_indirect"); result |= PopAndCheckSignature(param_types, "return_call_indirect"); result |= PopAndCheckReturnCall(result_types, "return_call_indirect"); diff --git a/test/typecheck/bad-returncallindirect-table64-type-mismatch.txt b/test/typecheck/bad-returncallindirect-table64-type-mismatch.txt new file mode 100644 index 000000000..940c333c3 --- /dev/null +++ b/test/typecheck/bad-returncallindirect-table64-type-mismatch.txt @@ -0,0 +1,16 @@ +;;; TOOL: wat2wasm +;;; ARGS: --enable-tail-call --enable-memory64 +;;; ERROR: 1 +(module + (type $t (func)) + (func $f) + (table i64 1 1 funcref) + (elem (i64.const 0) $f) + (func + i32.const 0 + return_call_indirect (type $t))) +(;; STDERR ;;; +out/test/typecheck/bad-returncallindirect-table64-type-mismatch.txt:11:5: error: type mismatch in return_call_indirect, expected [i64] but got [i32] + return_call_indirect (type $t))) + ^^^^^^^^^^^^^^^^^^^^ +;;; STDERR ;;)