Patch 8.2.0371
Problem:    Crash with combination of terminal popup and autocmd.
Solution:   Disallow closing a popup that is the current window.  Add a check
            that the current buffer is valid. (closes #5754)
Files:      src/macros.h, src/buffer.c, src/popupwin.c, src/terminal.c,
            src/testdir/test_terminal.vim


*** ../vim-8.2.0370/src/macros.h        2020-02-28 22:19:38.310023356 +0100
--- src/macros.h        2020-03-11 12:23:55.990247931 +0100
***************
*** 364,371 ****
--- 364,374 ----
  # define ESTACK_CHECK_SETUP estack_len_before = exestack.ga_len;
  # define ESTACK_CHECK_NOW if (estack_len_before != exestack.ga_len) \
        siemsg("Exestack length expected: %d, actual: %d", estack_len_before, 
exestack.ga_len);
+ # define CHECK_CURBUF if (curwin != NULL && curwin->w_buffer != curbuf) \
+               iemsg("curbuf != curwin->w_buffer")
  #else
  # define ESTACK_CHECK_DECLARATION
  # define ESTACK_CHECK_SETUP
  # define ESTACK_CHECK_NOW
+ # define CHECK_CURBUF
  #endif
*** ../vim-8.2.0370/src/buffer.c        2020-02-08 18:35:12.528045466 +0100
--- src/buffer.c        2020-03-11 07:50:04.683125949 +0100
***************
*** 508,513 ****
--- 508,514 ----
      int               wipe_buf = (action == DOBUF_WIPE || action == 
DOBUF_WIPE_REUSE);
      int               del_buf = (action == DOBUF_DEL || wipe_buf);
  
+     CHECK_CURBUF;
      /*
       * Force unloading or deleting when 'bufhidden' says so.
       * The caller must take care of NOT deleting/freeing when 'bufhidden' is
***************
*** 530,535 ****
--- 531,537 ----
  #ifdef FEAT_TERMINAL
      if (bt_terminal(buf) && (buf->b_nwindows == 1 || del_buf))
      {
+       CHECK_CURBUF;
        if (term_job_running(buf->b_term))
        {
            if (wipe_buf || unload_buf)
***************
*** 554,559 ****
--- 556,562 ----
            unload_buf = TRUE;
            wipe_buf = TRUE;
        }
+       CHECK_CURBUF;
      }
  #endif
  
***************
*** 743,748 ****
--- 746,752 ----
        if (del_buf)
            buf->b_p_bl = FALSE;
      }
+     // NOTE: at this point "curbuf" may be invalid!
  }
  
  /*
***************
*** 933,939 ****
--- 937,947 ----
        au_pending_free_buf = buf;
      }
      else
+     {
        vim_free(buf);
+       if (curbuf == buf)
+           curbuf = NULL;  // make clear it's not to be used
+     }
  }
  
  /*
*** ../vim-8.2.0370/src/popupwin.c      2020-03-06 21:43:14.414246402 +0100
--- src/popupwin.c      2020-03-11 14:03:58.633566371 +0100
***************
*** 2135,2141 ****
                    break;
            if (owp != NULL)
                win_enter(owp, FALSE);
!           else if (win_valid(prevwin))
                win_enter(prevwin, FALSE);
            else
                win_enter(firstwin, FALSE);
--- 2135,2141 ----
                    break;
            if (owp != NULL)
                win_enter(owp, FALSE);
!           else if (win_valid(prevwin) && wp != prevwin)
                win_enter(prevwin, FALSE);
            else
                win_enter(firstwin, FALSE);
***************
*** 2147,2157 ****
--- 2147,2159 ----
      if (wp == curwin && ERROR_IF_POPUP_WINDOW)
        return;
  
+     CHECK_CURBUF;
      if (wp->w_close_cb.cb_name != NULL)
        // Careful: This may make "wp" invalid.
        invoke_popup_callback(wp, arg);
  
      popup_close(id);
+     CHECK_CURBUF;
  }
  
      void
***************
*** 2505,2510 ****
--- 2507,2517 ----
      for (wp = first_popupwin; wp != NULL; prev = wp, wp = wp->w_next)
        if (wp->w_id == id)
        {
+           if (wp == curwin)
+           {
+               ERROR_IF_ANY_POPUP_WINDOW;
+               return;
+           }
            if (prev == NULL)
                first_popupwin = wp->w_next;
            else
***************
*** 2531,2536 ****
--- 2538,2548 ----
      for (wp = *root; wp != NULL; prev = wp, wp = wp->w_next)
        if (wp->w_id == id)
        {
+           if (wp == curwin)
+           {
+               ERROR_IF_ANY_POPUP_WINDOW;
+               return;
+           }
            if (prev == NULL)
                *root = wp->w_next;
            else
***************
*** 2881,2890 ****
  {
      // win_execute() may set "curwin" to a popup window temporarily, but many
      // commands are disallowed then.  When a terminal runs in the popup most
!     // things are allowed.
      if (WIN_IS_POPUP(curwin)
  # ifdef FEAT_TERMINAL
            && (also_with_term || curbuf->b_term == NULL)
  # endif
            )
      {
--- 2893,2903 ----
  {
      // win_execute() may set "curwin" to a popup window temporarily, but many
      // commands are disallowed then.  When a terminal runs in the popup most
!     // things are allowed.  When a terminal is finished it can be closed.
      if (WIN_IS_POPUP(curwin)
  # ifdef FEAT_TERMINAL
            && (also_with_term || curbuf->b_term == NULL)
+           && !term_is_finished(curbuf)
  # endif
            )
      {
*** ../vim-8.2.0370/src/terminal.c      2020-02-28 22:19:38.314023342 +0100
--- src/terminal.c      2020-03-10 19:53:06.484870815 +0100
***************
*** 382,387 ****
--- 382,388 ----
        curwin->w_buffer = curbuf;
        ++curbuf->b_nwindows;
      }
+     CHECK_CURBUF;
  
      // Wiping out the buffer will also close the window and call
      // free_terminal().
*** ../vim-8.2.0370/src/testdir/test_terminal.vim       2020-03-03 
22:56:36.302382831 +0100
--- src/testdir/test_terminal.vim       2020-03-11 14:15:57.889585751 +0100
***************
*** 2430,2432 ****
--- 2430,2456 ----
    call assert_equal('', bufname('^$'))
    call StopShellInTerminal(buf)
  endfunc
+ 
+ func Test_term_nasty_callback()
+   func OpenTerms()
+     set hidden
+     let g:buf0 = term_start('sh', #{hidden: 1})
+     call popup_create(g:buf0, {})
+     let g:buf1 = term_start('sh', #{hidden: 1, term_finish: 'close'})
+     call popup_create(g:buf1, {})
+     let g:buf2 = term_start(['sh', '-c'], #{curwin: 1, exit_cb: 
function('TermExit')})
+     sleep 100m
+     call popup_close(win_getid())
+   endfunc
+   func TermExit(...)
+     call term_sendkeys(bufnr('#'), "exit\<CR>")
+     call popup_close(win_getid())
+   endfu
+   call OpenTerms()
+ 
+   call term_sendkeys(g:buf0, "exit\<CR>")
+   sleep 50m
+   exe g:buf0 .. 'bwipe'
+   set hidden&
+ endfunc
+ 
*** ../vim-8.2.0370/src/version.c       2020-03-11 13:01:36.025436785 +0100
--- src/version.c       2020-03-11 14:16:19.989463949 +0100
***************
*** 740,741 ****
--- 740,743 ----
  {   /* Add new patch number below this line */
+ /**/
+     371,
  /**/

-- 
hundred-and-one symptoms of being an internet addict:
225. You sign up for free subscriptions for all the computer magazines

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\  an exciting new programming language -- http://www.Zimbu.org        ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/202003111321.02BDLHV7026639%40masaka.moolenaar.net.

Raspunde prin e-mail lui