Browse Source

fs: fix use after free in stat watcher

The uv_fs_poll_t handle was stopped but not closed, leaving libuv's internal
handle queue in a corrupted state.
v0.8.8-release
Ben Noordhuis 13 years ago
parent
commit
b1ffbdc975
  1. 34
      src/node_stat_watcher.cc
  2. 11
      src/node_stat_watcher.h

34
src/node_stat_watcher.cc

@ -49,19 +49,39 @@ void StatWatcher::Initialize(Handle<Object> target) {
} }
static void Delete(uv_handle_t* handle) {
delete reinterpret_cast<uv_fs_poll_t*>(handle);
}
StatWatcher::StatWatcher()
: ObjectWrap()
, watcher_(new uv_fs_poll_t)
{
uv_fs_poll_init(uv_default_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, void StatWatcher::Callback(uv_fs_poll_t* handle,
int status, int status,
const uv_statbuf_t* prev, const uv_statbuf_t* prev,
const uv_statbuf_t* curr) { const uv_statbuf_t* curr) {
StatWatcher* wrap = container_of(handle, StatWatcher, watcher_); StatWatcher* wrap = static_cast<StatWatcher*>(handle->data);
assert(handle == &wrap->watcher_); assert(wrap->watcher_ == handle);
HandleScope scope; HandleScope scope;
Local<Value> argv[3]; Local<Value> argv[3];
argv[0] = BuildStatsObject(curr); argv[0] = BuildStatsObject(curr);
argv[1] = BuildStatsObject(prev); argv[1] = BuildStatsObject(prev);
argv[2] = Integer::New(status); argv[2] = Integer::New(status);
if (status == -1) { if (status == -1) {
SetErrno(uv_last_error(wrap->watcher_.loop)); SetErrno(uv_last_error(wrap->watcher_->loop));
} }
if (onchange_sym.IsEmpty()) { if (onchange_sym.IsEmpty()) {
onchange_sym = NODE_PSYMBOL("onchange"); onchange_sym = NODE_PSYMBOL("onchange");
@ -88,8 +108,8 @@ Handle<Value> StatWatcher::Start(const Arguments& args) {
const bool persistent = args[1]->BooleanValue(); const bool persistent = args[1]->BooleanValue();
const uint32_t interval = args[2]->Uint32Value(); const uint32_t interval = args[2]->Uint32Value();
if (!persistent) uv_unref(reinterpret_cast<uv_handle_t*>(&wrap->watcher_)); if (!persistent) uv_unref(reinterpret_cast<uv_handle_t*>(wrap->watcher_));
uv_fs_poll_start(&wrap->watcher_, Callback, *path, interval); uv_fs_poll_start(wrap->watcher_, Callback, *path, interval);
wrap->Ref(); wrap->Ref();
return Undefined(); return Undefined();
@ -109,8 +129,8 @@ Handle<Value> StatWatcher::Stop(const Arguments& args) {
void StatWatcher::Stop () { void StatWatcher::Stop () {
if (!uv_is_active(reinterpret_cast<uv_handle_t*>(&watcher_))) return; if (!uv_is_active(reinterpret_cast<uv_handle_t*>(watcher_))) return;
uv_fs_poll_stop(&watcher_); uv_fs_poll_stop(watcher_);
Unref(); Unref();
} }

11
src/node_stat_watcher.h

@ -34,13 +34,8 @@ class StatWatcher : ObjectWrap {
protected: protected:
static v8::Persistent<v8::FunctionTemplate> constructor_template; static v8::Persistent<v8::FunctionTemplate> constructor_template;
StatWatcher() : ObjectWrap() { StatWatcher();
uv_fs_poll_init(uv_default_loop(), &watcher_); virtual ~StatWatcher();
}
~StatWatcher() {
Stop();
}
static v8::Handle<v8::Value> New(const v8::Arguments& args); static v8::Handle<v8::Value> New(const v8::Arguments& args);
static v8::Handle<v8::Value> Start(const v8::Arguments& args); static v8::Handle<v8::Value> Start(const v8::Arguments& args);
@ -53,7 +48,7 @@ class StatWatcher : ObjectWrap {
const uv_statbuf_t* curr); const uv_statbuf_t* curr);
void Stop(); void Stop();
uv_fs_poll_t watcher_; uv_fs_poll_t* watcher_;
}; };
} // namespace node } // namespace node

Loading…
Cancel
Save