summaryrefslogtreecommitdiff
path: root/src/wasm-interpreter.h
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2019-07-01 19:22:08 -0700
committerGitHub <noreply@github.com>2019-07-01 19:22:08 -0700
commitc3e45d4e5272486fae1ffb353c56e4d117fe4a21 (patch)
treea05826cdb1b587d1df7ec67cbc8c075635e064ac /src/wasm-interpreter.h
parentbe3135ca8db88ed7445dc2dd12ea78f55d963c7d (diff)
downloadbinaryen-c3e45d4e5272486fae1ffb353c56e4d117fe4a21.tar.gz
binaryen-c3e45d4e5272486fae1ffb353c56e4d117fe4a21.tar.bz2
binaryen-c3e45d4e5272486fae1ffb353c56e4d117fe4a21.zip
Limit interpreter depth in precompute, but not when running whole modules (#2191)
Keep limiting in precompute as before: that is useful since that pass is run as part of normal compilation, and we want to avoid native stack limits on all platforms. Also that pass is not likely to find any pattern of size 50 of higher that it can't precompute as a sum of smaller pieces. Restore the 250 limit from before for interpreting entire modules, as without that the fuzzer will sometimes hit the limit and cause a false positive.
Diffstat (limited to 'src/wasm-interpreter.h')
-rw-r--r--src/wasm-interpreter.h40
1 files changed, 25 insertions, 15 deletions
diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h
index 03264f454..560051917 100644
--- a/src/wasm-interpreter.h
+++ b/src/wasm-interpreter.h
@@ -45,8 +45,6 @@ using namespace cashew;
extern Name WASM, RETURN_FLOW;
-enum { maxInterpreterDepth = 50 };
-
// Stuff that flows around during executing expressions: a literal, or a change
// in control flow.
class Flow {
@@ -129,13 +127,16 @@ public:
template<typename SubType>
class ExpressionRunner : public OverriddenVisitor<SubType, Flow> {
protected:
- // Keep a record of call depth, to guard against excessive recursion.
- size_t depth = 0;
+ Index maxDepth;
+
+ Index depth = 0;
public:
+ ExpressionRunner(Index maxDepth) : maxDepth(maxDepth) {}
+
Flow visit(Expression* curr) {
depth++;
- if (depth > maxInterpreterDepth) {
+ if (depth > maxDepth) {
trap("interpreter recursion limit");
}
auto ret = OverriddenVisitor<SubType, Flow>::visit(curr);
@@ -1056,7 +1057,9 @@ class ConstantExpressionRunner
GlobalManager& globals;
public:
- ConstantExpressionRunner(GlobalManager& globals) : globals(globals) {}
+ ConstantExpressionRunner(GlobalManager& globals, Index maxDepth)
+ : ExpressionRunner<ConstantExpressionRunner<GlobalManager>>(maxDepth),
+ globals(globals) {}
Flow visitGlobalGet(GlobalGet* curr) { return Flow(globals[curr->name]); }
};
@@ -1232,9 +1235,10 @@ public:
memorySize = wasm.memory.initial;
// generate internal (non-imported) globals
ModuleUtils::iterDefinedGlobals(wasm, [&](Global* global) {
- globals[global->name] = ConstantExpressionRunner<GlobalManager>(globals)
- .visit(global->init)
- .value;
+ globals[global->name] =
+ ConstantExpressionRunner<GlobalManager>(globals, maxDepth)
+ .visit(global->init)
+ .value;
});
// initialize the rest of the external interface
@@ -1297,7 +1301,7 @@ private:
void initializeTableContents() {
for (auto& segment : wasm.table.segments) {
Address offset =
- (uint32_t)ConstantExpressionRunner<GlobalManager>(globals)
+ (uint32_t)ConstantExpressionRunner<GlobalManager>(globals, maxDepth)
.visit(segment.offset)
.value.geti32();
if (offset + segment.data.size() > wasm.table.initial) {
@@ -1340,7 +1344,7 @@ private:
// the memory.init and data.drop instructions.
Function dummyFunc;
FunctionScope dummyScope(&dummyFunc, {});
- RuntimeExpressionRunner runner(*this, dummyScope);
+ RuntimeExpressionRunner runner(*this, dummyScope, maxDepth);
runner.visit(&init);
runner.visit(&drop);
}
@@ -1387,8 +1391,11 @@ private:
FunctionScope& scope;
public:
- RuntimeExpressionRunner(ModuleInstanceBase& instance, FunctionScope& scope)
- : instance(instance), scope(scope) {}
+ RuntimeExpressionRunner(ModuleInstanceBase& instance,
+ FunctionScope& scope,
+ Index maxDepth)
+ : ExpressionRunner<RuntimeExpressionRunner>(maxDepth), instance(instance),
+ scope(scope) {}
Flow generateArguments(const ExpressionList& operands,
LiteralList& arguments) {
@@ -1788,7 +1795,7 @@ public:
// Internal function call. Must be public so that callTable implementations
// can use it (refactor?)
Literal callFunctionInternal(Name name, const LiteralList& arguments) {
- if (callDepth > maxInterpreterDepth) {
+ if (callDepth > maxDepth) {
externalInterface->trap("stack limit");
}
auto previousCallDepth = callDepth;
@@ -1807,7 +1814,8 @@ public:
}
#endif
- Flow flow = RuntimeExpressionRunner(*this, scope).visit(function->body);
+ Flow flow =
+ RuntimeExpressionRunner(*this, scope, maxDepth).visit(function->body);
// cannot still be breaking, it means we missed our stop
assert(!flow.breaking() || flow.breakTo == RETURN_FLOW);
Literal ret = flow.value;
@@ -1831,6 +1839,8 @@ public:
protected:
Address memorySize; // in pages
+ static const Index maxDepth = 250;
+
void trapIfGt(uint64_t lhs, uint64_t rhs, const char* msg) {
if (lhs > rhs) {
std::stringstream ss;