summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/tools/wasm-ctor-eval.cpp44
-rw-r--r--test/ctor-eval/overlapping-segments.wast27
-rw-r--r--test/ctor-eval/overlapping-segments.wast.ctors1
-rw-r--r--test/ctor-eval/overlapping-segments.wast.out21
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)
+ )
+ )
+ )
+)