]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.0.0871: using freed memory when clearing augroup at more prompt v9.0.0871
authorBram Moolenaar <Bram@vim.org>
Sun, 13 Nov 2022 17:53:46 +0000 (17:53 +0000)
committerBram Moolenaar <Bram@vim.org>
Sun, 13 Nov 2022 17:53:46 +0000 (17:53 +0000)
Problem:    Using freed memory when clearing augroup at more prompt.
Solution:   Delay clearing augroup until it's safe. (closes #11441)

src/autocmd.c
src/testdir/test_autocmd.vim
src/version.c

index cf0f0946a8116c6c17d6c81176eb3a2f962126d4..8a0992c092e973ec27497ca588f271a7b98daea9 100644 (file)
@@ -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;
 }
 
 /*
index 04f3e1431c13229a1bfe697739b2aa8d59958103..f2f3725b3d770214e683bead59edcbf79607cbe3 100644 (file)
@@ -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\<CR>")
+  call TermWait(buf, 50)
+  call term_sendkeys(buf, "G")
+
+  call StopVimInTerminal(buf)
+endfunc
+
 function s:Before_test_dirchanged()
   augroup test_dirchanged
     autocmd!
index 73c106e1d2323f41a2cb82636d4ce76723b4830d..b57fffe7d349b5eabcfa55a355426ac7da9493d1 100644 (file)
@@ -695,6 +695,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    871,
 /**/
     870,
 /**/