Reflect.parse() stack overflow (bug 632024, r=jorendorff)
authorDave Herman <dherman@mozilla.com>
Thu, 16 Jun 2011 23:27:26 -0700
changeset 71893 0cc25c98d38e335ea70ff0d6e5eb2b027ff00dc5
parent 71892 01f0e75fce222c172148fdda8a442a81056d61d1
child 71894 68ab9132fad7d7c157f6a48f2d3263c619d15de0
push idunknown
push userunknown
push dateunknown
reviewersjorendorff
bugs632024
milestone7.0a1
Reflect.parse() stack overflow (bug 632024, r=jorendorff)
js/src/jsreflect.cpp
js/src/tests/js1_8_5/extensions/reflect-parse.js
--- a/js/src/jsreflect.cpp
+++ b/js/src/jsreflect.cpp
@@ -1619,17 +1619,16 @@ class ASTSerializer
     BinaryOperator binop(TokenKind tk, JSOp op);
     UnaryOperator unop(TokenKind tk, JSOp op);
     AssignmentOperator aop(JSOp op);
 
     bool statements(JSParseNode *pn, NodeVector &elts);
     bool expressions(JSParseNode *pn, NodeVector &elts);
     bool xmls(JSParseNode *pn, NodeVector &elts);
     bool leftAssociate(JSParseNode *pn, Value *dst);
-    bool binaryOperands(JSParseNode *pn, NodeVector &elts);
     bool functionArgs(JSParseNode *pn, JSParseNode *pnargs, JSParseNode *pndestruct,
                       JSParseNode *pnbody, NodeVector &args);
 
     bool sourceElement(JSParseNode *pn, Value *dst);
 
     bool declaration(JSParseNode *pn, Value *dst);
     bool variableDeclaration(JSParseNode *pn, bool let, Value *dst);
     bool variableDeclarator(JSParseNode *pn, VarDeclKind *pkind, Value *dst);
@@ -2103,16 +2102,17 @@ ASTSerializer::forInit(JSParseNode *pn, 
            : (PN_TYPE(pn) == TOK_LET)
            ? variableDeclaration(pn, true, dst)
            : expression(pn, dst);
 }
 
 bool
 ASTSerializer::statement(JSParseNode *pn, Value *dst)
 {
+    JS_CHECK_RECURSION(cx, return false);
     switch (PN_TYPE(pn)) {
       case TOK_FUNCTION:
       case TOK_VAR:
       case TOK_LET:
         return declaration(pn, dst);
 
       case TOK_NAME:
         LOCAL_ASSERT(pn->pn_used);
@@ -2348,33 +2348,16 @@ ASTSerializer::leftAssociate(JSParseNode
         }
     }
 
     *dst = left;
     return true;
 }
 
 bool
-ASTSerializer::binaryOperands(JSParseNode *pn, NodeVector &elts)
-{
-    if (pn->pn_arity == PN_BINARY) {
-        Value left, right;
-
-        return expression(pn->pn_left, &left) &&
-               elts.append(left) &&
-               expression(pn->pn_right, &right) &&
-               elts.append(right);
-    }
-
-    LOCAL_ASSERT(pn->pn_arity == PN_LIST);
-
-    return expressions(pn, elts);
-}
-
-bool
 ASTSerializer::comprehensionBlock(JSParseNode *pn, Value *dst)
 {
     LOCAL_ASSERT(pn->pn_arity == PN_BINARY);
 
     JSParseNode *in = pn->pn_left;
 
     LOCAL_ASSERT(in && PN_TYPE(in) == TOK_IN);
 
@@ -2452,16 +2435,17 @@ ASTSerializer::generatorExpression(JSPar
 
     return expression(next->pn_kid->pn_kid, &body) &&
            builder.generatorExpression(body, blocks, filter, &pn->pn_pos, dst);
 }
 
 bool
 ASTSerializer::expression(JSParseNode *pn, Value *dst)
 {
+    JS_CHECK_RECURSION(cx, return false);
     switch (PN_TYPE(pn)) {
       case TOK_FUNCTION:
         return function(pn, AST_FUNC_EXPR, dst);
 
       case TOK_COMMA:
       {
         NodeVector exprs(cx);
         return expressions(pn, exprs) &&
@@ -2748,16 +2732,17 @@ ASTSerializer::expression(JSParseNode *p
         LOCAL_NOT_REACHED("unexpected expression type");
 #endif
     }
 }
 
 bool
 ASTSerializer::xml(JSParseNode *pn, Value *dst)
 {
+    JS_CHECK_RECURSION(cx, return false);
     switch (PN_TYPE(pn)) {
 #ifdef JS_HAS_XML_SUPPORT
       case TOK_LC:
       {
         Value expr;
         return expression(pn->pn_kid, &expr) &&
                builder.xmlEscapeExpression(expr, &pn->pn_pos, dst);
       }
@@ -2970,16 +2955,17 @@ ASTSerializer::objectPattern(JSParseNode
     }
 
     return builder.objectPattern(elts, &pn->pn_pos, dst);
 }
 
 bool
 ASTSerializer::pattern(JSParseNode *pn, VarDeclKind *pkind, Value *dst)
 {
+    JS_CHECK_RECURSION(cx, return false);
     switch (PN_TYPE(pn)) {
       case TOK_RC:
         return objectPattern(pn, pkind, dst);
 
       case TOK_RB:
         return arrayPattern(pn, pkind, dst);
 
       case TOK_NAME:
--- a/js/src/tests/js1_8_5/extensions/reflect-parse.js
+++ b/js/src/tests/js1_8_5/extensions/reflect-parse.js
@@ -780,16 +780,22 @@ assertStmt("let (x,y,z) { }", letStmt([{
                                        { id: ident("z"), init: null }],
                                       blockStmt([])));
 assertStmt("let (x = 1, y = x) { }", letStmt([{ id: ident("x"), init: lit(1) },
                                               { id: ident("y"), init: ident("x") }],
                                              blockStmt([])));
 assertError("let (x = 1, x = 2) { }", TypeError);
 
 
+// Bug 632024: no crashing on stack overflow
+try {
+    Reflect.parse(Array(3000).join("x + y - ") + "z")
+} catch (e) { }
+
+
 // E4X
 
 assertExpr("x..tagName", binExpr("..", ident("x"), lit("tagName")));
 assertExpr("x.*", dotExpr(ident("x"), xmlAnyName));
 assertExpr("x[*]", memExpr(ident("x"), xmlAnyName));
 assertExpr("x::y", xmlQualId(ident("x"), ident("y"), false));
 assertExpr("x::[foo]", xmlQualId(ident("x"), ident("foo"), true));
 assertExpr("x::[foo()]", xmlQualId(ident("x"), callExpr(ident("foo"), []), true));