neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

commit cd543d618dcf94e1a01f3d498a416e425ab75c23
parent 0fa678c02f569484e43b58253d8304ae5e5d0289
Author: Jan Edmund Lazo <jan.lazo@mail.utoronto.ca>
Date:   Sat, 13 Dec 2025 00:33:59 -0500

vim-patch:8.2.4763: using invalid pointer with "V:" in Ex mode

Problem:    Using invalid pointer with "V:" in Ex mode.
Solution:   Correctly handle the command being changed to "+".

https://github.com/vim/vim/commit/f50808ed135ab973296bca515ae4029b321afe47

Co-authored-by: Bram Moolenaar <Bram@vim.org>

Diffstat:
Msrc/nvim/ex_docmd.c | 27++++++++++++++++++++++-----
Mtest/old/testdir/test_ex_mode.vim | 12++++++++++++
2 files changed, 34 insertions(+), 5 deletions(-)

diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c @@ -2511,7 +2511,9 @@ static char *ex_range_without_command(exarg_T *eap) /// @return FAIL when the command is not to be executed. int parse_command_modifiers(exarg_T *eap, const char **errormsg, cmdmod_T *cmod, bool skip_only) { + char *orig_cmd = eap->cmd; char *cmd_start = NULL; + bool did_plus_cmd = false; bool has_visual_range = false; CLEAR_POINTER(cmod); @@ -2537,6 +2539,7 @@ int parse_command_modifiers(exarg_T *eap, const char **errormsg, cmdmod_T *cmod, && getline_equal(eap->ea_getline, eap->cookie, getexline) && curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count) { eap->cmd = exmode_plus; + did_plus_cmd = true; if (!skip_only) { ex_pressedreturn = true; } @@ -2767,12 +2770,26 @@ int parse_command_modifiers(exarg_T *eap, const char **errormsg, cmdmod_T *cmod, // Since the modifiers have been parsed put the colon on top of the // space: "'<,'>mod cmd" -> "mod:'<,'>cmd // Put eap->cmd after the colon. - memmove(cmd_start - 5, cmd_start, (size_t)(eap->cmd - cmd_start)); - eap->cmd -= 5; - memmove(eap->cmd - 1, ":'<,'>", 6); + if (did_plus_cmd) { + size_t len = strlen(cmd_start); + + // Special case: empty command may have been changed to "+": + // "'<,'>mod" -> "mod'<,'>+ + memmove(orig_cmd, cmd_start, len); + strcpy(orig_cmd + len, "'<,'>+"); + } else { + memmove(cmd_start - 5, cmd_start, (size_t)(eap->cmd - cmd_start)); + eap->cmd -= 5; + memmove(eap->cmd - 1, ":'<,'>", 6); + } } else { - // no modifiers, move the pointer back - eap->cmd -= 5; + // No modifiers, move the pointer back. + // Special case: empty command may have been changed to "+". + if (did_plus_cmd) { + eap->cmd = "'<,'>+"; + } else { + eap->cmd = orig_cmd; + } } } diff --git a/test/old/testdir/test_ex_mode.vim b/test/old/testdir/test_ex_mode.vim @@ -287,6 +287,18 @@ func Test_ex_mode_large_indent() bwipe! endfunc +" This was accessing illegal memory when using "+" for eap->cmd. +func Test_empty_command_visual_mode() + let lines =<< trim END + r<sfile> + 0norm0V: + :qall! + END + call writefile(lines, 'Xexmodescript') + call assert_equal(1, RunVim([], [], '-u NONE -e -s -S Xexmodescript')) + + call delete('Xexmodescript') +endfunc " Testing implicit print command func Test_implicit_print()