summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2008-07-22 20:16:55 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2008-07-22 20:16:55 +0000
commit0f293b96dc6effa127ec63e11dd16221f1329126 (patch)
treea5b7873a5ece9bef8355da8d437cf53f952c66ca
parent68a192c00799fd2097bab1aec594cd27203b1ec6 (diff)
fix all cases of strcpy on overlapping strings.
-rw-r--r--coreutils/printf.c2
-rw-r--r--editors/sed.c2
-rw-r--r--include/libbb.h1
-rw-r--r--libbb/lineedit.c2
-rw-r--r--libbb/parse_config.c2
-rw-r--r--libbb/safe_strncpy.c9
-rw-r--r--procps/nmeter.c2
7 files changed, 15 insertions, 5 deletions
diff --git a/coreutils/printf.c b/coreutils/printf.c
index 7f6235a87..72acbc751 100644
--- a/coreutils/printf.c
+++ b/coreutils/printf.c
@@ -289,7 +289,7 @@ static char **print_formatted(char *f, char **argv)
/* Remove size modifiers - "%Ld" would try to printf
* long long, we pass long, and it spews garbage */
if ((*f | 0x20) == 'l' || *f == 'h' || *f == 'z') {
- strcpy(f, f + 1);
+ overlapping_strcpy(f, f + 1);
}
//FIXME: actually, the same happens with bare "%d":
//it printfs an int, but we pass long!
diff --git a/editors/sed.c b/editors/sed.c
index 496d3d22e..eb31f7d2e 100644
--- a/editors/sed.c
+++ b/editors/sed.c
@@ -1219,7 +1219,7 @@ static void add_cmd_block(char *cmdstr)
slashes++;
/* Odd number of preceding slashes - newline is escaped */
if (slashes & 1) {
- strcpy(eol-1, eol);
+ overlapping_strcpy(eol - 1, eol);
eol = strchr(eol, '\n');
goto next;
}
diff --git a/include/libbb.h b/include/libbb.h
index 684e130c9..c0b731b36 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -540,6 +540,7 @@ ssize_t recv_from_to(int fd, void *buf, size_t len, int flags,
char *xstrdup(const char *s) FAST_FUNC;
char *xstrndup(const char *s, int n) FAST_FUNC;
+void overlapping_strcpy(char *dst, const char *src) FAST_FUNC;
char *safe_strncpy(char *dst, const char *src, size_t size) FAST_FUNC;
/* Guaranteed to NOT be a macro (smallest code). Saves nearly 2k on uclibc.
* But potentially slow, don't use in one-billion-times loops */
diff --git a/libbb/lineedit.c b/libbb/lineedit.c
index 2e16e6a0a..032da24e7 100644
--- a/libbb/lineedit.c
+++ b/libbb/lineedit.c
@@ -1552,7 +1552,7 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li
vi_case(CTRL('U')|vbit:)
/* Control-U -- Clear line before cursor */
if (cursor) {
- strcpy(command, command + cursor);
+ overlapping_strcpy(command, command + cursor);
command_len -= cursor;
redraw(cmdedit_y, command_len);
}
diff --git a/libbb/parse_config.c b/libbb/parse_config.c
index 5109066d8..d1b29218b 100644
--- a/libbb/parse_config.c
+++ b/libbb/parse_config.c
@@ -161,7 +161,7 @@ int FAST_FUNC config_read(parser_t *parser, char **tokens, unsigned flags, const
int n = strspn(line, delims);
if (n) {
ii -= n;
- strcpy(line, line + n);
+ overlapping_strcpy(line, line + n);
}
// cut trailing
if (ii) {
diff --git a/libbb/safe_strncpy.c b/libbb/safe_strncpy.c
index 649fa10cf..4acd9766b 100644
--- a/libbb/safe_strncpy.c
+++ b/libbb/safe_strncpy.c
@@ -16,3 +16,12 @@ char* FAST_FUNC safe_strncpy(char *dst, const char *src, size_t size)
dst[--size] = '\0';
return strncpy(dst, src, size);
}
+
+/* Like strcpy but can copy overlapping strings. */
+void FAST_FUNC overlapping_strcpy(char *dst, const char *src)
+{
+ while ((*dst = *src) != '\0') {
+ dst++;
+ src++;
+ }
+}
diff --git a/procps/nmeter.c b/procps/nmeter.c
index 8cff0b918..be039320b 100644
--- a/procps/nmeter.c
+++ b/procps/nmeter.c
@@ -800,7 +800,7 @@ int nmeter_main(int argc, char **argv)
if (!cur)
break;
if (cur[1] == '%') { // %%
- strcpy(cur, cur+1);
+ overlapping_strcpy(cur, cur + 1);
cur++;
goto again;
}