Skip to content

Commit 1e7e248

Browse files
authored
[ctor-eval] Fix evalling of overlapping table segments (#4440)
1 parent 8faada6 commit 1e7e248

File tree

4 files changed

+74
-19
lines changed

4 files changed

+74
-19
lines changed

src/tools/wasm-ctor-eval.cpp

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,7 @@ struct CtorEvalExternalInterface : EvallingModuleInstance::ExternalInterface {
319319
extra);
320320
}
321321

322+
// We assume the table is not modified FIXME
322323
Literals callTable(Name tableName,
323324
Index index,
324325
HeapType sig,
@@ -333,8 +334,9 @@ struct CtorEvalExternalInterface : EvallingModuleInstance::ExternalInterface {
333334
throw FailToEvalException("callTable on non-existing table");
334335
}
335336

336-
// we assume the table is not modified (hmm)
337-
// look through the segments, try to find the function
337+
// Look through the segments and find the function. Segments can overlap,
338+
// so we want the last one.
339+
Name targetFunc;
338340
for (auto& segment : wasm->elementSegments) {
339341
if (segment->table != tableName) {
340342
continue;
@@ -357,29 +359,33 @@ struct CtorEvalExternalInterface : EvallingModuleInstance::ExternalInterface {
357359
if (start <= index && index < end) {
358360
auto entry = segment->data[index - start];
359361
if (auto* get = entry->dynCast<RefFunc>()) {
360-
auto name = get->func;
361-
// if this is one of our functions, we can call it; if it was
362-
// imported, fail
363-
auto* func = wasm->getFunction(name);
364-
if (func->type != sig) {
365-
throw FailToEvalException(
366-
std::string("callTable signature mismatch: ") + name.str);
367-
}
368-
if (!func->imported()) {
369-
return instance.callFunctionInternal(name, arguments);
370-
} else {
371-
throw FailToEvalException(
372-
std::string("callTable on imported function: ") + name.str);
373-
}
362+
targetFunc = get->func;
374363
} else {
375364
throw FailToEvalException(
376365
std::string("callTable on uninitialized entry"));
377366
}
378367
}
379368
}
380-
throw FailToEvalException(
381-
std::string("callTable on index not found in static segments: ") +
382-
std::to_string(index));
369+
370+
if (!targetFunc.is()) {
371+
throw FailToEvalException(
372+
std::string("callTable on index not found in static segments: ") +
373+
std::to_string(index));
374+
}
375+
376+
// If this is one of our functions, we can call it; if it was
377+
// imported, fail.
378+
auto* func = wasm->getFunction(targetFunc);
379+
if (func->type != sig) {
380+
throw FailToEvalException(std::string("callTable signature mismatch: ") +
381+
targetFunc.str);
382+
}
383+
if (!func->imported()) {
384+
return instance.callFunctionInternal(targetFunc, arguments);
385+
} else {
386+
throw FailToEvalException(
387+
std::string("callTable on imported function: ") + targetFunc.str);
388+
}
383389
}
384390

385391
Index tableSize(Name tableName) override {
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
(module
2+
(type $none_=>_i32 (func (result i32)))
3+
4+
(table $0 46 funcref)
5+
(elem $0 (i32.const 9) $1)
6+
(elem $1 (i32.const 9) $0)
7+
8+
(export "test1" (func $2))
9+
10+
(func $0 (result i32)
11+
(unreachable)
12+
)
13+
(func $1 (result i32)
14+
(i32.const 65)
15+
)
16+
(func $2
17+
(drop
18+
(call_indirect (type $none_=>_i32)
19+
;; Calling the item at index $9 should call $0, which appears in the
20+
;; last of the overlapping segments. That function traps, which stops
21+
;; us from evalling anything here.
22+
(i32.const 9)
23+
)
24+
)
25+
)
26+
)
27+
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
test1
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
(module
2+
(type $none_=>_i32 (func (result i32)))
3+
(type $none_=>_none (func))
4+
(table $0 46 funcref)
5+
(elem $0 (i32.const 9) $1)
6+
(elem $1 (i32.const 9) $0)
7+
(export "test1" (func $2))
8+
(func $0 (result i32)
9+
(unreachable)
10+
)
11+
(func $1 (result i32)
12+
(i32.const 65)
13+
)
14+
(func $2
15+
(drop
16+
(call_indirect $0 (type $none_=>_i32)
17+
(i32.const 9)
18+
)
19+
)
20+
)
21+
)

0 commit comments

Comments
 (0)