diff options
author | Ben Noordhuis <info@bnoordhuis.nl> | 2012-08-20 12:52:26 +0200 |
---|---|---|
committer | Ben Noordhuis <info@bnoordhuis.nl> | 2012-08-20 17:29:58 +0200 |
commit | b1ffbdc975d58b31e3b13749c29fdc07049ea1d9 (patch) | |
tree | 6eec1adc71a3b7fea9c34d72221d27d7ce4eb82f /src/node_stat_watcher.cc | |
parent | 0844e2359bc6b5974db9ec5a8065561ffa87cdcc (diff) | |
download | android-node-v8-b1ffbdc975d58b31e3b13749c29fdc07049ea1d9.tar.gz android-node-v8-b1ffbdc975d58b31e3b13749c29fdc07049ea1d9.tar.bz2 android-node-v8-b1ffbdc975d58b31e3b13749c29fdc07049ea1d9.zip |
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.
Diffstat (limited to 'src/node_stat_watcher.cc')
-rw-r--r-- | src/node_stat_watcher.cc | 34 |
1 files changed, 27 insertions, 7 deletions
diff --git a/src/node_stat_watcher.cc b/src/node_stat_watcher.cc index 8f38033d1a..c3f668c086 100644 --- a/src/node_stat_watcher.cc +++ b/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, int status, const uv_statbuf_t* prev, const uv_statbuf_t* curr) { - StatWatcher* wrap = container_of(handle, StatWatcher, watcher_); - assert(handle == &wrap->watcher_); + StatWatcher* wrap = static_cast<StatWatcher*>(handle->data); + assert(wrap->watcher_ == handle); HandleScope scope; Local<Value> argv[3]; argv[0] = BuildStatsObject(curr); argv[1] = BuildStatsObject(prev); argv[2] = Integer::New(status); if (status == -1) { - SetErrno(uv_last_error(wrap->watcher_.loop)); + SetErrno(uv_last_error(wrap->watcher_->loop)); } if (onchange_sym.IsEmpty()) { onchange_sym = NODE_PSYMBOL("onchange"); @@ -88,8 +108,8 @@ Handle<Value> StatWatcher::Start(const Arguments& args) { 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); + if (!persistent) uv_unref(reinterpret_cast<uv_handle_t*>(wrap->watcher_)); + uv_fs_poll_start(wrap->watcher_, Callback, *path, interval); wrap->Ref(); return Undefined(); @@ -109,8 +129,8 @@ Handle<Value> StatWatcher::Stop(const Arguments& args) { void StatWatcher::Stop () { - if (!uv_is_active(reinterpret_cast<uv_handle_t*>(&watcher_))) return; - uv_fs_poll_stop(&watcher_); + if (!uv_is_active(reinterpret_cast<uv_handle_t*>(watcher_))) return; + uv_fs_poll_stop(watcher_); Unref(); } |