1
0
forked from aniani/vim

patch 8.2.4139: using freed memory in expression abbreviation

Problem:    Using freed memory if an expression abbreviation deletes the
            abbreviation.
Solution:   Do not access the pointer after evaluating the expression.
This commit is contained in:
Bram Moolenaar
2022-01-18 20:30:39 +00:00
parent ef7aadbe36
commit 94075b2b0e
3 changed files with 33 additions and 6 deletions

View File

@@ -226,7 +226,7 @@ map_add(
#endif #endif
int simplified) int simplified)
{ {
mapblock_T *mp = ALLOC_ONE(mapblock_T); mapblock_T *mp = ALLOC_CLEAR_ONE(mapblock_T);
if (mp == NULL) if (mp == NULL)
return FAIL; return FAIL;
@@ -1515,6 +1515,12 @@ check_abbr(
} }
if (mp != NULL) if (mp != NULL)
{ {
int noremap;
int silent;
#ifdef FEAT_EVAL
int expr;
#endif
// Found a match: // Found a match:
// Insert the rest of the abbreviation in typebuf.tb_buf[]. // Insert the rest of the abbreviation in typebuf.tb_buf[].
// This goes from end to start. // This goes from end to start.
@@ -1567,8 +1573,14 @@ check_abbr(
// insert the last typed char // insert the last typed char
(void)ins_typebuf(tb, 1, 0, TRUE, mp->m_silent); (void)ins_typebuf(tb, 1, 0, TRUE, mp->m_silent);
} }
// copy values here, calling eval_map_expr() may make "mp" invalid!
noremap = mp->m_noremap;
silent = mp->m_silent;
#ifdef FEAT_EVAL #ifdef FEAT_EVAL
if (mp->m_expr) expr = mp->m_expr;
if (expr)
s = eval_map_expr(mp, c); s = eval_map_expr(mp, c);
else else
#endif #endif
@@ -1576,11 +1588,11 @@ check_abbr(
if (s != NULL) if (s != NULL)
{ {
// insert the to string // insert the to string
(void)ins_typebuf(s, mp->m_noremap, 0, TRUE, mp->m_silent); (void)ins_typebuf(s, noremap, 0, TRUE, silent);
// no abbrev. for these chars // no abbrev. for these chars
typebuf.tb_no_abbr_cnt += (int)STRLEN(s) + j + 1; typebuf.tb_no_abbr_cnt += (int)STRLEN(s) + j + 1;
#ifdef FEAT_EVAL #ifdef FEAT_EVAL
if (mp->m_expr) if (expr)
vim_free(s); vim_free(s);
#endif #endif
} }
@@ -1590,7 +1602,7 @@ check_abbr(
if (has_mbyte) if (has_mbyte)
len = clen; // Delete characters instead of bytes len = clen; // Delete characters instead of bytes
while (len-- > 0) // delete the from string while (len-- > 0) // delete the from string
(void)ins_typebuf(tb, 1, 0, TRUE, mp->m_silent); (void)ins_typebuf(tb, 1, 0, TRUE, silent);
return TRUE; return TRUE;
} }
} }
@@ -1601,6 +1613,7 @@ check_abbr(
/* /*
* Evaluate the RHS of a mapping or abbreviations and take care of escaping * Evaluate the RHS of a mapping or abbreviations and take care of escaping
* special characters. * special characters.
* Careful: after this "mp" will be invalid if the mapping was deleted.
*/ */
char_u * char_u *
eval_map_expr( eval_map_expr(

View File

@@ -704,6 +704,11 @@ func Test_mapcomplete()
mapclear mapclear
endfunc endfunc
func GetAbbrText()
unabbr hola
return 'hello'
endfunc
" Test for <expr> in abbreviation " Test for <expr> in abbreviation
func Test_expr_abbr() func Test_expr_abbr()
new new
@@ -719,7 +724,14 @@ func Test_expr_abbr()
call assert_equal('', getline(1)) call assert_equal('', getline(1))
unabbr <expr> hte unabbr <expr> hte
close! " evaluating the expression deletes the abbreviation
abbr <expr> hola GetAbbrText()
call assert_equal('GetAbbrText()', maparg('hola', 'i', '1'))
call feedkeys("ahola \<Esc>", 'xt')
call assert_equal('hello ', getline('.'))
call assert_equal('', maparg('hola', 'i', '1'))
bwipe!
endfunc endfunc
" Test for storing mappings in different modes in a vimrc file " Test for storing mappings in different modes in a vimrc file

View File

@@ -750,6 +750,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 */
/**/
4139,
/**/ /**/
4138, 4138,
/**/ /**/