Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 5 Aug 2015 21:33:31 +0000 (UTC)
From:      Jilles Tjoelker <jilles@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r286344 - head/usr.bin/find
Message-ID:  <201508052133.t75LXVoI049908@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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);
 }
 
 /*



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201508052133.t75LXVoI049908>