Skip to content

Commit 39b8730

Browse files
trevnorrisrvagg
authored andcommitted
async_wrap: ensure all objects have internal field
If the constructor can't assign a class id then the heap snapshot will not be able to report the object. So ensure that all AsyncWrap instances use a FunctionTemplate instance with an internal field count >= 1. PR-URL: #3139 Reviewed-By: Fedor Indutny <[email protected]> Reviewed-By: Ben Noordhuis <[email protected]> Reviewed-by: Stephen Belanger <[email protected]>
1 parent 99e6607 commit 39b8730

File tree

6 files changed

+43
-12
lines changed

6 files changed

+43
-12
lines changed

lib/dns.js

+6-6
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ const uv = process.binding('uv');
88

99
const GetAddrInfoReqWrap = cares.GetAddrInfoReqWrap;
1010
const GetNameInfoReqWrap = cares.GetNameInfoReqWrap;
11+
const QueryReqWrap = cares.QueryReqWrap;
1112

1213
const isIp = net.isIP;
1314

@@ -223,12 +224,11 @@ function resolver(bindingName) {
223224
}
224225

225226
callback = makeAsync(callback);
226-
var req = {
227-
bindingName: bindingName,
228-
callback: callback,
229-
hostname: name,
230-
oncomplete: onresolve
231-
};
227+
var req = new QueryReqWrap();
228+
req.bindingName = bindingName;
229+
req.callback = callback;
230+
req.hostname = name;
231+
req.oncomplete = onresolve;
232232
var err = binding(req, name);
233233
if (err) throw errnoException(err, bindingName);
234234
callback.immediately = true;

src/async-wrap-inl.h

+5-4
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,11 @@ inline AsyncWrap::AsyncWrap(Environment* env,
1818
ProviderType provider,
1919
AsyncWrap* parent)
2020
: BaseObject(env, object), bits_(static_cast<uint32_t>(provider) << 1) {
21-
// Only set wrapper class id if object will be Wrap'd.
22-
if (object->InternalFieldCount() > 0)
23-
// Shift provider value over to prevent id collision.
24-
persistent().SetWrapperClassId(NODE_ASYNC_ID_OFFSET + provider);
21+
CHECK_NE(provider, PROVIDER_NONE);
22+
CHECK_GE(object->InternalFieldCount(), 1);
23+
24+
// Shift provider value over to prevent id collision.
25+
persistent().SetWrapperClassId(NODE_ASYNC_ID_OFFSET + provider);
2526

2627
// Check user controlled flag to see if the init callback should run.
2728
if (!env->using_asyncwrap())

src/cares_wrap.cc

+13
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,11 @@ static void NewGetNameInfoReqWrap(const FunctionCallbackInfo<Value>& args) {
8585
}
8686

8787

88+
static void NewQueryReqWrap(const FunctionCallbackInfo<Value>& args) {
89+
CHECK(args.IsConstructCall());
90+
}
91+
92+
8893
static int cmp_ares_tasks(const ares_task_t* a, const ares_task_t* b) {
8994
if (a->sock < b->sock)
9095
return -1;
@@ -1312,6 +1317,14 @@ static void Initialize(Local<Object> target,
13121317
FIXED_ONE_BYTE_STRING(env->isolate(), "GetNameInfoReqWrap"));
13131318
target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "GetNameInfoReqWrap"),
13141319
niw->GetFunction());
1320+
1321+
Local<FunctionTemplate> qrw =
1322+
FunctionTemplate::New(env->isolate(), NewQueryReqWrap);
1323+
qrw->InstanceTemplate()->SetInternalFieldCount(1);
1324+
qrw->SetClassName(
1325+
FIXED_ONE_BYTE_STRING(env->isolate(), "QueryReqWrap"));
1326+
target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "QueryReqWrap"),
1327+
qrw->GetFunction());
13151328
}
13161329

13171330
} // namespace cares_wrap

src/env-inl.h

