#define RANGE_NOMATCH 0
#define RANGE_ERROR (-1)
+/* Limit of recursion during matching attempts. */
+#define FNM_MAX_RECUR 64
+
#define ISSET(x, y) ((x) & (y))
#define FOLD(c) ((flags & FNM_CASEFOLD) && B_ISUPPER(c) ? tolower(c) : (c))
static int rangematch(const char *, char, int, char **);
+static int r_fnmatch(const char *, const char *, int, int);
#ifdef SYS
int xfnmatch(const char *pattern, const char *string, int flags)
#else
int fnmatch(const char *pattern, const char *string, int flags)
#endif
+{
+ int e;
+
+ e = r_fnmatch(pattern, string, flags, FNM_MAX_RECUR);
+ if (e == -1) { /* Too much recursion */
+ e = FNM_NOMATCH;
+ }
+ return (e);
+}
+
+static
+int r_fnmatch(const char *pattern, const char *string, int flags, int recur)
{
const char *stringstart;
char *newp;
char c, test;
+ int e;
+
+ if (recur-- <= 0) {
+ return (-1);
+ }
stringstart = string;
for ( ;; ) {
/* General case, use recursion. */
while ((test = *string) != EOS) {
- if (!fnmatch(pattern, string, flags & ~FNM_PERIOD)) {
- return (0);
+ e = r_fnmatch(pattern, string, flags & ~FNM_PERIOD, recur);
+ if (e != FNM_NOMATCH) { /* can be NOMATCH, -1 or MATCH */
+ return (e);
}
if (test == '/' && ISSET(flags, FNM_PATHNAME)) {
break;
/*10*/ {"x*", "x", FNM_PATHNAME | FNM_LEADING_DIR, 0},
{"x*", "x/y", FNM_PATHNAME | FNM_LEADING_DIR, 0},
{"x*", "x/y/z", FNM_PATHNAME | FNM_LEADING_DIR, 0},
- {"a*b/*", "abbb/.x", FNM_PATHNAME|FNM_PERIOD, FNM_NOMATCH}, /* ??? */
+ {"a*b/*", "abbb/.x", FNM_PATHNAME|FNM_PERIOD, FNM_NOMATCH},
{"a*b/*", "abbb/xy", FNM_PATHNAME|FNM_PERIOD, 0},
/*15*/ {"[A-[]", "A", 0, 0},
{"[A-[]", "a", 0, FNM_NOMATCH},
{ "a*b", "a.b", FNM_PATHNAME|FNM_PERIOD, 0 },
{ "a[.]b", "a.b", FNM_PATHNAME|FNM_PERIOD, 0 },
/*49*/ { "*a*", "a/b", FNM_PATHNAME|FNM_LEADING_DIR, 0 },
+ { "[/b", "[/b", 0, 0},
#ifdef FULL_TEST
/* This test takes a *long* time */
{"a*b*c*d*e*f*g*h*i*j*k*l*m*n*o*p*q*r*s*t*u*v*w*x*y*z*",