[vm] Prevent reinterpreting object null as a send port capability.
Also ensure that allocated port ids and well-formed object pointers are disjoint.
Bug: https://github.com/dart-lang/sdk/issues/37234
Change-Id: I15328c1ba34f2995089f084e8889b110507c4dbf
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/107223
Commit-Queue: Ryan Macnak <rmacnak@google.com>
Reviewed-by: Siva Annamalai <asiva@google.com>
Reviewed-by: RĂ©gis Crelier <regis@google.com>
diff --git a/runtime/lib/isolate_patch.dart b/runtime/lib/isolate_patch.dart
index 7c28e91..f43d181 100644
--- a/runtime/lib/isolate_patch.dart
+++ b/runtime/lib/isolate_patch.dart
@@ -197,6 +197,10 @@
@pragma("vm:entry-point")
class _SendPortImpl implements SendPort {
+ factory _SendPortImpl._uninstantiable() {
+ throw "Unreachable";
+ }
+
/*--- public interface ---*/
@pragma("vm:entry-point", "call")
void send(var message) {
diff --git a/runtime/vm/port.cc b/runtime/vm/port.cc
index 4ad4340..0b580dd 100644
--- a/runtime/vm/port.cc
+++ b/runtime/vm/port.cc
@@ -4,6 +4,8 @@
#include "vm/port.h"
+#include <utility>
+
#include "platform/utils.h"
#include "vm/dart_api_impl.h"
#include "vm/dart_entry.h"
@@ -82,14 +84,20 @@
}
Dart_Port PortMap::AllocatePort() {
- const Dart_Port kMASK = 0x3fffffff;
- Dart_Port result = prng_->NextUInt32() & kMASK;
+ Dart_Port result;
// Keep getting new values while we have an illegal port number or the port
// number is already in use.
- while ((result == 0) || (FindPort(result) >= 0)) {
- result = prng_->NextUInt32() & kMASK;
- }
+ do {
+ // Ensure port ids are representable in JavaScript for the benefit of
+ // vm-service clients such as Observatory.
+ const Dart_Port kMask1 = 0xFFFFFFFFFFFFF;
+ // Ensure port ids are never valid object pointers so that reinterpreting
+ // an object pointer as a port id never produces a used port id.
+ const Dart_Port kMask2 = 0x3;
+ result = (prng_->NextUInt64() & kMask1) | kMask2;
+ ASSERT(!reinterpret_cast<RawObject*>(result)->IsWellFormed());
+ } while (FindPort(result) >= 0);
ASSERT(result != 0);
ASSERT(FindPort(result) < 0);