forked from aniani/vim
		
	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 #11441)
This commit is contained in:
		| @@ -296,9 +296,14 @@ show_autocmd(AutoPat *ap, event_T event) | |||||||
|     if (ap->pat == NULL)		// pattern has been removed |     if (ap->pat == NULL)		// pattern has been removed | ||||||
| 	return; | 	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'); |     msg_putchar('\n'); | ||||||
|     if (got_int) |     if (got_int) | ||||||
| 	return; | 	goto theend; | ||||||
|     if (event != last_event || ap->group != last_group) |     if (event != last_event || ap->group != last_group) | ||||||
|     { |     { | ||||||
| 	if (ap->group != AUGROUP_DEFAULT) | 	if (ap->group != AUGROUP_DEFAULT) | ||||||
| @@ -314,8 +319,12 @@ show_autocmd(AutoPat *ap, event_T event) | |||||||
| 	last_group = ap->group; | 	last_group = ap->group; | ||||||
| 	msg_putchar('\n'); | 	msg_putchar('\n'); | ||||||
| 	if (got_int) | 	if (got_int) | ||||||
| 	    return; | 	    goto theend; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     if (ap->pat == NULL) | ||||||
|  | 	goto theend;  // timer might have cleared the pattern or group | ||||||
|  |  | ||||||
|     msg_col = 4; |     msg_col = 4; | ||||||
|     msg_outtrans(ap->pat); |     msg_outtrans(ap->pat); | ||||||
|  |  | ||||||
| @@ -328,21 +337,24 @@ show_autocmd(AutoPat *ap, event_T event) | |||||||
| 	    msg_putchar('\n'); | 	    msg_putchar('\n'); | ||||||
| 	msg_col = 14; | 	msg_col = 14; | ||||||
| 	if (got_int) | 	if (got_int) | ||||||
| 	    return; | 	    goto theend; | ||||||
| 	msg_outtrans(ac->cmd); | 	msg_outtrans(ac->cmd); | ||||||
| #ifdef FEAT_EVAL | #ifdef FEAT_EVAL | ||||||
| 	if (p_verbose > 0) | 	if (p_verbose > 0) | ||||||
| 	    last_set_msg(ac->script_ctx); | 	    last_set_msg(ac->script_ctx); | ||||||
| #endif | #endif | ||||||
| 	if (got_int) | 	if (got_int) | ||||||
| 	    return; | 	    goto theend; | ||||||
| 	if (ac->next != NULL) | 	if (ac->next != NULL) | ||||||
| 	{ | 	{ | ||||||
| 	    msg_putchar('\n'); | 	    msg_putchar('\n'); | ||||||
| 	    if (got_int) | 	    if (got_int) | ||||||
| 		return; | 		goto theend; | ||||||
| 	} | 	} | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | theend: | ||||||
|  |     --autocmd_busy; | ||||||
| } | } | ||||||
|  |  | ||||||
| /* | /* | ||||||
|   | |||||||
| @@ -62,6 +62,7 @@ if has('timers') | |||||||
|     set updatetime=20 |     set updatetime=20 | ||||||
|     call timer_start(200, 'ExitInsertMode') |     call timer_start(200, 'ExitInsertMode') | ||||||
|     call feedkeys('a', 'x!') |     call feedkeys('a', 'x!') | ||||||
|  |     sleep 30m | ||||||
|     call assert_equal(1, g:triggered) |     call assert_equal(1, g:triggered) | ||||||
|     unlet g:triggered |     unlet g:triggered | ||||||
|     au! CursorHoldI |     au! CursorHoldI | ||||||
| @@ -2159,6 +2160,27 @@ func Test_autocmd_user() | |||||||
|   unlet s:res |   unlet s:res | ||||||
| endfunc | 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() | function s:Before_test_dirchanged() | ||||||
|   augroup test_dirchanged |   augroup test_dirchanged | ||||||
|     autocmd! |     autocmd! | ||||||
|   | |||||||
| @@ -695,6 +695,8 @@ static char *(features[]) = | |||||||
|  |  | ||||||
| static int included_patches[] = | static int included_patches[] = | ||||||
| {   /* Add new patch number below this line */ | {   /* Add new patch number below this line */ | ||||||
|  | /**/ | ||||||
|  |     871, | ||||||
| /**/ | /**/ | ||||||
|     870, |     870, | ||||||
| /**/ | /**/ | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user