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
--- 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());