diff options
-rw-r--r-- | src/tools/wasm-ctor-eval.cpp | 44 | ||||
-rw-r--r-- | test/ctor-eval/overlapping-segments.wast | 27 | ||||
-rw-r--r-- | test/ctor-eval/overlapping-segments.wast.ctors | 1 | ||||
-rw-r--r-- | test/ctor-eval/overlapping-segments.wast.out | 21 |
4 files changed, 74 insertions, 19 deletions
diff --git a/src/tools/wasm-ctor-eval.cpp b/src/tools/wasm-ctor-eval.cpp index d2364dcc7..867335a20 100644 --- a/src/tools/wasm-ctor-eval.cpp +++ b/src/tools/wasm-ctor-eval.cpp @@ -319,6 +319,7 @@ struct CtorEvalExternalInterface : EvallingModuleInstance::ExternalInterface { extra); } + // We assume the table is not modified FIXME Literals callTable(Name tableName, Index index, HeapType sig, @@ -333,8 +334,9 @@ struct CtorEvalExternalInterface : EvallingModuleInstance::ExternalInterface { throw FailToEvalException("callTable on non-existing table"); } - // we assume the table is not modified (hmm) - // look through the segments, try to find the function + // Look through the segments and find the function. Segments can overlap, + // so we want the last one. + Name targetFunc; for (auto& segment : wasm->elementSegments) { if (segment->table != tableName) { continue; @@ -357,29 +359,33 @@ struct CtorEvalExternalInterface : EvallingModuleInstance::ExternalInterface { if (start <= index && index < end) { auto entry = segment->data[index - start]; if (auto* get = entry->dynCast<RefFunc>()) { - auto name = get->func; - // if this is one of our functions, we can call it; if it was - // imported, fail - auto* func = wasm->getFunction(name); - if (func->type != sig) { - throw FailToEvalException( - std::string("callTable signature mismatch: ") + name.str); - } - if (!func->imported()) { - return instance.callFunctionInternal(name, arguments); - } else { - throw FailToEvalException( - std::string("callTable on imported function: ") + name.str); - } + targetFunc = get->func; } else { throw FailToEvalException( std::string("callTable on uninitialized entry")); } } } - throw FailToEvalException( - std::string("callTable on index not found in static segments: ") + - std::to_string(index)); + + if (!targetFunc.is()) { + throw FailToEvalException( + std::string("callTable on index not found in static segments: ") + + std::to_string(index)); + } + + // If this is one of our functions, we can call it; if it was + // imported, fail. + auto* func = wasm->getFunction(targetFunc); + if (func->type != sig) { + throw FailToEvalException(std::string("callTable signature mismatch: ") + + targetFunc.str); + } + if (!func->imported()) { + return instance.callFunctionInternal(targetFunc, arguments); + } else { + throw FailToEvalException( + std::string("callTable on imported function: ") + targetFunc.str); + } } Index tableSize(Name tableName) override { diff --git a/test/ctor-eval/overlapping-segments.wast b/test/ctor-eval/overlapping-segments.wast new file mode 100644 index 000000000..bdd6ef905 --- /dev/null +++ b/test/ctor-eval/overlapping-segments.wast @@ -0,0 +1,27 @@ +(module + (type $none_=>_i32 (func (result i32))) + + (table $0 46 funcref) + (elem $0 (i32.const 9) $1) + (elem $1 (i32.const 9) $0) + + (export "test1" (func $2)) + + (func $0 (result i32) + (unreachable) + ) + (func $1 (result i32) + (i32.const 65) + ) + (func $2 + (drop + (call_indirect (type $none_=>_i32) + ;; Calling the item at index $9 should call $0, which appears in the + ;; last of the overlapping segments. That function traps, which stops + ;; us from evalling anything here. + (i32.const 9) + ) + ) + ) +) + diff --git a/test/ctor-eval/overlapping-segments.wast.ctors b/test/ctor-eval/overlapping-segments.wast.ctors new file mode 100644 index 000000000..a5bce3fd2 --- /dev/null +++ b/test/ctor-eval/overlapping-segments.wast.ctors @@ -0,0 +1 @@ +test1 diff --git a/test/ctor-eval/overlapping-segments.wast.out b/test/ctor-eval/overlapping-segments.wast.out new file mode 100644 index 000000000..5a5447391 --- /dev/null +++ b/test/ctor-eval/overlapping-segments.wast.out @@ -0,0 +1,21 @@ +(module + (type $none_=>_i32 (func (result i32))) + (type $none_=>_none (func)) + (table $0 46 funcref) + (elem $0 (i32.const 9) $1) + (elem $1 (i32.const 9) $0) + (export "test1" (func $2)) + (func $0 (result i32) + (unreachable) + ) + (func $1 (result i32) + (i32.const 65) + ) + (func $2 + (drop + (call_indirect $0 (type $none_=>_i32) + (i32.const 9) + ) + ) + ) +) |