Bug 758344 - Push more stuff when evaluating in a sandbox. r=mrbkap,a=akeybl
authorBobby Holley <bobbyholley@gmail.com>
Tue, 26 Jun 2012 22:23:08 +0200
changeset 98259 139156d111b682d78e9db1b9e2bfe6e69db5d662
parent 98258 c529dbb61c9d3818bcc94b28a2c77657a3427e3d
child 98260 e8e98b7790a4911b429c03537d2bff4dc9477cf1
push id1590
push userbobbyholley@gmail.com
push dateTue, 26 Jun 2012 20:23:27 +0000
treeherdermozilla-aurora@139156d111b6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmrbkap, akeybl
bugs758344
milestone15.0a2
Bug 758344 - Push more stuff when evaluating in a sandbox. r=mrbkap,a=akeybl
js/xpconnect/src/XPCComponents.cpp
--- a/js/xpconnect/src/XPCComponents.cpp
+++ b/js/xpconnect/src/XPCComponents.cpp
@@ -3591,16 +3591,65 @@ nsXPCComponents_Utils::EvalInSandbox(con
             frame->GetLineNumber(&lineNo);
         }
     }
 
     return xpc_EvalInSandbox(cx, sandbox, source, filename.get(), lineNo,
                              jsVersion, false, retval);
 }
 
+struct NS_STACK_CLASS AutoSecurityJunkPusher
+{
+    JSContext                *mCx;
+    nsIPrincipal             *mPrincipal;
+    XPCJSContextStack        *mStack;
+    nsIScriptSecurityManager *mSSM;
+    bool                      mPushed;
+
+    AutoSecurityJunkPusher(JSContext *cx, nsIPrincipal *principal)
+       : mCx(cx)
+       , mPrincipal(principal)
+       , mStack(XPCPerThreadData::GetData(cx)->GetJSContextStack())
+       , mSSM(XPCWrapper::GetSecurityManager())
+       , mPushed(false)
+    {}
+
+    bool Push() {
+        if (!mStack)
+            return false;
+
+        // First, push the js context.
+        if (!mStack->Push(mCx)) {
+            JS_ReportError(mCx, "Unable to initialize XPConnect with the sandbox context");
+            return false;
+        }
+
+        // Then, push the principal.
+        nsresult rv = mSSM->PushContextPrincipal(mCx, nsnull, mPrincipal);
+        if (NS_FAILED(rv)) {
+            mStack->Pop();
+            return false;
+        }
+
+        mPushed = true;
+        return true;
+    }
+
+    void Pop() {
+        MOZ_ASSERT(mPushed);
+        mSSM->PopContextPrincipal(mCx);
+        mStack->Pop();
+    }
+
+    ~AutoSecurityJunkPusher() {
+        if (mPushed)
+            Pop();
+    }
+};
+
 nsresult
 xpc_EvalInSandbox(JSContext *cx, JSObject *sandbox, const nsAString& source,
                   const char *filename, PRInt32 lineNo,
                   JSVersion jsVersion, bool returnStringOnly, jsval *rval)
 {
     JS_AbortIfWrongThread(JS_GetRuntime(cx));
 
 #ifdef DEBUG
@@ -3657,35 +3706,27 @@ xpc_EvalInSandbox(JSContext *cx, JSObjec
     if (!sandcx || !sandcx->GetJSContext()) {
         JS_ReportError(cx, "Can't prepare context for evalInSandbox");
         return NS_ERROR_OUT_OF_MEMORY;
     }
 
     if (jsVersion != JSVERSION_DEFAULT)
         JS_SetVersion(sandcx->GetJSContext(), jsVersion);
 
-    XPCPerThreadData *data = XPCPerThreadData::GetData(cx);
-    XPCJSContextStack *stack = nsnull;
-    if (data && (stack = data->GetJSContextStack())) {
-        if (!stack->Push(sandcx->GetJSContext())) {
-            JS_ReportError(cx,
-                           "Unable to initialize XPConnect with the sandbox context");
-            return NS_ERROR_FAILURE;
-        }
-    }
+    AutoSecurityJunkPusher pusher(sandcx->GetJSContext(), prin);
+    if (!pusher.Push())
+        return NS_ERROR_FAILURE;
 
     nsresult rv = NS_OK;
 
     {
         JSAutoRequest req(sandcx->GetJSContext());
         JSAutoEnterCompartment ac;
 
         if (!ac.enter(sandcx->GetJSContext(), sandbox)) {
-            if (stack)
-                unused << stack->Pop();
             return NS_ERROR_FAILURE;
         }
 
         jsval v;
         JSString *str = nsnull;
         JSBool ok =
             JS_EvaluateUCScriptForPrincipals(sandcx->GetJSContext(), sandbox,
                                              nsJSPrincipals::get(prin),
@@ -3751,19 +3792,16 @@ xpc_EvalInSandbox(JSContext *cx, JSObjec
             }
 
             if (NS_SUCCEEDED(rv)) {
                 *rval = v;
             }
         }
     }
 
-    if (stack)
-        unused << stack->Pop();
-
     return rv;
 }
 
 /* JSObject import (in AUTF8String registryLocation,
  *                  [optional] in JSObject targetObj);
  */
 NS_IMETHODIMP
 nsXPCComponents_Utils::Import(const nsACString& registryLocation,