[ VM ] Ensure randomly generated IDs are valid JS integers

Fixes https://github.com/dart-lang/sdk/issues/53081

TEST=Service tests

Change-Id: I0aaf3843c3a186336f5b2a8ee1e9356dd19251b8
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/317460
Reviewed-by: Derek Xu <derekx@google.com>
Commit-Queue: Ben Konyi <bkonyi@google.com>
This commit is contained in:
Ben Konyi 2023-08-01 15:50:11 +00:00 committed by Commit Queue
parent dc2abf0a80
commit 1f7384beb8
4 changed files with 33 additions and 8 deletions

View file

@ -34,7 +34,11 @@ namespace dart {
DEFINE_NATIVE_ENTRY(Capability_factory, 0, 1) {
ASSERT(
TypeArguments::CheckedHandle(zone, arguments->NativeArgAt(0)).IsNull());
uint64_t id = isolate->random()->NextUInt64();
// Keep capability IDs less than 2^53 so web clients of the service
// protocol can process it properly.
//
// See https://github.com/dart-lang/sdk/issues/53081.
uint64_t id = isolate->random()->NextJSInt();
return Capability::New(id);
}

View file

@ -393,7 +393,11 @@ IsolateGroup::IsolateGroup(std::shared_ptr<IsolateGroupSource> source,
}
{
WriteRwLocker wl(ThreadState::Current(), isolate_groups_rwlock_);
id_ = isolate_group_random_->NextUInt64();
// Keep isolate IDs less than 2^53 so web clients of the service
// protocol can process it properly.
//
// See https://github.com/dart-lang/sdk/issues/53081.
id_ = isolate_group_random_->NextJSInt();
}
heap_walk_class_table_ = class_table_ =
new ClassTable(&class_table_allocator_);
@ -1789,8 +1793,13 @@ Isolate* Isolate::InitIsolate(const char* name_prefix,
Isolate::VisitIsolates(&id_verifier);
#endif
result->set_origin_id(result->main_port());
result->set_pause_capability(result->random()->NextUInt64());
result->set_terminate_capability(result->random()->NextUInt64());
// Keep capability IDs less than 2^53 so web clients of the service
// protocol can process it properly.
//
// See https://github.com/dart-lang/sdk/issues/53081.
result->set_pause_capability(result->random()->NextJSInt());
result->set_terminate_capability(result->random()->NextJSInt());
#if !defined(PRODUCT)
result->debugger_ = new Debugger(result);

View file

@ -46,13 +46,13 @@ Dart_Port PortMap::AllocatePort() {
// Keep getting new values while we have an illegal port number or the port
// number is already in use.
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;
// Ensure port ids are representable in JavaScript for the benefit of
// vm-service clients such as Observatory.
result = prng_->NextJSInt() | kMask2;
// The two special marker ports are used for the hashset implementation and
// cannot be used as actual ports.

View file

@ -28,6 +28,18 @@ class Random {
static_cast<uint64_t>(NextUInt32());
}
// Returns a random number that's a valid JS integer.
//
// All IDs that can be returned over the service protocol should be
// representable as JS integers and should be generated using this method.
//
// See https://github.com/dart-lang/sdk/issues/53081.
uint64_t NextJSInt() {
// Number.MAX_SAFE_INTEGER (2 ^ 53 - 1)
const uint64_t kMaxJsInt = 0x1FFFFFFFFFFFFF;
return NextUInt64() & kMaxJsInt;
}
static uint64_t GlobalNextUInt64();
static void Init();
static void Cleanup();