Bug 1306200 part 2. When a promise is rejected with an object that cannot be securely unwrapped, report the underlying object as an error to its global before replacing the rejection value with a security error placeholder. r=waldo
authorBoris Zbarsky <bzbarsky@mit.edu>
Tue, 18 Apr 2017 20:56:48 -0400
changeset 565180 9142443a4ca244d10bb55b401df33098ccf78d3d
parent 565179 f549be8f0bf407ae7a92c9c3abe50e37d956201c
child 565181 56e6060973829ae7463ea251b33ea6a7aaaa8028
push id54802
push userdgottwald@mozilla.com
push dateWed, 19 Apr 2017 15:26:27 +0000
reviewerswaldo
bugs1306200
milestone55.0a1
Bug 1306200 part 2. When a promise is rejected with an object that cannot be securely unwrapped, report the underlying object as an error to its global before replacing the rejection value with a security error placeholder. r=waldo
js/src/builtin/Promise.cpp
--- a/js/src/builtin/Promise.cpp
+++ b/js/src/builtin/Promise.cpp
@@ -7,16 +7,17 @@
 
 #include "builtin/Promise.h"
 
 #include "mozilla/Atomics.h"
 #include "mozilla/TimeStamp.h"
 
 #include "jscntxt.h"
 #include "jsexn.h"
+#include "jsfriendapi.h"
 #include "jsiter.h"
 
 #include "gc/Heap.h"
 #include "js/Debug.h"
 #include "vm/AsyncFunction.h"
 #include "vm/AsyncIteration.h"
 
 #include "jsobjinlines.h"
@@ -805,16 +806,23 @@ RejectMaybeWrappedPromise(JSContext *cx,
         // values might be wrapped into a wrapper that throws whenever the
         // Promise's reaction handler wants to do anything useful with it. To
         // avoid that situation, we synthesize a generic error that doesn't
         // expose any privileged information but can safely be used in the
         // rejection handler.
         if (!promise->compartment()->wrap(cx, &reason))
             return false;
         if (reason.isObject() && !CheckedUnwrap(&reason.toObject())) {
+            // Report the existing reason, so we don't just drop it on the
+            // floor.
+            RootedObject realReason(cx, UncheckedUnwrap(&reason.toObject()));
+            RootedValue realReasonVal(cx, ObjectValue(*realReason));
+            RootedObject realGlobal(cx, &realReason->global());
+            ReportErrorToGlobal(cx, realGlobal, realReasonVal);
+
             // Async stacks are only properly adopted if there's at least one
             // interpreter frame active right now. If a thenable job with a
             // throwing `then` function got us here, that'll not be the case,
             // so we add one by throwing the error from self-hosted code.
             if (!GetInternalError(cx, JSMSG_PROMISE_ERROR_IN_WRAPPED_REJECTION_REASON, &reason))
                 return false;
         }
     }