summaryrefslogtreecommitdiff
path: root/src
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 /src
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.
Diffstat (limited to 'src')
-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;