summaryrefslogtreecommitdiffstats
path: root/usr.bin/find
diff options
context:
space:
mode:
authorjilles <jilles@FreeBSD.org>2015-08-28 20:53:08 +0000
committerjilles <jilles@FreeBSD.org>2015-08-28 20:53:08 +0000
commit461d06c693c3223ca34cea5045561db8eab04880 (patch)
tree95afb4bdf6c2df78b6446422273e67f919cac46e /usr.bin/find
parent655a5b9a1671aa2e1c7c81a6aabd4e7792f8dab5 (diff)
downloadFreeBSD-src-461d06c693c3223ca34cea5045561db8eab04880.zip
FreeBSD-src-461d06c693c3223ca34cea5045561db8eab04880.tar.gz
MFC r286344: 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
Diffstat (limited to 'usr.bin/find')
-rw-r--r--usr.bin/find/extern.h2
-rw-r--r--usr.bin/find/misc.c38
2 files changed, 25 insertions, 15 deletions
diff --git a/usr.bin/find/extern.h b/usr.bin/find/extern.h
index 90b9b29..357b09c 100644
--- a/usr.bin/find/extern.h
+++ b/usr.bin/find/extern.h
@@ -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 **);
diff --git a/usr.bin/find/misc.c b/usr.bin/find/misc.c
index 11a26be..df2e502 100644
--- a/usr.bin/find/misc.c
+++ b/usr.bin/find/misc.c
@@ -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);
}
/*
OpenPOWER on IntegriCloud