summaryrefslogtreecommitdiffstats
path: root/openbsd-compat
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2019-11-15 16:05:07 +1100
committerDamien Miller <djm@mindrot.org>2019-11-15 16:05:07 +1100
commit2cfb11abac85885de0cb888bbeb9a3e4303105ea (patch)
tree711364302c2f9a0dacef45ab451123c12af5c2a4 /openbsd-compat
parent228dd595c7882bb9b161dbb7d4dca15c8a5f03f5 (diff)
upstream commit
revision 1.47 date: 2017/05/08 14:53:27; author: millert; state: Exp; lines: +34 -21; commitid: sYfxfyUHAfarP8sE; Fix exponential CPU use with repeated '*' operators by changing '*' handling to be interative instead of recursive. Fix by Yves Orton, ported to OpenBSD glob.c by Ray Lai. OK tb@
Diffstat (limited to 'openbsd-compat')
-rw-r--r--openbsd-compat/glob.c55
1 files changed, 34 insertions, 21 deletions
diff --git a/openbsd-compat/glob.c b/openbsd-compat/glob.c
index 413dfc8c..27710b4d 100644
--- a/openbsd-compat/glob.c
+++ b/openbsd-compat/glob.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: glob.c,v 1.46 2015/12/28 22:08:18 mmcc Exp $ */
+/* $OpenBSD: glob.c,v 1.47 2017/05/08 14:53:27 millert Exp $ */
/*
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
@@ -137,9 +137,6 @@ typedef char Char;
#define GLOB_LIMIT_STAT 2048
#define GLOB_LIMIT_READDIR 16384
-/* Limit of recursion during matching attempts. */
-#define GLOB_LIMIT_RECUR 64
-
struct glob_lim {
size_t glim_malloc;
size_t glim_stat;
@@ -172,7 +169,7 @@ static const Char *
static int globexp1(const Char *, glob_t *, struct glob_lim *);
static int globexp2(const Char *, const Char *, glob_t *,
struct glob_lim *);
-static int match(Char *, Char *, Char *, int);
+static int match(Char *, Char *, Char *);
#ifdef DEBUG
static void qprintf(const char *, Char *);
#endif
@@ -763,7 +760,7 @@ glob3(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last,
break;
}
- if (!match(pathend, pattern, restpattern, GLOB_LIMIT_RECUR)) {
+ if (!match(pathend, pattern, restpattern)) {
*pathend = EOS;
continue;
}
@@ -893,17 +890,24 @@ globextend(const Char *path, glob_t *pglob, struct glob_lim *limitp,
/*
* pattern matching function for filenames. Each occurrence of the *
- * pattern causes a recursion level.
+ * pattern causes an iteration.
+ *
+ * Note, this function differs from the original as per the discussion
+ * here: https://research.swtch.com/glob
+ *
+ * Basically we removed the recursion and made it use the algorithm
+ * from Russ Cox to not go quadratic on cases like a file called
+ * ("a" x 100) . "x" matched against a pattern like "a*a*a*a*a*a*a*y".
*/
static int
-match(Char *name, Char *pat, Char *patend, int recur)
+match(Char *name, Char *pat, Char *patend)
{
int ok, negate_range;
Char c, k;
+ Char *nextp = NULL;
+ Char *nextn = NULL;
- if (recur-- == 0)
- return(GLOB_NOSPACE);
-
+loop:
while (pat < patend) {
c = *pat++;
switch (c & M_MASK) {
@@ -912,19 +916,19 @@ match(Char *name, Char *pat, Char *patend, int recur)
pat++; /* eat consecutive '*' */
if (pat == patend)
return(1);
- do {
- if (match(name, pat, patend, recur))
- return(1);
- } while (*name++ != EOS);
- return(0);
+ if (*name == EOS)
+ return(0);
+ nextn = name + 1;
+ nextp = pat - 1;
+ break;
case M_ONE:
if (*name++ == EOS)
- return(0);
+ goto fail;
break;
case M_SET:
ok = 0;
if ((k = *name++) == EOS)
- return(0);
+ goto fail;
if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS)
++pat;
while (((c = *pat++) & M_MASK) != M_END) {
@@ -943,15 +947,24 @@ match(Char *name, Char *pat, Char *patend, int recur)
ok = 1;
}
if (ok == negate_range)
- return(0);
+ goto fail;
break;
default:
if (*name++ != c)
- return(0);
+ goto fail;
break;
}
}
- return(*name == EOS);
+ if (*name == EOS)
+ return(1);
+
+fail:
+ if (nextn) {
+ pat = nextp;
+ name = nextn;
+ goto loop;
+ }
+ return(0);
}
/* Free allocated data belonging to a glob_t structure. */