svn commit: r286344 - head/usr.bin/find

Jilles Tjoelker jilles at FreeBSD.org
Wed Aug 5 21:33:32 UTC 2015


Author: jilles
Date: Wed Aug  5 21:33:30 2015
New Revision: 286344
URL: https://svnweb.freebsd.org/changeset/base/286344

Log:
  find: Fix segfault with very long path in -exec/-ok ... {} \;.
  
  If the resulting argument is longer than MAXPATHLEN, realloc() was called to
  extend the space, but the new pointer was not correctly stored.
  
  Different from what OpenBSD has done, rewrite brace_subst() to calculate the
  necessary space first and realloc() at most once.
  
  As before, the e_len fields are not updated in case of a realloc.
  Therefore, a following long argument will do another realloc.
  
  PR:		201750
  MFC after:	1 week

Modified:
  head/usr.bin/find/extern.h
  head/usr.bin/find/misc.c

Modified: head/usr.bin/find/extern.h
==============================================================================
--- head/usr.bin/find/extern.h	Wed Aug  5 21:22:25 2015	(r286343)
+++ head/usr.bin/find/extern.h	Wed Aug  5 21:33:30 2015	(r286344)
@@ -32,7 +32,7 @@
 
 #include <sys/cdefs.h>
 
-void	 brace_subst(char *, char **, char *, int);
+void	 brace_subst(char *, char **, char *, size_t);
 PLAN	*find_create(char ***);
 int	 find_execute(PLAN *, char **);
 PLAN	*find_formplan(char **);

Modified: head/usr.bin/find/misc.c
==============================================================================
--- head/usr.bin/find/misc.c	Wed Aug  5 21:22:25 2015	(r286343)
+++ head/usr.bin/find/misc.c	Wed Aug  5 21:33:30 2015	(r286344)
@@ -57,23 +57,33 @@ __FBSDID("$FreeBSD$");
  *	Replace occurrences of {} in s1 with s2 and return the result string.
  */
 void
-brace_subst(char *orig, char **store, char *path, int len)
+brace_subst(char *orig, char **store, char *path, size_t len)
 {
-	int plen;
-	char ch, *p;
+	const char *pastorigend, *p, *q;
+	char *dst;
+	size_t newlen, plen;
 
 	plen = strlen(path);
-	for (p = *store; (ch = *orig) != '\0'; ++orig)
-		if (ch == '{' && orig[1] == '}') {
-			while ((p - *store) + plen > len)
-				if (!(*store = realloc(*store, len *= 2)))
-					err(1, NULL);
-			memmove(p, path, plen);
-			p += plen;
-			++orig;
-		} else
-			*p++ = ch;
-	*p = '\0';
+	newlen = strlen(orig) + 1;
+	pastorigend = orig + newlen;
+	for (p = orig; (q = strstr(p, "{}")) != NULL; p = q + 2) {
+		if (plen > 2 && newlen + plen - 2 < newlen)
+			errx(2, "brace_subst overflow");
+		newlen += plen - 2;
+	}
+	if (newlen > len) {
+		*store = reallocf(*store, newlen);
+		if (*store == NULL)
+			err(2, NULL);
+	}
+	dst = *store;
+	for (p = orig; (q = strstr(p, "{}")) != NULL; p = q + 2) {
+		memcpy(dst, p, q - p);
+		dst += q - p;
+		memcpy(dst, path, plen);
+		dst += plen;
+	}
+	memcpy(dst, p, pastorigend - p);
 }
 
 /*


More information about the svn-src-head mailing list