[vm] Prevent Dart_NewSendPort from bypassing the arbitrary object checks.

In particular this affects SendPorts from dart:io's IOService and Flutter's IsolateNameServer.

TEST=ci
Bug: https://github.com/flutter/flutter/issues/109248
Change-Id: I28ed3073a6fe5583729637ae7914d914edc709e2
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/255261
Commit-Queue: Ryan Macnak <rmacnak@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
diff --git a/runtime/lib/isolate.cc b/runtime/lib/isolate.cc
index 5779116..1a600c5 100644
--- a/runtime/lib/isolate.cc
+++ b/runtime/lib/isolate.cc
@@ -101,21 +101,29 @@
   return Smi::New(hash);
 }
 
+static bool InSameGroup(Isolate* sender, const SendPort& receiver) {
+  // Cannot determine whether sender is in same group (yet).
+  if (sender->origin_id() == ILLEGAL_PORT) return false;
+
+  // Only allow arbitrary messages between isolates of the same IG.
+  return sender->origin_id() == receiver.origin_id();
+}
+
 DEFINE_NATIVE_ENTRY(SendPortImpl_sendInternal_, 0, 2) {
   GET_NON_NULL_NATIVE_ARGUMENT(SendPort, port, arguments->NativeArgAt(0));
-  // TODO(iposva): Allow for arbitrary messages to be sent.
   GET_NON_NULL_NATIVE_ARGUMENT(Instance, obj, arguments->NativeArgAt(1));
 
   const Dart_Port destination_port_id = port.Id();
-  const bool can_send_any_object = isolate->origin_id() == port.origin_id();
-  // We have to check whether the receiver has the same isolate group (e.g.
-  // native message handlers such as an IOService handler does not but does
-  // share the same origin port).
-  const bool same_group = PortMap::IsReceiverInThisIsolateGroup(
-      destination_port_id, isolate->group());
+  const bool same_group = InSameGroup(isolate, port);
+#if defined(DEBUG)
+  if (same_group) {
+    ASSERT(PortMap::IsReceiverInThisIsolateGroupOrClosed(destination_port_id,
+                                                         isolate->group()));
+  }
+#endif
+
   // TODO(turnidge): Throw an exception when the return value is false?
-  PortMap::PostMessage(WriteMessage(can_send_any_object, same_group, obj,
-                                    destination_port_id,
+  PortMap::PostMessage(WriteMessage(same_group, obj, destination_port_id,
                                     Message::kNormalPriority));
   return Object::null();
 }
@@ -326,7 +334,15 @@
   GET_NATIVE_ARGUMENT(SendPort, port, arguments->NativeArgAt(0));
   if (!port.IsNull()) {
     GET_NATIVE_ARGUMENT(Instance, obj, arguments->NativeArgAt(1));
-    if (!PortMap::IsReceiverInThisIsolateGroup(port.Id(), isolate->group())) {
+
+    const bool same_group = InSameGroup(isolate, port);
+#if defined(DEBUG)
+    if (same_group) {
+      ASSERT(PortMap::IsReceiverInThisIsolateGroupOrClosed(port.Id(),
+                                                           isolate->group()));
+    }
+#endif
+    if (!same_group) {
       const auto& error =
           String::Handle(String::New("exit with final message is only allowed "
                                      "for isolates in one isolate group."));
@@ -868,8 +884,7 @@
     }
     {
       // If parent isolate died, we ignore the fact that we cannot notify it.
-      PortMap::PostMessage(WriteMessage(/* can_send_any_object */ false,
-                                        /* same_group */ false, message,
+      PortMap::PostMessage(WriteMessage(/*same_group=*/false, message,
                                         state_->parent_port(),
                                         Message::kNormalPriority));
     }
@@ -959,7 +974,6 @@
   // serializable this will throw an exception.
   SerializedObjectBuffer message_buffer;
   message_buffer.set_message(WriteMessage(
-      /*can_send_any_object=*/true,
       /*same_group=*/true, message, ILLEGAL_PORT, Message::kNormalPriority));
 
   const char* utf8_package_config =
@@ -1041,14 +1055,11 @@
   SerializedObjectBuffer message_buffer;
   {
     arguments_buffer.set_message(WriteMessage(
-        /* can_send_any_object */ false,
-        /* same_group */ false, args, ILLEGAL_PORT, Message::kNormalPriority));
+        /*same_group=*/false, args, ILLEGAL_PORT, Message::kNormalPriority));
   }
   {
-    message_buffer.set_message(WriteMessage(/* can_send_any_object */ false,
-                                            /* same_group */ false, message,
-                                            ILLEGAL_PORT,
-                                            Message::kNormalPriority));
+    message_buffer.set_message(WriteMessage(
+        /*same_group=*/false, message, ILLEGAL_PORT, Message::kNormalPriority));
   }
 
   // Canonicalize the uri with respect to the current isolate.
@@ -1168,8 +1179,7 @@
   // Ensure message writer (and it's resources, e.g. forwarding tables) are
   // cleaned up before handling interrupts.
   {
-    PortMap::PostMessage(WriteMessage(/* can_send_any_object */ false,
-                                      /* same_group */ false, msg, port.Id(),
+    PortMap::PostMessage(WriteMessage(/*same_group=*/false, msg, port.Id(),
                                       Message::kOOBPriority));
   }
 
diff --git a/runtime/lib/vmservice.cc b/runtime/lib/vmservice.cc
index 16725ec..e544842 100644
--- a/runtime/lib/vmservice.cc
+++ b/runtime/lib/vmservice.cc
@@ -63,8 +63,7 @@
   // Serialize message.
   // TODO(turnidge): Throw an exception when the return value is false?
   bool result = PortMap::PostMessage(WriteMessage(
-      /* can_send_any_object */ false, /* same_group */ false, message, sp.Id(),
-      Message::kOOBPriority));
+      /* same_group */ false, message, sp.Id(), Message::kOOBPriority));
   return Bool::Get(result).ptr();
 #else
   return Object::null();
diff --git a/runtime/vm/benchmark_test.cc b/runtime/vm/benchmark_test.cc
index db27125..300538f 100644
--- a/runtime/vm/benchmark_test.cc
+++ b/runtime/vm/benchmark_test.cc
@@ -517,8 +517,8 @@
   for (intptr_t i = 0; i < kLoopCount; i++) {
     StackZone zone(thread);
     std::unique_ptr<Message> message =
-        WriteMessage(/* can_send_any_object */ true, /* same_group */ false,
-                     null_object, ILLEGAL_PORT, Message::kNormalPriority);
+        WriteMessage(/* same_group */ false, null_object, ILLEGAL_PORT,
+                     Message::kNormalPriority);
 
     // Read object back from the snapshot.
     ReadMessage(thread, message.get());
@@ -538,8 +538,8 @@
   for (intptr_t i = 0; i < kLoopCount; i++) {
     StackZone zone(thread);
     std::unique_ptr<Message> message =
-        WriteMessage(/* can_send_any_object */ true, /* same_group */ false,
-                     smi_object, ILLEGAL_PORT, Message::kNormalPriority);
+        WriteMessage(/* same_group */ false, smi_object, ILLEGAL_PORT,
+                     Message::kNormalPriority);
 
     // Read object back from the snapshot.
     ReadMessage(thread, message.get());
@@ -560,9 +560,9 @@
   timer.Start();
   for (intptr_t i = 0; i < kLoopCount; i++) {
     StackZone zone(thread);
-    std::unique_ptr<Message> message = WriteMessage(
-        /* can_send_any_object */ true, /* same_group */ false, array_object,
-        ILLEGAL_PORT, Message::kNormalPriority);
+    std::unique_ptr<Message> message =
+        WriteMessage(/* same_group */ false, array_object, ILLEGAL_PORT,
+                     Message::kNormalPriority);
 
     // Read object back from the snapshot.
     ReadMessage(thread, message.get());
@@ -592,9 +592,8 @@
   timer.Start();
   for (intptr_t i = 0; i < kLoopCount; i++) {
     StackZone zone(thread);
-    std::unique_ptr<Message> message =
-        WriteMessage(/* can_send_any_object */ true, /* same_group */ false,
-                     map, ILLEGAL_PORT, Message::kNormalPriority);
+    std::unique_ptr<Message> message = WriteMessage(
+        /* same_group */ false, map, ILLEGAL_PORT, Message::kNormalPriority);
 
     // Read object back from the snapshot.
     ReadMessage(thread, message.get());
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index 3a9196b..ffe08c1 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -2169,8 +2169,7 @@
   }
 
   const Object& object = Object::Handle(Z, Api::UnwrapHandle(handle));
-  return PortMap::PostMessage(WriteMessage(/* can_send_any_object */ false,
-                                           /* same_group */ false, object,
+  return PortMap::PostMessage(WriteMessage(/* same_group */ false, object,
                                            port_id, Message::kNormalPriority));
 }
 
@@ -2181,7 +2180,8 @@
     return Api::NewError("%s: illegal port_id %" Pd64 ".", CURRENT_FUNC,
                          port_id);
   }
-  return Api::NewHandle(T, SendPort::New(port_id));
+  int64_t origin_id = PortMap::GetOriginId(port_id);
+  return Api::NewHandle(T, SendPort::New(port_id, origin_id));
 }
 
 DART_EXPORT Dart_Handle Dart_SendPortGetId(Dart_Handle port,
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index 04b235d..8421e63 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -8297,6 +8297,48 @@
   EXPECT(Dart_CloseNativePort(port_id));
 }
 
+static void UnreachableMessageHandler(Dart_Port dest_port_id,
+                                      Dart_CObject* message) {
+  UNREACHABLE();
+}
+
+TEST_CASE(DartAPI_NativePortPostUserClass) {
+  const char* kScriptChars =
+      "import 'dart:isolate';\n"
+      "class ABC {}\n"
+      "void callPort(SendPort port) {\n"
+      "  port.send(new ABC());\n"
+      "}\n";
+  Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
+  Dart_EnterScope();
+
+  Dart_Port port_id =
+      Dart_NewNativePort("Port123", UnreachableMessageHandler, true);
+
+  // Test send with port open.
+  {
+    Dart_Handle send_port = Dart_NewSendPort(port_id);
+    EXPECT_VALID(send_port);
+    Dart_Handle dart_args[1];
+    dart_args[0] = send_port;
+    Dart_Handle result = Dart_Invoke(lib, NewString("callPort"), 1, dart_args);
+    EXPECT_ERROR(result, "");
+  }
+
+  // Test send with port closed.
+  {
+    Dart_CloseNativePort(port_id);
+    Dart_Handle send_port = Dart_NewSendPort(port_id);
+    EXPECT_VALID(send_port);
+    Dart_Handle dart_args[1];
+    dart_args[0] = send_port;
+    Dart_Handle result = Dart_Invoke(lib, NewString("callPort"), 1, dart_args);
+    EXPECT_ERROR(result, "");
+  }
+
+  Dart_ExitScope();
+}
+
 static void NewNativePort_nativeReceiveNull(Dart_Port dest_port_id,
                                             Dart_CObject* message) {
   EXPECT_NOTNULL(message);
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index e087b67..f4143de 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -126,8 +126,8 @@
 
 static std::unique_ptr<Message> SerializeMessage(Dart_Port dest_port,
                                                  const Instance& obj) {
-  return WriteMessage(/* can_send_any_object */ false, /* same_group */ false,
-                      obj, dest_port, Message::kNormalPriority);
+  return WriteMessage(/* same_group */ false, obj, dest_port,
+                      Message::kNormalPriority);
 }
 
 static std::unique_ptr<Message> SerializeMessage(Zone* zone,
@@ -1042,8 +1042,7 @@
   element = Capability::New(capability);
   msg.SetAt(2, element);
 
-  PortMap::PostMessage(WriteMessage(/* can_send_any_object */ false,
-                                    /* same_group */ false, msg, main_port(),
+  PortMap::PostMessage(WriteMessage(/* same_group */ false, msg, main_port(),
                                     Message::kOOBPriority));
 }
 
@@ -3435,8 +3434,7 @@
     element = Smi::New(Isolate::kBeforeNextEventAction);
     msg.SetAt(2, element);
     std::unique_ptr<Message> message = WriteMessage(
-        /* can_send_any_object */ false, /* same_group */ false, msg,
-        main_port(), Message::kOOBPriority);
+        /* same_group */ false, msg, main_port(), Message::kOOBPriority);
     bool posted = PortMap::PostMessage(std::move(message));
     ASSERT(posted);
   }
diff --git a/runtime/vm/message_snapshot.cc b/runtime/vm/message_snapshot.cc
index 2c2621a..936ec2a 100644
--- a/runtime/vm/message_snapshot.cc
+++ b/runtime/vm/message_snapshot.cc
@@ -3871,8 +3871,7 @@
   return ReadRef();
 }
 
-std::unique_ptr<Message> WriteMessage(bool can_send_any_object,
-                                      bool same_group,
+std::unique_ptr<Message> WriteMessage(bool same_group,
                                       const Object& obj,
                                       Dart_Port dest_port,
                                       Message::Priority priority) {
@@ -3887,7 +3886,7 @@
   }
 
   Thread* thread = Thread::Current();
-  MessageSerializer serializer(thread, can_send_any_object);
+  MessageSerializer serializer(thread, /*can_send_any_object=*/false);
 
   volatile bool has_exception = false;
   {
diff --git a/runtime/vm/message_snapshot.h b/runtime/vm/message_snapshot.h
index a584748..5ad0300 100644
--- a/runtime/vm/message_snapshot.h
+++ b/runtime/vm/message_snapshot.h
@@ -13,8 +13,7 @@
 
 namespace dart {
 
-std::unique_ptr<Message> WriteMessage(bool can_send_any_object,
-                                      bool same_group,
+std::unique_ptr<Message> WriteMessage(bool same_group,
                                       const Object& obj,
                                       Dart_Port dest_port,
                                       Message::Priority priority);
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 76817ed..c6b8060 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -25546,7 +25546,7 @@
 }
 
 SendPortPtr SendPort::New(Dart_Port id, Heap::Space space) {
-  return New(id, Isolate::Current()->origin_id(), space);
+  return New(id, ILLEGAL_PORT, space);
 }
 
 SendPortPtr SendPort::New(Dart_Port id,
diff --git a/runtime/vm/port.cc b/runtime/vm/port.cc
index 51029ae..ee8b129 100644
--- a/runtime/vm/port.cc
+++ b/runtime/vm/port.cc
@@ -266,16 +266,43 @@
   return handler->isolate();
 }
 
-bool PortMap::IsReceiverInThisIsolateGroup(Dart_Port receiver,
-                                           IsolateGroup* group) {
+Dart_Port PortMap::GetOriginId(Dart_Port id) {
   MutexLocker ml(mutex_);
   if (ports_ == nullptr) {
-    return false;
+    return ILLEGAL_PORT;
+  }
+  auto it = ports_->TryLookup(id);
+  if (it == ports_->end()) {
+    // Port does not exist.
+    return ILLEGAL_PORT;
+  }
+
+  MessageHandler* handler = (*it).handler;
+  Isolate* isolate = handler->isolate();
+  if (isolate == nullptr) {
+    // Message handler is a native port instead of an isolate.
+    return ILLEGAL_PORT;
+  }
+  return isolate->origin_id();
+}
+
+bool PortMap::IsReceiverInThisIsolateGroupOrClosed(Dart_Port receiver,
+                                                   IsolateGroup* group) {
+  MutexLocker ml(mutex_);
+  if (ports_ == nullptr) {
+    // Port was closed.
+    return true;
   }
   auto it = ports_->TryLookup(receiver);
-  if (it == ports_->end()) return false;
+  if (it == ports_->end()) {
+    // Port was closed.
+    return true;
+  }
   auto isolate = (*it).handler->isolate();
-  if (isolate == nullptr) return false;
+  if (isolate == nullptr) {
+    // Port belongs to a native port instead of an isolate.
+    return false;
+  }
   return isolate->group() == group;
 }
 
diff --git a/runtime/vm/port.h b/runtime/vm/port.h
index 4999ad4..e8b65ff 100644
--- a/runtime/vm/port.h
+++ b/runtime/vm/port.h
@@ -63,9 +63,12 @@
   // Returns the owning Isolate for port 'id'.
   static Isolate* GetIsolate(Dart_Port id);
 
+  // Returns the origin id for port 'id'.
+  static Dart_Port GetOriginId(Dart_Port id);
+
   // Whether the destination port's isolate is a member of [isolate_group].
-  static bool IsReceiverInThisIsolateGroup(Dart_Port receiver,
-                                           IsolateGroup* group);
+  static bool IsReceiverInThisIsolateGroupOrClosed(Dart_Port receiver,
+                                                   IsolateGroup* group);
 
   static void Init();
   static void Cleanup();
diff --git a/runtime/vm/service_isolate.cc b/runtime/vm/service_isolate.cc
index b8b855d..67f1b0e 100644
--- a/runtime/vm/service_isolate.cc
+++ b/runtime/vm/service_isolate.cc
@@ -113,8 +113,7 @@
       sp, VM_SERVICE_SERVER_INFO_MESSAGE_ID, false /* ignored */,
       Bool::Handle() /* ignored */));
   ASSERT(!message.IsNull());
-  PortMap::PostMessage(WriteMessage(/* can_send_any_object */ false,
-                                    /* same_group */ false, message, port_,
+  PortMap::PostMessage(WriteMessage(/* same_group */ false, message, port_,
                                     Message::kNormalPriority));
 }
 
@@ -124,8 +123,7 @@
   const Array& message = Array::Handle(MakeServerControlMessage(
       sp, VM_SERVICE_WEB_SERVER_CONTROL_MESSAGE_ID, enable, silenceOutput));
   ASSERT(!message.IsNull());
-  PortMap::PostMessage(WriteMessage(/* can_send_any_object */ false,
-                                    /* same_group */ false, message, port_,
+  PortMap::PostMessage(WriteMessage(/* same_group */ false, message, port_,
                                     Message::kNormalPriority));
 }
 
diff --git a/runtime/vm/snapshot_test.cc b/runtime/vm/snapshot_test.cc
index 1fb886c..31747a0 100644
--- a/runtime/vm/snapshot_test.cc
+++ b/runtime/vm/snapshot_test.cc
@@ -129,8 +129,8 @@
   // Write snapshot with object content.
   const Object& null_object = Object::Handle();
   std::unique_ptr<Message> message =
-      WriteMessage(/* can_send_any_object */ true, /* same_group */ false,
-                   null_object, ILLEGAL_PORT, Message::kNormalPriority);
+      WriteMessage(/* same_group */ false, null_object, ILLEGAL_PORT,
+                   Message::kNormalPriority);
 
   // Read object back from the snapshot.
   const Object& serialized_object =
@@ -150,9 +150,8 @@
 
   // Write snapshot with object content.
   const Smi& smi = Smi::Handle(Smi::New(124));
-  std::unique_ptr<Message> message =
-      WriteMessage(/* can_send_any_object */ true, /* same_group */ false, smi,
-                   ILLEGAL_PORT, Message::kNormalPriority);
+  std::unique_ptr<Message> message = WriteMessage(
+      /* same_group */ false, smi, ILLEGAL_PORT, Message::kNormalPriority);
 
   // Read object back from the snapshot.
   const Object& serialized_object =
@@ -173,9 +172,8 @@
 
   // Write snapshot with object content.
   const Smi& smi = Smi::Handle(Smi::New(-1));
-  std::unique_ptr<Message> message =
-      WriteMessage(/* can_send_any_object */ true, /* same_group */ false, smi,
-                   ILLEGAL_PORT, Message::kNormalPriority);
+  std::unique_ptr<Message> message = WriteMessage(
+      /* same_group */ false, smi, ILLEGAL_PORT, Message::kNormalPriority);
 
   // Read object back from the snapshot.
   const Object& serialized_object =
@@ -193,9 +191,8 @@
 
 Dart_CObject* SerializeAndDeserializeMint(Zone* zone, const Mint& mint) {
   // Write snapshot with object content.
-  std::unique_ptr<Message> message =
-      WriteMessage(/* can_send_any_object */ true, /* same_group */ false, mint,
-                   ILLEGAL_PORT, Message::kNormalPriority);
+  std::unique_ptr<Message> message = WriteMessage(
+      /* same_group */ false, mint, ILLEGAL_PORT, Message::kNormalPriority);
 
   {
     // Switch to a regular zone, where VM handle allocation is allowed.
@@ -264,9 +261,8 @@
 
   // Write snapshot with object content.
   const Double& dbl = Double::Handle(Double::New(101.29));
-  std::unique_ptr<Message> message =
-      WriteMessage(/* can_send_any_object */ true, /* same_group */ false, dbl,
-                   ILLEGAL_PORT, Message::kNormalPriority);
+  std::unique_ptr<Message> message = WriteMessage(
+      /* same_group */ false, dbl, ILLEGAL_PORT, Message::kNormalPriority);
 
   // Read object back from the snapshot.
   const Object& serialized_object =
@@ -288,8 +284,7 @@
   // Write snapshot with true object.
   const Bool& bl = Bool::True();
   std::unique_ptr<Message> message = WriteMessage(
-      /* can_send_any_object */ true, /* same_group */ false, bl, ILLEGAL_PORT,
-      Message::kNormalPriority);
+      /* same_group */ false, bl, ILLEGAL_PORT, Message::kNormalPriority);
 
   // Read object back from the snapshot.
   const Object& serialized_object =
@@ -313,8 +308,7 @@
   // Write snapshot with false object.
   const Bool& bl = Bool::False();
   std::unique_ptr<Message> message = WriteMessage(
-      /* can_send_any_object */ true, /* same_group */ false, bl, ILLEGAL_PORT,
-      Message::kNormalPriority);
+      /* same_group */ false, bl, ILLEGAL_PORT, Message::kNormalPriority);
 
   // Read object back from the snapshot.
   const Object& serialized_object =
@@ -334,8 +328,8 @@
   // Write snapshot with object content.
   const Capability& capability = Capability::Handle(Capability::New(12345));
   std::unique_ptr<Message> message =
-      WriteMessage(/* can_send_any_object */ true, /* same_group */ false,
-                   capability, ILLEGAL_PORT, Message::kNormalPriority);
+      WriteMessage(/* same_group */ false, capability, ILLEGAL_PORT,
+                   Message::kNormalPriority);
 
   // Read object back from the snapshot.
   Capability& obj = Capability::Handle();
@@ -357,8 +351,8 @@
   {                                                                            \
     const Object& before = Object::Handle(object);                             \
     std::unique_ptr<Message> message =                                         \
-        WriteMessage(/* can_send_any_object */ true, /* same_group */ false,   \
-                     before, ILLEGAL_PORT, Message::kNormalPriority);          \
+        WriteMessage(/* same_group */ false, before, ILLEGAL_PORT,             \
+                     Message::kNormalPriority);                                \
     const Object& after = Object::Handle(ReadMessage(thread, message.get()));  \
     EXPECT(before.ptr() == after.ptr());                                       \
   }
@@ -383,9 +377,8 @@
   EXPECT(Utf8::IsValid(reinterpret_cast<const uint8_t*>(cstr), strlen(cstr)));
   // Write snapshot with object content.
   String& str = String::Handle(String::New(cstr));
-  std::unique_ptr<Message> message =
-      WriteMessage(/* can_send_any_object */ true, /* same_group */ false, str,
-                   ILLEGAL_PORT, Message::kNormalPriority);
+  std::unique_ptr<Message> message = WriteMessage(
+      /* same_group */ false, str, ILLEGAL_PORT, Message::kNormalPriority);
 
   // Read object back from the snapshot.
   String& serialized_str = String::Handle();
@@ -424,9 +417,8 @@
     smi ^= Smi::New(i);
     array.SetAt(i, smi);
   }
-  std::unique_ptr<Message> message =
-      WriteMessage(/* can_send_any_object */ true, /* same_group */ false,
-                   array, ILLEGAL_PORT, Message::kNormalPriority);
+  std::unique_ptr<Message> message = WriteMessage(
+      /* same_group */ false, array, ILLEGAL_PORT, Message::kNormalPriority);
 
   // Read object back from the snapshot.
   Array& serialized_array = Array::Handle();
@@ -457,9 +449,8 @@
     smi ^= Smi::New(i);
     array.SetAt(i, smi);
   }
-  std::unique_ptr<Message> message =
-      WriteMessage(/* can_send_any_object */ true, /* same_group */ false,
-                   array, ILLEGAL_PORT, Message::kNormalPriority);
+  std::unique_ptr<Message> message = WriteMessage(
+      /* same_group */ false, array, ILLEGAL_PORT, Message::kNormalPriority);
 
   // Read object back from the snapshot.
   Array& serialized_array = Array::Handle();
@@ -536,9 +527,8 @@
   // Write snapshot with object content.
   const int kArrayLength = 0;
   Array& array = Array::Handle(Array::New(kArrayLength));
-  std::unique_ptr<Message> message =
-      WriteMessage(/* can_send_any_object */ true, /* same_group */ false,
-                   array, ILLEGAL_PORT, Message::kNormalPriority);
+  std::unique_ptr<Message> message = WriteMessage(
+      /* same_group */ false, array, ILLEGAL_PORT, Message::kNormalPriority);
 
   // Read object back from the snapshot.
   Array& serialized_array = Array::Handle();
@@ -563,8 +553,8 @@
     typed_data.SetUint8(i, i);
   }
   std::unique_ptr<Message> message =
-      WriteMessage(/* can_send_any_object */ true, /* same_group */ false,
-                   typed_data, ILLEGAL_PORT, Message::kNormalPriority);
+      WriteMessage(/* same_group */ false, typed_data, ILLEGAL_PORT,
+                   Message::kNormalPriority);
 
   // Read object back from the snapshot.
   TypedData& serialized_typed_data = TypedData::Handle();
@@ -593,8 +583,8 @@
       array.Set##darttype((i * scale), i);                                     \
     }                                                                          \
     std::unique_ptr<Message> message =                                         \
-        WriteMessage(/* can_send_any_object */ true, /* same_group */ false,   \
-                     array, ILLEGAL_PORT, Message::kNormalPriority);           \
+        WriteMessage(/* same_group */ false, array, ILLEGAL_PORT,              \
+                     Message::kNormalPriority);                                \
     TypedData& serialized_array = TypedData::Handle();                         \
     serialized_array ^= ReadMessage(thread, message.get());                    \
     for (int i = 0; i < kArrayLength; i++) {                                   \
@@ -613,8 +603,8 @@
                                reinterpret_cast<uint8_t*>(data), length));     \
     intptr_t scale = array.ElementSizeInBytes();                               \
     std::unique_ptr<Message> message =                                         \
-        WriteMessage(/* can_send_any_object */ true, /* same_group */ false,   \
-                     array, ILLEGAL_PORT, Message::kNormalPriority);           \
+        WriteMessage(/* same_group */ false, array, ILLEGAL_PORT,              \
+                     Message::kNormalPriority);                                \
     ExternalTypedData& serialized_array = ExternalTypedData::Handle();         \
     serialized_array ^= ReadMessage(thread, message.get());                    \
     for (int i = 0; i < length; i++) {                                         \
@@ -655,8 +645,8 @@
   TypedData& typed_data = TypedData::Handle(
       TypedData::New(kTypedDataUint8ArrayCid, kTypedDataLength));
   std::unique_ptr<Message> message =
-      WriteMessage(/* can_send_any_object */ true, /* same_group */ false,
-                   typed_data, ILLEGAL_PORT, Message::kNormalPriority);
+      WriteMessage(/* same_group */ false, typed_data, ILLEGAL_PORT,
+                   Message::kNormalPriority);
 
   // Read object back from the snapshot.
   TypedData& serialized_typed_data = TypedData::Handle();
@@ -772,17 +762,16 @@
   Object& obj = Object::Handle(Api::UnwrapHandle(result));
 
   // Serialize the object into a message.
-  return WriteMessage(/* can_send_any_object */ false, /* same_group */ false,
-                      obj, ILLEGAL_PORT, Message::kNormalPriority);
+  return WriteMessage(/* same_group */ false, obj, ILLEGAL_PORT,
+                      Message::kNormalPriority);
 }
 
 static void CheckString(Dart_Handle dart_string, const char* expected) {
   StackZone zone(Thread::Current());
   String& str = String::Handle();
   str ^= Api::UnwrapHandle(dart_string);
-  std::unique_ptr<Message> message =
-      WriteMessage(/* can_send_any_object */ false, /* same_group */ false, str,
-                   ILLEGAL_PORT, Message::kNormalPriority);
+  std::unique_ptr<Message> message = WriteMessage(
+      /* same_group */ false, str, ILLEGAL_PORT, Message::kNormalPriority);
 
   // Read object back from the snapshot into a C structure.
   ApiNativeScope scope;
@@ -797,9 +786,8 @@
   StackZone zone(Thread::Current());
   String& str = String::Handle();
   str ^= Api::UnwrapHandle(dart_string);
-  std::unique_ptr<Message> message =
-      WriteMessage(/* can_send_any_object */ false, /* same_group */ false, str,
-                   ILLEGAL_PORT, Message::kNormalPriority);
+  std::unique_ptr<Message> message = WriteMessage(
+      /* same_group */ false, str, ILLEGAL_PORT, Message::kNormalPriority);
 
   // Read object back from the snapshot into a C structure.
   ApiNativeScope scope;
@@ -901,9 +889,8 @@
       StackZone zone(thread);
       Smi& smi = Smi::Handle();
       smi ^= Api::UnwrapHandle(smi_result);
-      std::unique_ptr<Message> message =
-          WriteMessage(/* can_send_any_object */ false, /* same_group */ false,
-                       smi, ILLEGAL_PORT, Message::kNormalPriority);
+      std::unique_ptr<Message> message = WriteMessage(
+          /* same_group */ false, smi, ILLEGAL_PORT, Message::kNormalPriority);
 
       // Read object back from the snapshot into a C structure.
       ApiNativeScope scope;