Date: Wed, 8 Aug 2018 21:21:29 +0000 (UTC) From: Kyle Evans <kevans@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r337504 - head/usr.bin/apply Message-ID: <201808082121.w78LLTwb021886@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: kevans Date: Wed Aug 8 21:21:28 2018 New Revision: 337504 URL: https://svnweb.freebsd.org/changeset/base/337504 Log: apply(1): Fix magic number substitution with magic character ' ' Using a space as the magic character would result in problems if the command started with a number: - For a 'valid' number n, n < size of argv, it would erroneously get replaced with that argument; e.g. `apply -a ' ' -d 1rm x => `execxrm x` - For an 'invalid' number n, n >= size of argv, it would segfault. e.g. `apply -a ' ' 2to3 test.py` would try to access argv[2] This problem occurred because apply(1) would prepend "exec " to the command string before doing the actual magic number replacements, so it would come across "exec 2to3 1" and assume that the " 2" is also a magic number to be replaced. Re-work this to instead just append "exec " to the command sbuf and workaround the ugliness. This also simplifies stuff in the process. PR: 226948 Submitted by: Tobias Stoeckmann <tobias@stoeckmann.org> MFC after: 1 week Modified: head/usr.bin/apply/apply.c Modified: head/usr.bin/apply/apply.c ============================================================================== --- head/usr.bin/apply/apply.c Wed Aug 8 21:19:07 2018 (r337503) +++ head/usr.bin/apply/apply.c Wed Aug 8 21:21:28 2018 (r337504) @@ -55,7 +55,8 @@ __FBSDID("$FreeBSD$"); #include <string.h> #include <unistd.h> -#define EXEC "exec " +#define ISMAGICNO(p) \ + (p)[0] == magic && isdigit((unsigned char)(p)[1]) && (p)[1] != '0' static int exec_shell(const char *, const char *, const char *); static void usage(void); @@ -65,8 +66,9 @@ main(int argc, char *argv[]) { struct sbuf *cmdbuf; long arg_max; - int ch, debug, i, magic, n, nargs, offset, rval; + int ch, debug, i, magic, n, nargs, rval; size_t cmdsize; + char buf[4]; char *cmd, *name, *p, *shell, *slashp, *tmpshell; debug = 0; @@ -75,7 +77,7 @@ main(int argc, char *argv[]) while ((ch = getopt(argc, argv, "a:d0123456789")) != -1) switch (ch) { case 'a': - if (optarg[1] != '\0') + if (optarg[0] == '\0' || optarg[1] != '\0') errx(1, "illegal magic character specification"); magic = optarg[0]; @@ -105,7 +107,7 @@ main(int argc, char *argv[]) * largest one. */ for (n = 0, p = argv[0]; *p != '\0'; ++p) - if (p[0] == magic && isdigit(p[1]) && p[1] != '0') { + if (ISMAGICNO(p)) { ++p; if (p[0] - '0' > n) n = p[0] - '0'; @@ -134,28 +136,19 @@ main(int argc, char *argv[]) * Allocate enough space to hold the maximum command. Save the * size to pass to snprintf(). */ - cmdsize = sizeof(EXEC) - 1 + strlen(argv[0]) - + 9 * (sizeof(" %1") - 1) + 1; - if ((cmd = malloc(cmdsize)) == NULL) - err(1, NULL); - if (n == 0) { + cmdsize = strlen(argv[0]) + 9 * (sizeof(" %1") - 1) + 1; + if ((cmd = malloc(cmdsize)) == NULL) + err(1, NULL); + strlcpy(cmd, argv[0], cmdsize); + /* If nargs not set, default to a single argument. */ if (nargs == -1) nargs = 1; - p = cmd; - offset = snprintf(cmd, cmdsize, EXEC "%s", argv[0]); - if ((size_t)offset >= cmdsize) - errx(1, "snprintf() failed"); - p += offset; - cmdsize -= offset; for (i = 1; i <= nargs; i++) { - offset = snprintf(p, cmdsize, " %c%d", magic, i); - if ((size_t)offset >= cmdsize) - errx(1, "snprintf() failed"); - p += offset; - cmdsize -= offset; + snprintf(buf, sizeof(buf), " %c%d", magic, i); + strlcat(cmd, buf, cmdsize); } /* @@ -165,9 +158,8 @@ main(int argc, char *argv[]) if (nargs == 0) nargs = 1; } else { - offset = snprintf(cmd, cmdsize, EXEC "%s", argv[0]); - if ((size_t)offset >= cmdsize) - errx(1, "snprintf() failed"); + if ((cmd = strdup(argv[0])) == NULL) + err(1, NULL); nargs = n; } @@ -184,9 +176,10 @@ main(int argc, char *argv[]) */ for (rval = 0; argc > nargs; argc -= nargs, argv += nargs) { sbuf_clear(cmdbuf); + sbuf_cat(cmdbuf, "exec "); /* Expand command argv references. */ for (p = cmd; *p != '\0'; ++p) { - if (p[0] == magic && isdigit(p[1]) && p[1] != '0') { + if (ISMAGICNO(p)) { if (sbuf_cat(cmdbuf, argv[(++p)[0] - '0']) == -1) errc(1, ENOMEM, "sbuf");
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201808082121.w78LLTwb021886>