Mercurial > vim
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() |