Bug 1248948 - Don't pass non-SavedFrame objects to SavedFrame JSAPI functions; r=tromey r=evilpie
authorNick Fitzgerald <fitzgen@gmail.com>
Tue, 05 Apr 2016 13:51:00 +0200
changeset 291857 1e5447cbadfaaa24b8cdde74e117b6e122584722
parent 291856 cc6c0df12548c251921f7e94f577d7a77a080ad2
child 291858 26faa5d26ab77cec112d3d9a895d05cda09e08ef
push idunknown
push userunknown
push dateunknown
reviewerstromey, evilpie
bugs1248948
milestone48.0a1
Bug 1248948 - Don't pass non-SavedFrame objects to SavedFrame JSAPI functions; r=tromey r=evilpie
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
@@ -57,17 +57,18 @@ public:
         JS::Rooted<JSObject*> parentFrame(aCx);
         JS::Rooted<JSString*> asyncCause(aCx, JS_NewUCStringCopyN(aCx, mAsyncCause.BeginReading(),
                                                                   mAsyncCause.Length()));
         if (!asyncCause) {
           JS_ClearPendingException(aCx);
           return;
         }
 
-        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
@@ -5991,16 +5991,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
@@ -925,16 +925,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);