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);