summaryrefslogtreecommitdiff
path: root/openbsd-compat/glob.c
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2019-11-15 16:05:07 +1100
committerDamien Miller <djm@mindrot.org>2019-11-15 16:05:07 +1100
commit2cfb11abac85885de0cb888bbeb9a3e4303105ea (patch)
tree711364302c2f9a0dacef45ab451123c12af5c2a4 /openbsd-compat/glob.c
parent228dd595c7882bb9b161dbb7d4dca15c8a5f03f5 (diff)
upstream commit
revision 1.47 date: 2017/05/08 14:53:27; author: millert; state: Exp; lines: +34 -21; commitid: sYfxfyUHAfarP8sE; Fix exponential CPU use with repeated '*' operators by changing '*' handling to be interative instead of recursive. Fix by Yves Orton, ported to OpenBSD glob.c by Ray Lai. OK tb@
Diffstat (limited to 'openbsd-compat/glob.c')
-rw-r--r--openbsd-compat/glob.c55
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
143struct glob_lim { 140struct 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 *
172static int globexp1(const Char *, glob_t *, struct glob_lim *); 169static int globexp1(const Char *, glob_t *, struct glob_lim *);
173static int globexp2(const Char *, const Char *, glob_t *, 170static int globexp2(const Char *, const Char *, glob_t *,
174 struct glob_lim *); 171 struct glob_lim *);
175static int match(Char *, Char *, Char *, int); 172static int match(Char *, Char *, Char *);
176#ifdef DEBUG 173#ifdef DEBUG
177static void qprintf(const char *, Char *); 174static 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 */
898static int 902static int
899match(Char *name, Char *pat, Char *patend, int recur) 903match(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) 910loop:
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
961fail:
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. */