Bug 1248948 - Don't pass non-SavedFrame objects to SavedFrame JSAPI functions. r=tromey, r=evilpie, a=ritu
☠☠ backed out by ca4e2efb2ef9 ☠ ☠
authorNick Fitzgerald <fitzgen@gmail.com>
Tue, 05 Apr 2016 13:51:00 +0200
changeset 325772 5f050838a6a2f33a3802ed696793232d5054e226
parent 325771 57c47196d35c84cb26e67e68e5ceb178e3c8a0f3
child 325773 9b649cb10e0a589f7d23f547ff92977ad2ec4f6a
push id1128
push userjlund@mozilla.com
push dateWed, 01 Jun 2016 01:31:59 +0000
treeherdermozilla-release@fe0d30de989d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstromey, evilpie, ritu
bugs1248948
milestone47.0a2
Bug 1248948 - Don't pass non-SavedFrame objects to SavedFrame JSAPI functions. r=tromey, r=evilpie, a=ritu
docshell/base/timeline/JavascriptTimelineMarker.h
js/src/jsapi.h
js/src/vm/SavedStacks.cpp
--- a/docshell/base/timeline/JavascriptTimelineMarker.h
+++ b/docshell/base/timeline/JavascriptTimelineMarker.h
@@ -49,17 +49,18 @@ public:
       stackFrame.mSource.Construct(mFileName);
       stackFrame.mFunctionDisplayName.Construct(mFunctionName);
 
       if (mAsyncStack.isObject() && !mAsyncStack.isNullOrUndefined() &&
           mAsyncCause.isString()) {
         JS::Rooted<JSObject*> asyncStack(aCx, mAsyncStack.toObjectOrNull());
         JS::Rooted<JSString*> asyncCause(aCx, mAsyncCause.toString());
         JS::Rooted<JSObject*> parentFrame(aCx);
-        if (!JS::CopyAsyncStack(aCx, asyncStack, asyncCause, &parentFrame, 0)) {
+        if (JS::IsSavedFrame(asyncStack) &&
+            !JS::CopyAsyncStack(aCx, asyncStack, asyncCause, &parentFrame, 0)) {
           JS_ClearPendingException(aCx);
         } else {
           stackFrame.mAsyncParent = parentFrame;
         }
       }
 
       JS::Rooted<JS::Value> newStack(aCx);
       if (ToJSValue(aCx, stackFrame, &newStack)) {
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -5786,16 +5786,23 @@ GetSavedFrameParent(JSContext* cx, Handl
  * SavedFrame object, or a wrapper (CCW or Xray) around a SavedFrame object.
  *
  * Optional indent parameter specifies the number of white spaces to indent
  * each line.
  */
 extern JS_PUBLIC_API(bool)
 BuildStackString(JSContext* cx, HandleObject stack, MutableHandleString stringp, size_t indent = 0);
 
+/**
+ * Return true iff the given object is either a SavedFrame object or wrapper
+ * around a SavedFrame object, and it is not the SavedFrame.prototype object.
+ */
+extern JS_PUBLIC_API(bool)
+IsSavedFrame(JSObject* obj);
+
 } /* namespace JS */
 
 
 /* Stopwatch-based performance monitoring. */
 
 namespace js {
 
 class AutoStopwatch;
--- a/js/src/vm/SavedStacks.cpp
+++ b/js/src/vm/SavedStacks.cpp
@@ -881,16 +881,29 @@ BuildStackString(JSContext* cx, HandleOb
     JSString* str = sb.finishString();
     if (!str)
         return false;
     assertSameCompartment(cx, str);
     stringp.set(str);
     return true;
 }
 
+JS_PUBLIC_API(bool)
+IsSavedFrame(JSObject* obj)
+{
+    if (!obj)
+        return false;
+
+    JSObject* unwrapped = CheckedUnwrap(obj);
+    if (!unwrapped)
+        return false;
+
+    return js::SavedFrame::isSavedFrameAndNotProto(*unwrapped);
+}
+
 } /* namespace JS */
 
 namespace js {
 
 /* static */ bool
 SavedFrame::sourceProperty(JSContext* cx, unsigned argc, Value* vp)
 {
     THIS_SAVEDFRAME(cx, argc, vp, "(get source)", args, frame);