Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/lib/libc/gen Switch from a recursive pattern matching algori...
details: https://anonhg.NetBSD.org/src/rev/6add84883f1e
branches: trunk
changeset: 353270:6add84883f1e
user: christos <christos%NetBSD.org@localhost>
date: Wed Apr 26 14:56:54 2017 +0000
description:
Switch from a recursive pattern matching algorithm to handle '*'
to a backtracking one. Avoids DoS attacks with patterns "a*a*a*a*a*...b"
matching against "aaaaaaaaaaaa..." https://research.swtch.com/glob
diffstat:
lib/libc/gen/glob.c | 65 ++++++++++++++++++++++++++++++++--------------------
1 files changed, 40 insertions(+), 25 deletions(-)
diffs (112 lines):
diff -r a864bcafb2e0 -r 6add84883f1e lib/libc/gen/glob.c
--- a/lib/libc/gen/glob.c Wed Apr 26 14:52:57 2017 +0000
+++ b/lib/libc/gen/glob.c Wed Apr 26 14:56:54 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: glob.c,v 1.36 2016/09/04 18:27:08 joerg Exp $ */
+/* $NetBSD: glob.c,v 1.37 2017/04/26 14:56:54 christos Exp $ */
/*
* Copyright (c) 1989, 1993
@@ -37,7 +37,7 @@
#if 0
static char sccsid[] = "@(#)glob.c 8.3 (Berkeley) 10/13/93";
#else
-__RCSID("$NetBSD: glob.c,v 1.36 2016/09/04 18:27:08 joerg Exp $");
+__RCSID("$NetBSD: glob.c,v 1.37 2017/04/26 14:56:54 christos Exp $");
#endif
#endif /* LIBC_SCCS and not lint */
@@ -936,39 +936,45 @@
/*
- * pattern matching function for filenames. Each occurrence of the *
- * pattern causes a recursion level.
+ * pattern matching function for filenames.
*/
static int
match(const Char *name, const Char *pat, const Char *patend)
{
int ok, negate_range;
Char c, k;
+ const Char *patNext, *nameNext, *nameStart, *nameEnd;
_DIAGASSERT(name != NULL);
_DIAGASSERT(pat != NULL);
_DIAGASSERT(patend != NULL);
+ patNext = pat;
+ nameStart = nameNext = name;
+ nameEnd = NULL;
- while (pat < patend) {
- c = *pat++;
+ while (pat < patend || *name) {
+ c = *pat;
+ if (*name == EOS)
+ nameEnd = name;
switch (c & M_MASK) {
case M_ALL:
- while (pat < patend && (*pat & M_MASK) == M_ALL)
- pat++; /* eat consecutive '*' */
- if (pat == patend)
- return 1;
- for (; !match(name, pat, patend); name++)
- if (*name == EOS)
- return 0;
- return 1;
+ while (pat[1] == '*') pat++;
+ patNext = pat;
+ nameNext = name + 1;
+ pat++;
+ continue;
case M_ONE:
- if (*name++ == EOS)
- return 0;
- break;
+ if (*name == EOS)
+ break;
+ pat++;
+ name++;
+ continue;
case M_SET:
ok = 0;
- if ((k = *name++) == EOS)
- return 0;
+ if ((k = *name) == EOS)
+ break;
+ pat++;
+ name++;
if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS)
++pat;
while (((c = *pat++) & M_MASK) != M_END)
@@ -979,15 +985,24 @@
} else if (c == k)
ok = 1;
if (ok == negate_range)
- return 0;
- break;
+ break;
+ continue;
default:
- if (*name++ != c)
- return 0;
- break;
+ if (*name != c)
+ break;
+ pat++;
+ name++;
+ continue;
}
+ if (nameNext != nameStart
+ && (nameEnd == NULL || nameNext <= nameEnd)) {
+ pat = patNext;
+ name = nameNext;
+ continue;
+ }
+ return 0;
}
- return *name == EOS;
+ return 1;
}
/* Free allocated data belonging to a glob_t structure. */
Home |
Main Index |
Thread Index |
Old Index