diff options
author | zeertzjq <zeertzjq@outlook.com> | 2022-12-24 16:32:50 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-12-24 16:32:50 +0800 |
commit | 9be24110f68abc111c87c88d82f50f64a1d3ecdd (patch) | |
tree | d8fb658a64bd9099e3b4b128eac04c496c3a9896 /src/nvim/mapping.c | |
parent | 4d4e697ef0cc0cd4a95acbbdc22074adb537a5bf (diff) | |
download | rneovim-9be24110f68abc111c87c88d82f50f64a1d3ecdd.tar.gz rneovim-9be24110f68abc111c87c88d82f50f64a1d3ecdd.tar.bz2 rneovim-9be24110f68abc111c87c88d82f50f64a1d3ecdd.zip |
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.
https://github.com/vim/vim/commit/94075b2b0e8e3b75334799d2c082497fbf85ffa1
Co-authored-by: Bram Moolenaar <Bram@vim.org>
Diffstat (limited to 'src/nvim/mapping.c')
-rw-r--r-- | src/nvim/mapping.c | 19 |
1 files changed, 14 insertions, 5 deletions
diff --git a/src/nvim/mapping.c b/src/nvim/mapping.c index 3522e0de36..a412fd05b2 100644 --- a/src/nvim/mapping.c +++ b/src/nvim/mapping.c @@ -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. |