summaryrefslogtreecommitdiff
path: root/openbsd-compat/glob.c
diff options
context:
space:
mode:
authorColin Watson <cjwatson@debian.org>2011-01-24 12:43:25 +0000
committerColin Watson <cjwatson@debian.org>2011-01-24 12:43:25 +0000
commit626f1d986ff72aa514da63e34744e1de9cf21b9a (patch)
treed215a5280bc2e57251e4a9e08bfd3674ad824a94 /openbsd-compat/glob.c
parent6ed622cb6fe8f71bbe0d998cdd12280410bfb420 (diff)
parent0970072c89b079b022538e3c366fbfa2c53fc821 (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.c306
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
54static long
55get_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
135struct glob_lim {
136 size_t glim_malloc;
137 size_t glim_stat;
138 size_t glim_readdir;
139};
142 140
143static int compare(const void *, const void *); 141static int compare(const void *, const void *);
144static int g_Ctoc(const Char *, char *, u_int); 142static int g_Ctoc(const Char *, char *, u_int);
145static int g_lstat(Char *, struct stat *, glob_t *); 143static int g_lstat(Char *, struct stat *, glob_t *);
146static DIR *g_opendir(Char *, glob_t *); 144static DIR *g_opendir(Char *, glob_t *);
147static Char *g_strchr(Char *, int); 145static Char *g_strchr(const Char *, int);
146static int g_strncmp(const Char *, const char *, size_t);
148static int g_stat(Char *, struct stat *, glob_t *); 147static int g_stat(Char *, struct stat *, glob_t *);
149static int glob0(const Char *, glob_t *); 148static int glob0(const Char *, glob_t *, struct glob_lim *);
150static int glob1(Char *, Char *, glob_t *, size_t *); 149static int glob1(Char *, Char *, glob_t *, struct glob_lim *);
151static int glob2(Char *, Char *, Char *, Char *, Char *, Char *, 150static int glob2(Char *, Char *, Char *, Char *, Char *, Char *,
152 glob_t *, size_t *); 151 glob_t *, struct glob_lim *);
153static int glob3(Char *, Char *, Char *, Char *, Char *, 152static int glob3(Char *, Char *, Char *, Char *, Char *,
154 Char *, Char *, glob_t *, size_t *); 153 Char *, Char *, glob_t *, struct glob_lim *);
155static int globextend(const Char *, glob_t *, size_t *); 154static int globextend(const Char *, glob_t *, struct glob_lim *,
155 struct stat *);
156static const Char * 156static const Char *
157 globtilde(const Char *, Char *, size_t, glob_t *); 157 globtilde(const Char *, Char *, size_t, glob_t *);
158static int globexp1(const Char *, glob_t *); 158static int globexp1(const Char *, glob_t *, struct glob_lim *);
159static int globexp2(const Char *, const Char *, glob_t *, int *); 159static int globexp2(const Char *, const Char *, glob_t *,
160 struct glob_lim *);
160static int match(Char *, Char *, Char *); 161static int match(Char *, Char *, Char *);
161#ifdef DEBUG 162#ifdef DEBUG
162static void qprintf(const char *, Char *); 163static 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 */
214static int 222static int
215globexp1(const Char *pattern, glob_t *pglob) 223globexp1(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 */
237static int 243static int
238globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv) 244globexp2(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
408static int
409g_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
423static int
424g_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 */
410static int 457static int
411glob0(const Char *pattern, glob_t *pglob) 458glob0(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
503static int 563static int
504glob1(Char *pattern, Char *pattern_last, glob_t *pglob, size_t *limitp) 564glob1(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 */
521static int 581static int
522glob2(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, 582glob2(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,
581static int 649static int
582glob3(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, 650glob3(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 */
672static int 748static int
673globextend(const Char *path, glob_t *pglob, size_t *limitp) 749globextend(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
790static DIR * 931static DIR *
@@ -830,11 +971,11 @@ g_stat(Char *fn, struct stat *sb, glob_t *pglob)
830} 971}
831 972
832static Char * 973static Char *
833g_strchr(Char *str, int ch) 974g_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