Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
tls: ensure no synchronous callbacks
Make sure that no WriteItem's callback will be invoked synchronously.
Doing so may lead to the use of uninitialized `req` object, or even
worse use-after-free in the caller code.

Fix: #1512
  • Loading branch information
indutny committed Apr 29, 2015
commit df28a738443da3ebde03e24e4c1af68cdf9b21c3
30 changes: 28 additions & 2 deletions src/tls_wrap.cc
Original file line number Diff line number Diff line change
Expand Up @@ -109,14 +109,38 @@ bool TLSWrap::InvokeQueued(int status) {
WriteItemList queue;
pending_write_items_.MoveBack(&queue);
while (WriteItem* wi = queue.PopFront()) {
wi->w_->Done(status);
if (wi->async_) {
wi->w_->Done(status);
} else {
CheckWriteItem* check = new CheckWriteItem(wi->w_, status);
int err = uv_check_init(env()->event_loop(), &check->check_);
check->check_.data = check;
if (err == 0)
err = uv_check_start(&check->check_, CheckWriteItem::CheckCb);

// No luck today, do it on next InvokeQueued
if (err) {
delete check;
pending_write_items_.PushBack(wi);
continue;
}
}
delete wi;
}

return true;
}


void TLSWrap::CheckWriteItem::CheckCb(uv_check_t* check) {
CheckWriteItem* c = reinterpret_cast<CheckWriteItem*>(check->data);

c->w_->Done(c->status_);
uv_close(reinterpret_cast<uv_handle_t*>(check), nullptr);
delete c;
}


void TLSWrap::NewSessionDoneCb() {
Cycle();
}
Expand Down Expand Up @@ -556,7 +580,9 @@ int TLSWrap::DoWrite(WriteWrap* w,
}

// Queue callback to execute it on next tick
write_item_queue_.PushBack(new WriteItem(w));
WriteItem* item = new WriteItem(w);
WriteItem::SyncScope item_async(item);
write_item_queue_.PushBack(item);
w->Dispatched();

// Write queued data
Expand Down
32 changes: 31 additions & 1 deletion src/tls_wrap.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,16 +65,46 @@ class TLSWrap : public crypto::SSLWrap<TLSWrap>,
// Write callback queue's item
class WriteItem {
public:
explicit WriteItem(WriteWrap* w) : w_(w) {
class SyncScope {
public:
explicit SyncScope(WriteItem* item) : item_(item) {
item_->async_ = false;
}
~SyncScope() {
item_->async_ = true;
}

private:
WriteItem* item_;
};

explicit WriteItem(WriteWrap* w) : w_(w), async_(false) {
}
~WriteItem() {
w_ = nullptr;
}

WriteWrap* w_;
bool async_;
ListNode<WriteItem> member_;
};

class CheckWriteItem {
public:
CheckWriteItem(WriteWrap* w, int status) : w_(w), status_(status) {
}

~CheckWriteItem() {
w_ = nullptr;
}

static void CheckCb(uv_check_t* check);

WriteWrap* w_;
int status_;
uv_check_t check_;
};

TLSWrap(Environment* env,
Kind kind,
StreamBase* stream,
Expand Down