Skip to content

Commit 1230062

Browse files
trevnorrisMylesBorins
authored andcommitted
src: no abort from getter if object isn't wrapped
v8::Object::GetAlignedPointerFromInternalField() returns a random value if Wrap() hasn't been run on the object handle. Causing v8 to abort if certain getters are accessed. It's possible to access these getters and functions during class construction through the AsyncWrap init() callback, and also possible in a subset of those scenarios while running the persistent handle visitor. Mitigate this issue by manually setting the internal aligned pointer field to nullptr in the BaseObject constructor and add necessary logic to return appropriate values when nullptr is encountered. PR-URL: #6184 Reviewed-By: Ben Noordhuis <[email protected]> Reviewed-By: Anna Henningsen <[email protected]>
1 parent 19d6f06 commit 1230062

23 files changed

+446
-175
lines changed

src/base-object-inl.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ inline BaseObject::BaseObject(Environment* env, v8::Local<v8::Object> handle)
1414
: handle_(env->isolate(), handle),
1515
env_(env) {
1616
CHECK_EQ(false, handle.IsEmpty());
17+
// The zero field holds a pointer to the handle. Immediately set it to
18+
// nullptr in case it's accessed by the user before construction is complete.
19+
if (handle->InternalFieldCount() > 0)
20+
handle->SetAlignedPointerInInternalField(0, nullptr);
1721
}
1822

1923

