Skip to content

Commit 7f75140

Browse files
authored
[Stack Switching] Throw on trying to suspend through JS (#7825)
Avoid asserting there.
1 parent 3812783 commit 7f75140

File tree

3 files changed

+58
-1
lines changed

3 files changed

+58
-1
lines changed

scripts/test/fuzzing.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@
116116
'cont_simple.wast',
117117
'gufa-cont.wast',
118118
'cont_many_unhandled.wast',
119+
'cont_export.wast',
119120
# TODO: fix split_wast() on tricky escaping situations like a string ending
120121
# in \\" (the " is not escaped - there is an escaped \ before it)
121122
'string-lifting-section.wast',

src/tools/execution-results.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,10 @@ struct LoggingExternalInterface : public ShellExternalInterface {
255255

256256
// Call the function.
257257
auto flow = instance->callFunction(func->name, arguments);
258-
assert(!flow.suspendTag);
258+
// Suspending through JS is not valid.
259+
if (flow.suspendTag) {
260+
throwJSException();
261+
}
259262
return flow.values;
260263
}
261264

test/lit/exec/cont_export.wast

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
;; NOTE: Assertions have been generated by update_lit_checks.py --output=fuzz-exec and should not be edited.
2+
3+
;; RUN: foreach %s %t wasm-opt -all --fuzz-exec-before -q -o /dev/null 2>&1 | filecheck %s
4+
5+
(module
6+
(type $none (func))
7+
(type $cont (cont $none))
8+
9+
(import "fuzzing-support" "log" (func $log (param i32)))
10+
11+
(import "fuzzing-support" "call-export" (func $call-export (param i32 i32)))
12+
13+
(tag $tag (type $none))
14+
15+
;; CHECK: [fuzz-exec] calling suspend
16+
;; CHECK-NEXT: [LoggingExternalInterface logging 10]
17+
;; CHECK-NEXT: [exception thrown: unhandled suspend]
18+
(func $suspend (export "suspend")
19+
;; Helper for below.
20+
(call $log (i32.const 10))
21+
(suspend $tag)
22+
(call $log (i32.const 20))
23+
)
24+
25+
;; CHECK: [fuzz-exec] calling call-call-export
26+
;; CHECK-NEXT: [LoggingExternalInterface logging 10]
27+
;; CHECK-NEXT: [exception thrown: __private externref]
28+
(func $call-call-export (export "call-call-export")
29+
;; Call suspend as an export. We cannot suspend through JS, so we throw.
30+
(call $call-export
31+
(i32.const 0)
32+
(i32.const 0)
33+
)
34+
)
35+
36+
;; CHECK: [fuzz-exec] calling handled
37+
;; CHECK-NEXT: [LoggingExternalInterface logging 10]
38+
;; CHECK-NEXT: [exception thrown: __private externref]
39+
(func $handled (export "handled")
40+
;; As above, but inside a continuation, so it would be handled - if we could
41+
;; suspend though JS. But we can't, so we throw.
42+
(drop
43+
(block $inner (result (ref $cont))
44+
(resume $cont (on $tag $inner)
45+
(cont.new $cont
46+
(ref.func $call-call-export)
47+
)
48+
)
49+
(unreachable)
50+
)
51+
)
52+
)
53+
)

0 commit comments

Comments
 (0)