vim-patch:8.2.5092: using "'<,'>" in Ex mode may compare unrelated pointers

Problem:    Using "'<,'>" in Ex mode may compare unrelated pointers.
Solution:   Set eap->cmd to "+" only later.

48ce135e6d

Co-authored-by: Bram Moolenaar <Bram@vim.org>
This commit is contained in:
Jan Edmund Lazo
2025-12-13 00:57:57 -05:00
parent cd543d618d
commit edd99f09c7

View File

@@ -2513,14 +2513,16 @@ int parse_command_modifiers(exarg_T *eap, const char **errormsg, cmdmod_T *cmod,
{ {
char *orig_cmd = eap->cmd; char *orig_cmd = eap->cmd;
char *cmd_start = NULL; char *cmd_start = NULL;
bool did_plus_cmd = false; bool use_plus_cmd = false;
bool has_visual_range = false; bool has_visual_range = false;
CLEAR_POINTER(cmod); CLEAR_POINTER(cmod);
if (strncmp(eap->cmd, "'<,'>", 5) == 0) { if (strncmp(eap->cmd, "'<,'>", 5) == 0) {
// The automatically inserted Visual area range is skipped, so that // The automatically inserted Visual area range is skipped, so that
// typing ":cmdmod cmd" in Visual mode works without having to move the // typing ":cmdmod cmd" in Visual mode works without having to move the
// range to after the modififiers. // range to after the modififiers. The command will be
// "'<,'>cmdmod cmd", parse "cmdmod cmd" and then put back "'<,'>"
// before "cmd" below.
eap->cmd += 5; eap->cmd += 5;
cmd_start = eap->cmd; cmd_start = eap->cmd;
has_visual_range = true; has_visual_range = true;
@@ -2534,15 +2536,16 @@ int parse_command_modifiers(exarg_T *eap, const char **errormsg, cmdmod_T *cmod,
eap->cmd++; eap->cmd++;
} }
// in ex mode, an empty line works like :+ // in ex mode, an empty command (after modifiers) works like :+
if (*eap->cmd == NUL && exmode_active if (*eap->cmd == NUL && exmode_active
&& getline_equal(eap->ea_getline, eap->cookie, getexline) && getline_equal(eap->ea_getline, eap->cookie, getexline)
&& curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count) { && curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count) {
eap->cmd = exmode_plus; eap->cmd = exmode_plus;
did_plus_cmd = true; use_plus_cmd = true;
if (!skip_only) { if (!skip_only) {
ex_pressedreturn = true; ex_pressedreturn = true;
} }
break; // no modifiers following
} }
// ignore comment and empty lines // ignore comment and empty lines
@@ -2770,11 +2773,11 @@ 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 // Since the modifiers have been parsed put the colon on top of the
// space: "'<,'>mod cmd" -> "mod:'<,'>cmd // space: "'<,'>mod cmd" -> "mod:'<,'>cmd
// Put eap->cmd after the colon. // Put eap->cmd after the colon.
if (did_plus_cmd) { if (use_plus_cmd) {
size_t len = strlen(cmd_start); size_t len = strlen(cmd_start);
// Special case: empty command may have been changed to "+": // Special case: empty command uses "+":
// "'<,'>mod" -> "mod'<,'>+ // "'<,'>mods" -> "mods'<,'>+
memmove(orig_cmd, cmd_start, len); memmove(orig_cmd, cmd_start, len);
strcpy(orig_cmd + len, "'<,'>+"); strcpy(orig_cmd + len, "'<,'>+");
} else { } else {
@@ -2784,13 +2787,15 @@ int parse_command_modifiers(exarg_T *eap, const char **errormsg, cmdmod_T *cmod,
} }
} else { } else {
// No modifiers, move the pointer back. // No modifiers, move the pointer back.
// Special case: empty command may have been changed to "+". // Special case: change empty command to "+".
if (did_plus_cmd) { if (use_plus_cmd) {
eap->cmd = "'<,'>+"; eap->cmd = "'<,'>+";
} else { } else {
eap->cmd = orig_cmd; eap->cmd = orig_cmd;
} }
} }
} else if (use_plus_cmd) {
eap->cmd = exmode_plus;
} }
return OK; return OK;