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:
23
src/map.c
23
src/map.c
@@ -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(
|
||||||
|
@@ -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
|
||||||
|
@@ -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,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user