Low firefox Logic Error 🔧 Commit mapped

Overview

Low
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Impactlow
DescriptionInvalid pointer, undefined behavior in the DOM: Notifications component
ComponentDOM
Bug ClassLogic Error
Tracker2067657
Fix commitfd0114b06814 (firefox) +23/-18
CISA KEVNot listed
Creditedzx
Disclosed2026-10-13

Changed Functions

FunctionChangeNotes
if
dom/notification/Notification.cpp
modified

Files Changed

  • dom/notification/Notification.cpp
  • dom/notification/Notification.h
diff --git a/dom/notification/Notification.cpp b/dom/notification/Notification.cpp
index d7118f90578..f9c5180cfd5 100644
--- a/dom/notification/Notification.cpp
+++ b/dom/notification/Notification.cpp
@@ -281,12 +281,6 @@ already_AddRefed<Notification> Notification::Constructor(
       notification);
 
   ContextInfo contextInfo = notification->GetContextInfo();
-  if (!notification->CreateActor(contextInfo)) {
-    notification->Deactivate();
-    aRv.ThrowUnknownError("Failed to create actor.");
-    return nullptr;
-  }
-
   notification->LoadImageAndShow(WrapNotNull(promise.get()),
                                  std::move(contextInfo));
 
@@ -777,7 +771,8 @@ Notification::ContextInfo Notification::GetContextInfo() {
   };
 }
 
-bool Notification::CreateActor(const ContextInfo& aInfo) {
+WeakPtr<notification::NotificationChild> Notification::CreateActor(
+    const ContextInfo& aInfo) {
   mozilla::ipc::PBackgroundChild* backgroundActor =
       mozilla::ipc::BackgroundChild::GetOrCreateForCurrentThread();
 
@@ -797,7 +792,7 @@ bool Notification::CreateActor(const ContextInfo& aInfo) {
       window ? window->GetWindowGlobalChild() : nullptr);
 
   if (!childEndpoint.Bind(mActor, aInfo.mTarget)) {
-    return false;
+    return nullptr;
   }
 
   (void)backgroundActor->SendCreateNotificationParent(
@@ -805,7 +800,7 @@ bool Notification::CreateActor(const ContextInfo& aInfo) {
       WrapNotNull(aInfo.mEffectiveStoragePrincipal), aInfo.mIsSecureContext,
       mScope, mIPCNotification);
 
-  return true;
+  return mActor;
 }
 
 void Notification::LoadImageAndShow(NotNull<Promise*> aPromise,
@@ -813,7 +808,7 @@ void Notification::LoadImageAndShow(NotNull<Promise*> aPromise,
   nsCOMPtr<nsIURI> uri = mIPCNotification.options().icon();
   Maybe<ClientInfo> clientInfo = GetParentObject()->GetClientInfo();
   if (!uri || clientInfo.isNothing()) {
-    SendShow(aPromise, Nothing());
+    SendShow(aPromise, Nothing(), std::move(aInfo));
     return;
   }
 
@@ -829,7 +824,7 @@ void Notification::LoadImageAndShow(NotNull<Promise*> aPromise,
   using IPCImagePromise = mozilla::MozPromise<Maybe<IPCImage>, bool, true>;
   InvokeAsync(
       GetMainThreadSerialEventTarget(), __func__,
-      [uri, clientInfo, contextInfo = std::move(aInfo)]() {
+      [uri, clientInfo, contextInfo = aInfo]() {
         // Don't load the image if we aren't even allowed to show the
         // notification.
         NotificationPermission permission = GetNotificationPermission(
@@ -890,22 +885,30 @@ void Notification::LoadImageAndShow(NotNull<Promise*> aPromise,
       ->Then(
           GetCurrentSerialEventTarget(), __func__,
           [self = RefPtr{this}, promise = WrapNotNull(RefPtr{aPromise.get()}),
-           workerRef = std::move(workerRef)](Maybe<IPCImage>&& aImage) {
+           workerRef = std::move(workerRef),
+           contextInfo = aInfo](Maybe<IPCImage>&& aImage) mutable {
             // SendShow must happen on the original (potentially Worker) thread.
-            self->SendShow(promise, std::move(aImage));
+            self->SendShow(promise, std::move(aImage), std::move(contextInfo));
           },
           [](bool) {});
 }
 
-void Notification::SendShow(NotNull<Promise*> aPromise,
-                            Maybe<IPCImage>&& aIcon) {
+void Notification::SendShow(NotNull<Promise*> aPromise, Maybe<IPCImage>&& aIcon,
+                            ContextInfo&& aInfo) {
   if (mIsClosed) {
     MOZ_ASSERT(mIPCNotification.options().icon(),
                "Closure before SendShow can only happen with image resources");
     return;
   }
 
-  mActor->SendShow(std::move(aIcon))
+  RefPtr<notification::NotificationChild> actor = CreateActor(aInfo).get();
+  if (!actor) {
+    Deactivate();
+    aPromise->MaybeRejectWithUnknownError("Failed to create actor.");
+    return;
+  }
+
+  actor->SendShow(std::move(aIcon))
       ->Then(
           GetCurrentSerialEventTarget(), __func__,
           [self = RefPtr{this}, promise = WrapNotNull(RefPtr(aPromise.get()))](
diff --git a/dom/notification/Notification.h b/dom/notification/Notification.h
index 6a18fde8402..e7cf8a52884 100644
--- a/dom/notification/Notification.h
+++ b/dom/notification/Notification.h
@@ -209,9 +209,11 @@ class Notification : public DOMEventTargetHelper, public SupportsWeakPtr {
   };
   ContextInfo GetContextInfo();
 
-  bool CreateActor(const ContextInfo& aInfo);
+  WeakPtr<notification::NotificationChild> CreateActor(
+      const ContextInfo& aInfo);
   void LoadImageAndShow(NotNull<Promise*> aPromise, ContextInfo&& aInfo);
-  void SendShow(NotNull<Promise*> aPromise, Maybe<IPCImage>&& aIcon);
+  void SendShow(NotNull<Promise*> aPromise, Maybe<IPCImage>&& aIcon,
+                ContextInfo&& aInfo);
 
   // Resolve possibly-relative URL either for icon or navigate.
   static already_AddRefed<nsIURI> ResolveURL(nsIGlobalObject* aGlobal,
Loading diff…