Medium firefox Memory Corruption 🔧 Commit mapped

Overview

Medium
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
Impactmoderate
DescriptionMemory safety bugs present in Firefox ESR 140.11, Thunderbird ESR 140.11, Firefox 151 and Thunderbird 151. Some of these bugs showed evidence of memory corruption and we presume that with enough effort some of these could have been exploited to run arbitrary code.
ComponentWidget
Bug ClassMemory Corruption
Tracker2011842
Fix commit9c267d0a950b (firefox) +82/-2
CISA KEVNot listed
CreditedChristian Holler, Jens Stutte, Nika Layzell, Randell Jesup, Tom Schuster and the Mozilla Fuzzing Team
Disclosed2026-06-16

Changed Functions

FunctionChangeNotes
switch
widget/WidgetEventImpl.cpp
modified

Files Changed

  • widget/EventForwards.h
  • widget/WidgetEventImpl.cpp
  • widget/nsGUIEventIPC.h
diff --git a/widget/EventForwards.h b/widget/EventForwards.h
index 82cba445004..907fccbf945 100644
--- a/widget/EventForwards.h
+++ b/widget/EventForwards.h
@@ -117,6 +117,15 @@ enum EventClassID : uint8_t {
 
 const char* ToChar(EventClassID aEventClassID);
 
+/**
+ * Return true if aMessage is a valid EventMessage value for aClassID when an
+ * event is read from another process.  This is used to reject events whose
+ * mMessage/mClass combination is inconsistent and therefore likely tampered
+ * with by a compromised content process.
+ */
+[[nodiscard]] bool IsValidMessageForIPC(EventMessage aMessage,
+                                        EventClassID aClassID);
+
 typedef uint16_t Modifiers;
 
 #define NS_DEFINE_KEYNAME(aCPPName, aDOMKeyName) KEY_NAME_INDEX_##aCPPName,
diff --git a/widget/WidgetEventImpl.cpp b/widget/WidgetEventImpl.cpp
index e5ee9b94d70..c4d3b451dd7 100644
--- a/widget/WidgetEventImpl.cpp
+++ b/widget/WidgetEventImpl.cpp
@@ -185,6 +185,75 @@ bool IsForbiddenDispatchingToNonElementContent(EventMessage aMessage) {
   }
 }
 
+bool IsValidMessageForIPC(EventMessage aMessage, EventClassID aClassID) {
+  switch (aMessage) {
+    case eKeyDown:
+    case eKeyUp:
+    case eKeyPress:
+      return aClassID == eKeyboardEventClass;
+    case eMouseMove:
+    case eMouseUp:
+    case eMouseDown:
+    case eMouseEnterIntoWidget:
+    case eMouseExitFromWidget:
+    case eMouseDoubleClick:
+    case eMouseActivate:
+    case eMouseOver:
+    case eMouseOut:
+    case eMouseHitTest:
+    case eMouseEnter:
+    case eMouseLeave:
+    case eMouseTouchDrag:
+    case eMouseLongTap:
+    case eMouseExploreByTouch:
+      return aClassID == eMouseEventClass;
+    case eWheel:
+    case eWheelOperationStart:
+    case eWheelOperationEnd:
+      return aClassID == eWheelEventClass;
+    case eDragEnter:
+    case eDragOver:
+    case eDragExit:
+    case eDrag:
+    case eDragEnd:
+    case eDragStart:
+    case eDrop:
+    case eDragLeave:
+      return aClassID == eDragEventClass;
+    case ePointerMove:
+    case ePointerUp:
+    case ePointerDown:
+    case ePointerOver:
+    case ePointerOut:
+    case ePointerEnter:
+    case ePointerLeave:
+    case ePointerCancel:
+    case ePointerRawUpdate:
+    case ePointerGotCapture:
+    case ePointerLostCapture:
+    case ePointerClick:
+    case ePointerAuxClick:
+    case eContextMenu:
+      return aClassID == ePointerEventClass;
+    case eTouchStart:
+    case eTouchMove:
+    case eTouchEnd:
+    case eTouchCancel:
+    case eTouchPointerCancel:
+      return aClassID == eTouchEventClass;
+    case eCompositionStart:
+    case eCompositionEnd:
+    case eCompositionChange:
+    case eCompositionCommitAsIs:
+    case eCompositionCommit:
+      return aClassID == eCompositionEventClass;
+    case eSetSelection:
+      return aClassID == eSelectionEventClass;
+    default:
+      return false;
+  }
+}
+
 const char* ToChar(EventClassID aEventClassID) {
   switch (aEventClassID) {
 #define NS_ROOT_EVENT_CLASS(aPrefix, aName) \
diff --git a/widget/nsGUIEventIPC.h b/widget/nsGUIEventIPC.h
index f9f005abac0..baf960fdb59 100644
--- a/widget/nsGUIEventIPC.h
+++ b/widget/nsGUIEventIPC.h
@@ -83,13 +83,15 @@ struct ParamTraits<mozilla::WidgetEvent> {
             ToChar(aExpectedEventClassID), ToChar(aResult->mClass),
             ToChar(aResult->mMessage))
             .c_str());
-    if (aResult->mClass == aExpectedEventClassID) [[likely]] {
+    if (aResult->mClass == aExpectedEventClassID &&
+        mozilla::IsValidMessageForIPC(aResult->mMessage, aExpectedEventClassID))
+        [[likely]] {
       return true;
     }
     // Clear mClass value to avoid the assertion failure in the destructor in
     // the debug build because it's not a fault in this process.
     aResult->mClass = mozilla::eEventClassUninitialized;
-    // Don't allow illegal mClass value.
+    // Don't allow illegal mClass/mMessage combination.
     return false;
   }
 
Loading diff…