diff options
author | Alon Zakai <azakai@google.com> | 2019-06-03 19:09:46 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-06-03 19:09:46 -0700 |
commit | 9d4f053070fa4a0d61663901d5206c025d694bb2 (patch) | |
tree | b721ef95e0570192d84a8601a6b6dfe62ae90a20 | |
parent | fe99e3458f11d1a01fa3ad5b68883dbcba3903af (diff) | |
download | binaryen-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.h | 13 |
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; |