Sun Apr 24 15:41:23 2011 UTC ()
Pull up following revision(s) (requested by spz in ticket #1597):
	lib/libc/gen/glob.c: revision 1.28
	lib/libc/gen/glob.c: revision 1.29
prevent resource DoS from brace expansion (from Maksymilian Arciemowicz)
remove stray printf.


(riz)
diff -r1.23.4.1 -r1.23.4.1.2.1 src/lib/libc/gen/glob.c

cvs diff -r1.23.4.1 -r1.23.4.1.2.1 src/lib/libc/gen/glob.c (expand / switch to unified diff)

--- src/lib/libc/gen/glob.c 2010/07/19 18:14:08 1.23.4.1
+++ src/lib/libc/gen/glob.c 2011/04/24 15:41:23 1.23.4.1.2.1
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: glob.c,v 1.23.4.1 2010/07/19 18:14:08 riz Exp $ */ 1/* $NetBSD: glob.c,v 1.23.4.1.2.1 2011/04/24 15:41:23 riz Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1989, 1993 4 * Copyright (c) 1989, 1993
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to Berkeley by 7 * This code is derived from software contributed to Berkeley by
8 * Guido van Rossum. 8 * Guido van Rossum.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -27,27 +27,27 @@ @@ -27,27 +27,27 @@
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE. 32 * SUCH DAMAGE.
33 */ 33 */
34 34
35#include <sys/cdefs.h> 35#include <sys/cdefs.h>
36#if defined(LIBC_SCCS) && !defined(lint) 36#if defined(LIBC_SCCS) && !defined(lint)
37#if 0 37#if 0
38static char sccsid[] = "@(#)glob.c 8.3 (Berkeley) 10/13/93"; 38static char sccsid[] = "@(#)glob.c 8.3 (Berkeley) 10/13/93";
39#else 39#else
40__RCSID("$NetBSD: glob.c,v 1.23.4.1 2010/07/19 18:14:08 riz Exp $"); 40__RCSID("$NetBSD: glob.c,v 1.23.4.1.2.1 2011/04/24 15:41:23 riz Exp $");
41#endif 41#endif
42#endif /* LIBC_SCCS and not lint */ 42#endif /* LIBC_SCCS and not lint */
43 43
44/* 44/*
45 * glob(3) -- a superset of the one defined in POSIX 1003.2. 45 * glob(3) -- a superset of the one defined in POSIX 1003.2.
46 * 46 *
47 * The [!...] convention to negate a range is supported (SysV, Posix, ksh). 47 * The [!...] convention to negate a range is supported (SysV, Posix, ksh).
48 * 48 *
49 * Optional extra services, controlled by flags not defined by POSIX: 49 * Optional extra services, controlled by flags not defined by POSIX:
50 * 50 *
51 * GLOB_MAGCHAR: 51 * GLOB_MAGCHAR:
52 * Set in gl_flags if pattern contained a globbing character. 52 * Set in gl_flags if pattern contained a globbing character.
53 * GLOB_NOMAGIC: 53 * GLOB_NOMAGIC:
@@ -77,33 +77,38 @@ __RCSID("$NetBSD: glob.c,v 1.23.4.1 2010 @@ -77,33 +77,38 @@ __RCSID("$NetBSD: glob.c,v 1.23.4.1 2010
77#include <errno.h> 77#include <errno.h>
78#include <glob.h> 78#include <glob.h>
79#include <pwd.h> 79#include <pwd.h>
80#include <stdio.h> 80#include <stdio.h>
81#include <stddef.h> 81#include <stddef.h>
82#include <stdlib.h> 82#include <stdlib.h>
83#include <string.h> 83#include <string.h>
84#include <unistd.h> 84#include <unistd.h>
85 85
86#ifdef HAVE_NBTOOL_CONFIG_H 86#ifdef HAVE_NBTOOL_CONFIG_H
87#define NO_GETPW_R 87#define NO_GETPW_R
88#endif 88#endif
89 89
90#define GLOB_LIMIT_MALLOC 65536 90#define GLOB_LIMIT_STRING 65536 /* number of readdirs */
91#define GLOB_LIMIT_STAT 128 91#define GLOB_LIMIT_STAT 128 /* number of stat system calls */
92#define GLOB_LIMIT_READDIR 16384 92#define GLOB_LIMIT_READDIR 16384 /* total buffer size of path strings */
93 93#define GLOB_LIMIT_PATH 1024 /* number of path elements */
94#define GLOB_INDEX_MALLOC 0 94#define GLOB_LIMIT_BRACE 128 /* Number of brace calls */
95#define GLOB_INDEX_STAT 1 95
96#define GLOB_INDEX_READDIR 2 96struct glob_limit {
 97 size_t l_string;
 98 size_t l_stat;
 99 size_t l_readdir;
 100 size_t l_brace;
 101};
