Firefox · Toolkit
CVE-2026-109713
Logic Error in Toolkit
Overview
High
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Files Changed
toolkit/crashreporter/crash_helper_common/src/ipc_queue.rstoolkit/crashreporter/crash_helper_common/src/ipc_queue/windows.rstoolkit/crashreporter/crash_helper_common/src/platform/windows.rs
Patch
diff --git a/toolkit/crashreporter/crash_helper_common/src/ipc_queue.rs b/toolkit/crashreporter/crash_helper_common/src/ipc_queue.rs
index f5794f0bbf3..884d305e1bf 100644
--- a/toolkit/crashreporter/crash_helper_common/src/ipc_queue.rs
+++ b/toolkit/crashreporter/crash_helper_common/src/ipc_queue.rs
@@ -24,6 +24,8 @@ pub enum IPCQueueError {
IPCListenerError(#[from] IPCListenerError),
#[error("Underlying message error: {0}")]
MessageError(#[from] MessageError),
+ #[error("Unexpected event: {0}")]
+ UnexpectedEvent(&'static str),
}
/*****************************************************************************
diff --git a/toolkit/crashreporter/crash_helper_common/src/ipc_queue/windows.rs b/toolkit/crashreporter/crash_helper_common/src/ipc_queue/windows.rs
index 662b811dae2..c081e503a3d 100644
--- a/toolkit/crashreporter/crash_helper_common/src/ipc_queue/windows.rs
+++ b/toolkit/crashreporter/crash_helper_common/src/ipc_queue/windows.rs
@@ -185,25 +185,8 @@ impl IPCQueue {
)
};
- if number_of_bytes_transferred == 0 {
- // This is an event on the listener
- debug_assert!(
- self.listener.as_raw() as IPCConnectorKey == completion_key,
- "Completion event doesn't match the listener"
- );
- let operation = self.listen_operation.take();
- if let Some(operation) = operation {
- operation.accept().map_err(IPCQueueError::WaitError)?;
- }
- let connector = Rc::new(self.listener.replace_pipe()?);
- self.insert_connector(&connector);
-
- // After the pipe is connected the listener handle will have been
- // replaced with a new one, so associate the new handle with the
- // completion queue.
- self.add_handle(self.listener.as_raw())?;
-
- events.push(IPCEvent::Connect(connector));
+ if self.is_listener(completion_key) {
+ events.push(self.handle_listener_event(number_of_bytes_transferred)?);
} else {
let element = self
.connectors
@@ -213,7 +196,7 @@ impl IPCQueue {
.operation
.take()
.expect("No pending receive operation");
- let buffer = operation.collect_recv();
+ let buffer = operation.collect_recv(number_of_bytes_transferred as usize);
let header = Header::decode(buffer)?;
let payload = element.connector.recv(header.size);
match payload {
@@ -237,6 +220,36 @@ impl IPCQueue {
Ok(events)
}
+
+ fn is_listener(&self, completion_key: IPCConnectorKey) -> bool {
+ self.listener.as_raw() as IPCConnectorKey == completion_key
+ }
+
+ fn handle_listener_event(
+ &mut self,
+ number_of_bytes_transferred: u32,
+ ) -> Result<IPCEvent, IPCQueueError> {
+ // A connection event will have 0 bytes transferred
+ if number_of_bytes_transferred != 0 {
+ return Err(IPCQueueError::UnexpectedEvent(
+ "Non-zero transfer received on the listener",
+ ));
+ }
+
+ let operation = self.listen_operation.take();
+ if let Some(operation) = operation {
+ operation.accept().map_err(IPCQueueError::WaitError)?;
+ }
+ let connector = Rc::new(self.listener.replace_pipe()?);
+ self.insert_connector(&connector);
+
+ // After the pipe is connected the listener handle will have been
+ // replaced with a new one, so associate the new handle with the
+ // completion queue.
+ self.add_handle(self.listener.as_raw())?;
+
+ Ok(IPCEvent::Connect(connector))
+ }
}
impl Drop for IPCQueue {
diff --git a/toolkit/crashreporter/crash_helper_common/src/platform/windows.rs b/toolkit/crashreporter/crash_helper_common/src/platform/windows.rs
index a25d3931326..d719008805f 100644
--- a/toolkit/crashreporter/crash_helper_common/src/platform/windows.rs
+++ b/toolkit/crashreporter/crash_helper_common/src/platform/windows.rs
@@ -421,8 +421,19 @@ impl OverlappedOperation {
Self::sched_recv_internal(handle, None, expected_size)
}
- pub(crate) fn collect_recv(mut self) -> Vec<u8> {
- self.buffer.take().expect("Missing receive buffer")
+ pub(crate) fn collect_recv(mut self, len: usize) -> Vec<u8> {
+ let mut buffer = self.buffer.take().expect("Missing receive buffer");
+
+ // We assert here because if this happens then we've hit a logic bug in
+ // our code. The size of the receive operation and buffer length are
+ // tied together so this should never happen.
+ assert!(
+ len <= buffer.len(),
+ "More bytes received than the buffer would allow"
+ );
+
+ buffer.truncate(len);
+ buffer
}
pub(crate) fn send(
Loading diff…
References
On This Page