comparison src/buffer.c @ 23869:5a4f9c5c1b99 v8.2.2476

patch 8.2.2476: using freed memory when splitting window while closing buffer Commit: https://github.com/vim/vim/commit/983d83ff1cd796ff321074335fa53fbe7ac45a46 Author: Bram Moolenaar <Bram@vim.org> Date: Sun Feb 7 12:12:43 2021 +0100 patch 8.2.2476: using freed memory when splitting window while closing buffer Problem: Using freed memory when using an autocommand to split a window while a buffer is being closed. Solution: Disallow splitting when the buffer has b_locked_split set.
author Bram Moolenaar <Bram@vim.org>
date Sun, 07 Feb 2021 12:15:03 +0100
parents 29eccef07e2f
children 44be09b25619
comparison
equal deleted inserted replaced
23868:1a97398d5e5a 23869:5a4f9c5c1b99
593 593
594 // When the buffer is no longer in a window, trigger BufWinLeave 594 // When the buffer is no longer in a window, trigger BufWinLeave
595 if (buf->b_nwindows == 1) 595 if (buf->b_nwindows == 1)
596 { 596 {
597 ++buf->b_locked; 597 ++buf->b_locked;
598 ++buf->b_locked_split;
598 if (apply_autocmds(EVENT_BUFWINLEAVE, buf->b_fname, buf->b_fname, 599 if (apply_autocmds(EVENT_BUFWINLEAVE, buf->b_fname, buf->b_fname,
599 FALSE, buf) 600 FALSE, buf)
600 && !bufref_valid(&bufref)) 601 && !bufref_valid(&bufref))
601 { 602 {
602 // Autocommands deleted the buffer. 603 // Autocommands deleted the buffer.
603 aucmd_abort: 604 aucmd_abort:
604 emsg(_(e_auabort)); 605 emsg(_(e_auabort));
605 return FALSE; 606 return FALSE;
606 } 607 }
607 --buf->b_locked; 608 --buf->b_locked;
609 --buf->b_locked_split;
608 if (abort_if_last && one_window()) 610 if (abort_if_last && one_window())
609 // Autocommands made this the only window. 611 // Autocommands made this the only window.
610 goto aucmd_abort; 612 goto aucmd_abort;
611 613
612 // When the buffer becomes hidden, but is not unloaded, trigger 614 // When the buffer becomes hidden, but is not unloaded, trigger
613 // BufHidden 615 // BufHidden
614 if (!unload_buf) 616 if (!unload_buf)
615 { 617 {
616 ++buf->b_locked; 618 ++buf->b_locked;
619 ++buf->b_locked_split;
617 if (apply_autocmds(EVENT_BUFHIDDEN, buf->b_fname, buf->b_fname, 620 if (apply_autocmds(EVENT_BUFHIDDEN, buf->b_fname, buf->b_fname,
618 FALSE, buf) 621 FALSE, buf)
619 && !bufref_valid(&bufref)) 622 && !bufref_valid(&bufref))
620 // Autocommands deleted the buffer. 623 // Autocommands deleted the buffer.
621 goto aucmd_abort; 624 goto aucmd_abort;
622 --buf->b_locked; 625 --buf->b_locked;
626 --buf->b_locked_split;
623 if (abort_if_last && one_window()) 627 if (abort_if_last && one_window())
624 // Autocommands made this the only window. 628 // Autocommands made this the only window.
625 goto aucmd_abort; 629 goto aucmd_abort;
626 } 630 }
627 #ifdef FEAT_EVAL 631 #ifdef FEAT_EVAL
798 win_T *the_curwin = curwin; 802 win_T *the_curwin = curwin;
799 tabpage_T *the_curtab = curtab; 803 tabpage_T *the_curtab = curtab;
800 804
801 // Make sure the buffer isn't closed by autocommands. 805 // Make sure the buffer isn't closed by autocommands.
802 ++buf->b_locked; 806 ++buf->b_locked;
807 ++buf->b_locked_split;
803 set_bufref(&bufref, buf); 808 set_bufref(&bufref, buf);
804 if (buf->b_ml.ml_mfp != NULL) 809 if (buf->b_ml.ml_mfp != NULL)
805 { 810 {
806 if (apply_autocmds(EVENT_BUFUNLOAD, buf->b_fname, buf->b_fname, 811 if (apply_autocmds(EVENT_BUFUNLOAD, buf->b_fname, buf->b_fname,
807 FALSE, buf) 812 FALSE, buf)
824 && !bufref_valid(&bufref)) 829 && !bufref_valid(&bufref))
825 // autocommands deleted the buffer 830 // autocommands deleted the buffer
826 return; 831 return;
827 } 832 }
828 --buf->b_locked; 833 --buf->b_locked;
834 --buf->b_locked_split;
829 835
830 // If the buffer was in curwin and the window has changed, go back to that 836 // If the buffer was in curwin and the window has changed, go back to that
831 // window, if it still exists. This avoids that ":edit x" triggering a 837 // window, if it still exists. This avoids that ":edit x" triggering a
832 // "tabnext" BufUnload autocmd leaves a window behind without a buffer. 838 // "tabnext" BufUnload autocmd leaves a window behind without a buffer.
833 if (is_curwin && curwin != the_curwin && win_valid_any_tab(the_curwin)) 839 if (is_curwin && curwin != the_curwin && win_valid_any_tab(the_curwin))
1716 // close_windows() or apply_autocmds() may change curbuf and wipe out "buf" 1722 // close_windows() or apply_autocmds() may change curbuf and wipe out "buf"
1717 prevbuf = curbuf; 1723 prevbuf = curbuf;
1718 set_bufref(&prevbufref, prevbuf); 1724 set_bufref(&prevbufref, prevbuf);
1719 set_bufref(&newbufref, buf); 1725 set_bufref(&newbufref, buf);
1720 1726
1721 // Autocommands may delete the current buffer and/or the buffer we want to go 1727 // Autocommands may delete the current buffer and/or the buffer we want to
1722 // to. In those cases don't close the buffer. 1728 // go to. In those cases don't close the buffer.
1723 if (!apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, FALSE, curbuf) 1729 if (!apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, FALSE, curbuf)
1724 || (bufref_valid(&prevbufref) 1730 || (bufref_valid(&prevbufref)
1725 && bufref_valid(&newbufref) 1731 && bufref_valid(&newbufref)
1726 #ifdef FEAT_EVAL 1732 #ifdef FEAT_EVAL
1727 && !aborting() 1733 && !aborting()