97 102
98/* 103/*
99 * XXX: For NetBSD 1.4.x compatibility. (kill me l8r) 104 * XXX: For NetBSD 1.4.x compatibility. (kill me l8r)
100 */ 105 */
101#ifndef _DIAGASSERT 106#ifndef _DIAGASSERT
102#define _DIAGASSERT(a) 107#define _DIAGASSERT(a)
103#endif 108#endif
104 109
105#define DOLLAR '$' 110#define DOLLAR '$'
106#define DOT '.' 111#define DOT '.'
107#define EOS '\0' 112#define EOS '\0'
108#define LBRACKET '[' 113#define LBRACKET '['
109#define NOT '!' 114#define NOT '!'
@@ -148,51 +153,50 @@ typedef char Char; @@ -148,51 +153,50 @@ typedef char Char;
148#define M_NOT META('!') 153#define M_NOT META('!')
149#define M_ONE META('?') 154#define M_ONE META('?')
150#define M_RNG META('-') 155#define M_RNG META('-')
151#define M_SET META('[') 156#define M_SET META('[')
152#define ismeta(c) (((c)&M_QUOTE) != 0) 157#define ismeta(c) (((c)&M_QUOTE) != 0)
153 158
154 159
155static int compare(const void *, const void *); 160static int compare(const void *, const void *);
156static int g_Ctoc(const Char *, char *, size_t); 161static int g_Ctoc(const Char *, char *, size_t);
157static int g_lstat(Char *, __gl_stat_t *, glob_t *); 162static int g_lstat(Char *, __gl_stat_t *, glob_t *);
158static DIR *g_opendir(Char *, glob_t *); 163static DIR *g_opendir(Char *, glob_t *);
159static Char *g_strchr(const Char *, int); 164static Char *g_strchr(const Char *, int);
160static int g_stat(Char *, __gl_stat_t *, glob_t *); 165static int g_stat(Char *, __gl_stat_t *, glob_t *);
161static int glob0(const Char *, glob_t *, size_t *); 166static int glob0(const Char *, glob_t *, struct glob_limit *);
162static int glob1(Char *, glob_t *, size_t *); 167static int glob1(Char *, glob_t *, struct glob_limit *);
163static int glob2(Char *, Char *, Char *, Char *, glob_t *, 168static int glob2(Char *, Char *, Char *, const Char *, glob_t *,
164 size_t *); 169 struct glob_limit *);
165static int glob3(Char *, Char *, Char *, Char *, Char *, glob_t *, 170static int glob3(Char *, Char *, Char *, const Char *, const Char *,
166 size_t *); 171 glob_t *, struct glob_limit *);
167static int globextend(const Char *, glob_t *, size_t *); 172static int globextend(const Char *, glob_t *, struct glob_limit *);
168static const Char *globtilde(const Char *, Char *, size_t, glob_t *); 173static const Char *globtilde(const Char *, Char *, size_t, glob_t *);
169static int globexp1(const Char *, glob_t *, size_t *); 174static int globexp1(const Char *, glob_t *, struct glob_limit *);
170static int globexp2(const Char *, const Char *, glob_t *, int *, 175static int globexp2(const Char *, const Char *, glob_t *, int *,
171 size_t *); 176 struct glob_limit *);
172static int match(Char *, Char *, Char *); 177static int match(const Char *, const Char *, const Char *);
173#ifdef DEBUG 178#ifdef DEBUG
174static void qprintf(const char *, Char *); 179static void qprintf(const char *, Char *);
175#endif 180#endif
176 181
177int 182int
178glob(const char *pattern, int flags, int (*errfunc)(const char *, int), 183glob(const char *pattern, int flags, int (*errfunc)(const char *, int),
179 glob_t *pglob) 184 glob_t *pglob)
180{ 185{
181 const u_char *patnext; 186 const u_char *patnext;
182 int c; 187 int c;
183 Char *bufnext, *bufend, patbuf[MAXPATHLEN+1]; 188 Char *bufnext, *bufend, patbuf[MAXPATHLEN+1];
184 /* 0 = malloc(), 1 = stat(), 2 = readdir() */ 189 struct glob_limit limit = { 0, 0, 0, 0 };
185 size_t limit[] = { 0, 0, 0 }; 
186 190
187 _DIAGASSERT(pattern != NULL); 191 _DIAGASSERT(pattern != NULL);
188 192
189 patnext = (const u_char *) pattern; 193 patnext = (const u_char *) pattern;
190 if (!(flags & GLOB_APPEND)) { 194 if (!(flags & GLOB_APPEND)) {
191 pglob->gl_pathc = 0; 195 pglob->gl_pathc = 0;
192 pglob->gl_pathv = NULL; 196 pglob->gl_pathv = NULL;
193 if (!(flags & GLOB_DOOFFS)) 197 if (!(flags & GLOB_DOOFFS))
194 pglob->gl_offs = 0; 198 pglob->gl_offs = 0;
195 } 199 }
196 pglob->gl_flags = flags & ~GLOB_MAGCHAR; 200 pglob->gl_flags = flags & ~GLOB_MAGCHAR;
197 pglob->gl_errfunc = errfunc; 201 pglob->gl_errfunc = errfunc;
198 pglob->gl_matchc = 0; 202 pglob->gl_matchc = 0;
@@ -208,65 +212,71 @@ glob(const char *pattern, int flags, int @@ -208,65 +212,71 @@ glob(const char *pattern, int flags, int
208 if (c == QUOTE) { 212 if (c == QUOTE) {
209 if ((c = *patnext++) == EOS) { 213 if ((c = *patnext++) == EOS) {
210 c = QUOTE; 214 c = QUOTE;
211 --patnext; 215 --patnext;
212 } 216 }
213 *bufnext++ = c | M_PROTECT; 217 *bufnext++ = c | M_PROTECT;
214 } 218 }
215 else 219 else
216 *bufnext++ = c; 220 *bufnext++ = c;
217 } 221 }
218 *bufnext = EOS; 222 *bufnext = EOS;
219 223
220 if (flags & GLOB_BRACE) 224 if (flags & GLOB_BRACE)
221 return globexp1(patbuf, pglob, limit); 225 return globexp1(patbuf, pglob, &limit);
222 else 226 else
223 return glob0(patbuf, pglob, limit); 227 return glob0(patbuf, pglob, &limit);
224} 228}
225 229
226/* 230/*
227 * Expand recursively a glob {} pattern. When there is no more expansion 231 * Expand recursively a glob {} pattern. When there is no more expansion
228 * invoke the standard globbing routine to glob the rest of the magic 232 * invoke the standard globbing routine to glob the rest of the magic
229 * characters 233 * characters
230 */ 234 */
231static int 235static int
232globexp1(const Char *pattern, glob_t *pglob, size_t *limit) 236globexp1(const Char *pattern, glob_t *pglob, struct glob_limit *limit)
233{ 237{
234 const Char* ptr = pattern; 238 const Char* ptr = pattern;
235 int rv; 239 int rv;
236 240
237 _DIAGASSERT(pattern != NULL); 241 _DIAGASSERT(pattern != NULL);
238 _DIAGASSERT(pglob != NULL); 242 _DIAGASSERT(pglob != NULL);
239 243
 244 if ((pglob->gl_flags & GLOB_LIMIT) &&
 245 limit->l_brace++ >= GLOB_LIMIT_BRACE) {
 246 errno = 0;
 247 return GLOB_NOSPACE;
 248 }
 249
240 /* Protect a single {}, for find(1), like csh */ 250 /* Protect a single {}, for find(1), like csh */
241 if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS) 251 if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS)
242 return glob0(pattern, pglob, limit); 252 return glob0(pattern, pglob, limit);
243 253
244 while ((ptr = (const Char *) g_strchr(ptr, LBRACE)) != NULL) 254 while ((ptr = (const Char *) g_strchr(ptr, LBRACE)) != NULL)
245 if (!globexp2(ptr, pattern, pglob, &rv, limit)) 255 if (!globexp2(ptr, pattern, pglob, &rv, limit))
246 return rv; 256 return rv;
247 257
248 return glob0(pattern, pglob, limit); 258 return glob0(pattern, pglob, limit);
249} 259}
250 260
251 261
252/* 262/*
253 * Recursive brace globbing helper. Tries to expand a single brace. 263 * Recursive brace globbing helper. Tries to expand a single brace.
254 * If it succeeds then it invokes globexp1 with the new pattern. 264 * If it succeeds then it invokes globexp1 with the new pattern.
255 * If it fails then it tries to glob the rest of the pattern and returns. 265 * If it fails then it tries to glob the rest of the pattern and returns.
256 */ 266 */
257static int 267static int
258globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv, 268globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv,
259 size_t *limit) 269 struct glob_limit *limit)
260{ 270{
261 int i; 271 int i;
262 Char *lm, *ls; 272 Char *lm, *ls;
263 const Char *pe, *pm, *pl; 273 const Char *pe, *pm, *pl;
264 Char patbuf[MAXPATHLEN + 1]; 274 Char patbuf[MAXPATHLEN + 1];
265 275
266 _DIAGASSERT(ptr != NULL); 276 _DIAGASSERT(ptr != NULL);
267 _DIAGASSERT(pattern != NULL); 277 _DIAGASSERT(pattern != NULL);
268 _DIAGASSERT(pglob != NULL); 278 _DIAGASSERT(pglob != NULL);
269 _DIAGASSERT(rv != NULL); 279 _DIAGASSERT(rv != NULL);
270 280
271 /* copy part up to the brace */ 281 /* copy part up to the brace */
272 for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++) 282 for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++)
@@ -451,27 +461,27 @@ globtilde(const Char *pattern, Char *pat @@ -451,27 +461,27 @@ globtilde(const Char *pattern, Char *pat
451 461
452 return patbuf; 462 return patbuf;
453} 463}
454  464
455 465
456/* 466/*
457 * The main glob() routine: compiles the pattern (optionally processing 467 * The main glob() routine: compiles the pattern (optionally processing
458 * quotes), calls glob1() to do the real pattern matching, and finally 468 * quotes), calls glob1() to do the real pattern matching, and finally
459 * sorts the list (unless unsorted operation is requested). Returns 0 469 * sorts the list (unless unsorted operation is requested). Returns 0
460 * if things went well, nonzero if errors occurred. It is not an error 470 * if things went well, nonzero if errors occurred. It is not an error
461 * to find no matches. 471 * to find no matches.
462 */ 472 */
463static int 473static int
464glob0(const Char *pattern, glob_t *pglob, size_t *limit) 474glob0(const Char *pattern, glob_t *pglob, struct glob_limit *limit)
465{ 475{
466 const Char *qpatnext; 476 const Char *qpatnext;
467 int c, error; 477 int c, error;
468 __gl_size_t oldpathc; 478 __gl_size_t oldpathc;
469 Char *bufnext, patbuf[MAXPATHLEN+1]; 479 Char *bufnext, patbuf[MAXPATHLEN+1];
470 480
471 _DIAGASSERT(pattern != NULL); 481 _DIAGASSERT(pattern != NULL);
472 _DIAGASSERT(pglob != NULL); 482 _DIAGASSERT(pglob != NULL);
473 483
474 if ((qpatnext = globtilde(pattern, patbuf, sizeof(patbuf), 484 if ((qpatnext = globtilde(pattern, patbuf, sizeof(patbuf),
475 pglob)) == NULL) 485 pglob)) == NULL)
476 return GLOB_ABEND; 486 return GLOB_ABEND;
477 oldpathc = pglob->gl_pathc; 487 oldpathc = pglob->gl_pathc;
@@ -557,77 +567,78 @@ glob0(const Char *pattern, glob_t *pglob @@ -557,77 +567,78 @@ glob0(const Char *pattern, glob_t *pglob
557} 567}
558 568
559static int 569static int
560compare(const void *p, const void *q) 570compare(const void *p, const void *q)
561{ 571{
562 572
563 _DIAGASSERT(p != NULL); 573 _DIAGASSERT(p != NULL);
564 _DIAGASSERT(q != NULL); 574 _DIAGASSERT(q != NULL);
565 575
566 return strcoll(*(const char * const *)p, *(const char * const *)q); 576 return strcoll(*(const char * const *)p, *(const char * const *)q);
567} 577}
568 578
569static int 579static int
570glob1(Char *pattern, glob_t *pglob, size_t *limit) 580glob1(Char *pattern, glob_t *pglob, struct glob_limit *limit)
571{ 581{
572 Char pathbuf[MAXPATHLEN+1]; 582 Char pathbuf[MAXPATHLEN+1];
573 583
574 _DIAGASSERT(pattern != NULL); 584 _DIAGASSERT(pattern != NULL);
575 _DIAGASSERT(pglob != NULL); 585 _DIAGASSERT(pglob != NULL);
576 586
577 /* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */ 587 /* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */
578 if (*pattern == EOS) 588 if (*pattern == EOS)
579 return 0; 589 return 0;
580 /* 590 /*
581 * we save one character so that we can use ptr >= limit, 591 * we save one character so that we can use ptr >= limit,
582 * in the general case when we are appending non nul chars only. 592 * in the general case when we are appending non nul chars only.
583 */ 593 */
584 return glob2(pathbuf, pathbuf, 594 return glob2(pathbuf, pathbuf,
585 pathbuf + (sizeof(pathbuf) / sizeof(*pathbuf)) - 1, pattern, 595 pathbuf + (sizeof(pathbuf) / sizeof(*pathbuf)) - 1, pattern,
586 pglob, limit); 596 pglob, limit);
587} 597}
588 598
589/* 599/*
590 * The functions glob2 and glob3 are mutually recursive; there is one level 600 * The functions glob2 and glob3 are mutually recursive; there is one level
591 * of recursion for each segment in the pattern that contains one or more 601 * of recursion for each segment in the pattern that contains one or more
592 * meta characters. 602 * meta characters.
593 */ 603 */
594static int 604static int
595glob2(Char *pathbuf, Char *pathend, Char *pathlim, Char *pattern, glob_t *pglob, 605glob2(Char *pathbuf, Char *pathend, Char *pathlim, const Char *pattern,
596 size_t *limit) 606 glob_t *pglob, struct glob_limit *limit)
597{ 607{
598 __gl_stat_t sb; 608 __gl_stat_t sb;
599 Char *p, *q; 609 const Char *p;
 610 Char *q;
600 int anymeta; 611 int anymeta;
601 Char *pend; 612 Char *pend;
602 ptrdiff_t diff; 613 ptrdiff_t diff;
603 614
604 _DIAGASSERT(pathbuf != NULL); 615 _DIAGASSERT(pathbuf != NULL);
605 _DIAGASSERT(pathend != NULL); 616 _DIAGASSERT(pathend != NULL);
606 _DIAGASSERT(pattern != NULL); 617 _DIAGASSERT(pattern != NULL);
607 _DIAGASSERT(pglob != NULL); 618 _DIAGASSERT(pglob != NULL);
608 619
609 /* 620 /*
610 * Loop over pattern segments until end of pattern or until 621 * Loop over pattern segments until end of pattern or until
611 * segment with meta character found. 622 * segment with meta character found.
612 */ 623 */
613 for (anymeta = 0;;) { 624 for (anymeta = 0;;) {
614 if (*pattern == EOS) { /* End of pattern? */ 625 if (*pattern == EOS) { /* End of pattern? */
615 *pathend = EOS; 626 *pathend = EOS;
616 if (g_lstat(pathbuf, &sb, pglob)) 627 if (g_lstat(pathbuf, &sb, pglob))
617 return 0; 628 return 0;
618  629
619 if ((pglob->gl_flags & GLOB_LIMIT) && 630 if ((pglob->gl_flags & GLOB_LIMIT) &&
620 limit[GLOB_INDEX_STAT]++ >= GLOB_LIMIT_STAT) { 631 limit->l_stat++ >= GLOB_LIMIT_STAT) {
621 errno = 0; 632 errno = 0;
622 *pathend++ = SEP; 633 *pathend++ = SEP;
623 *pathend = EOS; 634 *pathend = EOS;
624 return GLOB_NOSPACE; 635 return GLOB_NOSPACE;
625 } 636 }
626 if (((pglob->gl_flags & GLOB_MARK) && 637 if (((pglob->gl_flags & GLOB_MARK) &&
627 pathend[-1] != SEP) && (S_ISDIR(sb.st_mode) || 638 pathend[-1] != SEP) && (S_ISDIR(sb.st_mode) ||
628 (S_ISLNK(sb.st_mode) && 639 (S_ISLNK(sb.st_mode) &&
629 (g_stat(pathbuf, &sb, pglob) == 0) && 640 (g_stat(pathbuf, &sb, pglob) == 0) &&
630 S_ISDIR(sb.st_mode)))) { 641 S_ISDIR(sb.st_mode)))) {
631 if (pathend >= pathlim) 642 if (pathend >= pathlim)
632 return GLOB_ABORTED; 643 return GLOB_ABORTED;
633 *pathend++ = SEP; 644 *pathend++ = SEP;
@@ -673,28 +684,28 @@ glob2(Char *pathbuf, Char *pathend, Char @@ -673,28 +684,28 @@ glob2(Char *pathbuf, Char *pathend, Char
673 while (*pattern == SEP) { 684 while (*pattern == SEP) {
674 if (pathend >= pathlim) 685 if (pathend >= pathlim)
675 return GLOB_ABORTED; 686 return GLOB_ABORTED;
676 *pathend++ = *pattern++; 687 *pathend++ = *pattern++;
677 } 688 }
678 } else /* Need expansion, recurse. */ 689 } else /* Need expansion, recurse. */
679 return glob3(pathbuf, pathend, pathlim, pattern, p, 690 return glob3(pathbuf, pathend, pathlim, pattern, p,
680 pglob, limit); 691 pglob, limit);
681 } 692 }
682 /* NOTREACHED */ 693 /* NOTREACHED */
683} 694}
684 695
685static int 696static int
686glob3(Char *pathbuf, Char *pathend, Char *pathlim, Char *pattern, 697glob3(Char *pathbuf, Char *pathend, Char *pathlim, const Char *pattern,
687 Char *restpattern, glob_t *pglob, size_t *limit) 698 const Char *restpattern, glob_t *pglob, struct glob_limit *limit)
688{ 699{
689 struct dirent *dp; 700 struct dirent *dp;
690 DIR *dirp; 701 DIR *dirp;
691 int error; 702 int error;
692 char buf[MAXPATHLEN]; 703 char buf[MAXPATHLEN];
693 704
694 /* 705 /*
695 * The readdirfunc declaration can't be prototyped, because it is 706 * The readdirfunc declaration can't be prototyped, because it is
696 * assigned, below, to two functions which are prototyped in glob.h 707 * assigned, below, to two functions which are prototyped in glob.h
697 * and dirent.h as taking pointers to differently typed opaque 708 * and dirent.h as taking pointers to differently typed opaque
698 * structures. 709 * structures.
699 */ 710 */
700 struct dirent *(*readdirfunc)(void *); 711 struct dirent *(*readdirfunc)(void *);
@@ -730,27 +741,27 @@ glob3(Char *pathbuf, Char *pathend, Char @@ -730,27 +741,27 @@ glob3(Char *pathbuf, Char *pathend, Char
730 741
731 error = 0; 742 error = 0;
732 743
733 /* Search directory for matching names. */ 744 /* Search directory for matching names. */
734 if (pglob->gl_flags & GLOB_ALTDIRFUNC) 745 if (pglob->gl_flags & GLOB_ALTDIRFUNC)
735 readdirfunc = pglob->gl_readdir; 746 readdirfunc = pglob->gl_readdir;
736 else 747 else
737 readdirfunc = (struct dirent *(*)__P((void *))) readdir; 748 readdirfunc = (struct dirent *(*)__P((void *))) readdir;
738 while ((dp = (*readdirfunc)(dirp)) != NULL) { 749 while ((dp = (*readdirfunc)(dirp)) != NULL) {
739 u_char *sc; 750 u_char *sc;
740 Char *dc; 751 Char *dc;
741 752
742 if ((pglob->gl_flags & GLOB_LIMIT) && 753 if ((pglob->gl_flags & GLOB_LIMIT) &&
743 limit[GLOB_INDEX_READDIR]++ >= GLOB_LIMIT_READDIR) { 754 limit->l_readdir++ >= GLOB_LIMIT_READDIR) {
744 errno = 0; 755 errno = 0;
745 *pathend++ = SEP; 756 *pathend++ = SEP;
746 *pathend = EOS; 757 *pathend = EOS;
747 return GLOB_NOSPACE; 758 return GLOB_NOSPACE;
748 } 759 }
749 760
750 /* 761 /*
751 * Initial DOT must be matched literally, unless we have 762 * Initial DOT must be matched literally, unless we have
752 * GLOB_PERIOD set. 763 * GLOB_PERIOD set.
753 */ 764 */
754 if ((pglob->gl_flags & GLOB_PERIOD) == 0) 765 if ((pglob->gl_flags & GLOB_PERIOD) == 0)
755 if (dp->d_name[0] == DOT && *pattern != DOT) 766 if (dp->d_name[0] == DOT && *pattern != DOT)
756 continue; 767 continue;
@@ -819,79 +830,83 @@ glob3(Char *pathbuf, Char *pathend, Char @@ -819,79 +830,83 @@ glob3(Char *pathbuf, Char *pathend, Char
819 * add the new item, and update gl_pathc. 830 * add the new item, and update gl_pathc.
820 * 831 *
821 * This assumes the BSD realloc, which only copies the block when its size 832 * This assumes the BSD realloc, which only copies the block when its size
822 * crosses a power-of-two boundary; for v7 realloc, this would cause quadratic 833 * crosses a power-of-two boundary; for v7 realloc, this would cause quadratic
823 * behavior. 834 * behavior.
824 * 835 *
825 * Return 0 if new item added, error code if memory couldn't be allocated. 836 * Return 0 if new item added, error code if memory couldn't be allocated.
826 * 837 *
827 * Invariant of the glob_t structure: 838 * Invariant of the glob_t structure:
828 * Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and 839 * Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and
829 * gl_pathv points to (gl_offs + gl_pathc + 1) items. 840 * gl_pathv points to (gl_offs + gl_pathc + 1) items.
830 */ 841 */
831static int 842static int
832globextend(const Char *path, glob_t *pglob, size_t *limit) 843globextend(const Char *path, glob_t *pglob, struct glob_limit *limit)
833{ 844{
834 char **pathv; 845 char **pathv;
835 size_t i, newsize, len; 846 size_t i, newsize, len;
836 char *copy; 847 char *copy;
837 const Char *p; 848 const Char *p;
838 849
839 _DIAGASSERT(path != NULL); 850 _DIAGASSERT(path != NULL);
840 _DIAGASSERT(pglob != NULL); 851 _DIAGASSERT(pglob != NULL);
841 852
842 newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs); 853 newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs);
 854 if ((pglob->gl_flags & GLOB_LIMIT) &&
 855 newsize > GLOB_LIMIT_PATH * sizeof(*pathv))
 856 goto nospace;
843 pathv = pglob->gl_pathv ? realloc(pglob->gl_pathv, newsize) : 857 pathv = pglob->gl_pathv ? realloc(pglob->gl_pathv, newsize) :
844 malloc(newsize); 858 malloc(newsize);
845 if (pathv == NULL) 859 if (pathv == NULL)
846 return GLOB_NOSPACE; 860 return GLOB_NOSPACE;
847 861
848 if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) { 862 if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) {
849 /* first time around -- clear initial gl_offs items */ 863 /* first time around -- clear initial gl_offs items */
850 pathv += pglob->gl_offs; 864 pathv += pglob->gl_offs;
851 for (i = pglob->gl_offs + 1; --i > 0; ) 865 for (i = pglob->gl_offs + 1; --i > 0; )
852 *--pathv = NULL; 866 *--pathv = NULL;
853 } 867 }
854 pglob->gl_pathv = pathv; 868 pglob->gl_pathv = pathv;
855 869
856 for (p = path; *p++;) 870 for (p = path; *p++;)
857 continue; 871 continue;
858 len = (size_t)(p - path); 872 len = (size_t)(p - path);
859 limit[GLOB_INDEX_MALLOC] += len; 873 limit->l_string += len;
860 if ((copy = malloc(len)) != NULL) { 874 if ((copy = malloc(len)) != NULL) {
861 if (g_Ctoc(path, copy, len)) { 875 if (g_Ctoc(path, copy, len)) {
862 free(copy); 876 free(copy);
863 return GLOB_ABORTED; 877 return GLOB_ABORTED;
864 } 878 }
865 pathv[pglob->gl_offs + pglob->gl_pathc++] = copy; 879 pathv[pglob->gl_offs + pglob->gl_pathc++] = copy;
866 } 880 }
867 pathv[pglob->gl_offs + pglob->gl_pathc] = NULL; 881 pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
868 882
869 if ((pglob->gl_flags & GLOB_LIMIT) && 883 if ((pglob->gl_flags & GLOB_LIMIT) &&
870 (newsize + limit[GLOB_INDEX_MALLOC]) >= GLOB_LIMIT_MALLOC) { 884 (newsize + limit->l_string) >= GLOB_LIMIT_STRING)
871 errno = 0; 885 goto nospace;
872 return GLOB_NOSPACE; 
873 } 
874 886
875 return copy == NULL ? GLOB_NOSPACE : 0; 887 return copy == NULL ? GLOB_NOSPACE : 0;
 888nospace:
 889 errno = 0;
 890 return GLOB_NOSPACE;
876} 891}
877 892
878 893
879/* 894/*
880 * pattern matching function for filenames. Each occurrence of the * 895 * pattern matching function for filenames. Each occurrence of the *
881 * pattern causes a recursion level. 896 * pattern causes a recursion level.
882 */ 897 */
883static int 898static int
884match(Char *name, Char *pat, Char *patend) 899match(const Char *name, const Char *pat, const Char *patend)
885{ 900{
886 int ok, negate_range; 901 int ok, negate_range;
887 Char c, k; 902 Char c, k;
888 903
889 _DIAGASSERT(name != NULL); 904 _DIAGASSERT(name != NULL);
890 _DIAGASSERT(pat != NULL); 905 _DIAGASSERT(pat != NULL);
891 _DIAGASSERT(patend != NULL); 906 _DIAGASSERT(patend != NULL);
892 907
893 while (pat < patend) { 908 while (pat < patend) {
894 c = *pat++; 909 c = *pat++;
895 switch (c & M_MASK) { 910 switch (c & M_MASK) {
896 case M_ALL: 911 case M_ALL:
897 if (pat == patend) 912 if (pat == patend)