Skip to content

Commit 600ccd0

Browse files
authored
[Stack Switching] Simplify clearing of continuation store in the fuzzer (#7871)
Use RAII to ensure we don't miss any code paths when clearing the continuation state after an export call. Also remove an entirely unused function, that was confusing during debugging.
1 parent b9d5c23 commit 600ccd0

File tree

2 files changed

+58
-25
lines changed

2 files changed

+58
-25
lines changed

src/tools/execution-results.h

Lines changed: 7 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -443,27 +443,14 @@ struct ExecutionResults {
443443

444444
bool operator!=(ExecutionResults& other) { return !((*this) == other); }
445445

446-
FunctionResult run(Function* func, Module& wasm) {
447-
LoggingExternalInterface interface(loggings, wasm);
448-
try {
449-
ModuleRunner instance(wasm, &interface);
450-
instance.setRelaxedBehavior(ModuleRunner::RelaxedBehavior::Execute);
451-
instance.instantiate();
452-
interface.setModuleRunner(&instance);
453-
return run(func, wasm, instance);
454-
} catch (const TrapException&) {
455-
// May throw in instance creation (init of offsets).
456-
return {};
457-
} catch (const HostLimitException&) {
458-
// May throw in instance creation (e.g. array.new of huge size).
459-
// This should be ignored and not compared with, as optimizations can
460-
// change whether a host limit is reached.
461-
ignore = true;
462-
return {};
463-
}
464-
}
465-
466446
FunctionResult run(Function* func, Module& wasm, ModuleRunner& instance) {
447+
// Clear the continuation state after each run of an export.
448+
struct CleanUp {
449+
ModuleRunner& instance;
450+
CleanUp(ModuleRunner& instance) : instance(instance) {}
451+
~CleanUp() { instance.clearContinuationStore(); }
452+
} cleanUp(instance);
453+
467454
try {
468455
// call the method
469456
Literals arguments;
@@ -472,30 +459,25 @@ struct ExecutionResults {
472459
if (!param.isDefaultable()) {
473460
std::cout << "[trap fuzzer can only send defaultable parameters to "
474461
"exports]\n";
475-
instance.clearContinuationStore();
476462
return Trap{};
477463
}
478464
arguments.push_back(Literal::makeZero(param));
479465
}
480466
auto flow = instance.callFunction(func->name, arguments);
481467
if (flow.suspendTag) {
482468
std::cout << "[exception thrown: unhandled suspend]" << std::endl;
483-
instance.clearContinuationStore();
484469
return Exception{};
485470
}
486471
return flow.values;
487472
} catch (const TrapException&) {
488-
instance.clearContinuationStore();
489473
return Trap{};
490474
} catch (const WasmException& e) {
491-
instance.clearContinuationStore();
492475
std::cout << "[exception thrown: " << e << "]" << std::endl;
493476
return Exception{};
494477
} catch (const HostLimitException&) {
495478
// This should be ignored and not compared with, as optimizations can
496479
// change whether a host limit is reached.
497480
ignore = true;
498-
instance.clearContinuationStore();
499481
return {};
500482
}
501483
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
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+
;; Three exports, one which suspends, another that does a resume-throw but
6+
;; catches it, and another that does a suspend through a call to JS, then a
7+
;; normal suspend. This is a regression test for a bug where the global state of
8+
;; continuations got into a confused state in the middle, and asserted.
9+
10+
(module
11+
(type $func (func))
12+
(type $cont (cont $func))
13+
14+
(import "fuzzing-support" "call-export-catch" (func $call-export-catch (param i32) (result i32)))
15+
16+
(tag $tag (type $func))
17+
18+
;; CHECK: [fuzz-exec] calling suspend
19+
;; CHECK-NEXT: [exception thrown: unhandled suspend]
20+
(func $suspend (export "suspend")
21+
(suspend $tag)
22+
)
23+
24+
;; CHECK: [fuzz-exec] calling try-resume
25+
(func $try-resume (export "try-resume")
26+
(block $block
27+
(try_table (catch_all $block)
28+
(resume_throw $cont $tag
29+
(cont.new $cont
30+
(ref.func $nop)
31+
)
32+
)
33+
)
34+
)
35+
)
36+
37+
;; CHECK: [fuzz-exec] calling call-suspend
38+
;; CHECK-NEXT: [exception thrown: unhandled suspend]
39+
(func $call-suspend (export "call-suspend")
40+
(drop
41+
(call $call-export-catch
42+
(i32.const 0)
43+
)
44+
)
45+
(suspend $tag)
46+
)
47+
48+
(func $nop
49+
)
50+
)
51+

0 commit comments

Comments
 (0)