diff options
author | Heejin Ahn <aheejin@gmail.com> | 2021-12-06 17:12:07 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-12-06 17:12:07 -0800 |
commit | f0d835165aea108b213a2b9ea148453a917223d5 (patch) | |
tree | 8f695d97d3d8a46c4ff0cf308b8a90f4030fd218 /src | |
parent | f0668172831da496a6a781c82fa4b2dc0f4c9028 (diff) | |
download | binaryen-f0d835165aea108b213a2b9ea148453a917223d5.tar.gz binaryen-f0d835165aea108b213a2b9ea148453a917223d5.tar.bz2 binaryen-f0d835165aea108b213a2b9ea148453a917223d5.zip |
[EH] Make interpreter handle uncaught exceptions (#4369)
When a wasm exception is thrown and uncaught in the interpreter, it
caused the whole interpreter to crash, rather than gracefully reporting
it. This fixes the problem, and also compares whether an uncaught
exception happened when comparing the results before and after
optimizations in `--fuzz-exec`. To do that, when `--fuzz-exec` is given,
we now compare results even when the function does not have return
values. Logs for some existing test have changed because of this.
Diffstat (limited to 'src')
-rw-r--r-- | src/tools/execution-results.h | 52 |
1 files changed, 28 insertions, 24 deletions
diff --git a/src/tools/execution-results.h b/src/tools/execution-results.h index b689ffc66..18f4a399c 100644 --- a/src/tools/execution-results.h +++ b/src/tools/execution-results.h @@ -87,7 +87,11 @@ struct LoggingExternalInterface : public ShellExternalInterface { // we can only get results when there are no imports. we then call each method // that has a result, with some values struct ExecutionResults { - std::map<Name, Literals> results; + struct FunctionResult { + Literals values; + bool exception; // Whether an exception is uncaught and the function crashes + }; + std::map<Name, FunctionResult> results; Loggings loggings; // If set, we should ignore this and not compare it to anything. @@ -106,26 +110,20 @@ struct ExecutionResults { } std::cout << "[fuzz-exec] calling " << exp->name << "\n"; auto* func = wasm.getFunction(exp->value); - if (func->getResults() != Type::none) { - // this has a result - Literals ret = run(func, wasm, instance); - results[exp->name] = ret; - // ignore the result if we hit an unreachable and returned no value - if (ret.size() > 0) { - std::cout << "[fuzz-exec] note result: " << exp->name << " => "; - auto resultType = func->getResults(); - if (resultType.isRef()) { - // Don't print reference values, as funcref(N) contains an index - // for example, which is not guaranteed to remain identical after - // optimizations. - std::cout << resultType << '\n'; - } else { - std::cout << ret << '\n'; - } + FunctionResult ret = run(func, wasm, instance); + results[exp->name] = ret; + // ignore the result if we hit an unreachable and returned no value + if (ret.values.size() > 0) { + std::cout << "[fuzz-exec] note result: " << exp->name << " => "; + auto resultType = func->getResults(); + if (resultType.isRef()) { + // Don't print reference values, as funcref(N) contains an index + // for example, which is not guaranteed to remain identical after + // optimizations. + std::cout << resultType << '\n'; + } else { + std::cout << ret.values << '\n'; } - } else { - // no result, run it anyhow (it might modify memory etc.) - run(func, wasm, instance); } } } catch (const TrapException&) { @@ -191,7 +189,10 @@ struct ExecutionResults { return false; } std::cout << "[fuzz-exec] comparing " << name << '\n'; - if (!areEqual(results[name], other.results[name])) { + if (!areEqual(results[name].values, other.results[name].values)) { + return false; + } + if (results[name].exception != other.results[name].exception) { return false; } } @@ -209,7 +210,7 @@ struct ExecutionResults { bool operator!=(ExecutionResults& other) { return !((*this) == other); } - Literals run(Function* func, Module& wasm) { + FunctionResult run(Function* func, Module& wasm) { LoggingExternalInterface interface(loggings); try { ModuleInstance instance(wasm, &interface); @@ -220,7 +221,7 @@ struct ExecutionResults { } } - Literals run(Function* func, Module& wasm, ModuleInstance& instance) { + FunctionResult run(Function* func, Module& wasm, ModuleInstance& instance) { try { LiteralList arguments; // init hang support, if present @@ -236,9 +237,12 @@ struct ExecutionResults { } arguments.push_back(Literal::makeZero(param)); } - return instance.callFunction(func->name, arguments); + return {instance.callFunction(func->name, arguments), false}; } catch (const TrapException&) { return {}; + } catch (const WasmException& e) { + std::cout << "[exception thrown: " << e << "]" << std::endl; + return {{}, true}; } catch (const HostLimitException&) { // This should be ignored and not compared with, as optimizations can // change whether a host limit is reached. |