Bug 668261 - Change EvalInContext to not clobber callee early; don't propagate rval on js::Execute failure so that rval-clobbering callers don't trigger assert (r=waldo)
authorLuke Wagner <luke@mozilla.com>
Thu, 30 Jun 2011 09:26:42 -0700
changeset 72361 f59568ec0513a083130f0bec33041b7b64c543fb
parent 72360 c1afc79e767612212f89e23455b2fd7ca30c8943
child 72362 944648af74d830dd137a012f1859eac6efa33e74
push idunknown
push userunknown
push dateunknown
reviewerswaldo
bugs668261
milestone7.0a1
Bug 668261 - Change EvalInContext to not clobber callee early; don't propagate rval on js::Execute failure so that rval-clobbering callers don't trigger assert (r=waldo)
js/src/jit-test/tests/basic/testThrowWhileWrappingException.js
js/src/jsinterp.cpp
js/src/shell/js.cpp
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/testThrowWhileWrappingException.js
@@ -0,0 +1,7 @@
+var caught = false;
+try {
+    evalcx("eval(\"throw<x/>\")", Function.a)
+} catch (e) {
+    caught = true;
+}
+assertEq(caught, true);
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -901,17 +901,17 @@ Execute(JSContext *cx, JSScript *script,
     if (script->hasSharps && !InitSharpSlots(cx, fp))
         return false;
 #endif
 
     Probes::startExecution(cx, script);
 
     AutoPreserveEnumerators preserve(cx);
     JSBool ok = RunScript(cx, script, fp);
-    if (result)
+    if (result && ok)
         *result = fp->returnValue();
 
     Probes::stopExecution(cx, script);
 
     return !!ok;
 }
 
 bool
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -3629,23 +3629,25 @@ EvalInContext(JSContext *cx, uintN argc,
     }
 
     if (!sobj) {
         sobj = NewSandbox(cx, lazy, split);
         if (!sobj)
             return false;
     }
 
-    *vp = OBJECT_TO_JSVAL(sobj);
-    if (srclen == 0)
+    if (srclen == 0) {
+        JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(sobj));
         return true;
+    }
 
     JSStackFrame *fp = JS_GetScriptedCaller(cx, NULL);
     JSScript *script = JS_GetFrameScript(cx, fp);
     jsbytecode *pc = JS_GetFramePC(cx, fp);
+    jsval rval;
     {
         JSAutoEnterCompartment ac;
         uintN flags;
         JSObject *unwrapped = sobj->unwrap(&flags);
         if (flags & JSWrapper::CROSS_COMPARTMENT) {
             sobj = unwrapped;
             if (!ac.enter(cx, sobj))
                 return false;
@@ -3656,21 +3658,26 @@ EvalInContext(JSContext *cx, uintN argc,
             return false;
         if (!(sobj->getClass()->flags & JSCLASS_IS_GLOBAL)) {
             JS_ReportError(cx, "Invalid scope argument to evalcx");
             return false;
         }
         if (!JS_EvaluateUCScript(cx, sobj, src, srclen,
                                  script->filename,
                                  JS_PCToLineNumber(cx, script, pc),
-                                 vp)) {
+                                 &rval)) {
             return false;
         }
     }
-    return cx->compartment->wrap(cx, Valueify(vp));
+
+    if (!cx->compartment->wrap(cx, Valueify(&rval)))
+        return false;
+
+    JS_SET_RVAL(cx, vp, rval);
+    return true;
 }
 
 static JSBool
 EvalInFrame(JSContext *cx, uintN argc, jsval *vp)
 {
     jsval *argv = JS_ARGV(cx, vp);
     if (argc < 2 ||
         !JSVAL_IS_INT(argv[0]) ||