From caaaeca6afcb308ed848ec2e07f7cc19ff2cc26c Mon Sep 17 00:00:00 2001 From: "shaver%mozilla.org" Date: Sat, 24 Dec 2005 01:09:19 +0000 Subject: [PATCH] Bug 319490: return in finally should clear pending exceptions. r=mrbkap, sr=brendan. git-svn-id: svn://10.0.0.236/trunk@186549 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/js/src/jsemit.c | 18 ++++++++++++++++-- mozilla/js/src/jsemit.h | 7 +++++-- mozilla/js/src/jsinterp.c | 2 ++ mozilla/js/src/jsopcode.c | 6 ++++-- 4 files changed, 27 insertions(+), 6 deletions(-) diff --git a/mozilla/js/src/jsemit.c b/mozilla/js/src/jsemit.c index fcb53c7b607..af6602258d0 100644 --- a/mozilla/js/src/jsemit.c +++ b/mozilla/js/src/jsemit.c @@ -1193,12 +1193,12 @@ js_SetJumpOffset(JSContext *cx, JSCodeGenerator *cg, jsbytecode *pc, } JSBool -js_InWithStatement(JSTreeContext *tc) +js_InStatement(JSTreeContext *tc, JSStmtType type) { JSStmtInfo *stmt; for (stmt = tc->topStmt; stmt; stmt = stmt->down) { - if (stmt->type == STMT_WITH) + if (stmt->type == type) return JS_TRUE; } return JS_FALSE; @@ -3872,6 +3872,20 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) break; case TOK_RETURN: + /* + * If we're in a finally clause, then returning must clear any pending + * exception state. Failure to do so could cause a subsequent + * non-throwing API failure or native use of JS_IsPendingException to + * mislead. + */ + if (js_InStatement(&cg->treeContext, STMT_SUBROUTINE) && + (js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0 || + js_Emit1(cx, cg, JSOP_EXCEPTION) < 0 || + js_NewSrcNote(cx, cg, SRC_HIDDEN) < 0 || + js_Emit1(cx, cg, JSOP_POP) < 0)) { + return JS_FALSE; + } + /* Push a return value */ pn2 = pn->pn_kid; if (pn2) { diff --git a/mozilla/js/src/jsemit.h b/mozilla/js/src/jsemit.h index f83fe61c98a..2ea17e2b425 100644 --- a/mozilla/js/src/jsemit.h +++ b/mozilla/js/src/jsemit.h @@ -305,9 +305,12 @@ extern JSBool js_SetJumpOffset(JSContext *cx, JSCodeGenerator *cg, jsbytecode *pc, ptrdiff_t off); -/* Test whether we're in a with statement. */ +/* Test whether we're in a statement of given type. */ extern JSBool -js_InWithStatement(JSTreeContext *tc); +js_InStatement(JSTreeContext *tc, JSStmtType type); + +/* Test whether we're in a with statement. */ +#define js_InWithStatement(tc) js_InStatement(tc, STMT_WITH) /* Test whether we're in a catch block with exception named by atom. */ extern JSBool diff --git a/mozilla/js/src/jsinterp.c b/mozilla/js/src/jsinterp.c index 5edd210e15e..e8578f97369 100644 --- a/mozilla/js/src/jsinterp.c +++ b/mozilla/js/src/jsinterp.c @@ -2099,6 +2099,7 @@ interrupt: END_CASE(JSOP_LEAVEWITH) BEGIN_CASE(JSOP_SETRVAL) + JS_ASSERT(!cx->throwing); fp->rval = POP_OPND(); END_CASE(JSOP_SETRVAL) @@ -2108,6 +2109,7 @@ interrupt: /* FALL THROUGH */ BEGIN_CASE(JSOP_RETRVAL) /* fp->rval already set */ + JS_ASSERT(!cx->throwing); if (inlineCallCount) inline_return: { diff --git a/mozilla/js/src/jsopcode.c b/mozilla/js/src/jsopcode.c index c5d1e12f4d6..06dafcce8d0 100644 --- a/mozilla/js/src/jsopcode.c +++ b/mozilla/js/src/jsopcode.c @@ -1232,8 +1232,10 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb) case JSOP_EXCEPTION: /* - * The only other JSOP_EXCEPTION case occurs as part of a code - * sequence that follows a SRC_CATCH-annotated JSOP_NOP. + * The only other JSOP_EXCEPTION cases occur as part of a code + * sequence that follows a SRC_CATCH-annotated JSOP_NOP or + * precedes a SRC_HIDDEN-annotated JSOP_POP emitted when + * returning from within a finally clause. */ sn = js_GetSrcNote(jp->script, pc); LOCAL_ASSERT(sn && SN_TYPE(sn) == SRC_HIDDEN);