Skip to content

Commit f054c33

Browse files
kvakilUlisesGascon
authored andcommitted
src: add IsolateScopes before using isolates
The V8 API requires entering an isolate before using it. We were often not doing this, which worked fine in practice. However when (multi-cage) pointer compression is enabled, the correct isolate needs to be active in order to decompress pointers correctly, otherwise it causes crashes. Fix this by sprinkling in some calls to v8::Isolate::Scope::Scope where they were missing. This also introduces RAIIIsolateWithoutEntering which is used in JSONParser to avoid otherwise exposing the Isolate::Scope outside of the class. Tested by compiling with `--experimental-enable-pointer-compression` locally and running all tests. Refs: nodejs/build#3204 (comment) Refs: https://bugs.chromium.org/p/v8/issues/detail?id=14292 PR-URL: #50680 Refs: v8/v8@475c8cd Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Darshan Sen <raisinten@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
1 parent e22ce95 commit f054c33

File tree

7 files changed

+41
-7
lines changed

7 files changed

+41
-7
lines changed

src/api/environment.cc

+7
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,8 @@ void SetIsolateMiscHandlers(v8::Isolate* isolate, const IsolateSettings& s) {
313313

314314
void SetIsolateUpForNode(v8::Isolate* isolate,
315315
const IsolateSettings& settings) {
316+
Isolate::Scope isolate_scope(isolate);
317+
316318
SetIsolateErrorHandlers(isolate, settings);
317319
SetIsolateMiscHandlers(isolate, settings);
318320
}
@@ -354,6 +356,9 @@ Isolate* NewIsolate(Isolate::CreateParams* params,
354356

355357
SetIsolateCreateParamsForNode(params);
356358
Isolate::Initialize(isolate, *params);
359+
360+
Isolate::Scope isolate_scope(isolate);
361+
357362
if (snapshot_data == nullptr) {
358363
// If in deserialize mode, delay until after the deserialization is
359364
// complete.
@@ -428,6 +433,8 @@ Environment* CreateEnvironment(
428433
ThreadId thread_id,
429434
std::unique_ptr<InspectorParentHandle> inspector_parent_handle) {
430435
Isolate* isolate = isolate_data->isolate();
436+
437+
Isolate::Scope isolate_scope(isolate);
431438
HandleScope handle_scope(isolate);
432439

433440
const bool use_snapshot = context.IsEmpty();

src/env.cc

+3
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,8 @@ IsolateDataSerializeInfo IsolateData::Serialize(SnapshotCreator* creator) {
349349

350350
void IsolateData::DeserializeProperties(const IsolateDataSerializeInfo* info) {
351351
size_t i = 0;
352+
353+
v8::Isolate::Scope isolate_scope(isolate_);
352354
HandleScope handle_scope(isolate_);
353355

354356
if (per_process::enabled_debug_list.enabled(DebugCategory::MKSNAPSHOT)) {
@@ -431,6 +433,7 @@ void IsolateData::CreateProperties() {
431433
// One byte because our strings are ASCII and we can safely skip V8's UTF-8
432434
// decoding step.
433435

436+
v8::Isolate::Scope isolate_scope(isolate_);
434437
HandleScope handle_scope(isolate_);
435438

436439
#define V(PropertyName, StringValue) \

src/json_parser.cc

+3
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ bool JSONParser::Parse(const std::string& content) {
1717
DCHECK(!parsed_);
1818

1919
Isolate* isolate = isolate_.get();
20+
v8::Isolate::Scope isolate_scope(isolate);
2021
v8::HandleScope handle_scope(isolate);
2122

2223
Local<Context> context = Context::New(isolate);
@@ -45,6 +46,7 @@ bool JSONParser::Parse(const std::string& content) {
4546
std::optional<std::string> JSONParser::GetTopLevelStringField(
4647
std::string_view field) {
4748
Isolate* isolate = isolate_.get();
49+
v8::Isolate::Scope isolate_scope(isolate);
4850
v8::HandleScope handle_scope(isolate);
4951

5052
Local<Context> context = context_.Get(isolate);
@@ -70,6 +72,7 @@ std::optional<std::string> JSONParser::GetTopLevelStringField(
7072

7173
std::optional<bool> JSONParser::GetTopLevelBoolField(std::string_view field) {
7274
Isolate* isolate = isolate_.get();
75+
v8::Isolate::Scope isolate_scope(isolate);
7376
v8::HandleScope handle_scope(isolate);
7477

7578
Local<Context> context = context_.Get(isolate);

src/json_parser.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class JSONParser {
2424
private:
2525
// We might want a lighter-weight JSON parser for this use case. But for now
2626
// using V8 is good enough.
27-
RAIIIsolate isolate_;
27+
RAIIIsolateWithoutEntering isolate_;
2828

2929
v8::Global<v8::Context> context_;
3030
v8::Global<v8::Object> content_;

src/node_sea.cc

+2
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,9 @@ std::optional<std::string> GenerateCodeCache(std::string_view main_path,
414414
RAIIIsolate raii_isolate(SnapshotBuilder::GetEmbeddedSnapshotData());
415415
Isolate* isolate = raii_isolate.get();
416416

417+
v8::Isolate::Scope isolate_scope(isolate);
417418
HandleScope handle_scope(isolate);
419+
418420
Local<Context> context = Context::New(isolate);
419421
Context::Scope context_scope(context);
420422

src/util.cc

+7-2
Original file line numberDiff line numberDiff line change
@@ -678,7 +678,7 @@ Local<String> UnionBytes::ToStringChecked(Isolate* isolate) const {
678678
}
679679
}
680680

681-
RAIIIsolate::RAIIIsolate(const SnapshotData* data)
681+
RAIIIsolateWithoutEntering::RAIIIsolateWithoutEntering(const SnapshotData* data)
682682
: allocator_{ArrayBuffer::Allocator::NewDefaultAllocator()} {
683683
isolate_ = Isolate::Allocate();
684684
CHECK_NOT_NULL(isolate_);
@@ -692,9 +692,14 @@ RAIIIsolate::RAIIIsolate(const SnapshotData* data)
692692
Isolate::Initialize(isolate_, params);
693693
}
694694

695-
RAIIIsolate::~RAIIIsolate() {
695+
RAIIIsolateWithoutEntering::~RAIIIsolateWithoutEntering() {
696696
per_process::v8_platform.Platform()->UnregisterIsolate(isolate_);
697697
isolate_->Dispose();
698698
}
699699

700+
RAIIIsolate::RAIIIsolate(const SnapshotData* data)
701+
: isolate_{data}, isolate_scope_{isolate_.get()} {}
702+
703+
RAIIIsolate::~RAIIIsolate() {}
704+
700705
} // namespace node

src/util.h

+18-4
Original file line numberDiff line numberDiff line change
@@ -969,11 +969,11 @@ void SetConstructorFunction(v8::Isolate* isolate,
969969
SetConstructorFunctionFlag flag =
970970
SetConstructorFunctionFlag::SET_CLASS_NAME);
971971

972-
// Simple RAII class to spin up a v8::Isolate instance.
973-
class RAIIIsolate {
972+
// Like RAIIIsolate, except doesn't enter the isolate while it's in scope.
973+
class RAIIIsolateWithoutEntering {
974974
public:
975-
explicit RAIIIsolate(const SnapshotData* data = nullptr);
976-
~RAIIIsolate();
975+
explicit RAIIIsolateWithoutEntering(const SnapshotData* data = nullptr);
976+
~RAIIIsolateWithoutEntering();
977977

978978
v8::Isolate* get() const { return isolate_; }
979979

@@ -982,6 +982,20 @@ class RAIIIsolate {
982982
v8::Isolate* isolate_;
983983
};
984984

985+
// Simple RAII class to spin up a v8::Isolate instance and enter it
986+
// immediately.
987+
class RAIIIsolate {
988+
public:
989+
explicit RAIIIsolate(const SnapshotData* data = nullptr);
990+
~RAIIIsolate();
991+
992+
v8::Isolate* get() const { return isolate_.get(); }
993+
994+
private:
995+
RAIIIsolateWithoutEntering isolate_;
996+
v8::Isolate::Scope isolate_scope_;
997+
};
998+
985999
} // namespace node
9861000

9871001
#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS

0 commit comments

Comments
 (0)