Skip site navigation (1)Skip section navigation (2)
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>