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:
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()