mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
term: ensure term->buf is valid
The fallowing test (reduced), submitted by @mhinz may free term->buf, leaving the pointer dangling. ```vim let s:buf = -1 function! s:exit_handler() execute 'bdelete!' s:buf endfunction vnew let s:buf = bufnr('%') let id = termopen('sleep 1', { 'on_exit': function('s:exit_handler') }) call s:test() ``` When the buffer is known to be closing, set term->buf to NULL, and check buf_valid() in on_refresh(). Helped-by: Marco Hinz (@mhinz)
This commit is contained in:
parent
013bd4461d
commit
8cac2eea75
@ -307,9 +307,12 @@ void terminal_close(Terminal *term, char *msg)
|
|||||||
term->forward_mouse = false;
|
term->forward_mouse = false;
|
||||||
term->closed = true;
|
term->closed = true;
|
||||||
if (!msg || exiting) {
|
if (!msg || exiting) {
|
||||||
// If no msg was given, this was called by close_buffer(buffer.c) so we
|
// If no msg was given, this was called by close_buffer(buffer.c). Or if
|
||||||
// should not wait for the user to press a key. Also cannot wait if
|
// exiting, we must inform the buffer the terminal no longer exists so that
|
||||||
// `exiting == true`
|
// close_buffer() doesn't call this again.
|
||||||
|
term->buf->terminal = NULL;
|
||||||
|
term->buf = NULL;
|
||||||
|
// We should not wait for the user to press a key.
|
||||||
term->opts.close_cb(term->opts.data);
|
term->opts.close_cb(term->opts.data);
|
||||||
} else {
|
} else {
|
||||||
terminal_receive(term, msg, strlen(msg));
|
terminal_receive(term, msg, strlen(msg));
|
||||||
@ -451,7 +454,9 @@ end:
|
|||||||
|
|
||||||
void terminal_destroy(Terminal *term)
|
void terminal_destroy(Terminal *term)
|
||||||
{
|
{
|
||||||
term->buf->terminal = NULL;
|
if (term->buf) {
|
||||||
|
term->buf->terminal = NULL;
|
||||||
|
}
|
||||||
term->buf = NULL;
|
term->buf = NULL;
|
||||||
pmap_del(ptr_t)(invalidated_terminals, term);
|
pmap_del(ptr_t)(invalidated_terminals, term);
|
||||||
for (size_t i = 0 ; i < term->sb_current; i++) {
|
for (size_t i = 0 ; i < term->sb_current; i++) {
|
||||||
@ -930,8 +935,13 @@ static void on_refresh(Event event)
|
|||||||
// be used act on terminal output.
|
// be used act on terminal output.
|
||||||
block_autocmds();
|
block_autocmds();
|
||||||
map_foreach(invalidated_terminals, term, stub, {
|
map_foreach(invalidated_terminals, term, stub, {
|
||||||
if (!term->buf) {
|
// TODO(SplinterOfChaos): Find the condition that makes term->buf invalid.
|
||||||
|
bool valid = true;
|
||||||
|
if (!term->buf || !(valid = buf_valid(term->buf))) {
|
||||||
// destroyed by `close_buffer`. Dont do anything else
|
// destroyed by `close_buffer`. Dont do anything else
|
||||||
|
if (!valid) {
|
||||||
|
term->buf = NULL;
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
bool pending_resize = term->pending_resize;
|
bool pending_resize = term->pending_resize;
|
||||||
|
Loading…
Reference in New Issue
Block a user