Commit d5a51910678f8aea2b7efe077efc678141762dfc

Russell Belfer 2012-10-11T13:39:53

Import DOS fix for fnmatch Because fnmatch uses recursion, there were some input sequences that cause seriously degenerate behavior. This imports a fix that imposes a max recursion limiter to avoid the worst of it.

diff --git a/src/fnmatch.c b/src/fnmatch.c
index 835d811..f394274 100644
--- a/src/fnmatch.c
+++ b/src/fnmatch.c
@@ -24,13 +24,16 @@
 
 static int rangematch(const char *, char, int, char **);
 
-int
-p_fnmatch(const char *pattern, const char *string, int flags)
+static int
+p_fnmatchx(const char *pattern, const char *string, int flags, size_t recurs)
 {
 		const char *stringstart;
 		char *newp;
 		char c, test;
 
+		if (recurs-- == 0)
+				return FNM_NORES;
+
 		for (stringstart = string;;)
 				switch (c = *pattern++) {
 				case EOS:
@@ -75,8 +78,11 @@ p_fnmatch(const char *pattern, const char *string, int flags)
 
 						/* General case, use recursion. */
 						while ((test = *string) != EOS) {
-								if (!p_fnmatch(pattern, string, flags & ~FNM_PERIOD))
-										return (0);
+								int e;
+
+								e = p_fnmatchx(pattern, string, flags & ~FNM_PERIOD, recurs);
+								if (e != FNM_NOMATCH)
+										return e;
 								if (test == '/' && (flags & FNM_PATHNAME))
 										break;
 								++string;
@@ -178,3 +184,9 @@ rangematch(const char *pattern, char test, int flags, char **newp)
 		return (ok == negate ? RANGE_NOMATCH : RANGE_MATCH);
 }
 
+int
+p_fnmatch(const char *pattern, const char *string, int flags)
+{
+		return p_fnmatchx(pattern, string, flags, 64);
+}
+
diff --git a/src/fnmatch.h b/src/fnmatch.h
index 7faef09..913efd1 100644
--- a/src/fnmatch.h
+++ b/src/fnmatch.h
@@ -11,12 +11,13 @@
 
 #define FNM_NOMATCH		1		/* Match failed. */
 #define FNM_NOSYS		2		/* Function not supported (unused). */
+#define	FNM_NORES		3		/* Out of resources */
 
-#define FNM_NOESCAPE		0x01		/* Disable backslash escaping. */
-#define FNM_PATHNAME		0x02		/* Slash must be matched by slash. */
+#define FNM_NOESCAPE	0x01		/* Disable backslash escaping. */
+#define FNM_PATHNAME	0x02		/* Slash must be matched by slash. */
 #define FNM_PERIOD		0x04		/* Period must be matched by period. */
 #define FNM_LEADING_DIR 0x08		/* Ignore /<tail> after Imatch. */
-#define FNM_CASEFOLD		0x10		/* Case insensitive search. */
+#define FNM_CASEFOLD	0x10		/* Case insensitive search. */
 
 #define FNM_IGNORECASE	FNM_CASEFOLD
 #define FNM_FILE_NAME	FNM_PATHNAME