summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2019-06-03 19:09:46 -0700
committerGitHub <noreply@github.com>2019-06-03 19:09:46 -0700
commit9d4f053070fa4a0d61663901d5206c025d694bb2 (patch)
treeb721ef95e0570192d84a8601a6b6dfe62ae90a20
parentfe99e3458f11d1a01fa3ad5b68883dbcba3903af (diff)
downloadbinaryen-9d4f053070fa4a0d61663901d5206c025d694bb2.tar.gz
binaryen-9d4f053070fa4a0d61663901d5206c025d694bb2.tar.bz2
binaryen-9d4f053070fa4a0d61663901d5206c025d694bb2.zip
Add a recursion limit for the interpreter's expression runner (#2160)
We previously had one for calls (the spec tests check for infinite recursion). This is an internal limit of the interpreter, until we un-recursify it, which may make sense at some point - but it's unlikely interpreting massively-recursive things will be beneficial in the optimizer anyhow, since if it could do something with them, it could also do so on the smaller pieces iteratively.
-rw-r--r--src/wasm-interpreter.h13
1 files changed, 11 insertions, 2 deletions
diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h
index 85a50163a..7dd9688c3 100644
--- a/src/wasm-interpreter.h
+++ b/src/wasm-interpreter.h
@@ -45,7 +45,7 @@ using namespace cashew;
extern Name WASM, RETURN_FLOW;
-enum { maxCallDepth = 250 };
+enum { maxInterpreterDepth = 250 };
// Stuff that flows around during executing expressions: a literal, or a change
// in control flow.
@@ -128,8 +128,16 @@ public:
// Execute an expression
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;
+
public:
Flow visit(Expression* curr) {
+ depth++;
+ if (depth > maxInterpreterDepth) {
+ trap("interpreter recursion limit");
+ }
auto ret = OverriddenVisitor<SubType, Flow>::visit(curr);
if (!ret.breaking() &&
(isConcreteType(curr->type) || isConcreteType(ret.value.type))) {
@@ -142,6 +150,7 @@ public:
#endif
assert(ret.value.type == curr->type);
}
+ depth--;
return ret;
}
@@ -1790,7 +1799,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 > maxCallDepth) {
+ if (callDepth > maxInterpreterDepth) {
externalInterface->trap("stack limit");
}
auto previousCallDepth = callDepth;