diff options
author | oni-link <knil.ino@gmail.com> | 2015-08-15 11:36:14 +0200 |
---|---|---|
committer | Justin M. Keyes <justinkz@gmail.com> | 2015-08-16 14:09:29 -0400 |
commit | db7b970057c92127624ebafa7affaf77fdff6750 (patch) | |
tree | 18534593b69f97f2e0cda79e0631f3320aa92eec | |
parent | 2bd3351c37bb916086f791b3f0e8bef960ce7b25 (diff) | |
download | rneovim-db7b970057c92127624ebafa7affaf77fdff6750.tar.gz rneovim-db7b970057c92127624ebafa7affaf77fdff6750.tar.bz2 rneovim-db7b970057c92127624ebafa7affaf77fdff6750.zip |
rstream.c: Prevent stream closing if a read event is still queued. #3172
Processing a stream's output can be queued. If stream_close() is called
before the queue is processed, the RBuffer containing the stream's data
is freed and the next read event would try to access freed memory.
To fix this behavior, use the stream's pending requests counter.
-rw-r--r-- | src/nvim/event/rstream.c | 19 |
1 files changed, 17 insertions, 2 deletions
diff --git a/src/nvim/event/rstream.c b/src/nvim/event/rstream.c index 0a720bb852..9f3fbc25ff 100644 --- a/src/nvim/event/rstream.c +++ b/src/nvim/event/rstream.c @@ -177,10 +177,25 @@ static void read_event(void **argv) bool eof = (uintptr_t)argv[2]; stream->read_cb(stream, stream->buffer, count, stream->data, eof); } + stream->pending_reqs--; + if (stream->closed && !stream->pending_reqs) { + stream_close_handle(stream); + } } static void invoke_read_cb(Stream *stream, size_t count, bool eof) { - CREATE_EVENT(stream->events, read_event, 3, stream, - (void *)(uintptr_t *)count, (void *)(uintptr_t)eof); + if (stream->closed) { + return; + } + + // Don't let the stream be closed before the event is processed. + stream->pending_reqs++; + + CREATE_EVENT(stream->events, + read_event, + 3, + stream, + (void *)(uintptr_t *)count, + (void *)(uintptr_t)eof); } |