commit bdc69cc7c58f40970172d5beb97226e3a5387faf
parent d8f433388e61874bab828c184ff34d69f273c11a
Author: Christian Holler (:decoder) <choller@mozilla.com>
Date: Tue, 30 Sep 2025 16:16:45 +0000
Bug 1990079 - Add IPC helper code to work with buffers. r=ipc-reviewers,jld
Differential Revision: https://phabricator.services.mozilla.com/D266449
Diffstat:
4 files changed, 77 insertions(+), 0 deletions(-)
diff --git a/ipc/chromium/src/chrome/common/ipc_message.cc b/ipc/chromium/src/chrome/common/ipc_message.cc
@@ -130,6 +130,15 @@ void Message::SetAttachedFileHandles(
attached_handles_ = std::move(handles);
}
+bool Message::has_any_attachments() const {
+ return !attached_ports_.IsEmpty() || !attached_handles_.IsEmpty()
+#if defined(XP_DARWIN)
+ || !attached_send_rights_.IsEmpty() ||
+ !attached_receive_rights_.IsEmpty()
+#endif
+ ;
+}
+
uint32_t Message::num_handles() const { return attached_handles_.Length(); }
void Message::WritePort(mozilla::ipc::ScopedPort port) {
diff --git a/ipc/chromium/src/chrome/common/ipc_message.h b/ipc/chromium/src/chrome/common/ipc_message.h
@@ -236,6 +236,8 @@ class Message : public mojo::core::ports::UserMessage, public Pickle {
const char* name() const { return StringFromIPCMessageType(type()); }
+ bool has_any_attachments() const;
+
uint32_t num_handles() const;
bool is_relay() const { return header()->flags.IsRelay(); }
diff --git a/ipc/glue/SerializeToBytesUtil.h b/ipc/glue/SerializeToBytesUtil.h
@@ -0,0 +1,65 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_ipc_SerializeToBytesUtil_h
+#define mozilla_ipc_SerializeToBytesUtil_h
+
+#include "chrome/common/ipc_message_utils.h"
+#include "chrome/common/ipc_message.h"
+
+namespace mozilla::ipc {
+
+// This file contains a pair of functions which (ab-)use the IPC::ParamTraits
+// serializers with a temporary on-stack IPC::Message to serialize &
+// de-serialize a value from a byte span.
+//
+// NOTE: This is _not_ efficient, and is _not_ guaranteed to work for arbitrary
+// types! Many IPC serializers depend on the IPC::Message supporting additional
+// information, such as attached endpoints and file handles.
+
+template <typename T>
+void SerializeToBytesUtil(T&& aValue, nsTArray<char>& aBytes) {
+ IPC::Message tmpMessage(MSG_ROUTING_NONE, -1);
+
+ {
+ IPC::MessageWriter writer(tmpMessage);
+ IPC::WriteParam(&writer, std::forward<T>(aValue));
+ }
+
+ MOZ_RELEASE_ASSERT(!tmpMessage.has_any_attachments(),
+ "Value contains attachments (e.g. endpoints, file "
+ "handles) which cannot be serialized as bytes");
+
+ aBytes.SetLength(tmpMessage.size() - IPC::Message::HeaderSize());
+
+ IPC::MessageReader reader(tmpMessage);
+ bool readOk = reader.ReadBytesInto(aBytes.Elements(), aBytes.Length());
+ MOZ_RELEASE_ASSERT(readOk);
+ // Double-check that the entire Message body was used.
+ MOZ_RELEASE_ASSERT(!reader.HasBytesAvailable(1));
+}
+
+template <typename T>
+IPC::ReadResult<T> DeserializeFromBytesUtil(const Span<char>& aBytes) {
+ IPC::Message tmpMessage(MSG_ROUTING_NONE, -1);
+
+ {
+ IPC::MessageWriter writer(tmpMessage);
+ writer.WriteBytes(aBytes.Elements(), aBytes.Length());
+ }
+
+ IPC::MessageReader reader(tmpMessage);
+ auto rv = IPC::ReadParam<T>(&reader);
+ if (rv.isOk() && reader.HasBytesAvailable(1)) {
+ // Unexpected trailing data after deserialization.
+ return {};
+ }
+ return rv;
+}
+
+} // namespace mozilla::ipc
+
+#endif // mozilla_ipc_SerializeToBytesUtil_h
diff --git a/ipc/glue/moz.build b/ipc/glue/moz.build
@@ -55,6 +55,7 @@ EXPORTS.mozilla.ipc += [
"RustMessageUtils.h",
"ScopedPort.h",
"SerializedStructuredCloneBuffer.h",
+ "SerializeToBytesUtil.h",
"SharedMemoryCursor.h",
"SharedMemoryHandle.h",
"SharedMemoryMapping.h",