src/fs_event_wrap.cc

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,8 @@ void FSEventWrap::New(const FunctionCallbackInfo<Value>& args) {
8484
void FSEventWrap::Start(const FunctionCallbackInfo<Value>& args) {
8585
Environment* env = Environment::GetCurrent(args);
8686

87-
FSEventWrap* wrap = Unwrap<FSEventWrap>(args.Holder());
88-
CHECK_EQ(wrap->initialized_, false);
87+
FSEventWrap* wrap;
88+
ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
8989

9090
if (args.Length() < 1 || !args[0]->IsString()) {
9191
return env->ThrowTypeError("filename must be a valid string");
@@ -165,7 +165,8 @@ void FSEventWrap::OnEvent(uv_fs_event_t* handle, const char* filename,
165165

166166

167167
void FSEventWrap::Close(const FunctionCallbackInfo<Value>& args) {
168-
FSEventWrap* wrap = Unwrap<FSEventWrap>(args.Holder());
168+
FSEventWrap* wrap;
169+
ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
169170

170171
if (wrap == nullptr || wrap->initialized_ == false)
171172
return;

src/handle_wrap.cc

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ using v8::Value;
1818

1919

2020
void HandleWrap::Ref(const FunctionCallbackInfo<Value>& args) {
21-
HandleWrap* wrap = Unwrap<HandleWrap>(args.Holder());
21+
HandleWrap* wrap;
22+
ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
2223

2324
if (IsAlive(wrap)) {
2425
uv_ref(wrap->handle__);
@@ -28,7 +29,8 @@ void HandleWrap::Ref(const FunctionCallbackInfo<Value>& args) {
2829

2930

3031
void HandleWrap::Unref(const FunctionCallbackInfo<Value>& args) {
31-
HandleWrap* wrap = Unwrap<HandleWrap>(args.Holder());
32+
HandleWrap* wrap;
33+
ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
3234

3335
if (IsAlive(wrap)) {
3436
uv_unref(wrap->handle__);
@@ -40,7 +42,8 @@ void HandleWrap::Unref(const FunctionCallbackInfo<Value>& args) {
4042
void HandleWrap::Close(const FunctionCallbackInfo<Value>& args) {
4143
Environment* env = Environment::GetCurrent(args);
4244

43-
HandleWrap* wrap = Unwrap<HandleWrap>(args.Holder());
45+
HandleWrap* wrap;
46+
ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
4447

4548
// guard against uninitialized handle or double close
4649
if (!IsAlive(wrap))

src/js_stream.cc

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,8 @@ static void FreeCallback(char* data, void* hint) {
135135

136136

137137
void JSStream::DoAlloc(const FunctionCallbackInfo<Value>& args) {
138-
JSStream* wrap = Unwrap<JSStream>(args.Holder());
138+
JSStream* wrap;
139+
ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
139140

140141
uv_buf_t buf;
141142
wrap->OnAlloc(args[0]->Int32Value(), &buf);
@@ -150,7 +151,8 @@ void JSStream::DoAlloc(const FunctionCallbackInfo<Value>& args) {
150151

151152

152153
void JSStream::DoRead(const FunctionCallbackInfo<Value>& args) {
153-
JSStream* wrap = Unwrap<JSStream>(args.Holder());
154+
JSStream* wrap;
155+
ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
154156

155157
CHECK(Buffer::HasInstance(args[1]));
156158
uv_buf_t buf = uv_buf_init(Buffer::Data(args[1]), Buffer::Length(args[1]));
@@ -159,23 +161,29 @@ void JSStream::DoRead(const FunctionCallbackInfo<Value>& args) {
159161

160162

161163
void JSStream::DoAfterWrite(const FunctionCallbackInfo<Value>& args) {
162-
JSStream* wrap = Unwrap<JSStream>(args.Holder());
163-
WriteWrap* w = Unwrap<WriteWrap>(args[0].As<Object>());
164+
JSStream* wrap;
165+
CHECK(args[0]->IsObject());
166+
WriteWrap* w;
167+
ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
168+
ASSIGN_OR_RETURN_UNWRAP(&w, args[0].As<Object>());
164169

165170
wrap->OnAfterWrite(w);
166171
}
167172

168173

169174
template <class Wrap>
170175
void JSStream::Finish(const FunctionCallbackInfo<Value>& args) {
171-
Wrap* w = Unwrap<Wrap>(args[0].As<Object>());
176+
Wrap* w;
177+
CHECK(args[0]->IsObject());
178+
ASSIGN_OR_RETURN_UNWRAP(&w, args[0].As<Object>());
172179

173180
w->Done(args[1]->Int32Value());
174181
}
175182

176183

177184
void JSStream::ReadBuffer(const FunctionCallbackInfo<Value>& args) {
178-
JSStream* wrap = Unwrap<JSStream>(args.Holder());
185+
JSStream* wrap;
186+
ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
179187

180188
CHECK(Buffer::HasInstance(args[0]));
181189
char* data = Buffer::Data(args[0]);
@@ -197,7 +205,8 @@ void JSStream::ReadBuffer(const FunctionCallbackInfo<Value>& args) {
197205

198206

199207
void JSStream::EmitEOF(const FunctionCallbackInfo<Value>& args) {
200-
JSStream* wrap = Unwrap<JSStream>(args.Holder());
208+
JSStream* wrap;
209+
ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
201210

202211
wrap->OnRead(UV_EOF, nullptr);
203212
}

src/node_contextify.cc

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -340,8 +340,8 @@ class ContextifyContext {
340340
static void GlobalPropertyGetterCallback(
341341
Local<Name> property,
342342
const PropertyCallbackInfo<Value>& args) {
343-
ContextifyContext* ctx =
344-
Unwrap<ContextifyContext>(args.Data().As<Object>());
343+
ContextifyContext* ctx;
344+
ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Data().As<Object>());
345345

346346
// Stil initializing
347347
if (ctx->context_.IsEmpty())
@@ -370,8 +370,8 @@ class ContextifyContext {
370370
Local<Name> property,
371371
Local<Value> value,
372372
const PropertyCallbackInfo<Value>& args) {
373-
ContextifyContext* ctx =
374-
Unwrap<ContextifyContext>(args.Data().As<Object>());
373+
ContextifyContext* ctx;
374+
ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Data().As<Object>());
375375

376376
// Stil initializing
377377
if (ctx->context_.IsEmpty())
@@ -384,8 +384,8 @@ class ContextifyContext {
384384
static void GlobalPropertyQueryCallback(
385385
Local<Name> property,
386386
const PropertyCallbackInfo<Integer>& args) {
387-
ContextifyContext* ctx =
388-
Unwrap<ContextifyContext>(args.Data().As<Object>());
387+
ContextifyContext* ctx;
388+
ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Data().As<Object>());
389389

390390
// Stil initializing
391391
if (ctx->context_.IsEmpty())
@@ -411,8 +411,8 @@ class ContextifyContext {
411411
static void GlobalPropertyDeleterCallback(
412412
Local<Name> property,
413413
const PropertyCallbackInfo<Boolean>& args) {
414-
ContextifyContext* ctx =
415-
Unwrap<ContextifyContext>(args.Data().As<Object>());
414+
ContextifyContext* ctx;
415+
ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Data().As<Object>());
416416

417417
// Stil initializing
418418
if (ctx->context_.IsEmpty())
@@ -427,8 +427,8 @@ class ContextifyContext {
427427

428428
static void GlobalPropertyEnumeratorCallback(
429429
const PropertyCallbackInfo<Array>& args) {
430-
ContextifyContext* ctx =
431-
Unwrap<ContextifyContext>(args.Data().As<Object>());
430+
ContextifyContext* ctx;
431+
ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Data().As<Object>());
432432

433433
// Stil initializing
434434
if (ctx->context_.IsEmpty())
@@ -690,7 +690,8 @@ class ContextifyScript : public BaseObject {
690690
return false;
691691
}
692692

693-
ContextifyScript* wrapped_script = Unwrap<ContextifyScript>(args.Holder());
693+
ContextifyScript* wrapped_script;
694+
ASSIGN_OR_RETURN_UNWRAP(&wrapped_script, args.Holder(), false);
694695
Local<UnboundScript> unbound_script =
695696
PersistentToLocal(env->isolate(), wrapped_script->script_);
696697
Local<Script> script = unbound_script->BindToCurrentContext();

0 commit comments

Comments
 (0)