diff options
author | Colin Watson <cjwatson@debian.org> | 2011-01-24 11:46:57 +0000 |
---|---|---|
committer | Colin Watson <cjwatson@debian.org> | 2011-01-24 11:46:57 +0000 |
commit | 0970072c89b079b022538e3c366fbfa2c53fc821 (patch) | |
tree | b7024712d74234bb5a8b036ccbc9109e2e211296 /openbsd-compat/glob.c | |
parent | 4e8aa4da57000c7bba8e5c49163bc0c0ca383f78 (diff) | |
parent | 478ff799463ca926a8dfbabf058f4e84aaffc65a (diff) |
merge 5.7p1
Diffstat (limited to 'openbsd-compat/glob.c')
-rw-r--r-- | openbsd-compat/glob.c | 306 |
1 files changed, 223 insertions, 83 deletions
diff --git a/openbsd-compat/glob.c b/openbsd-compat/glob.c index 74b506403..0341225cd 100644 --- a/openbsd-compat/glob.c +++ b/openbsd-compat/glob.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: glob.c,v 1.26 2005/11/28 17:50:12 deraadt Exp $ */ | 1 | /* $OpenBSD: glob.c,v 1.35 2011/01/12 01:53:14 djm 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. |
@@ -33,36 +33,6 @@ | |||
33 | 33 | ||
34 | /* OPENBSD ORIGINAL: lib/libc/gen/glob.c */ | 34 | /* OPENBSD ORIGINAL: lib/libc/gen/glob.c */ |
35 | 35 | ||
36 | #include "includes.h" | ||
37 | |||
38 | #include <sys/types.h> | ||
39 | #include <sys/stat.h> | ||
40 | |||
41 | #include <dirent.h> | ||
42 | #include <ctype.h> | ||
43 | #include <errno.h> | ||
44 | #include <pwd.h> | ||
45 | #include <stdlib.h> | ||
46 | #include <string.h> | ||
47 | #include <unistd.h> | ||
48 | |||
49 | #if !defined(HAVE_GLOB) || !defined(GLOB_HAS_ALTDIRFUNC) || \ | ||
50 | !defined(GLOB_HAS_GL_MATCHC) || \ | ||
51 | !defined(HAVE_DECL_GLOB_NOMATCH) || HAVE_DECL_GLOB_NOMATCH == 0 || \ | ||
52 | defined(BROKEN_GLOB) | ||
53 | |||
54 | static long | ||
55 | get_arg_max(void) | ||
56 | { | ||
57 | #ifdef ARG_MAX | ||
58 | return(ARG_MAX); | ||
59 | #elif defined(HAVE_SYSCONF) && defined(_SC_ARG_MAX) | ||
60 | return(sysconf(_SC_ARG_MAX)); | ||
61 | #else | ||
62 | return(256); /* XXX: arbitrary */ | ||
63 | #endif | ||
64 | } | ||
65 | |||
66 | /* | 36 | /* |
67 | * glob(3) -- a superset of the one defined in POSIX 1003.2. | 37 | * glob(3) -- a superset of the one defined in POSIX 1003.2. |
68 | * | 38 | * |
@@ -88,6 +58,25 @@ get_arg_max(void) | |||
88 | * Number of matches in the current invocation of glob. | 58 | * Number of matches in the current invocation of glob. |
89 | */ | 59 | */ |
90 | 60 | ||
61 | #include "includes.h" | ||
62 | |||
63 | #include <sys/types.h> | ||
64 | #include <sys/stat.h> | ||
65 | |||
66 | #include <dirent.h> | ||
67 | #include <ctype.h> | ||
68 | #include <errno.h> | ||
69 | #include <pwd.h> | ||
70 | #include <stdlib.h> | ||
71 | #include <string.h> | ||
72 | #include <unistd.h> | ||
73 | |||
74 | #if !defined(HAVE_GLOB) || !defined(GLOB_HAS_ALTDIRFUNC) || \ | ||
75 | !defined(GLOB_HAS_GL_MATCHC) || !defined(GLOB_HAS_GL_STATV) || \ | ||
76 | !defined(HAVE_DECL_GLOB_NOMATCH) || HAVE_DECL_GLOB_NOMATCH == 0 || \ | ||
77 | defined(BROKEN_GLOB) | ||
78 | |||
79 | #include "charclass.h" | ||
91 | 80 | ||
92 | #define DOLLAR '$' | 81 | #define DOLLAR '$' |
93 | #define DOT '.' | 82 | #define DOT '.' |
@@ -100,7 +89,6 @@ get_arg_max(void) | |||
100 | #define RBRACKET ']' | 89 | #define RBRACKET ']' |
101 | #define SEP '/' | 90 | #define SEP '/' |
102 | #define STAR '*' | 91 | #define STAR '*' |
103 | #undef TILDE /* Some platforms may already define it */ | ||
104 | #define TILDE '~' | 92 | #define TILDE '~' |
105 | #define UNDERSCORE '_' | 93 | #define UNDERSCORE '_' |
106 | #define LBRACE '{' | 94 | #define LBRACE '{' |
@@ -137,26 +125,39 @@ typedef char Char; | |||
137 | #define M_ONE META('?') | 125 | #define M_ONE META('?') |
138 | #define M_RNG META('-') | 126 | #define M_RNG META('-') |
139 | #define M_SET META('[') | 127 | #define M_SET META('[') |
128 | #define M_CLASS META(':') | ||
140 | #define ismeta(c) (((c)&M_QUOTE) != 0) | 129 | #define ismeta(c) (((c)&M_QUOTE) != 0) |
141 | 130 | ||
131 | #define GLOB_LIMIT_MALLOC 65536 | ||
132 | #define GLOB_LIMIT_STAT 128 | ||
133 | #define GLOB_LIMIT_READDIR 16384 | ||
134 | |||
135 | struct glob_lim { | ||
136 | size_t glim_malloc; | ||
137 | size_t glim_stat; | ||
138 | size_t glim_readdir; | ||
139 | }; | ||
142 | 140 | ||
143 | static int compare(const void *, const void *); | 141 | static int compare(const void *, const void *); |
144 | static int g_Ctoc(const Char *, char *, u_int); | 142 | static int g_Ctoc(const Char *, char *, u_int); |
145 | static int g_lstat(Char *, struct stat *, glob_t *); | 143 | static int g_lstat(Char *, struct stat *, glob_t *); |
146 | static DIR *g_opendir(Char *, glob_t *); | 144 | static DIR *g_opendir(Char *, glob_t *); |
147 | static Char *g_strchr(Char *, int); | 145 | static Char *g_strchr(const Char *, int); |
146 | static int g_strncmp(const Char *, const char *, size_t); | ||
148 | static int g_stat(Char *, struct stat *, glob_t *); | 147 | static int g_stat(Char *, struct stat *, glob_t *); |
149 | static int glob0(const Char *, glob_t *); | 148 | static int glob0(const Char *, glob_t *, struct glob_lim *); |
150 | static int glob1(Char *, Char *, glob_t *, size_t *); | 149 | static int glob1(Char *, Char *, glob_t *, struct glob_lim *); |
151 | static int glob2(Char *, Char *, Char *, Char *, Char *, Char *, | 150 | static int glob2(Char *, Char *, Char *, Char *, Char *, Char *, |
152 | glob_t *, size_t *); | 151 | glob_t *, struct glob_lim *); |
153 | static int glob3(Char *, Char *, Char *, Char *, Char *, | 152 | static int glob3(Char *, Char *, Char *, Char *, Char *, |
154 | Char *, Char *, glob_t *, size_t *); | 153 | Char *, Char *, glob_t *, struct glob_lim *); |
155 | static int globextend(const Char *, glob_t *, size_t *); | 154 | static int globextend(const Char *, glob_t *, struct glob_lim *, |
155 | struct stat *); | ||
156 | static const Char * | 156 | static const Char * |
157 | globtilde(const Char *, Char *, size_t, glob_t *); | 157 | globtilde(const Char *, Char *, size_t, glob_t *); |
158 | static int globexp1(const Char *, glob_t *); | 158 | static int globexp1(const Char *, glob_t *, struct glob_lim *); |
159 | static int globexp2(const Char *, const Char *, glob_t *, int *); | 159 | static int globexp2(const Char *, const Char *, glob_t *, |
160 | struct glob_lim *); | ||
160 | static int match(Char *, Char *, Char *); | 161 | static int match(Char *, Char *, Char *); |
161 | #ifdef DEBUG | 162 | #ifdef DEBUG |
162 | static void qprintf(const char *, Char *); | 163 | static void qprintf(const char *, Char *); |
@@ -169,11 +170,13 @@ glob(const char *pattern, int flags, int (*errfunc)(const char *, int), | |||
169 | const u_char *patnext; | 170 | const u_char *patnext; |
170 | int c; | 171 | int c; |
171 | Char *bufnext, *bufend, patbuf[MAXPATHLEN]; | 172 | Char *bufnext, *bufend, patbuf[MAXPATHLEN]; |
173 | struct glob_lim limit = { 0, 0, 0 }; | ||
172 | 174 | ||
173 | patnext = (u_char *) pattern; | 175 | patnext = (u_char *) pattern; |
174 | if (!(flags & GLOB_APPEND)) { | 176 | if (!(flags & GLOB_APPEND)) { |
175 | pglob->gl_pathc = 0; | 177 | pglob->gl_pathc = 0; |
176 | pglob->gl_pathv = NULL; | 178 | pglob->gl_pathv = NULL; |
179 | pglob->gl_statv = NULL; | ||
177 | if (!(flags & GLOB_DOOFFS)) | 180 | if (!(flags & GLOB_DOOFFS)) |
178 | pglob->gl_offs = 0; | 181 | pglob->gl_offs = 0; |
179 | } | 182 | } |
@@ -181,6 +184,11 @@ glob(const char *pattern, int flags, int (*errfunc)(const char *, int), | |||
181 | pglob->gl_errfunc = errfunc; | 184 | pglob->gl_errfunc = errfunc; |
182 | pglob->gl_matchc = 0; | 185 | pglob->gl_matchc = 0; |
183 | 186 | ||
187 | if (pglob->gl_offs < 0 || pglob->gl_pathc < 0 || | ||
188 | pglob->gl_offs >= INT_MAX || pglob->gl_pathc >= INT_MAX || | ||
189 | pglob->gl_pathc >= INT_MAX - pglob->gl_offs - 1) | ||
190 | return GLOB_NOSPACE; | ||
191 | |||
184 | bufnext = patbuf; | 192 | bufnext = patbuf; |
185 | bufend = bufnext + MAXPATHLEN - 1; | 193 | bufend = bufnext + MAXPATHLEN - 1; |
186 | if (flags & GLOB_NOESCAPE) | 194 | if (flags & GLOB_NOESCAPE) |
@@ -201,9 +209,9 @@ glob(const char *pattern, int flags, int (*errfunc)(const char *, int), | |||
201 | *bufnext = EOS; | 209 | *bufnext = EOS; |
202 | 210 | ||
203 | if (flags & GLOB_BRACE) | 211 | if (flags & GLOB_BRACE) |
204 | return globexp1(patbuf, pglob); | 212 | return globexp1(patbuf, pglob, &limit); |
205 | else | 213 | else |
206 | return glob0(patbuf, pglob); | 214 | return glob0(patbuf, pglob, &limit); |
207 | } | 215 | } |
208 | 216 | ||
209 | /* | 217 | /* |
@@ -212,20 +220,18 @@ glob(const char *pattern, int flags, int (*errfunc)(const char *, int), | |||
212 | * characters | 220 | * characters |
213 | */ | 221 | */ |
214 | static int | 222 | static int |
215 | globexp1(const Char *pattern, glob_t *pglob) | 223 | globexp1(const Char *pattern, glob_t *pglob, struct glob_lim *limitp) |
216 | { | 224 | { |
217 | const Char* ptr = pattern; | 225 | const Char* ptr = pattern; |
218 | int rv; | ||
219 | 226 | ||
220 | /* Protect a single {}, for find(1), like csh */ | 227 | /* Protect a single {}, for find(1), like csh */ |
221 | if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS) | 228 | if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS) |
222 | return glob0(pattern, pglob); | 229 | return glob0(pattern, pglob, limitp); |
223 | 230 | ||
224 | while ((ptr = (const Char *) g_strchr((Char *) ptr, LBRACE)) != NULL) | 231 | if ((ptr = (const Char *) g_strchr(ptr, LBRACE)) != NULL) |
225 | if (!globexp2(ptr, pattern, pglob, &rv)) | 232 | return globexp2(ptr, pattern, pglob, limitp); |
226 | return rv; | ||
227 | 233 | ||
228 | return glob0(pattern, pglob); | 234 | return glob0(pattern, pglob, limitp); |
229 | } | 235 | } |
230 | 236 | ||
231 | 237 | ||
@@ -235,9 +241,10 @@ globexp1(const Char *pattern, glob_t *pglob) | |||
235 | * If it fails then it tries to glob the rest of the pattern and returns. | 241 | * If it fails then it tries to glob the rest of the pattern and returns. |
236 | */ | 242 | */ |
237 | static int | 243 | static int |
238 | globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv) | 244 | globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, |
245 | struct glob_lim *limitp) | ||
239 | { | 246 | { |
240 | int i; | 247 | int i, rv; |
241 | Char *lm, *ls; | 248 | Char *lm, *ls; |
242 | const Char *pe, *pm, *pl; | 249 | const Char *pe, *pm, *pl; |
243 | Char patbuf[MAXPATHLEN]; | 250 | Char patbuf[MAXPATHLEN]; |
@@ -270,10 +277,8 @@ globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv) | |||
270 | } | 277 | } |
271 | 278 | ||
272 | /* Non matching braces; just glob the pattern */ | 279 | /* Non matching braces; just glob the pattern */ |
273 | if (i != 0 || *pe == EOS) { | 280 | if (i != 0 || *pe == EOS) |
274 | *rv = glob0(patbuf, pglob); | 281 | return glob0(patbuf, pglob, limitp); |
275 | return 0; | ||
276 | } | ||
277 | 282 | ||
278 | for (i = 0, pl = pm = ptr; pm <= pe; pm++) { | 283 | for (i = 0, pl = pm = ptr; pm <= pe; pm++) { |
279 | switch (*pm) { | 284 | switch (*pm) { |
@@ -319,7 +324,9 @@ globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv) | |||
319 | #ifdef DEBUG | 324 | #ifdef DEBUG |
320 | qprintf("globexp2:", patbuf); | 325 | qprintf("globexp2:", patbuf); |
321 | #endif | 326 | #endif |
322 | *rv = globexp1(patbuf, pglob); | 327 | rv = globexp1(patbuf, pglob, limitp); |
328 | if (rv && rv != GLOB_NOMATCH) | ||
329 | return rv; | ||
323 | 330 | ||
324 | /* move after the comma, to the next string */ | 331 | /* move after the comma, to the next string */ |
325 | pl = pm + 1; | 332 | pl = pm + 1; |
@@ -330,7 +337,6 @@ globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv) | |||
330 | break; | 337 | break; |
331 | } | 338 | } |
332 | } | 339 | } |
333 | *rv = 0; | ||
334 | return 0; | 340 | return 0; |
335 | } | 341 | } |
336 | 342 | ||
@@ -399,6 +405,47 @@ globtilde(const Char *pattern, Char *patbuf, size_t patbuf_len, glob_t *pglob) | |||
399 | return patbuf; | 405 | return patbuf; |
400 | } | 406 | } |
401 | 407 | ||
408 | static int | ||
409 | g_strncmp(const Char *s1, const char *s2, size_t n) | ||
410 | { | ||
411 | int rv = 0; | ||
412 | |||
413 | while (n--) { | ||
414 | rv = *(Char *)s1 - *(const unsigned char *)s2++; | ||
415 | if (rv) | ||
416 | break; | ||
417 | if (*s1++ == '\0') | ||
418 | break; | ||
419 | } | ||
420 | return rv; | ||
421 | } | ||
422 | |||
423 | static int | ||
424 | g_charclass(const Char **patternp, Char **bufnextp) | ||
425 | { | ||
426 | const Char *pattern = *patternp + 1; | ||
427 | Char *bufnext = *bufnextp; | ||
428 | const Char *colon; | ||
429 | struct cclass *cc; | ||
430 | size_t len; | ||
431 | |||
432 | if ((colon = g_strchr(pattern, ':')) == NULL || colon[1] != ']') | ||
433 | return 1; /* not a character class */ | ||
434 | |||
435 | len = (size_t)(colon - pattern); | ||
436 | for (cc = cclasses; cc->name != NULL; cc++) { | ||
437 | if (!g_strncmp(pattern, cc->name, len) && cc->name[len] == '\0') | ||
438 | break; | ||
439 | } | ||
440 | if (cc->name == NULL) | ||
441 | return -1; /* invalid character class */ | ||
442 | *bufnext++ = M_CLASS; | ||
443 | *bufnext++ = (Char)(cc - &cclasses[0]); | ||
444 | *bufnextp = bufnext; | ||
445 | *patternp += len + 3; | ||
446 | |||
447 | return 0; | ||
448 | } | ||
402 | 449 | ||
403 | /* | 450 | /* |
404 | * The main glob() routine: compiles the pattern (optionally processing | 451 | * The main glob() routine: compiles the pattern (optionally processing |
@@ -408,12 +455,11 @@ globtilde(const Char *pattern, Char *patbuf, size_t patbuf_len, glob_t *pglob) | |||
408 | * to find no matches. | 455 | * to find no matches. |
409 | */ | 456 | */ |
410 | static int | 457 | static int |
411 | glob0(const Char *pattern, glob_t *pglob) | 458 | glob0(const Char *pattern, glob_t *pglob, struct glob_lim *limitp) |
412 | { | 459 | { |
413 | const Char *qpatnext; | 460 | const Char *qpatnext; |
414 | int c, err, oldpathc; | 461 | int c, err, oldpathc; |
415 | Char *bufnext, patbuf[MAXPATHLEN]; | 462 | Char *bufnext, patbuf[MAXPATHLEN]; |
416 | size_t limit = 0; | ||
417 | 463 | ||
418 | qpatnext = globtilde(pattern, patbuf, MAXPATHLEN, pglob); | 464 | qpatnext = globtilde(pattern, patbuf, MAXPATHLEN, pglob); |
419 | oldpathc = pglob->gl_pathc; | 465 | oldpathc = pglob->gl_pathc; |
@@ -427,7 +473,7 @@ glob0(const Char *pattern, glob_t *pglob) | |||
427 | if (c == NOT) | 473 | if (c == NOT) |
428 | ++qpatnext; | 474 | ++qpatnext; |
429 | if (*qpatnext == EOS || | 475 | if (*qpatnext == EOS || |
430 | g_strchr((Char *) qpatnext+1, RBRACKET) == NULL) { | 476 | g_strchr(qpatnext+1, RBRACKET) == NULL) { |
431 | *bufnext++ = LBRACKET; | 477 | *bufnext++ = LBRACKET; |
432 | if (c == NOT) | 478 | if (c == NOT) |
433 | --qpatnext; | 479 | --qpatnext; |
@@ -438,6 +484,20 @@ glob0(const Char *pattern, glob_t *pglob) | |||
438 | *bufnext++ = M_NOT; | 484 | *bufnext++ = M_NOT; |
439 | c = *qpatnext++; | 485 | c = *qpatnext++; |
440 | do { | 486 | do { |
487 | if (c == LBRACKET && *qpatnext == ':') { | ||
488 | do { | ||
489 | err = g_charclass(&qpatnext, | ||
490 | &bufnext); | ||
491 | if (err) | ||
492 | break; | ||
493 | c = *qpatnext++; | ||
494 | } while (c == LBRACKET && *qpatnext == ':'); | ||
495 | if (err == -1 && | ||
496 | !(pglob->gl_flags & GLOB_NOCHECK)) | ||
497 | return GLOB_NOMATCH; | ||
498 | if (c == RBRACKET) | ||
499 | break; | ||
500 | } | ||
441 | *bufnext++ = CHAR(c); | 501 | *bufnext++ = CHAR(c); |
442 | if (*qpatnext == RANGE && | 502 | if (*qpatnext == RANGE && |
443 | (c = qpatnext[1]) != RBRACKET) { | 503 | (c = qpatnext[1]) != RBRACKET) { |
@@ -471,7 +531,7 @@ glob0(const Char *pattern, glob_t *pglob) | |||
471 | qprintf("glob0:", patbuf); | 531 | qprintf("glob0:", patbuf); |
472 | #endif | 532 | #endif |
473 | 533 | ||
474 | if ((err = glob1(patbuf, patbuf+MAXPATHLEN-1, pglob, &limit)) != 0) | 534 | if ((err = glob1(patbuf, patbuf+MAXPATHLEN-1, pglob, limitp)) != 0) |
475 | return(err); | 535 | return(err); |
476 | 536 | ||
477 | /* | 537 | /* |
@@ -484,7 +544,7 @@ glob0(const Char *pattern, glob_t *pglob) | |||
484 | if ((pglob->gl_flags & GLOB_NOCHECK) || | 544 | if ((pglob->gl_flags & GLOB_NOCHECK) || |
485 | ((pglob->gl_flags & GLOB_NOMAGIC) && | 545 | ((pglob->gl_flags & GLOB_NOMAGIC) && |
486 | !(pglob->gl_flags & GLOB_MAGCHAR))) | 546 | !(pglob->gl_flags & GLOB_MAGCHAR))) |
487 | return(globextend(pattern, pglob, &limit)); | 547 | return(globextend(pattern, pglob, limitp, NULL)); |
488 | else | 548 | else |
489 | return(GLOB_NOMATCH); | 549 | return(GLOB_NOMATCH); |
490 | } | 550 | } |
@@ -501,7 +561,7 @@ compare(const void *p, const void *q) | |||
501 | } | 561 | } |
502 | 562 | ||
503 | static int | 563 | static int |
504 | glob1(Char *pattern, Char *pattern_last, glob_t *pglob, size_t *limitp) | 564 | glob1(Char *pattern, Char *pattern_last, glob_t *pglob, struct glob_lim *limitp) |
505 | { | 565 | { |
506 | Char pathbuf[MAXPATHLEN]; | 566 | Char pathbuf[MAXPATHLEN]; |
507 | 567 | ||
@@ -520,7 +580,7 @@ glob1(Char *pattern, Char *pattern_last, glob_t *pglob, size_t *limitp) | |||
520 | */ | 580 | */ |
521 | static int | 581 | static int |
522 | glob2(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, | 582 | glob2(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, |
523 | Char *pattern, Char *pattern_last, glob_t *pglob, size_t *limitp) | 583 | Char *pattern, Char *pattern_last, glob_t *pglob, struct glob_lim *limitp) |
524 | { | 584 | { |
525 | struct stat sb; | 585 | struct stat sb; |
526 | Char *p, *q; | 586 | Char *p, *q; |
@@ -536,6 +596,14 @@ glob2(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, | |||
536 | if (g_lstat(pathbuf, &sb, pglob)) | 596 | if (g_lstat(pathbuf, &sb, pglob)) |
537 | return(0); | 597 | return(0); |
538 | 598 | ||
599 | if ((pglob->gl_flags & GLOB_LIMIT) && | ||
600 | limitp->glim_stat++ >= GLOB_LIMIT_STAT) { | ||
601 | errno = 0; | ||
602 | *pathend++ = SEP; | ||
603 | *pathend = EOS; | ||
604 | return(GLOB_NOSPACE); | ||
605 | } | ||
606 | |||
539 | if (((pglob->gl_flags & GLOB_MARK) && | 607 | if (((pglob->gl_flags & GLOB_MARK) && |
540 | pathend[-1] != SEP) && (S_ISDIR(sb.st_mode) || | 608 | pathend[-1] != SEP) && (S_ISDIR(sb.st_mode) || |
541 | (S_ISLNK(sb.st_mode) && | 609 | (S_ISLNK(sb.st_mode) && |
@@ -547,7 +615,7 @@ glob2(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, | |||
547 | *pathend = EOS; | 615 | *pathend = EOS; |
548 | } | 616 | } |
549 | ++pglob->gl_matchc; | 617 | ++pglob->gl_matchc; |
550 | return(globextend(pathbuf, pglob, limitp)); | 618 | return(globextend(pathbuf, pglob, limitp, &sb)); |
551 | } | 619 | } |
552 | 620 | ||
553 | /* Find end of next segment, copy tentatively to pathend. */ | 621 | /* Find end of next segment, copy tentatively to pathend. */ |
@@ -581,7 +649,7 @@ glob2(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, | |||
581 | static int | 649 | static int |
582 | glob3(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, | 650 | glob3(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, |
583 | Char *pattern, Char *restpattern, Char *restpattern_last, glob_t *pglob, | 651 | Char *pattern, Char *restpattern, Char *restpattern_last, glob_t *pglob, |
584 | size_t *limitp) | 652 | struct glob_lim *limitp) |
585 | { | 653 | { |
586 | struct dirent *dp; | 654 | struct dirent *dp; |
587 | DIR *dirp; | 655 | DIR *dirp; |
@@ -624,6 +692,14 @@ glob3(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, | |||
624 | u_char *sc; | 692 | u_char *sc; |
625 | Char *dc; | 693 | Char *dc; |
626 | 694 | ||
695 | if ((pglob->gl_flags & GLOB_LIMIT) && | ||
696 | limitp->glim_readdir++ >= GLOB_LIMIT_READDIR) { | ||
697 | errno = 0; | ||
698 | *pathend++ = SEP; | ||
699 | *pathend = EOS; | ||
700 | return(GLOB_NOSPACE); | ||
701 | } | ||
702 | |||
627 | /* Initial DOT must be matched literally. */ | 703 | /* Initial DOT must be matched literally. */ |
628 | if (dp->d_name[0] == DOT && *pattern != DOT) | 704 | if (dp->d_name[0] == DOT && *pattern != DOT) |
629 | continue; | 705 | continue; |
@@ -670,25 +746,44 @@ glob3(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, | |||
670 | * gl_pathv points to (gl_offs + gl_pathc + 1) items. | 746 | * gl_pathv points to (gl_offs + gl_pathc + 1) items. |
671 | */ | 747 | */ |
672 | static int | 748 | static int |
673 | globextend(const Char *path, glob_t *pglob, size_t *limitp) | 749 | globextend(const Char *path, glob_t *pglob, struct glob_lim *limitp, |
750 | struct stat *sb) | ||
674 | { | 751 | { |
675 | char **pathv; | 752 | char **pathv; |
676 | int i; | 753 | ssize_t i; |
677 | u_int newsize, len; | 754 | size_t newn, len; |
678 | char *copy; | 755 | char *copy = NULL; |
679 | const Char *p; | 756 | const Char *p; |
680 | 757 | struct stat **statv; | |
681 | newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs); | 758 | |
682 | pathv = pglob->gl_pathv ? realloc((char *)pglob->gl_pathv, newsize) : | 759 | newn = 2 + pglob->gl_pathc + pglob->gl_offs; |
683 | malloc(newsize); | 760 | if (pglob->gl_offs >= INT_MAX || |
684 | if (pathv == NULL) { | 761 | pglob->gl_pathc >= INT_MAX || |
762 | newn >= INT_MAX || | ||
763 | SIZE_MAX / sizeof(*pathv) <= newn || | ||
764 | SIZE_MAX / sizeof(*statv) <= newn) { | ||
765 | nospace: | ||
766 | for (i = pglob->gl_offs; i < (ssize_t)(newn - 2); i++) { | ||
767 | if (pglob->gl_pathv && pglob->gl_pathv[i]) | ||
768 | free(pglob->gl_pathv[i]); | ||
769 | if ((pglob->gl_flags & GLOB_KEEPSTAT) != 0 && | ||
770 | pglob->gl_pathv && pglob->gl_pathv[i]) | ||
771 | free(pglob->gl_statv[i]); | ||
772 | } | ||
685 | if (pglob->gl_pathv) { | 773 | if (pglob->gl_pathv) { |
686 | free(pglob->gl_pathv); | 774 | free(pglob->gl_pathv); |
687 | pglob->gl_pathv = NULL; | 775 | pglob->gl_pathv = NULL; |
688 | } | 776 | } |
777 | if (pglob->gl_statv) { | ||
778 | free(pglob->gl_statv); | ||
779 | pglob->gl_statv = NULL; | ||
780 | } | ||
689 | return(GLOB_NOSPACE); | 781 | return(GLOB_NOSPACE); |
690 | } | 782 | } |
691 | 783 | ||
784 | pathv = realloc(pglob->gl_pathv, newn * sizeof(*pathv)); | ||
785 | if (pathv == NULL) | ||
786 | goto nospace; | ||
692 | if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) { | 787 | if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) { |
693 | /* first time around -- clear initial gl_offs items */ | 788 | /* first time around -- clear initial gl_offs items */ |
694 | pathv += pglob->gl_offs; | 789 | pathv += pglob->gl_offs; |
@@ -697,10 +792,39 @@ globextend(const Char *path, glob_t *pglob, size_t *limitp) | |||
697 | } | 792 | } |
698 | pglob->gl_pathv = pathv; | 793 | pglob->gl_pathv = pathv; |
699 | 794 | ||
795 | if ((pglob->gl_flags & GLOB_KEEPSTAT) != 0) { | ||
796 | statv = realloc(pglob->gl_statv, newn * sizeof(*statv)); | ||
797 | if (statv == NULL) | ||
798 | goto nospace; | ||
799 | if (pglob->gl_statv == NULL && pglob->gl_offs > 0) { | ||
800 | /* first time around -- clear initial gl_offs items */ | ||
801 | statv += pglob->gl_offs; | ||
802 | for (i = pglob->gl_offs; --i >= 0; ) | ||
803 | *--statv = NULL; | ||
804 | } | ||
805 | pglob->gl_statv = statv; | ||
806 | if (sb == NULL) | ||
807 | statv[pglob->gl_offs + pglob->gl_pathc] = NULL; | ||
808 | else { | ||
809 | limitp->glim_malloc += sizeof(**statv); | ||
810 | if ((pglob->gl_flags & GLOB_LIMIT) && | ||
811 | limitp->glim_malloc >= GLOB_LIMIT_MALLOC) { | ||
812 | errno = 0; | ||
813 | return(GLOB_NOSPACE); | ||
814 | } | ||
815 | if ((statv[pglob->gl_offs + pglob->gl_pathc] = | ||
816 | malloc(sizeof(**statv))) == NULL) | ||
817 | goto copy_error; | ||
818 | memcpy(statv[pglob->gl_offs + pglob->gl_pathc], sb, | ||
819 | sizeof(*sb)); | ||
820 | } | ||
821 | statv[pglob->gl_offs + pglob->gl_pathc + 1] = NULL; | ||
822 | } | ||
823 | |||
700 | for (p = path; *p++;) | 824 | for (p = path; *p++;) |
701 | ; | 825 | ; |
702 | len = (size_t)(p - path); | 826 | len = (size_t)(p - path); |
703 | *limitp += len; | 827 | limitp->glim_malloc += len; |
704 | if ((copy = malloc(len)) != NULL) { | 828 | if ((copy = malloc(len)) != NULL) { |
705 | if (g_Ctoc(path, copy, len)) { | 829 | if (g_Ctoc(path, copy, len)) { |
706 | free(copy); | 830 | free(copy); |
@@ -711,11 +835,12 @@ globextend(const Char *path, glob_t *pglob, size_t *limitp) | |||
711 | pathv[pglob->gl_offs + pglob->gl_pathc] = NULL; | 835 | pathv[pglob->gl_offs + pglob->gl_pathc] = NULL; |
712 | 836 | ||
713 | if ((pglob->gl_flags & GLOB_LIMIT) && | 837 | if ((pglob->gl_flags & GLOB_LIMIT) && |
714 | newsize + *limitp >= (u_int) get_arg_max()) { | 838 | (newn * sizeof(*pathv)) + limitp->glim_malloc > |
839 | GLOB_LIMIT_MALLOC) { | ||
715 | errno = 0; | 840 | errno = 0; |
716 | return(GLOB_NOSPACE); | 841 | return(GLOB_NOSPACE); |
717 | } | 842 | } |
718 | 843 | copy_error: | |
719 | return(copy == NULL ? GLOB_NOSPACE : 0); | 844 | return(copy == NULL ? GLOB_NOSPACE : 0); |
720 | } | 845 | } |
721 | 846 | ||
@@ -751,13 +876,21 @@ match(Char *name, Char *pat, Char *patend) | |||
751 | return(0); | 876 | return(0); |
752 | if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS) | 877 | if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS) |
753 | ++pat; | 878 | ++pat; |
754 | while (((c = *pat++) & M_MASK) != M_END) | 879 | while (((c = *pat++) & M_MASK) != M_END) { |
880 | if ((c & M_MASK) == M_CLASS) { | ||
881 | Char idx = *pat & M_MASK; | ||
882 | if (idx < NCCLASSES && | ||
883 | cclasses[idx].isctype(k)) | ||
884 | ok = 1; | ||
885 | ++pat; | ||
886 | } | ||
755 | if ((*pat & M_MASK) == M_RNG) { | 887 | if ((*pat & M_MASK) == M_RNG) { |
756 | if (c <= k && k <= pat[1]) | 888 | if (c <= k && k <= pat[1]) |
757 | ok = 1; | 889 | ok = 1; |
758 | pat += 2; | 890 | pat += 2; |
759 | } else if (c == k) | 891 | } else if (c == k) |
760 | ok = 1; | 892 | ok = 1; |
893 | } | ||
761 | if (ok == negate_range) | 894 | if (ok == negate_range) |
762 | return(0); | 895 | return(0); |
763 | break; | 896 | break; |
@@ -785,6 +918,14 @@ globfree(glob_t *pglob) | |||
785 | free(pglob->gl_pathv); | 918 | free(pglob->gl_pathv); |
786 | pglob->gl_pathv = NULL; | 919 | pglob->gl_pathv = NULL; |
787 | } | 920 | } |
921 | if (pglob->gl_statv != NULL) { | ||
922 | for (i = 0; i < pglob->gl_pathc; i++) { | ||
923 | if (pglob->gl_statv[i] != NULL) | ||
924 | free(pglob->gl_statv[i]); | ||
925 | } | ||
926 | free(pglob->gl_statv); | ||
927 | pglob->gl_statv = NULL; | ||
928 | } | ||
788 | } | 929 | } |
789 | 930 | ||
790 | static DIR * | 931 | static DIR * |
@@ -830,11 +971,11 @@ g_stat(Char *fn, struct stat *sb, glob_t *pglob) | |||
830 | } | 971 | } |
831 | 972 | ||
832 | static Char * | 973 | static Char * |
833 | g_strchr(Char *str, int ch) | 974 | g_strchr(const Char *str, int ch) |
834 | { | 975 | { |
835 | do { | 976 | do { |
836 | if (*str == ch) | 977 | if (*str == ch) |
837 | return (str); | 978 | return ((Char *)str); |
838 | } while (*str++); | 979 | } while (*str++); |
839 | return (NULL); | 980 | return (NULL); |
840 | } | 981 | } |
@@ -870,5 +1011,4 @@ qprintf(const char *str, Char *s) | |||
870 | #endif | 1011 | #endif |
871 | 1012 | ||
872 | #endif /* !defined(HAVE_GLOB) || !defined(GLOB_HAS_ALTDIRFUNC) || | 1013 | #endif /* !defined(HAVE_GLOB) || !defined(GLOB_HAS_ALTDIRFUNC) || |
873 | !defined(GLOB_HAS_GL_MATCHC) */ | 1014 | !defined(GLOB_HAS_GL_MATCHC) || !defined(GLOB_HAS_GL_STATV) */ |
874 | |||