Module Name:    othersrc
Committed By:   lukem
Date:           Wed Jan 23 05:13:48 UTC 2019

Modified Files:
        othersrc/libexec/tnftpd/libnetbsd: fnmatch.c ftpfnmatch.h

Log Message:
sync to fnmatch.c 1.26, fnmatch.h

Update from NetBSD src/lib/libc/gen/fnmatch.c 1.18 to 1.26.
Update from NetBSD src/include/fnmatch.h 1.8 to 1.13.

Notable changes:
- Implement FNM_LEADING_DIR.
- Limit recursions to avoid DoS attacks. From Maksymilian Arciemowicz.
- Treat a backslash followed by NUL as NUL.


To generate a diff of this commit:
cvs rdiff -u -r1.3 -r1.4 othersrc/libexec/tnftpd/libnetbsd/fnmatch.c \
    othersrc/libexec/tnftpd/libnetbsd/ftpfnmatch.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: othersrc/libexec/tnftpd/libnetbsd/fnmatch.c
diff -u othersrc/libexec/tnftpd/libnetbsd/fnmatch.c:1.3 othersrc/libexec/tnftpd/libnetbsd/fnmatch.c:1.4
--- othersrc/libexec/tnftpd/libnetbsd/fnmatch.c:1.3	Sun Sep 21 16:35:25 2008
+++ othersrc/libexec/tnftpd/libnetbsd/fnmatch.c	Wed Jan 23 05:13:48 2019
@@ -1,5 +1,5 @@
-/* $NetBSD: fnmatch.c,v 1.3 2008/09/21 16:35:25 lukem Exp $ */
-/* from NetBSD: fnmatch.c,v 1.18 2000/06/28 01:13:36 thorpej Exp */
+/* $NetBSD: fnmatch.c,v 1.4 2019/01/23 05:13:48 lukem Exp $ */
+/* from NetBSD: fnmatch.c,v 1.26 2014/10/12 22:32:33 christos Exp */
 
 /*
  * Copyright (c) 1989, 1993, 1994
@@ -42,38 +42,83 @@
 
 #define	EOS	'\0'
 
-static const char *rangematch(const char *, int, int);
-
-static int
+static inline int
 foldcase(int ch, int flags)
 {
 
 	if ((flags & FNM_CASEFOLD) != 0 && isupper(ch))
-		return (tolower(ch));
-	return (ch);
+		return tolower(ch);
+	return ch;
 }
 
 #define	FOLDCASE(ch, flags)	foldcase((unsigned char)(ch), (flags))
 
-int
-fnmatch(const char *pattern, const char *string, int flags)
+static const char *
+rangematch(const char *pattern, int test, int flags)
 {
-	const char *stringstart;
+	int negate, ok, need;
+	char c, c2;
+
+	/*
+	 * A bracket expression starting with an unquoted circumflex
+	 * character produces unspecified results (IEEE 1003.2-1992,
+	 * 3.13.2).  This implementation treats it like '!', for
+	 * consistency with the regular expression syntax.
+	 * J.T. Conklin (conk...@ngai.kaleida.com)
+	 */
+	if ((negate = (*pattern == '!' || *pattern == '^')) != 0)
+		++pattern;
+	
+	need = 1;
+	for (ok = 0; (c = FOLDCASE(*pattern++, flags)) != ']' || need;) {
+		need = 0;
+		if (c == '/')
+			return (void *)-1;
+		if (c == '\\' && !(flags & FNM_NOESCAPE))
+			c = FOLDCASE(*pattern++, flags);
+		if (c == EOS)
+			return NULL;
+		if (*pattern == '-' 
+		    && (c2 = FOLDCASE(*(pattern + 1), flags)) != EOS &&
+		        c2 != ']') {
+			pattern += 2;
+			if (c2 == '\\' && !(flags & FNM_NOESCAPE))
+				c2 = FOLDCASE(*pattern++, flags);
+			if (c2 == EOS)
+				return NULL;
+			if (c <= test && test <= c2)
+				ok = 1;
+		} else if (c == test)
+			ok = 1;
+	}
+	return ok == negate ? NULL : pattern;
+}
+
+
+static int
+fnmatchx(const char *pattern, const char *string, int flags, size_t recursion)
+{
+	const char *stringstart, *r;
 	char c, test;
 
-	for (stringstart = string;;)
+	if (recursion-- == 0)
+		return FNM_NORES;
+
+	for (stringstart = string;;) {
 		switch (c = FOLDCASE(*pattern++, flags)) {
 		case EOS:
-			return (*string == EOS ? 0 : FNM_NOMATCH);
+			if ((flags & FNM_LEADING_DIR) && *string == '/')
+				return 0;
+			return *string == EOS ? 0 : FNM_NOMATCH;
 		case '?':
 			if (*string == EOS)
-				return (FNM_NOMATCH);
+				return FNM_NOMATCH;
 			if (*string == '/' && (flags & FNM_PATHNAME))
-				return (FNM_NOMATCH);
+				return FNM_NOMATCH;
 			if (*string == '.' && (flags & FNM_PERIOD) &&
 			    (string == stringstart ||
 			    ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
-				return (FNM_NOMATCH);
+				return FNM_NOMATCH;
 			++string;
 			break;
 		case '*':
@@ -85,91 +130,71 @@ fnmatch(const char *pattern, const char 
 			if (*string == '.' && (flags & FNM_PERIOD) &&
 			    (string == stringstart ||
 			    ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
-				return (FNM_NOMATCH);
+				return FNM_NOMATCH;
 
 			/* Optimize for pattern with * at end or before /. */
 			if (c == EOS) {
 				if (flags & FNM_PATHNAME)
-					return (strchr(string, '/') == NULL ?
-					    0 : FNM_NOMATCH);
+					return (flags & FNM_LEADING_DIR) ||
+					    strchr(string, '/') == NULL ?
+					    0 : FNM_NOMATCH;
 				else
-					return (0);
+					return 0;
 			} else if (c == '/' && flags & FNM_PATHNAME) {
 				if ((string = strchr(string, '/')) == NULL)
-					return (FNM_NOMATCH);
+					return FNM_NOMATCH;
 				break;
 			}
 
 			/* General case, use recursion. */
 			while ((test = FOLDCASE(*string, flags)) != EOS) {
-				if (!fnmatch(pattern, string,
-					     flags & ~FNM_PERIOD))
-					return (0);
+				int e;
+				switch ((e = fnmatchx(pattern, string,
+				    flags & ~FNM_PERIOD, recursion))) {
+				case FNM_NOMATCH:
+					break;
+				default:
+					return e;
+				}
 				if (test == '/' && flags & FNM_PATHNAME)
 					break;
 				++string;
 			}
-			return (FNM_NOMATCH);
+			return FNM_NOMATCH;
 		case '[':
 			if (*string == EOS)
-				return (FNM_NOMATCH);
+				return FNM_NOMATCH;
 			if (*string == '/' && flags & FNM_PATHNAME)
-				return (FNM_NOMATCH);
-			if ((pattern =
-			    rangematch(pattern, FOLDCASE(*string, flags),
-				       flags)) == NULL)
-				return (FNM_NOMATCH);
+				return FNM_NOMATCH;
+			if ((r = rangematch(pattern,
+			    FOLDCASE(*string, flags), flags)) == NULL)
+				return FNM_NOMATCH;
+			if (r == (void *)-1) {
+				if (*string != '[')
+					return FNM_NOMATCH;
+			} else
+				pattern = r;
 			++string;
 			break;
 		case '\\':
 			if (!(flags & FNM_NOESCAPE)) {
 				if ((c = FOLDCASE(*pattern++, flags)) == EOS) {
-					c = '\\';
+					c = '\0';
 					--pattern;
 				}
 			}
 			/* FALLTHROUGH */
 		default:
 			if (c != FOLDCASE(*string++, flags))
-				return (FNM_NOMATCH);
+				return FNM_NOMATCH;
 			break;
 		}
+	}
 	/* NOTREACHED */
 }
 
-static const char *
-rangematch(const char *pattern, int test, int flags)
+int
+fnmatch(const char *pattern, const char *string, int flags)
 {
-	int negate, ok;
-	char c, c2;
-
-	/*
-	 * A bracket expression starting with an unquoted circumflex
-	 * character produces unspecified results (IEEE 1003.2-1992,
-	 * 3.13.2).  This implementation treats it like '!', for
-	 * consistency with the regular expression syntax.
-	 * J.T. Conklin (conk...@ngai.kaleida.com)
-	 */
-	if ((negate = (*pattern == '!' || *pattern == '^')) != 0)
-		++pattern;
-	
-	for (ok = 0; (c = FOLDCASE(*pattern++, flags)) != ']';) {
-		if (c == '\\' && !(flags & FNM_NOESCAPE))
-			c = FOLDCASE(*pattern++, flags);
-		if (c == EOS)
-			return (NULL);
-		if (*pattern == '-' 
-		    && (c2 = FOLDCASE(*(pattern+1), flags)) != EOS &&
-		        c2 != ']') {
-			pattern += 2;
-			if (c2 == '\\' && !(flags & FNM_NOESCAPE))
-				c2 = FOLDCASE(*pattern++, flags);
-			if (c2 == EOS)
-				return (NULL);
-			if (c <= test && test <= c2)
-				ok = 1;
-		} else if (c == test)
-			ok = 1;
-	}
-	return (ok == negate ? NULL : pattern);
+	return fnmatchx(pattern, string, flags, 64);
 }
Index: othersrc/libexec/tnftpd/libnetbsd/ftpfnmatch.h
diff -u othersrc/libexec/tnftpd/libnetbsd/ftpfnmatch.h:1.3 othersrc/libexec/tnftpd/libnetbsd/ftpfnmatch.h:1.4
--- othersrc/libexec/tnftpd/libnetbsd/ftpfnmatch.h:1.3	Sun Sep 21 16:35:25 2008
+++ othersrc/libexec/tnftpd/libnetbsd/ftpfnmatch.h	Wed Jan 23 05:13:48 2019
@@ -1,5 +1,5 @@
-/* $NetBSD: ftpfnmatch.h,v 1.3 2008/09/21 16:35:25 lukem Exp $ */
-/* from	NetBSD: fnmatch.h,v 1.8 2001/10/27 15:41:18 kleink Exp */
+/* $NetBSD: ftpfnmatch.h,v 1.4 2019/01/23 05:13:48 lukem Exp $ */
+/* from NetBSD: fnmatch.h,v 1.13 2011/01/31 04:49:46 christos Exp */
 
 /*-
  * Copyright (c) 1992, 1993
@@ -37,11 +37,13 @@
 
 #define	FNM_NOMATCH	1	/* Match failed. */
 #define	FNM_NOSYS	2	/* Function not implemented. */
+#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_PERIOD	0x04	/* Period must be matched by period. */
 #define	FNM_CASEFOLD	0x08	/* Pattern is matched case-insensitive */
+#define	FNM_LEADING_DIR	0x10	/* Ignore /<tail> after Imatch. */
 
 int	 fnmatch(const char *, const char *, int);
 

Reply via email to