From f058359ba5e08c555d7e6f192217f890b83cd46c Mon Sep 17 00:00:00 2001 From: Tom Jones Date: Tue, 5 Jul 2022 16:03:51 +0100 Subject: [PATCH] xargs: terminate if line replacement cannot be constructed If the line with replacement cannot be constructed xargs should terminate as documented in the man page We encounter this error, but gnu/xargs doesn't because they have a much larger limit for created outputs (~10000 lines). Reviewed by: oshogbo Sponsored by: Klara, Inc. Differential Revision: https://reviews.freebsd.org/D35574 --- usr.bin/xargs/strnsubst.c | 15 ++++++++++----- usr.bin/xargs/xargs.c | 8 ++++++-- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/usr.bin/xargs/strnsubst.c b/usr.bin/xargs/strnsubst.c index d826d33c0967..1fa35d453f49 100644 --- a/usr.bin/xargs/strnsubst.c +++ b/usr.bin/xargs/strnsubst.c @@ -12,11 +12,12 @@ __FBSDID("$FreeBSD$"); #include +#include #include #include #include -void strnsubst(char **, const char *, const char *, size_t); +bool strnsubst(char **, const char *, const char *, size_t); /* * Replaces str with a string consisting of str with match replaced with @@ -26,16 +27,19 @@ void strnsubst(char **, const char *, const char *, size_t); * str as well as the new contents are handled in an appropriate manner. * If replstr is NULL, then that internally is changed to a nil-string, so * that we can still pretend to do somewhat meaningful substitution. - * No value is returned. + * + * Returns true if truncation was needed to do the replacement, true if + * truncation was not required. */ -void +bool strnsubst(char **str, const char *match, const char *replstr, size_t maxsize) { char *s1, *s2, *this; + bool error = false; s1 = *str; if (s1 == NULL) - return; + return false; /* * If maxsize is 0 then set it to the length of s1, because we have * to duplicate s1. XXX we maybe should double-check whether the match @@ -67,6 +71,7 @@ strnsubst(char **str, const char *match, const char *replstr, size_t maxsize) if ((strlen(s2) + strlen(s1) + strlen(replstr) - strlen(match) + 1) > maxsize) { strlcat(s2, s1, maxsize); + error = true; goto done; } strncat(s2, s1, (uintptr_t)this - (uintptr_t)s1); @@ -76,7 +81,7 @@ strnsubst(char **str, const char *match, const char *replstr, size_t maxsize) strcat(s2, s1); done: *str = s2; - return; + return error; } #ifdef TEST diff --git a/usr.bin/xargs/xargs.c b/usr.bin/xargs/xargs.c index 2825a26f4dfa..7b664cfde1cc 100644 --- a/usr.bin/xargs/xargs.c +++ b/usr.bin/xargs/xargs.c @@ -61,6 +61,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -73,7 +74,7 @@ static void prerun(int, char *[]); static int prompt(void); static void run(char **); static void usage(void); -void strnsubst(char **, const char *, const char *, size_t); +bool strnsubst(char **, const char *, const char *, size_t); static pid_t xwait(int block, int *status); static void xexit(const char *, const int); static void waitchildren(const char *, int); @@ -517,7 +518,10 @@ prerun(int argc, char *argv[]) while (--argc) { *tmp = *avj++; if (repls && strstr(*tmp, replstr) != NULL) { - strnsubst(tmp++, replstr, inpline, (size_t)Sflag); + if (strnsubst(tmp++, replstr, inpline, (size_t)Sflag)) { + warnx("comamnd line cannot be assembled, too long"); + xexit(*argv, 1); + } if (repls > 0) repls--; } else {