diff options
-rw-r--r-- | openbsd-compat/glob.c | 55 |
1 files changed, 34 insertions, 21 deletions
diff --git a/openbsd-compat/glob.c b/openbsd-compat/glob.c index 413dfc8cb..27710b4d6 100644 --- a/openbsd-compat/glob.c +++ b/openbsd-compat/glob.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: glob.c,v 1.46 2015/12/28 22:08:18 mmcc Exp $ */ | 1 | /* $OpenBSD: glob.c,v 1.47 2017/05/08 14:53:27 millert Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 1989, 1993 | 3 | * Copyright (c) 1989, 1993 |
4 | * The Regents of the University of California. All rights reserved. | 4 | * The Regents of the University of California. All rights reserved. |
@@ -137,9 +137,6 @@ typedef char Char; | |||
137 | #define GLOB_LIMIT_STAT 2048 | 137 | #define GLOB_LIMIT_STAT 2048 |
138 | #define GLOB_LIMIT_READDIR 16384 | 138 | #define GLOB_LIMIT_READDIR 16384 |
139 | 139 | ||
140 | /* Limit of recursion during matching attempts. */ | ||
141 | #define GLOB_LIMIT_RECUR 64 | ||
142 | |||
143 | struct glob_lim { | 140 | struct glob_lim { |
144 | size_t glim_malloc; | 141 | size_t glim_malloc; |
145 | size_t glim_stat; | 142 | size_t glim_stat; |
@@ -172,7 +169,7 @@ static const Char * | |||
172 | static int globexp1(const Char *, glob_t *, struct glob_lim *); | 169 | static int globexp1(const Char *, glob_t *, struct glob_lim *); |
173 | static int globexp2(const Char *, const Char *, glob_t *, | 170 | static int globexp2(const Char *, const Char *, glob_t *, |
174 | struct glob_lim *); | 171 | struct glob_lim *); |
175 | static int match(Char *, Char *, Char *, int); | 172 | static int match(Char *, Char *, Char *); |
176 | #ifdef DEBUG | 173 | #ifdef DEBUG |
177 | static void qprintf(const char *, Char *); | 174 | static void qprintf(const char *, Char *); |
178 | #endif | 175 | #endif |
@@ -763,7 +760,7 @@ glob3(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, | |||
763 | break; | 760 | break; |
764 | } | 761 | } |
765 | 762 | ||
766 | if (!match(pathend, pattern, restpattern, GLOB_LIMIT_RECUR)) { | 763 | if (!match(pathend, pattern, restpattern)) { |
767 | *pathend = EOS; | 764 | *pathend = EOS; |
768 | continue; | 765 | continue; |
769 | } | 766 | } |
@@ -893,17 +890,24 @@ globextend(const Char *path, glob_t *pglob, struct glob_lim *limitp, | |||
893 | 890 | ||
894 | /* | 891 | /* |
895 | * pattern matching function for filenames. Each occurrence of the * | 892 | * pattern matching function for filenames. Each occurrence of the * |
896 | * pattern causes a recursion level. | 893 | * pattern causes an iteration. |
894 | * | ||
895 | * Note, this function differs from the original as per the discussion | ||
896 | * here: https://research.swtch.com/glob | ||
897 | * | ||
898 | * Basically we removed the recursion and made it use the algorithm | ||
899 | * from Russ Cox to not go quadratic on cases like a file called | ||
900 | * ("a" x 100) . "x" matched against a pattern like "a*a*a*a*a*a*a*y". | ||
897 | */ | 901 | */ |
898 | static int | 902 | static int |
899 | match(Char *name, Char *pat, Char *patend, int recur) | 903 | match(Char *name, Char *pat, Char *patend) |
900 | { | 904 | { |
901 | int ok, negate_range; | 905 | int ok, negate_range; |
902 | Char c, k; | 906 | Char c, k; |
907 | Char *nextp = NULL; | ||
908 | Char *nextn = NULL; | ||
903 | 909 | ||
904 | if (recur-- == 0) | 910 | loop: |
905 | return(GLOB_NOSPACE); | ||
906 | |||
907 | while (pat < patend) { | 911 | while (pat < patend) { |
908 | c = *pat++; | 912 | c = *pat++; |
909 | switch (c & M_MASK) { | 913 | switch (c & M_MASK) { |
@@ -912,19 +916,19 @@ match(Char *name, Char *pat, Char *patend, int recur) | |||
912 | pat++; /* eat consecutive '*' */ | 916 | pat++; /* eat consecutive '*' */ |
913 | if (pat == patend) | 917 | if (pat == patend) |
914 | return(1); | 918 | return(1); |
915 | do { | 919 | if (*name == EOS) |
916 | if (match(name, pat, patend, recur)) | 920 | return(0); |
917 | return(1); | 921 | nextn = name + 1; |
918 | } while (*name++ != EOS); | 922 | nextp = pat - 1; |
919 | return(0); | 923 | break; |
920 | case M_ONE: | 924 | case M_ONE: |
921 | if (*name++ == EOS) | 925 | if (*name++ == EOS) |
922 | return(0); | 926 | goto fail; |
923 | break; | 927 | break; |
924 | case M_SET: | 928 | case M_SET: |
925 | ok = 0; | 929 | ok = 0; |
926 | if ((k = *name++) == EOS) | 930 | if ((k = *name++) == EOS) |
927 | return(0); | 931 | goto fail; |
928 | if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS) | 932 | if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS) |
929 | ++pat; | 933 | ++pat; |
930 | while (((c = *pat++) & M_MASK) != M_END) { | 934 | while (((c = *pat++) & M_MASK) != M_END) { |
@@ -943,15 +947,24 @@ match(Char *name, Char *pat, Char *patend, int recur) | |||
943 | ok = 1; | 947 | ok = 1; |
944 | } | 948 | } |
945 | if (ok == negate_range) | 949 | if (ok == negate_range) |
946 | return(0); | 950 | goto fail; |
947 | break; | 951 | break; |
948 | default: | 952 | default: |
949 | if (*name++ != c) | 953 | if (*name++ != c) |
950 | return(0); | 954 | goto fail; |
951 | break; | 955 | break; |
952 | } | 956 | } |
953 | } | 957 | } |
954 | return(*name == EOS); | 958 | if (*name == EOS) |
959 | return(1); | ||
960 | |||
961 | fail: | ||
962 | if (nextn) { | ||
963 | pat = nextp; | ||
964 | name = nextn; | ||
965 | goto loop; | ||
966 | } | ||
967 | return(0); | ||
955 | } | 968 | } |
956 | 969 | ||
957 | /* Free allocated data belonging to a glob_t structure. */ | 970 | /* Free allocated data belonging to a glob_t structure. */ |