Bug 1300476 - Prevent passing references through InvokeAsync - r=froydnj
authorGerald Squelart <gsquelart@mozilla.com>
Thu, 27 Oct 2016 15:13:37 +1100
changeset 319814 54ad8aaf59c75e5f5b45ba8e95c1c470a06d9b38
parent 319813 3d6e90d77c8d84f3777cdd955793fef6921eea4f
child 319815 ed22ec2c58924267a99e6d81658c4dc387f19fc3
push id20748
push userphilringnalda@gmail.com
push dateFri, 28 Oct 2016 03:39:55 +0000
treeherderfx-team@715360440695 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj
bugs1300476, 1313497
milestone52.0a1
Bug 1300476 - Prevent passing references through InvokeAsync - r=froydnj Passing references to an async call is dangerous because referenced objects could be destroyed before/during the call, or even be stored by the callee. The assertion message points at bug 1313497, which is a follow-up to (eventually) re-allow references in a safer manner. MozReview-Commit-ID: FTgI5CGCVAe
xpcom/threads/MozPromise.h
--- a/xpcom/threads/MozPromise.h
+++ b/xpcom/threads/MozPromise.h
@@ -9,16 +9,17 @@
 
 #include "mozilla/AbstractThread.h"
 #include "mozilla/IndexSequence.h"
 #include "mozilla/Logging.h"
 #include "mozilla/Maybe.h"
 #include "mozilla/Mutex.h"
 #include "mozilla/Monitor.h"
 #include "mozilla/Tuple.h"
+#include "mozilla/TypeTraits.h"
 
 #include "nsTArray.h"
 #include "nsThreadUtils.h"
 
 namespace mozilla {
 
 extern LazyLogModule gMozPromiseLog;
 
@@ -963,23 +964,42 @@ public:
     return NS_OK;
   }
 
 private:
   RefPtr<typename PromiseType::Private> mProxyPromise;
   nsAutoPtr<MethodCall<PromiseType, ThisType, ArgTypes...>> mMethodCall;
 };
 
+constexpr bool Any()
+{
+  return false;
+}
+
+template <typename T1>
+constexpr bool Any(T1 a)
+{
+  return static_cast<bool>(a);
+}
+
+template <typename T1, typename... Ts>
+constexpr bool Any(T1 a, Ts... aOthers)
+{
+  return a || Any(aOthers...);
+}
+
 } // namespace detail
 
 template<typename PromiseType, typename ThisType, typename ...ArgTypes, typename ...ActualArgTypes>
 static RefPtr<PromiseType>
 InvokeAsync(AbstractThread* aTarget, ThisType* aThisVal, const char* aCallerName,
             RefPtr<PromiseType>(ThisType::*aMethod)(ArgTypes...), ActualArgTypes&&... aArgs)
 {
+  static_assert(!detail::Any(IsReference<ArgTypes>::value...),
+                "Cannot pass reference types through InvokeAsync, see bug 1313497 if you require it");
   typedef detail::MethodCall<PromiseType, ThisType, ArgTypes...> MethodCallType;
   typedef detail::ProxyRunnable<PromiseType, ThisType, ArgTypes...> ProxyRunnableType;
 
   MethodCallType* methodCall = new MethodCallType(aMethod, aThisVal, Forward<ActualArgTypes>(aArgs)...);
   RefPtr<typename PromiseType::Private> p = new (typename PromiseType::Private)(aCallerName);
   RefPtr<ProxyRunnableType> r = new ProxyRunnableType(p, methodCall);
   MOZ_ASSERT(aTarget->IsDispatchReliable());
   aTarget->Dispatch(r.forget());