fix(terminal): coverity USE_AFTER_FREE #18978

Problem:
Coverity reports use after free:

    *** CID 352784:  Memory - illegal accesses  (USE_AFTER_FREE)
    /src/nvim/buffer.c: 1508 in set_curbuf()
    1502         if (old_tw != curbuf->b_p_tw) {
    1503           check_colorcolumn(curwin);
    1504         }
    1505       }
    1506
    1507       if (bufref_valid(&prevbufref) && prevbuf->terminal != NULL) {
    >>>     CID 352784:  Memory - illegal accesses  (USE_AFTER_FREE)
    >>>     Calling "terminal_check_size" dereferences freed pointer "prevbuf->terminal".
    1508         terminal_check_size(prevbuf->terminal);
    1509       }
    1510     }
    1511
    1512     /// Enter a new current buffer.
    1513     /// Old curbuf must have been abandoned already!  This also means "curbuf" may

Solution:
Change terminal_destroy and terminal_close to set caller storage to NULL,
similar to XFREE_CLEAR. This aligns with the pattern found already in:
terminal_destroy e897ccad3e
term_delayed_free 3e59c1e20d
This commit is contained in:
Justin M. Keyes
2022-06-18 18:53:12 +02:00
committed by GitHub
parent 9c0f2253a5
commit ff6b8f5435
4 changed files with 18 additions and 10 deletions

View File

@@ -275,8 +275,12 @@ Terminal *terminal_open(buf_T *buf, TerminalOptions opts)
return rv;
}
void terminal_close(Terminal *term, int status)
/// Closes the Terminal buffer.
///
/// May call terminal_destroy, which sets caller storage to NULL.
void terminal_close(Terminal **termpp, int status)
{
Terminal *term = *termpp;
if (term->destroy) {
return;
}
@@ -285,7 +289,7 @@ void terminal_close(Terminal *term, int status)
if (entered_free_all_mem) {
// If called from close_buffer() inside free_all_mem(), the main loop has
// already been freed, so it is not safe to call the close callback here.
terminal_destroy(term);
terminal_destroy(termpp);
return;
}
#endif
@@ -586,8 +590,11 @@ static int terminal_execute(VimState *state, int key)
return 1;
}
void terminal_destroy(Terminal *term)
/// Frees the given Terminal structure and sets the caller storage to NULL (in the spirit of
/// XFREE_CLEAR).
void terminal_destroy(Terminal **termpp)
{
Terminal *term = *termpp;
buf_T *buf = handle_get_buffer(term->buf_handle);
if (buf) {
term->buf_handle = 0;
@@ -608,6 +615,7 @@ void terminal_destroy(Terminal *term)
xfree(term->sb_buffer);
vterm_free(term->vt);
xfree(term);
*termpp = NULL; // coverity[dead-store]
}
}