summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/passes/Bysyncify.cpp73
-rw-r--r--test/passes/bysyncify.txt138
-rw-r--r--test/passes/bysyncify_optimize-level=1.txt46
-rw-r--r--test/passes/bysyncify_pass-arg=bysyncify-ignore-imports.txt46
-rw-r--r--test/passes/bysyncify_pass-arg=bysyncify-ignore-indirect.txt46
-rw-r--r--test/passes/bysyncify_pass-arg=bysyncify-imports@env.import,env.import2.txt92
-rw-r--r--test/unit/input/bysyncify-stackOverflow.wast22
-rw-r--r--test/unit/input/bysyncify.js43
-rw-r--r--test/unit/test_bysyncify.py1
9 files changed, 375 insertions, 132 deletions
diff --git a/src/passes/Bysyncify.cpp b/src/passes/Bysyncify.cpp
index cb85f0b0a..0897375fe 100644
--- a/src/passes/Bysyncify.cpp
+++ b/src/passes/Bysyncify.cpp
@@ -174,6 +174,17 @@
// we are recreating the call stack. At that point you should call
// bysyncify_stop_rewind and then execution can resume normally.
//
+// Note that the bysyncify_* API calls will verify that the data structure
+// is valid, checking if the current location is past the end. If so, they
+// will throw a wasm unreachable. No check is done during unwinding or
+// rewinding, to keep things fast - in principle, from when unwinding begins
+// and until it ends there should be no memory accesses aside from the
+// bysyncify code itself (and likewise when rewinding), so there should be
+// no chance of memory corruption causing odd errors. However, the low
+// overhead of this approach does cause an error only to be shown when
+// unwinding/rewinding finishes, and not at the specific spot where the
+// stack end was exceeded.
+//
// By default this pass is very carefuly: it assumes that any import and
// any indirect call may start an unwind/rewind operation. If you know more
// specific information you can inform bysyncify about that, which can reduce
@@ -1056,38 +1067,36 @@ private:
void addFunctions(Module* module) {
Builder builder(*module);
- auto makeFunction = [&](Name name,
- bool setData,
- State state,
- Expression* extra) {
+ auto makeFunction = [&](Name name, bool setData, State state) {
std::vector<Type> params;
if (setData) {
params.push_back(i32);
}
auto* body = builder.makeBlock();
- if (setData) {
- // Verify the data is valid.
- auto* stackPos = builder.makeLoad(4,
- false,
- int32_t(DataOffset::BStackPos),
- 4,
- builder.makeLocalGet(0, i32),
- i32);
- auto* stackEnd = builder.makeLoad(4,
- false,
- int32_t(DataOffset::BStackEnd),
- 4,
- builder.makeLocalGet(0, i32),
- i32);
- body->list.push_back(
- builder.makeIf(builder.makeBinary(GtUInt32, stackPos, stackEnd),
- builder.makeUnreachable()));
- }
body->list.push_back(builder.makeGlobalSet(
BYSYNCIFY_STATE, builder.makeConst(Literal(int32_t(state)))));
- if (extra) {
- body->list.push_back(extra);
+ if (setData) {
+ body->list.push_back(
+ builder.makeGlobalSet(BYSYNCIFY_DATA, builder.makeLocalGet(0, i32)));
}
+ // Verify the data is valid.
+ auto* stackPos =
+ builder.makeLoad(4,
+ false,
+ int32_t(DataOffset::BStackPos),
+ 4,
+ builder.makeGlobalGet(BYSYNCIFY_DATA, i32),
+ i32);
+ auto* stackEnd =
+ builder.makeLoad(4,
+ false,
+ int32_t(DataOffset::BStackEnd),
+ 4,
+ builder.makeGlobalGet(BYSYNCIFY_DATA, i32),
+ i32);
+ body->list.push_back(
+ builder.makeIf(builder.makeBinary(GtUInt32, stackPos, stackEnd),
+ builder.makeUnreachable()));
body->finalize();
auto* func = builder.makeFunction(
name, std::move(params), none, std::vector<Type>{}, body);
@@ -1095,18 +1104,10 @@ private:
module->addExport(builder.makeExport(name, name, ExternalKind::Function));
};
- makeFunction(
- BYSYNCIFY_START_UNWIND,
- true,
- State::Unwinding,
- builder.makeGlobalSet(BYSYNCIFY_DATA, builder.makeLocalGet(0, i32)));
- makeFunction(BYSYNCIFY_STOP_UNWIND, false, State::Normal, nullptr);
- makeFunction(
- BYSYNCIFY_START_REWIND,
- true,
- State::Rewinding,
- builder.makeGlobalSet(BYSYNCIFY_DATA, builder.makeLocalGet(0, i32)));
- makeFunction(BYSYNCIFY_STOP_REWIND, false, State::Normal, nullptr);
+ makeFunction(BYSYNCIFY_START_UNWIND, true, State::Unwinding);
+ makeFunction(BYSYNCIFY_STOP_UNWIND, false, State::Normal);
+ makeFunction(BYSYNCIFY_START_REWIND, true, State::Rewinding);
+ makeFunction(BYSYNCIFY_STOP_REWIND, false, State::Normal);
}
};
diff --git a/test/passes/bysyncify.txt b/test/passes/bysyncify.txt
index fbbc09d45..a9a780972 100644
--- a/test/passes/bysyncify.txt
+++ b/test/passes/bysyncify.txt
@@ -297,52 +297,74 @@
(nop)
)
(func $bysyncify_start_unwind (; 6 ;) (param $0 i32)
+ (global.set $__bysyncify_state
+ (i32.const 1)
+ )
+ (global.set $__bysyncify_data
+ (local.get $0)
+ )
(if
(i32.gt_u
(i32.load
- (local.get $0)
+ (global.get $__bysyncify_data)
)
(i32.load offset=4
- (local.get $0)
+ (global.get $__bysyncify_data)
)
)
(unreachable)
)
- (global.set $__bysyncify_state
- (i32.const 1)
- )
- (global.set $__bysyncify_data
- (local.get $0)
- )
)
(func $bysyncify_stop_unwind (; 7 ;)
(global.set $__bysyncify_state
(i32.const 0)
)
- )
- (func $bysyncify_start_rewind (; 8 ;) (param $0 i32)
(if
(i32.gt_u
(i32.load
- (local.get $0)
+ (global.get $__bysyncify_data)
)
(i32.load offset=4
- (local.get $0)
+ (global.get $__bysyncify_data)
)
)
(unreachable)
)
+ )
+ (func $bysyncify_start_rewind (; 8 ;) (param $0 i32)
(global.set $__bysyncify_state
(i32.const 2)
)
(global.set $__bysyncify_data
(local.get $0)
)
+ (if
+ (i32.gt_u
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.load offset=4
+ (global.get $__bysyncify_data)
+ )
+ )
+ (unreachable)
+ )
)
(func $bysyncify_stop_rewind (; 9 ;)
(global.set $__bysyncify_state
(i32.const 0)
)
+ (if
+ (i32.gt_u
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.load offset=4
+ (global.get $__bysyncify_data)
+ )
+ )
+ (unreachable)
+ )
)
)
(module
@@ -2808,52 +2830,74 @@
(nop)
)
(func $bysyncify_start_unwind (; 19 ;) (param $0 i32)
+ (global.set $__bysyncify_state
+ (i32.const 1)
+ )
+ (global.set $__bysyncify_data
+ (local.get $0)
+ )
(if
(i32.gt_u
(i32.load
- (local.get $0)
+ (global.get $__bysyncify_data)
)
(i32.load offset=4
- (local.get $0)
+ (global.get $__bysyncify_data)
)
)
(unreachable)
)
- (global.set $__bysyncify_state
- (i32.const 1)
- )
- (global.set $__bysyncify_data
- (local.get $0)
- )
)
(func $bysyncify_stop_unwind (; 20 ;)
(global.set $__bysyncify_state
(i32.const 0)
)
- )
- (func $bysyncify_start_rewind (; 21 ;) (param $0 i32)
(if
(i32.gt_u
(i32.load
- (local.get $0)
+ (global.get $__bysyncify_data)
)
(i32.load offset=4
- (local.get $0)
+ (global.get $__bysyncify_data)
)
)
(unreachable)
)
+ )
+ (func $bysyncify_start_rewind (; 21 ;) (param $0 i32)
(global.set $__bysyncify_state
(i32.const 2)
)
(global.set $__bysyncify_data
(local.get $0)
)
+ (if
+ (i32.gt_u
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.load offset=4
+ (global.get $__bysyncify_data)
+ )
+ )
+ (unreachable)
+ )
)
(func $bysyncify_stop_rewind (; 22 ;)
(global.set $__bysyncify_state
(i32.const 0)
)
+ (if
+ (i32.gt_u
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.load offset=4
+ (global.get $__bysyncify_data)
+ )
+ )
+ (unreachable)
+ )
)
)
(module
@@ -2865,51 +2909,73 @@
(export "bysyncify_start_rewind" (func $bysyncify_start_rewind))
(export "bysyncify_stop_rewind" (func $bysyncify_stop_rewind))
(func $bysyncify_start_unwind (; 0 ;) (param $0 i32)
+ (global.set $__bysyncify_state
+ (i32.const 1)
+ )
+ (global.set $__bysyncify_data
+ (local.get $0)
+ )
(if
(i32.gt_u
(i32.load
- (local.get $0)
+ (global.get $__bysyncify_data)
)
(i32.load offset=4
- (local.get $0)
+ (global.get $__bysyncify_data)
)
)
(unreachable)
)
- (global.set $__bysyncify_state
- (i32.const 1)
- )
- (global.set $__bysyncify_data
- (local.get $0)
- )
)
(func $bysyncify_stop_unwind (; 1 ;)
(global.set $__bysyncify_state
(i32.const 0)
)
- )
- (func $bysyncify_start_rewind (; 2 ;) (param $0 i32)
(if
(i32.gt_u
(i32.load
- (local.get $0)
+ (global.get $__bysyncify_data)
)
(i32.load offset=4
- (local.get $0)
+ (global.get $__bysyncify_data)
)
)
(unreachable)
)
+ )
+ (func $bysyncify_start_rewind (; 2 ;) (param $0 i32)
(global.set $__bysyncify_state
(i32.const 2)
)
(global.set $__bysyncify_data
(local.get $0)
)
+ (if
+ (i32.gt_u
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.load offset=4
+ (global.get $__bysyncify_data)
+ )
+ )
+ (unreachable)
+ )
)
(func $bysyncify_stop_rewind (; 3 ;)
(global.set $__bysyncify_state
(i32.const 0)
)
+ (if
+ (i32.gt_u
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.load offset=4
+ (global.get $__bysyncify_data)
+ )
+ )
+ (unreachable)
+ )
)
)
diff --git a/test/passes/bysyncify_optimize-level=1.txt b/test/passes/bysyncify_optimize-level=1.txt
index b09368ec4..7b1093964 100644
--- a/test/passes/bysyncify_optimize-level=1.txt
+++ b/test/passes/bysyncify_optimize-level=1.txt
@@ -1564,51 +1564,73 @@
)
)
(func $bysyncify_start_unwind (; 19 ;) (param $0 i32)
+ (global.set $__bysyncify_state
+ (i32.const 1)
+ )
+ (global.set $__bysyncify_data
+ (local.get $0)
+ )
(if
(i32.gt_u
(i32.load
- (local.get $0)
+ (global.get $__bysyncify_data)
)
(i32.load offset=4
- (local.get $0)
+ (global.get $__bysyncify_data)
)
)
(unreachable)
)
- (global.set $__bysyncify_state
- (i32.const 1)
- )
- (global.set $__bysyncify_data
- (local.get $0)
- )
)
(func $bysyncify_stop_unwind (; 20 ;)
(global.set $__bysyncify_state
(i32.const 0)
)
- )
- (func $bysyncify_start_rewind (; 21 ;) (param $0 i32)
(if
(i32.gt_u
(i32.load
- (local.get $0)
+ (global.get $__bysyncify_data)
)
(i32.load offset=4
- (local.get $0)
+ (global.get $__bysyncify_data)
)
)
(unreachable)
)
+ )
+ (func $bysyncify_start_rewind (; 21 ;) (param $0 i32)
(global.set $__bysyncify_state
(i32.const 2)
)
(global.set $__bysyncify_data
(local.get $0)
)
+ (if
+ (i32.gt_u
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.load offset=4
+ (global.get $__bysyncify_data)
+ )
+ )
+ (unreachable)
+ )
)
(func $bysyncify_stop_rewind (; 22 ;)
(global.set $__bysyncify_state
(i32.const 0)
)
+ (if
+ (i32.gt_u
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.load offset=4
+ (global.get $__bysyncify_data)
+ )
+ )
+ (unreachable)
+ )
)
)
diff --git a/test/passes/bysyncify_pass-arg=bysyncify-ignore-imports.txt b/test/passes/bysyncify_pass-arg=bysyncify-ignore-imports.txt
index 515fa365a..96133d648 100644
--- a/test/passes/bysyncify_pass-arg=bysyncify-ignore-imports.txt
+++ b/test/passes/bysyncify_pass-arg=bysyncify-ignore-imports.txt
@@ -211,51 +211,73 @@
)
)
(func $bysyncify_start_unwind (; 7 ;) (param $0 i32)
+ (global.set $__bysyncify_state
+ (i32.const 1)
+ )
+ (global.set $__bysyncify_data
+ (local.get $0)
+ )
(if
(i32.gt_u
(i32.load
- (local.get $0)
+ (global.get $__bysyncify_data)
)
(i32.load offset=4
- (local.get $0)
+ (global.get $__bysyncify_data)
)
)
(unreachable)
)
- (global.set $__bysyncify_state
- (i32.const 1)
- )
- (global.set $__bysyncify_data
- (local.get $0)
- )
)
(func $bysyncify_stop_unwind (; 8 ;)
(global.set $__bysyncify_state
(i32.const 0)
)
- )
- (func $bysyncify_start_rewind (; 9 ;) (param $0 i32)
(if
(i32.gt_u
(i32.load
- (local.get $0)
+ (global.get $__bysyncify_data)
)
(i32.load offset=4
- (local.get $0)
+ (global.get $__bysyncify_data)
)
)
(unreachable)
)
+ )
+ (func $bysyncify_start_rewind (; 9 ;) (param $0 i32)
(global.set $__bysyncify_state
(i32.const 2)
)
(global.set $__bysyncify_data
(local.get $0)
)
+ (if
+ (i32.gt_u
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.load offset=4
+ (global.get $__bysyncify_data)
+ )
+ )
+ (unreachable)
+ )
)
(func $bysyncify_stop_rewind (; 10 ;)
(global.set $__bysyncify_state
(i32.const 0)
)
+ (if
+ (i32.gt_u
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.load offset=4
+ (global.get $__bysyncify_data)
+ )
+ )
+ (unreachable)
+ )
)
)
diff --git a/test/passes/bysyncify_pass-arg=bysyncify-ignore-indirect.txt b/test/passes/bysyncify_pass-arg=bysyncify-ignore-indirect.txt
index 64e516cf8..846e05035 100644
--- a/test/passes/bysyncify_pass-arg=bysyncify-ignore-indirect.txt
+++ b/test/passes/bysyncify_pass-arg=bysyncify-ignore-indirect.txt
@@ -517,51 +517,73 @@
(nop)
)
(func $bysyncify_start_unwind (; 7 ;) (param $0 i32)
+ (global.set $__bysyncify_state
+ (i32.const 1)
+ )
+ (global.set $__bysyncify_data
+ (local.get $0)
+ )
(if
(i32.gt_u
(i32.load
- (local.get $0)
+ (global.get $__bysyncify_data)
)
(i32.load offset=4
- (local.get $0)
+ (global.get $__bysyncify_data)
)
)
(unreachable)
)
- (global.set $__bysyncify_state
- (i32.const 1)
- )
- (global.set $__bysyncify_data
- (local.get $0)
- )
)
(func $bysyncify_stop_unwind (; 8 ;)
(global.set $__bysyncify_state
(i32.const 0)
)
- )
- (func $bysyncify_start_rewind (; 9 ;) (param $0 i32)
(if
(i32.gt_u
(i32.load
- (local.get $0)
+ (global.get $__bysyncify_data)
)
(i32.load offset=4
- (local.get $0)
+ (global.get $__bysyncify_data)
)
)
(unreachable)
)
+ )
+ (func $bysyncify_start_rewind (; 9 ;) (param $0 i32)
(global.set $__bysyncify_state
(i32.const 2)
)
(global.set $__bysyncify_data
(local.get $0)
)
+ (if
+ (i32.gt_u
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.load offset=4
+ (global.get $__bysyncify_data)
+ )
+ )
+ (unreachable)
+ )
)
(func $bysyncify_stop_rewind (; 10 ;)
(global.set $__bysyncify_state
(i32.const 0)
)
+ (if
+ (i32.gt_u
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.load offset=4
+ (global.get $__bysyncify_data)
+ )
+ )
+ (unreachable)
+ )
)
)
diff --git a/test/passes/bysyncify_pass-arg=bysyncify-imports@env.import,env.import2.txt b/test/passes/bysyncify_pass-arg=bysyncify-imports@env.import,env.import2.txt
index b22e7d82a..02d353a7a 100644
--- a/test/passes/bysyncify_pass-arg=bysyncify-imports@env.import,env.import2.txt
+++ b/test/passes/bysyncify_pass-arg=bysyncify-imports@env.import,env.import2.txt
@@ -295,52 +295,74 @@
(nop)
)
(func $bysyncify_start_unwind (; 6 ;) (param $0 i32)
+ (global.set $__bysyncify_state
+ (i32.const 1)
+ )
+ (global.set $__bysyncify_data
+ (local.get $0)
+ )
(if
(i32.gt_u
(i32.load
- (local.get $0)
+ (global.get $__bysyncify_data)
)
(i32.load offset=4
- (local.get $0)
+ (global.get $__bysyncify_data)
)
)
(unreachable)
)
- (global.set $__bysyncify_state
- (i32.const 1)
- )
- (global.set $__bysyncify_data
- (local.get $0)
- )
)
(func $bysyncify_stop_unwind (; 7 ;)
(global.set $__bysyncify_state
(i32.const 0)
)
- )
- (func $bysyncify_start_rewind (; 8 ;) (param $0 i32)
(if
(i32.gt_u
(i32.load
- (local.get $0)
+ (global.get $__bysyncify_data)
)
(i32.load offset=4
- (local.get $0)
+ (global.get $__bysyncify_data)
)
)
(unreachable)
)
+ )
+ (func $bysyncify_start_rewind (; 8 ;) (param $0 i32)
(global.set $__bysyncify_state
(i32.const 2)
)
(global.set $__bysyncify_data
(local.get $0)
)
+ (if
+ (i32.gt_u
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.load offset=4
+ (global.get $__bysyncify_data)
+ )
+ )
+ (unreachable)
+ )
)
(func $bysyncify_stop_rewind (; 9 ;)
(global.set $__bysyncify_state
(i32.const 0)
)
+ (if
+ (i32.gt_u
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.load offset=4
+ (global.get $__bysyncify_data)
+ )
+ )
+ (unreachable)
+ )
)
)
(module
@@ -1961,51 +1983,73 @@
(nop)
)
(func $bysyncify_start_unwind (; 19 ;) (param $0 i32)
+ (global.set $__bysyncify_state
+ (i32.const 1)
+ )
+ (global.set $__bysyncify_data
+ (local.get $0)
+ )
(if
(i32.gt_u
(i32.load
- (local.get $0)
+ (global.get $__bysyncify_data)
)
(i32.load offset=4
- (local.get $0)
+ (global.get $__bysyncify_data)
)
)
(unreachable)
)
- (global.set $__bysyncify_state
- (i32.const 1)
- )
- (global.set $__bysyncify_data
- (local.get $0)
- )
)
(func $bysyncify_stop_unwind (; 20 ;)
(global.set $__bysyncify_state
(i32.const 0)
)
- )
- (func $bysyncify_start_rewind (; 21 ;) (param $0 i32)
(if
(i32.gt_u
(i32.load
- (local.get $0)
+ (global.get $__bysyncify_data)
)
(i32.load offset=4
- (local.get $0)
+ (global.get $__bysyncify_data)
)
)
(unreachable)
)
+ )
+ (func $bysyncify_start_rewind (; 21 ;) (param $0 i32)
(global.set $__bysyncify_state
(i32.const 2)
)
(global.set $__bysyncify_data
(local.get $0)
)
+ (if
+ (i32.gt_u
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.load offset=4
+ (global.get $__bysyncify_data)
+ )
+ )
+ (unreachable)
+ )
)
(func $bysyncify_stop_rewind (; 22 ;)
(global.set $__bysyncify_state
(i32.const 0)
)
+ (if
+ (i32.gt_u
+ (i32.load
+ (global.get $__bysyncify_data)
+ )
+ (i32.load offset=4
+ (global.get $__bysyncify_data)
+ )
+ )
+ (unreachable)
+ )
)
)
diff --git a/test/unit/input/bysyncify-stackOverflow.wast b/test/unit/input/bysyncify-stackOverflow.wast
new file mode 100644
index 000000000..a36a06b40
--- /dev/null
+++ b/test/unit/input/bysyncify-stackOverflow.wast
@@ -0,0 +1,22 @@
+(module
+ (memory 1 2)
+ (import "env" "sleep" (func $sleep))
+ (export "memory" (memory 0))
+ (func "many_locals" (param $x i32) (result i32)
+ (local $y i32)
+ (local $z i32)
+ (local.set $y
+ (i32.add (local.get $x) (i32.const 10))
+ )
+ (local.set $z
+ (i32.add (local.get $y) (i32.const 20))
+ )
+ (call $sleep)
+ (select
+ (local.get $y)
+ (local.get $z)
+ (local.get $x)
+ )
+ )
+)
+
diff --git a/test/unit/input/bysyncify.js b/test/unit/input/bysyncify.js
index 2e1bb4895..be6d32903 100644
--- a/test/unit/input/bysyncify.js
+++ b/test/unit/input/bysyncify.js
@@ -252,10 +252,53 @@ function coroutineTests() {
]), 'check yielded values')
}
+function stackOverflowAssertTests() {
+ console.log('\nstack overflow assertion tests\n\n');
+
+ // Get and compile the wasm.
+
+ var binary = fs.readFileSync('c.wasm');
+
+ var module = new WebAssembly.Module(binary);
+
+ var DATA_ADDR = 4;
+
+ var instance = new WebAssembly.Instance(module, {
+ env: {
+ sleep: function() {
+ console.log('sleep...');
+ exports.bysyncify_start_unwind(DATA_ADDR);
+ view[DATA_ADDR >> 2] = DATA_ADDR + 8;
+ // The end of the stack will be reached as the stack is tiny.
+ view[DATA_ADDR + 4 >> 2] = view[DATA_ADDR >> 2] + 1;
+ }
+ }
+ });
+
+ var exports = instance.exports;
+ var view = new Int32Array(exports.memory.buffer);
+ exports.many_locals();
+ assert(view[DATA_ADDR >> 2] > view[DATA_ADDR + 4 >> 2], 'should have wrote past the end of the stack');
+ // All API calls should now fail, since we wrote past the end of the
+ // stack
+ var fails = 0;
+ ['bysyncify_stop_unwind', 'bysyncify_start_rewind', 'bysyncify_stop_rewind', 'bysyncify_start_unwind'].forEach(function(name) {
+ try {
+ exports[name](DATA_ADDR);
+ console.log('no fail on', name);
+ } catch (e) {
+ console.log('expected fail on', name);
+ fails++;
+ }
+ });
+ assert(fails == 4, 'all 4 should have failed');
+}
+
// Main
sleepTests();
coroutineTests();
+stackOverflowAssertTests();
console.log('\ntests completed successfully');
diff --git a/test/unit/test_bysyncify.py b/test/unit/test_bysyncify.py
index 8d5a780e8..407f3f7f9 100644
--- a/test/unit/test_bysyncify.py
+++ b/test/unit/test_bysyncify.py
@@ -10,6 +10,7 @@ class BysyncifyTest(BinaryenTestCase):
print(args)
run_process(WASM_OPT + args + [self.input_path('bysyncify-sleep.wast'), '--bysyncify', '-o', 'a.wasm'])
run_process(WASM_OPT + args + [self.input_path('bysyncify-coroutine.wast'), '--bysyncify', '-o', 'b.wasm'])
+ run_process(WASM_OPT + args + [self.input_path('bysyncify-stackOverflow.wast'), '--bysyncify', '-o', 'c.wasm'])
print(' file size: %d' % os.path.getsize('a.wasm'))
run_process([NODEJS, self.input_path('bysyncify.js')])