summaryrefslogtreecommitdiff
path: root/src/node_stat_watcher.cc
diff options
context:
space:
mode:
authorBen Noordhuis <info@bnoordhuis.nl>2012-08-20 12:52:26 +0200
committerBen Noordhuis <info@bnoordhuis.nl>2012-08-20 17:29:58 +0200
commitb1ffbdc975d58b31e3b13749c29fdc07049ea1d9 (patch)
tree6eec1adc71a3b7fea9c34d72221d27d7ce4eb82f /src/node_stat_watcher.cc
parent0844e2359bc6b5974db9ec5a8065561ffa87cdcc (diff)
downloadandroid-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.cc34
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();
}