diff options
Diffstat (limited to 'openbsd-compat')
-rw-r--r-- | openbsd-compat/glob.c | 102 |
1 files changed, 63 insertions, 39 deletions
diff --git a/openbsd-compat/glob.c b/openbsd-compat/glob.c index e52bef729..692e81045 100644 --- a/openbsd-compat/glob.c +++ b/openbsd-compat/glob.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: glob.c,v 1.33 2010/09/26 22:15:39 djm Exp $ */ | 1 | /* $OpenBSD: glob.c,v 1.34 2010/10/08 21:48:42 nicm 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. |
@@ -76,18 +76,6 @@ | |||
76 | !defined(HAVE_DECL_GLOB_NOMATCH) || HAVE_DECL_GLOB_NOMATCH == 0 || \ | 76 | !defined(HAVE_DECL_GLOB_NOMATCH) || HAVE_DECL_GLOB_NOMATCH == 0 || \ |
77 | defined(BROKEN_GLOB) | 77 | defined(BROKEN_GLOB) |
78 | 78 | ||
79 | static long | ||
80 | get_arg_max(void) | ||
81 | { | ||
82 | #ifdef ARG_MAX | ||
83 | return(ARG_MAX); | ||
84 | #elif defined(HAVE_SYSCONF) && defined(_SC_ARG_MAX) | ||
85 | return(sysconf(_SC_ARG_MAX)); | ||
86 | #else | ||
87 | return(256); /* XXX: arbitrary */ | ||
88 | #endif | ||
89 | } | ||
90 | |||
91 | #include "charclass.h" | 79 | #include "charclass.h" |
92 | 80 | ||
93 | #define DOLLAR '$' | 81 | #define DOLLAR '$' |
@@ -140,6 +128,15 @@ typedef char Char; | |||
140 | #define M_CLASS META(':') | 128 | #define M_CLASS META(':') |
141 | #define ismeta(c) (((c)&M_QUOTE) != 0) | 129 | #define ismeta(c) (((c)&M_QUOTE) != 0) |
142 | 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 | }; | ||
143 | 140 | ||
144 | static int compare(const void *, const void *); | 141 | static int compare(const void *, const void *); |
145 | static int g_Ctoc(const Char *, char *, u_int); | 142 | static int g_Ctoc(const Char *, char *, u_int); |
@@ -148,17 +145,19 @@ static DIR *g_opendir(Char *, glob_t *); | |||
148 | static Char *g_strchr(const Char *, int); | 145 | static Char *g_strchr(const Char *, int); |
149 | static int g_strncmp(const Char *, const char *, size_t); | 146 | static int g_strncmp(const Char *, const char *, size_t); |
150 | static int g_stat(Char *, struct stat *, glob_t *); | 147 | static int g_stat(Char *, struct stat *, glob_t *); |
151 | static int glob0(const Char *, glob_t *); | 148 | static int glob0(const Char *, glob_t *, struct glob_lim *); |
152 | static int glob1(Char *, Char *, glob_t *, size_t *); | 149 | static int glob1(Char *, Char *, glob_t *, struct glob_lim *); |
153 | static int glob2(Char *, Char *, Char *, Char *, Char *, Char *, | 150 | static int glob2(Char *, Char *, Char *, Char *, Char *, Char *, |
154 | glob_t *, size_t *); | 151 | glob_t *, struct glob_lim *); |
155 | static int glob3(Char *, Char *, Char *, Char *, Char *, | 152 | static int glob3(Char *, Char *, Char *, Char *, Char *, |
156 | Char *, Char *, glob_t *, size_t *); | 153 | Char *, Char *, glob_t *, struct glob_lim *); |
157 | static int globextend(const Char *, glob_t *, size_t *, struct stat *); | 154 | static int globextend(const Char *, glob_t *, struct glob_lim *, |
155 | struct stat *); | ||
158 | static const Char * | 156 | static const Char * |
159 | globtilde(const Char *, Char *, size_t, glob_t *); | 157 | globtilde(const Char *, Char *, size_t, glob_t *); |
160 | static int globexp1(const Char *, glob_t *); | 158 | static int globexp1(const Char *, glob_t *, struct glob_lim *); |
161 | static int globexp2(const Char *, const Char *, glob_t *); | 159 | static int globexp2(const Char *, const Char *, glob_t *, |
160 | struct glob_lim *); | ||
162 | static int match(Char *, Char *, Char *); | 161 | static int match(Char *, Char *, Char *); |
163 | #ifdef DEBUG | 162 | #ifdef DEBUG |
164 | static void qprintf(const char *, Char *); | 163 | static void qprintf(const char *, Char *); |
@@ -171,6 +170,7 @@ glob(const char *pattern, int flags, int (*errfunc)(const char *, int), | |||
171 | const u_char *patnext; | 170 | const u_char *patnext; |
172 | int c; | 171 | int c; |
173 | Char *bufnext, *bufend, patbuf[MAXPATHLEN]; | 172 | Char *bufnext, *bufend, patbuf[MAXPATHLEN]; |
173 | struct glob_lim limit = { 0, 0, 0 }; | ||
174 | 174 | ||
175 | patnext = (u_char *) pattern; | 175 | patnext = (u_char *) pattern; |
176 | if (!(flags & GLOB_APPEND)) { | 176 | if (!(flags & GLOB_APPEND)) { |
@@ -204,9 +204,9 @@ glob(const char *pattern, int flags, int (*errfunc)(const char *, int), | |||
204 | *bufnext = EOS; | 204 | *bufnext = EOS; |
205 | 205 | ||
206 | if (flags & GLOB_BRACE) | 206 | if (flags & GLOB_BRACE) |
207 | return globexp1(patbuf, pglob); | 207 | return globexp1(patbuf, pglob, &limit); |
208 | else | 208 | else |
209 | return glob0(patbuf, pglob); | 209 | return glob0(patbuf, pglob, &limit); |
210 | } | 210 | } |
211 | 211 | ||
212 | /* | 212 | /* |
@@ -215,18 +215,18 @@ glob(const char *pattern, int flags, int (*errfunc)(const char *, int), | |||
215 | * characters | 215 | * characters |
216 | */ | 216 | */ |
217 | static int | 217 | static int |
218 | globexp1(const Char *pattern, glob_t *pglob) | 218 | globexp1(const Char *pattern, glob_t *pglob, struct glob_lim *limitp) |
219 | { | 219 | { |
220 | const Char* ptr = pattern; | 220 | const Char* ptr = pattern; |
221 | 221 | ||
222 | /* Protect a single {}, for find(1), like csh */ | 222 | /* Protect a single {}, for find(1), like csh */ |
223 | if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS) | 223 | if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS) |
224 | return glob0(pattern, pglob); | 224 | return glob0(pattern, pglob, limitp); |
225 | 225 | ||
226 | if ((ptr = (const Char *) g_strchr(ptr, LBRACE)) != NULL) | 226 | if ((ptr = (const Char *) g_strchr(ptr, LBRACE)) != NULL) |
227 | return globexp2(ptr, pattern, pglob); | 227 | return globexp2(ptr, pattern, pglob, limitp); |
228 | 228 | ||
229 | return glob0(pattern, pglob); | 229 | return glob0(pattern, pglob, limitp); |
230 | } | 230 | } |
231 | 231 | ||
232 | 232 | ||
@@ -236,7 +236,8 @@ globexp1(const Char *pattern, glob_t *pglob) | |||
236 | * If it fails then it tries to glob the rest of the pattern and returns. | 236 | * If it fails then it tries to glob the rest of the pattern and returns. |
237 | */ | 237 | */ |
238 | static int | 238 | static int |
239 | globexp2(const Char *ptr, const Char *pattern, glob_t *pglob) | 239 | globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, |
240 | struct glob_lim *limitp) | ||
240 | { | 241 | { |
241 | int i, rv; | 242 | int i, rv; |
242 | Char *lm, *ls; | 243 | Char *lm, *ls; |
@@ -272,7 +273,7 @@ globexp2(const Char *ptr, const Char *pattern, glob_t *pglob) | |||
272 | 273 | ||
273 | /* Non matching braces; just glob the pattern */ | 274 | /* Non matching braces; just glob the pattern */ |
274 | if (i != 0 || *pe == EOS) | 275 | if (i != 0 || *pe == EOS) |
275 | return glob0(patbuf, pglob); | 276 | return glob0(patbuf, pglob, limitp); |
276 | 277 | ||
277 | for (i = 0, pl = pm = ptr; pm <= pe; pm++) { | 278 | for (i = 0, pl = pm = ptr; pm <= pe; pm++) { |
278 | switch (*pm) { | 279 | switch (*pm) { |
@@ -318,7 +319,7 @@ globexp2(const Char *ptr, const Char *pattern, glob_t *pglob) | |||
318 | #ifdef DEBUG | 319 | #ifdef DEBUG |
319 | qprintf("globexp2:", patbuf); | 320 | qprintf("globexp2:", patbuf); |
320 | #endif | 321 | #endif |
321 | rv = globexp1(patbuf, pglob); | 322 | rv = globexp1(patbuf, pglob, limitp); |
322 | if (rv && rv != GLOB_NOMATCH) | 323 | if (rv && rv != GLOB_NOMATCH) |
323 | return rv; | 324 | return rv; |
324 | 325 | ||
@@ -449,12 +450,11 @@ g_charclass(const Char **patternp, Char **bufnextp) | |||
449 | * to find no matches. | 450 | * to find no matches. |
450 | */ | 451 | */ |
451 | static int | 452 | static int |
452 | glob0(const Char *pattern, glob_t *pglob) | 453 | glob0(const Char *pattern, glob_t *pglob, struct glob_lim *limitp) |
453 | { | 454 | { |
454 | const Char *qpatnext; | 455 | const Char *qpatnext; |
455 | int c, err, oldpathc; | 456 | int c, err, oldpathc; |
456 | Char *bufnext, patbuf[MAXPATHLEN]; | 457 | Char *bufnext, patbuf[MAXPATHLEN]; |
457 | size_t limit = 0; | ||
458 | 458 | ||
459 | qpatnext = globtilde(pattern, patbuf, MAXPATHLEN, pglob); | 459 | qpatnext = globtilde(pattern, patbuf, MAXPATHLEN, pglob); |
460 | oldpathc = pglob->gl_pathc; | 460 | oldpathc = pglob->gl_pathc; |
@@ -526,7 +526,7 @@ glob0(const Char *pattern, glob_t *pglob) | |||
526 | qprintf("glob0:", patbuf); | 526 | qprintf("glob0:", patbuf); |
527 | #endif | 527 | #endif |
528 | 528 | ||
529 | if ((err = glob1(patbuf, patbuf+MAXPATHLEN-1, pglob, &limit)) != 0) | 529 | if ((err = glob1(patbuf, patbuf+MAXPATHLEN-1, pglob, limitp)) != 0) |
530 | return(err); | 530 | return(err); |
531 | 531 | ||
532 | /* | 532 | /* |
@@ -539,7 +539,7 @@ glob0(const Char *pattern, glob_t *pglob) | |||
539 | if ((pglob->gl_flags & GLOB_NOCHECK) || | 539 | if ((pglob->gl_flags & GLOB_NOCHECK) || |
540 | ((pglob->gl_flags & GLOB_NOMAGIC) && | 540 | ((pglob->gl_flags & GLOB_NOMAGIC) && |
541 | !(pglob->gl_flags & GLOB_MAGCHAR))) | 541 | !(pglob->gl_flags & GLOB_MAGCHAR))) |
542 | return(globextend(pattern, pglob, &limit, NULL)); | 542 | return(globextend(pattern, pglob, limitp, NULL)); |
543 | else | 543 | else |
544 | return(GLOB_NOMATCH); | 544 | return(GLOB_NOMATCH); |
545 | } | 545 | } |
@@ -556,7 +556,7 @@ compare(const void *p, const void *q) | |||
556 | } | 556 | } |
557 | 557 | ||
558 | static int | 558 | static int |
559 | glob1(Char *pattern, Char *pattern_last, glob_t *pglob, size_t *limitp) | 559 | glob1(Char *pattern, Char *pattern_last, glob_t *pglob, struct glob_lim *limitp) |
560 | { | 560 | { |
561 | Char pathbuf[MAXPATHLEN]; | 561 | Char pathbuf[MAXPATHLEN]; |
562 | 562 | ||
@@ -575,7 +575,7 @@ glob1(Char *pattern, Char *pattern_last, glob_t *pglob, size_t *limitp) | |||
575 | */ | 575 | */ |
576 | static int | 576 | static int |
577 | glob2(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, | 577 | glob2(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, |
578 | Char *pattern, Char *pattern_last, glob_t *pglob, size_t *limitp) | 578 | Char *pattern, Char *pattern_last, glob_t *pglob, struct glob_lim *limitp) |
579 | { | 579 | { |
580 | struct stat sb; | 580 | struct stat sb; |
581 | Char *p, *q; | 581 | Char *p, *q; |
@@ -591,6 +591,14 @@ glob2(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, | |||
591 | if (g_lstat(pathbuf, &sb, pglob)) | 591 | if (g_lstat(pathbuf, &sb, pglob)) |
592 | return(0); | 592 | return(0); |
593 | 593 | ||
594 | if ((pglob->gl_flags & GLOB_LIMIT) && | ||
595 | limitp->glim_stat++ >= GLOB_LIMIT_STAT) { | ||
596 | errno = 0; | ||
597 | *pathend++ = SEP; | ||
598 | *pathend = EOS; | ||
599 | return(GLOB_NOSPACE); | ||
600 | } | ||
601 | |||
594 | if (((pglob->gl_flags & GLOB_MARK) && | 602 | if (((pglob->gl_flags & GLOB_MARK) && |
595 | pathend[-1] != SEP) && (S_ISDIR(sb.st_mode) || | 603 | pathend[-1] != SEP) && (S_ISDIR(sb.st_mode) || |
596 | (S_ISLNK(sb.st_mode) && | 604 | (S_ISLNK(sb.st_mode) && |
@@ -636,7 +644,7 @@ glob2(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, | |||
636 | static int | 644 | static int |
637 | glob3(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, | 645 | glob3(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, |
638 | Char *pattern, Char *restpattern, Char *restpattern_last, glob_t *pglob, | 646 | Char *pattern, Char *restpattern, Char *restpattern_last, glob_t *pglob, |
639 | size_t *limitp) | 647 | struct glob_lim *limitp) |
640 | { | 648 | { |
641 | struct dirent *dp; | 649 | struct dirent *dp; |
642 | DIR *dirp; | 650 | DIR *dirp; |
@@ -679,6 +687,14 @@ glob3(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, | |||
679 | u_char *sc; | 687 | u_char *sc; |
680 | Char *dc; | 688 | Char *dc; |
681 | 689 | ||
690 | if ((pglob->gl_flags & GLOB_LIMIT) && | ||
691 | limitp->glim_readdir++ >= GLOB_LIMIT_READDIR) { | ||
692 | errno = 0; | ||
693 | *pathend++ = SEP; | ||
694 | *pathend = EOS; | ||
695 | return(GLOB_NOSPACE); | ||
696 | } | ||
697 | |||
682 | /* Initial DOT must be matched literally. */ | 698 | /* Initial DOT must be matched literally. */ |
683 | if (dp->d_name[0] == DOT && *pattern != DOT) | 699 | if (dp->d_name[0] == DOT && *pattern != DOT) |
684 | continue; | 700 | continue; |
@@ -725,7 +741,8 @@ glob3(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, | |||
725 | * gl_pathv points to (gl_offs + gl_pathc + 1) items. | 741 | * gl_pathv points to (gl_offs + gl_pathc + 1) items. |
726 | */ | 742 | */ |
727 | static int | 743 | static int |
728 | globextend(const Char *path, glob_t *pglob, size_t *limitp, struct stat *sb) | 744 | globextend(const Char *path, glob_t *pglob, struct glob_lim *limitp, |
745 | struct stat *sb) | ||
729 | { | 746 | { |
730 | char **pathv; | 747 | char **pathv; |
731 | ssize_t i; | 748 | ssize_t i; |
@@ -781,6 +798,12 @@ globextend(const Char *path, glob_t *pglob, size_t *limitp, struct stat *sb) | |||
781 | if (sb == NULL) | 798 | if (sb == NULL) |
782 | statv[pglob->gl_offs + pglob->gl_pathc] = NULL; | 799 | statv[pglob->gl_offs + pglob->gl_pathc] = NULL; |
783 | else { | 800 | else { |
801 | limitp->glim_malloc += sizeof(**statv); | ||
802 | if ((pglob->gl_flags & GLOB_LIMIT) && | ||
803 | limitp->glim_malloc >= GLOB_LIMIT_MALLOC) { | ||
804 | errno = 0; | ||
805 | return(GLOB_NOSPACE); | ||
806 | } | ||
784 | if ((statv[pglob->gl_offs + pglob->gl_pathc] = | 807 | if ((statv[pglob->gl_offs + pglob->gl_pathc] = |
785 | malloc(sizeof(**statv))) == NULL) | 808 | malloc(sizeof(**statv))) == NULL) |
786 | goto copy_error; | 809 | goto copy_error; |
@@ -793,7 +816,7 @@ globextend(const Char *path, glob_t *pglob, size_t *limitp, struct stat *sb) | |||
793 | for (p = path; *p++;) | 816 | for (p = path; *p++;) |
794 | ; | 817 | ; |
795 | len = (size_t)(p - path); | 818 | len = (size_t)(p - path); |
796 | *limitp += len; | 819 | limitp->glim_malloc += len; |
797 | if ((copy = malloc(len)) != NULL) { | 820 | if ((copy = malloc(len)) != NULL) { |
798 | if (g_Ctoc(path, copy, len)) { | 821 | if (g_Ctoc(path, copy, len)) { |
799 | free(copy); | 822 | free(copy); |
@@ -804,7 +827,8 @@ globextend(const Char *path, glob_t *pglob, size_t *limitp, struct stat *sb) | |||
804 | pathv[pglob->gl_offs + pglob->gl_pathc] = NULL; | 827 | pathv[pglob->gl_offs + pglob->gl_pathc] = NULL; |
805 | 828 | ||
806 | if ((pglob->gl_flags & GLOB_LIMIT) && | 829 | if ((pglob->gl_flags & GLOB_LIMIT) && |
807 | (newn * sizeof(*pathv)) + *limitp >= (u_int) get_arg_max()) { | 830 | (newn * sizeof(*pathv)) + limitp->glim_malloc > |
831 | GLOB_LIMIT_MALLOC) { | ||
808 | errno = 0; | 832 | errno = 0; |
809 | return(GLOB_NOSPACE); | 833 | return(GLOB_NOSPACE); |
810 | } | 834 | } |