mirror of
https://github.com/nodejs/node.git
synced 2026-11-09 15:11:11 -05:00
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: https://github.com/nodejs/node/pull/6184 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Anna Henningsen <anna@addaleax.net>
119 lines
3.1 KiB
C++
119 lines
3.1 KiB
C++
#include "node_stat_watcher.h"
|
|
#include "async-wrap.h"
|
|
#include "async-wrap-inl.h"
|
|
#include "env.h"
|
|
#include "env-inl.h"
|
|
#include "util.h"
|
|
#include "util-inl.h"
|
|
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
|
|
namespace node {
|
|
|
|
using v8::Context;
|
|
using v8::FunctionCallbackInfo;
|
|
using v8::FunctionTemplate;
|
|
using v8::HandleScope;
|
|
using v8::Integer;
|
|
using v8::Local;
|
|
using v8::Object;
|
|
using v8::Value;
|
|
|
|
|
|
void StatWatcher::Initialize(Environment* env, Local<Object> target) {
|
|
HandleScope scope(env->isolate());
|
|
|
|
Local<FunctionTemplate> t = env->NewFunctionTemplate(StatWatcher::New);
|
|
t->InstanceTemplate()->SetInternalFieldCount(1);
|
|
t->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "StatWatcher"));
|
|
|
|
env->SetProtoMethod(t, "start", StatWatcher::Start);
|
|
env->SetProtoMethod(t, "stop", StatWatcher::Stop);
|
|
|
|
target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "StatWatcher"),
|
|
t->GetFunction());
|
|
}
|
|
|
|
|
|
static void Delete(uv_handle_t* handle) {
|
|
delete reinterpret_cast<uv_fs_poll_t*>(handle);
|
|
}
|
|
|
|
|
|
StatWatcher::StatWatcher(Environment* env, Local<Object> wrap)
|
|
: AsyncWrap(env, wrap, AsyncWrap::PROVIDER_STATWATCHER),
|
|
watcher_(new uv_fs_poll_t) {
|
|
MakeWeak<StatWatcher>(this);
|
|
uv_fs_poll_init(env->event_loop(), watcher_);
|
|
watcher_->data = static_cast<void*>(this);
|
|
}
|
|
|
|
|
|
StatWatcher::~StatWatcher() {
|
|
Stop();
|
|
uv_close(reinterpret_cast<uv_handle_t*>(watcher_), Delete);
|
|
}
|
|
|
|
|
|
void StatWatcher::Callback(uv_fs_poll_t* handle,
|
|
int status,
|
|
const uv_stat_t* prev,
|
|
const uv_stat_t* curr) {
|
|
StatWatcher* wrap = static_cast<StatWatcher*>(handle->data);
|
|
CHECK_EQ(wrap->watcher_, handle);
|
|
Environment* env = wrap->env();
|
|
HandleScope handle_scope(env->isolate());
|
|
Context::Scope context_scope(env->context());
|
|
Local<Value> argv[] = {
|
|
BuildStatsObject(env, curr),
|
|
BuildStatsObject(env, prev),
|
|
Integer::New(env->isolate(), status)
|
|
};
|
|
wrap->MakeCallback(env->onchange_string(), arraysize(argv), argv);
|
|
}
|
|
|
|
|
|
void StatWatcher::New(const FunctionCallbackInfo<Value>& args) {
|
|
CHECK(args.IsConstructCall());
|
|
Environment* env = Environment::GetCurrent(args);
|
|
new StatWatcher(env, args.This());
|
|
}
|
|
|
|
|
|
void StatWatcher::Start(const FunctionCallbackInfo<Value>& args) {
|
|
CHECK_EQ(args.Length(), 3);
|
|
|
|
StatWatcher* wrap;
|
|
ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
|
|
node::Utf8Value path(args.GetIsolate(), args[0]);
|
|
const bool persistent = args[1]->BooleanValue();
|
|
const uint32_t interval = args[2]->Uint32Value();
|
|
|
|
if (!persistent)
|
|
uv_unref(reinterpret_cast<uv_handle_t*>(wrap->watcher_));
|
|
uv_fs_poll_start(wrap->watcher_, Callback, *path, interval);
|
|
wrap->ClearWeak();
|
|
}
|
|
|
|
|
|
void StatWatcher::Stop(const FunctionCallbackInfo<Value>& args) {
|
|
StatWatcher* wrap;
|
|
ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
|
|
Environment* env = wrap->env();
|
|
Context::Scope context_scope(env->context());
|
|
wrap->MakeCallback(env->onstop_string(), 0, nullptr);
|
|
wrap->Stop();
|
|
}
|
|
|
|
|
|
void StatWatcher::Stop() {
|
|
if (!uv_is_active(reinterpret_cast<uv_handle_t*>(watcher_)))
|
|
return;
|
|
uv_fs_poll_stop(watcher_);
|
|
MakeWeak<StatWatcher>(this);
|
|
}
|
|
|
|
|
|
} // namespace node
|