Bug 1484524 - Workaround for a nullptr-induced crash in cache IPC. r=edenchuang, a=pascalc
authorYaron Tausky <ytausky@mozilla.com>
Wed, 10 Oct 2018 12:36:41 +0000
changeset 490272 39d6cdbcbf64
parent 490271 818b81b2177e
child 490273 491779804da9
push id9970
push userryanvm@gmail.com
push date2018-10-11 18:08 +0000
treeherdermozilla-beta@491779804da9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersedenchuang, pascalc
bugs1484524
milestone63.0
Bug 1484524 - Workaround for a nullptr-induced crash in cache IPC. r=edenchuang, a=pascalc DOM cache IPC code requires a StrongWorkerRef to its worker when invoked from a WorkerGlobalScope. Under certain condition, e.g. when worker termination was initiated, it's no longer possible to obtain such a reference, and said code fails silently by storing a nullptr in the CacheOpArgs object. This leads to a crash when that object gets serialized. This is a temporary workaround for this problem, until a more reasonable solution is implemented. Differential Revision: https://phabricator.services.mozilla.com/D8200
dom/cache/TypeUtils.cpp
--- a/dom/cache/TypeUtils.cpp
+++ b/dom/cache/TypeUtils.cpp
@@ -506,13 +506,33 @@ TypeUtils::SerializeCacheStream(nsIInput
 
   cacheStream.controlChild() = nullptr;
   cacheStream.controlParent() = nullptr;
 
   UniquePtr<AutoIPCStream> autoStream(new AutoIPCStream(cacheStream.stream()));
   autoStream->Serialize(aStream, GetIPCManager());
 
   aStreamCleanupList.AppendElement(std::move(autoStream));
+
+  // This nested condition guards against silent failures in IPC code
+  // that would cause a crash when the message is sent. Specifically,
+  // if IPCStreamSource::Initialize fails to get a StrongWorkerRef
+  // (e.g. when the worker terminates), a nullptr is silently stored
+  // in IPCRemoteStreamType.
+  // This is a workaround, requested in bug 1484524, and a more
+  // reasonable solution should replace it.
+  if (cacheStream.stream().type() == OptionalIPCStream::TIPCStream) {
+    const auto& ipcStream = cacheStream.stream().get_IPCStream();
+    if (ipcStream.type() == IPCStream::TIPCRemoteStream) {
+      const auto& ipcRemoteStream = ipcStream.get_IPCRemoteStream();
+      using mozilla::ipc::IPCRemoteStreamType;
+      if (ipcRemoteStream.stream().type() == IPCRemoteStreamType::TPChildToParentStreamChild) {
+        if (!ipcRemoteStream.stream().get_PChildToParentStreamChild()) {
+          aRv.Throw(NS_ERROR_FAILURE);
+        }
+      }
+    }
+  }
 }
 
 } // namespace cache
 } // namespace dom
 } // namespace mozilla