diff options
author | Colin Watson <cjwatson@debian.org> | 2011-01-24 12:43:25 +0000 |
---|---|---|
committer | Colin Watson <cjwatson@debian.org> | 2011-01-24 12:43:25 +0000 |
commit | 626f1d986ff72aa514da63e34744e1de9cf21b9a (patch) | |
tree | d215a5280bc2e57251e4a9e08bfd3674ad824a94 /openbsd-compat/glob.c | |
parent | 6ed622cb6fe8f71bbe0d998cdd12280410bfb420 (diff) | |
parent | 0970072c89b079b022538e3c366fbfa2c53fc821 (diff) |
* New upstream release (http://www.openssh.org/txt/release-5.7):
- Implement Elliptic Curve Cryptography modes for key exchange (ECDH)
and host/user keys (ECDSA) as specified by RFC5656. ECDH and ECDSA
offer better performance than plain DH and DSA at the same equivalent
symmetric key length, as well as much shorter keys.
- sftp(1)/sftp-server(8): add a protocol extension to support a hard
link operation. It is available through the "ln" command in the
client. The old "ln" behaviour of creating a symlink is available
using its "-s" option or through the preexisting "symlink" command.
- scp(1): Add a new -3 option to scp: Copies between two remote hosts
are transferred through the local host (closes: #508613).
- ssh(1): "atomically" create the listening mux socket by binding it on
a temporary name and then linking it into position after listen() has
succeeded. This allows the mux clients to determine that the server
socket is either ready or stale without races (closes: #454784).
Stale server sockets are now automatically removed (closes: #523250).
- ssh(1): install a SIGCHLD handler to reap expired child process
(closes: #594687).
- ssh(1)/ssh-agent(1): honour $TMPDIR for client xauth and ssh-agent
temporary directories (closes: #357469, although only if you arrange
for ssh-agent to actually see $TMPDIR since the setgid bit will cause
it to be stripped off).
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 | |||