[git commit] vi: fix "s /find/repl" with whitespace before /
Denys Vlasenko
vda.linux at googlemail.com
Fri Feb 6 21:56:16 UTC 2026
commit: https://git.busybox.net/busybox/commit/?id=3620c4ee677224aed6d6fa02aa8d034b4495370e
branch: https://git.busybox.net/busybox/log/?h=master
function old new delta
colon 3977 4005 +28
Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
editors/vi.c | 23 ++++++++++++-----------
include/libbb.h | 2 ++
2 files changed, 14 insertions(+), 11 deletions(-)
diff --git a/editors/vi.c b/editors/vi.c
index 5bc180b5d..814a63a7b 100644
--- a/editors/vi.c
+++ b/editors/vi.c
@@ -2850,7 +2850,7 @@ static void colon(char *buf)
not_implemented(p);
#else
char c, *q, *r;
- char *fn, cmd[MAX_INPUT_LEN], *cmdend, *args;
+ char *fn, cmd[MAX_INPUT_LEN], *args;
char *exp = NULL;
char *useforce;
int cmdlen;
@@ -2890,15 +2890,14 @@ static void colon(char *buf)
goto ret;
// get the COMMAND into cmd[]
- strcpy(cmd, buf);
- cmdend = skip_non_whitespace(cmd);
- // get any ARGuments
- args = skip_whitespace(cmdend);
-//NB: arguments can be accessed in buf[] as well, there is no need to copy them into cmd[]?
- *cmdend = '\0';
+ args = skip_non_whitespace(buf);
+ safe_strncpy(cmd, buf, (args - buf) + 1);
+//NB: in "s/find/repl" and "!CMD" cases, we copy unnecessary data into buf[]
useforce = last_char_is(cmd, '!');
if (useforce && useforce > cmd)
*useforce = '\0'; // "CMD!" -> "CMD" (unless single "!")
+ // find ARGuments
+ args = skip_whitespace(args);
// assume the command will want a range, certain commands
// (read, substitute) need to adjust these assumptions
@@ -3151,7 +3150,9 @@ static void colon(char *buf)
editing = 0;
}
# if ENABLE_FEATURE_VI_SET
- } else if (strncmp(cmd, "set", cmdlen) == 0) { // set or clear features
+ } else if (strncmp(cmd, "set", cmdlen) == 0 // set or clear features
+ IF_FEATURE_VI_SEARCH(&& cmdlen > 1) // (do not confuse with "s /find/repl/")
+ ) {
# if ENABLE_FEATURE_VI_SETOPTS
char *argp, *argn, oldch;
# endif
@@ -3210,12 +3211,12 @@ static void colon(char *buf)
int undo = 0;
# endif
# endif
-
+ buf = skip_whitespace(buf + 1); // spaces allowed: "s /find/repl/"
// F points to the "find" pattern
// R points to the "replace" pattern
// replace the cmd line delimiters "/" with NULs
- c = buf[1]; // what is the delimiter
- F = buf + 2; // start of "find"
+ c = buf[0]; // what is the delimiter
+ F = buf + 1; // start of "find"
R = strchr_backslash(F, c); // middle delimiter
if (!R)
goto colon_s_fail;
diff --git a/include/libbb.h b/include/libbb.h
index 6ce01ea94..baf0f29e5 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -939,6 +939,8 @@ int parse_pasv_epsv(char *buf) FAST_FUNC;
/* 0 if argv[0] is NULL: */
unsigned string_array_len(char **argv) FAST_FUNC;
void overlapping_strcpy(char *dst, const char *src) FAST_FUNC;
+/* Like strncpy but make sure the resulting string is always 0 terminated: */
+/* writes SIZE chars, the [SIZE-1] char is always NUL (unless SIZE==0). */
char *safe_strncpy(char *dst, const char *src, size_t size) FAST_FUNC;
char *strncpy_IFNAMSIZ(char *dst, const char *src) FAST_FUNC;
unsigned count_strstr(const char *str, const char *sub) FAST_FUNC;
More information about the busybox-cvs
mailing list