+13
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,13 @@ inline Environment::Environment(v8::Local<v8::Context> context,
221221
set_as_external(v8::External::New(isolate(), this));
222222
set_binding_cache_object(v8::Object::New(isolate()));
223223
set_module_load_list_array(v8::Array::New(isolate()));
224+
225+
v8::Local<v8::FunctionTemplate> fn = v8::FunctionTemplate::New(isolate());
226+
fn->SetClassName(FIXED_ONE_BYTE_STRING(isolate(), "InternalFieldObject"));
227+
v8::Local<v8::ObjectTemplate> obj = fn->InstanceTemplate();
228+
obj->SetInternalFieldCount(1);
229+
set_generic_internal_field_template(obj);
230+
224231
RB_INIT(&cares_task_list_);
225232
handle_cleanup_waiting_ = 0;
226233
}
@@ -513,6 +520,12 @@ inline void Environment::SetTemplateMethod(v8::Local<v8::FunctionTemplate> that,
513520
function->SetName(name_string); // NODE_SET_METHOD() compatibility.
514521
}
515522

523+
inline v8::Local<v8::Object> Environment::NewInternalFieldObject() {
524+
v8::MaybeLocal<v8::Object> m_obj =
525+
generic_internal_field_template()->NewInstance(context());
526+
return m_obj.ToLocalChecked();
527+
}
528+
516529
#define V(PropertyName, StringValue) \
517530
inline \
518531
v8::Local<v8::String> Environment::IsolateData::PropertyName() const { \

src/env.h

+2
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,7 @@ namespace node {
237237
V(context, v8::Context) \
238238
V(domain_array, v8::Array) \
239239
V(fs_stats_constructor_function, v8::Function) \
240+
V(generic_internal_field_template, v8::ObjectTemplate) \
240241
V(jsstream_constructor_template, v8::FunctionTemplate) \
241242
V(module_load_list_array, v8::Array) \
242243
V(pipe_constructor_template, v8::FunctionTemplate) \
@@ -488,6 +489,7 @@ class Environment {
488489
const char* name,
489490
v8::FunctionCallback callback);
490491

492+
inline v8::Local<v8::Object> NewInternalFieldObject();
491493

492494
// Strings are shared across shared contexts. The getters simply proxy to
493495
// the per-isolate primitive.

src/node_crypto.cc

+4-2
Original file line numberDiff line numberDiff line change
@@ -4624,6 +4624,7 @@ class PBKDF2Request : public AsyncWrap {
46244624
iter_(iter) {
46254625
if (key() == nullptr)
46264626
FatalError("node::PBKDF2Request()", "Out of Memory");
4627+
Wrap(object, this);
46274628
}
46284629

46294630
~PBKDF2Request() override {
@@ -4833,7 +4834,7 @@ void PBKDF2(const FunctionCallbackInfo<Value>& args) {
48334834
digest = EVP_sha1();
48344835
}
48354836

4836-
obj = Object::New(env->isolate());
4837+
obj = env->NewInternalFieldObject();
48374838
req = new PBKDF2Request(env,
48384839
obj,
48394840
digest,
@@ -4885,6 +4886,7 @@ class RandomBytesRequest : public AsyncWrap {
48854886
data_(static_cast<char*>(malloc(size))) {
48864887
if (data() == nullptr)
48874888
FatalError("node::RandomBytesRequest()", "Out of Memory");
4889+
Wrap(object, this);
48884890
}
48894891

48904892
~RandomBytesRequest() override {
@@ -5001,7 +5003,7 @@ void RandomBytes(const FunctionCallbackInfo<Value>& args) {
50015003
if (size < 0 || size > Buffer::kMaxLength)
50025004
return env->ThrowRangeError("size is not a valid Smi");
50035005

5004-
Local<Object> obj = Object::New(env->isolate());
5006+
Local<Object> obj = env->NewInternalFieldObject();
50055007
RandomBytesRequest* req = new RandomBytesRequest(env, obj, size);
50065008

50075009
if (args[1]->IsFunction()) {

0 commit comments

Comments
 (0)