# HG changeset patch # User Bram Moolenaar # Date 1668362405 -3600 # Node ID df4957f0ccb5b6670341fd81a9b7f425148dfb55 # Parent f6694a9612d2afcbb706868f6fae2e4278d14339 patch 9.0.0871: using freed memory when clearing augroup at more prompt Commit: https://github.com/vim/vim/commit/3b014befa006b7224a84d7d58d9603fc261f34cd Author: Bram Moolenaar Date: Sun Nov 13 17:53:46 2022 +0000 patch 9.0.0871: using freed memory when clearing augroup at more prompt Problem: Using freed memory when clearing augroup at more prompt. Solution: Delay clearing augroup until it's safe. (closes https://github.com/vim/vim/issues/11441) diff --git a/src/autocmd.c b/src/autocmd.c --- a/src/autocmd.c +++ b/src/autocmd.c @@ -296,9 +296,14 @@ show_autocmd(AutoPat *ap, event_T event) if (ap->pat == NULL) // pattern has been removed return; + // Make sure no info referenced by "ap" is cleared, e.g. when a timer + // clears an augroup. Jump to "theend" after this! + // "ap->pat" may be cleared anyway. + ++autocmd_busy; + msg_putchar('\n'); if (got_int) - return; + goto theend; if (event != last_event || ap->group != last_group) { if (ap->group != AUGROUP_DEFAULT) @@ -314,8 +319,12 @@ show_autocmd(AutoPat *ap, event_T event) last_group = ap->group; msg_putchar('\n'); if (got_int) - return; + goto theend; } + + if (ap->pat == NULL) + goto theend; // timer might have cleared the pattern or group + msg_col = 4; msg_outtrans(ap->pat); @@ -328,21 +337,24 @@ show_autocmd(AutoPat *ap, event_T event) msg_putchar('\n'); msg_col = 14; if (got_int) - return; + goto theend; msg_outtrans(ac->cmd); #ifdef FEAT_EVAL if (p_verbose > 0) last_set_msg(ac->script_ctx); #endif if (got_int) - return; + goto theend; if (ac->next != NULL) { msg_putchar('\n'); if (got_int) - return; + goto theend; } } + +theend: + --autocmd_busy; } /* diff --git a/src/testdir/test_autocmd.vim b/src/testdir/test_autocmd.vim --- a/src/testdir/test_autocmd.vim +++ b/src/testdir/test_autocmd.vim @@ -62,6 +62,7 @@ if has('timers') set updatetime=20 call timer_start(200, 'ExitInsertMode') call feedkeys('a', 'x!') + sleep 30m call assert_equal(1, g:triggered) unlet g:triggered au! CursorHoldI @@ -2159,6 +2160,27 @@ func Test_autocmd_user() unlet s:res endfunc +func Test_autocmd_user_clear_group() + CheckRunVimInTerminal + + let lines =<< trim END + autocmd! User + for i in range(1, 999) + exe 'autocmd User ' .. 'Foo' .. i .. ' bar' + endfor + au CmdlineLeave : call timer_start(0, {-> execute('autocmd! User')}) + END + call writefile(lines, 'XautoUser', 'D') + let buf = RunVimInTerminal('-S XautoUser', {'rows': 10}) + + " this was using freed memory + call term_sendkeys(buf, ":autocmd User\") + call TermWait(buf, 50) + call term_sendkeys(buf, "G") + + call StopVimInTerminal(buf) +endfunc + function s:Before_test_dirchanged() augroup test_dirchanged autocmd! diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -696,6 +696,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 871, +/**/ 870, /**/ 869,