vim-patch:8.2.4139: using freed memory in expression abbreviation (#21522)

Problem:    Using freed memory if an expression abbreviation deletes the
            abbreviation.
Solution:   Do not access the pointer after evaluating the expression.

94075b2b0e

Co-authored-by: Bram Moolenaar <Bram@vim.org>
This commit is contained in:
zeertzjq
2022-12-24 16:32:50 +08:00
committed by GitHub
parent 4d4e697ef0
commit 9be24110f6
3 changed files with 31 additions and 10 deletions

View File

@@ -1517,17 +1517,23 @@ bool check_abbr(int c, char *ptr, int col, int mincol)
// insert the last typed char
(void)ins_typebuf((char *)tb, 1, 0, true, mp->m_silent);
}
if (mp->m_expr) {
// copy values here, calling eval_map_expr() may make "mp" invalid!
const int noremap = mp->m_noremap;
const bool silent = mp->m_silent;
const bool expr = mp->m_expr;
if (expr) {
s = eval_map_expr(mp, c);
} else {
s = mp->m_str;
}
if (s != NULL) {
// 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
typebuf.tb_no_abbr_cnt += (int)strlen(s) + j + 1;
if (mp->m_expr) {
if (expr) {
xfree(s);
}
}
@@ -1536,7 +1542,7 @@ bool check_abbr(int c, char *ptr, int col, int mincol)
tb[1] = NUL;
len = clen; // Delete characters instead of bytes
while (len-- > 0) { // delete the from string
(void)ins_typebuf((char *)tb, 1, 0, true, mp->m_silent);
(void)ins_typebuf((char *)tb, 1, 0, true, silent);
}
return true;
}
@@ -1546,6 +1552,7 @@ bool check_abbr(int c, char *ptr, int col, int mincol)
/// Evaluate the RHS of a mapping or abbreviations and take care of escaping
/// special characters.
/// Careful: after this "mp" will be invalid if the mapping was deleted.
///
/// @param c NUL or typed character for abbreviation
char *eval_map_expr(mapblock_T *mp, int c)
@@ -1560,6 +1567,8 @@ char *eval_map_expr(mapblock_T *mp, int c)
vim_unescape_ks((char_u *)expr);
}
const bool replace_keycodes = mp->m_replace_keycodes;
// Forbid changing text or using ":normal" to avoid most of the bad side
// effects. Also restore the cursor position.
textlock++;
@@ -1596,7 +1605,7 @@ char *eval_map_expr(mapblock_T *mp, int c)
char *res = NULL;
if (mp->m_replace_keycodes) {
if (replace_keycodes) {
replace_termcodes(p, strlen(p), &res, REPTERM_DO_LT, NULL, CPO_TO_CPO_FLAGS);
} else {
// Escape K_SPECIAL in the result to be able to use the string as typeahead.