summaryrefslogtreecommitdiff
path: root/openbsd-compat/glob.c
diff options
context:
space:
mode:
authorColin Watson <cjwatson@debian.org>2020-02-21 11:57:14 +0000
committerColin Watson <cjwatson@debian.org>2020-02-21 11:57:14 +0000
commitf0de78bd4f29fa688c5df116f3f9cd43543a76d0 (patch)
tree856b0dee3f2764c13a32dad5ffe2424fab7fef41 /openbsd-compat/glob.c
parent4213eec74e74de6310c27a40c3e9759a08a73996 (diff)
parent8aa3455b16fddea4c0144a7c4a1edb10ec67dcc8 (diff)
Import openssh_8.2p1.orig.tar.gz
Diffstat (limited to 'openbsd-compat/glob.c')
-rw-r--r--openbsd-compat/glob.c149
1 files changed, 79 insertions, 70 deletions
diff --git a/openbsd-compat/glob.c b/openbsd-compat/glob.c
index 7c97e67f5..1e346a8f6 100644
--- a/openbsd-compat/glob.c
+++ b/openbsd-compat/glob.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: glob.c,v 1.38 2011/09/22 06:27:29 djm Exp $ */ 1/* $OpenBSD: glob.c,v 1.48 2019/02/04 16:45:40 millert 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.
@@ -70,6 +70,9 @@
70#include <limits.h> 70#include <limits.h>
71#include <pwd.h> 71#include <pwd.h>
72#include <stdlib.h> 72#include <stdlib.h>
73#ifdef HAVE_STDINT_H
74#include <stdint.h>
75#endif
73#include <string.h> 76#include <string.h>
74#include <unistd.h> 77#include <unistd.h>
75 78
@@ -131,12 +134,9 @@ typedef char Char;
131#define ismeta(c) (((c)&M_QUOTE) != 0) 134#define ismeta(c) (((c)&M_QUOTE) != 0)
132 135
133#define GLOB_LIMIT_MALLOC 65536 136#define GLOB_LIMIT_MALLOC 65536
134#define GLOB_LIMIT_STAT 128 137#define GLOB_LIMIT_STAT 2048
135#define GLOB_LIMIT_READDIR 16384 138#define GLOB_LIMIT_READDIR 16384
136 139
137/* Limit of recursion during matching attempts. */
138#define GLOB_LIMIT_RECUR 64
139
140struct glob_lim { 140struct glob_lim {
141 size_t glim_malloc; 141 size_t glim_malloc;
142 size_t glim_stat; 142 size_t glim_stat;
@@ -150,7 +150,7 @@ struct glob_path_stat {
150 150
151static int compare(const void *, const void *); 151static int compare(const void *, const void *);
152static int compare_gps(const void *, const void *); 152static int compare_gps(const void *, const void *);
153static int g_Ctoc(const Char *, char *, u_int); 153static int g_Ctoc(const Char *, char *, size_t);
154static int g_lstat(Char *, struct stat *, glob_t *); 154static int g_lstat(Char *, struct stat *, glob_t *);
155static DIR *g_opendir(Char *, glob_t *); 155static DIR *g_opendir(Char *, glob_t *);
156static Char *g_strchr(const Char *, int); 156static Char *g_strchr(const Char *, int);
@@ -169,7 +169,7 @@ static const Char *
169static int globexp1(const Char *, glob_t *, struct glob_lim *); 169static int globexp1(const Char *, glob_t *, struct glob_lim *);
170static int globexp2(const Char *, const Char *, glob_t *, 170static int globexp2(const Char *, const Char *, glob_t *,
171 struct glob_lim *); 171 struct glob_lim *);
172static int match(Char *, Char *, Char *, int); 172static int match(Char *, Char *, Char *);
173#ifdef DEBUG 173#ifdef DEBUG
174static void qprintf(const char *, Char *); 174static void qprintf(const char *, Char *);
175#endif 175#endif
@@ -180,12 +180,9 @@ glob(const char *pattern, int flags, int (*errfunc)(const char *, int),
180{ 180{
181 const u_char *patnext; 181 const u_char *patnext;
182 int c; 182 int c;
183 Char *bufnext, *bufend, patbuf[MAXPATHLEN]; 183 Char *bufnext, *bufend, patbuf[PATH_MAX];
184 struct glob_lim limit = { 0, 0, 0 }; 184 struct glob_lim limit = { 0, 0, 0 };
185 185
186 if (strnlen(pattern, PATH_MAX) == PATH_MAX)
187 return(GLOB_NOMATCH);
188
189 patnext = (u_char *) pattern; 186 patnext = (u_char *) pattern;
190 if (!(flags & GLOB_APPEND)) { 187 if (!(flags & GLOB_APPEND)) {
191 pglob->gl_pathc = 0; 188 pglob->gl_pathc = 0;
@@ -198,13 +195,15 @@ glob(const char *pattern, int flags, int (*errfunc)(const char *, int),
198 pglob->gl_errfunc = errfunc; 195 pglob->gl_errfunc = errfunc;
199 pglob->gl_matchc = 0; 196 pglob->gl_matchc = 0;
200 197
201 if (pglob->gl_offs < 0 || pglob->gl_pathc < 0 || 198 if (strnlen(pattern, PATH_MAX) == PATH_MAX)
202 pglob->gl_offs >= INT_MAX || pglob->gl_pathc >= INT_MAX || 199 return(GLOB_NOMATCH);
203 pglob->gl_pathc >= INT_MAX - pglob->gl_offs - 1) 200
201 if (pglob->gl_offs >= SSIZE_MAX || pglob->gl_pathc >= SSIZE_MAX ||
202 pglob->gl_pathc >= SSIZE_MAX - pglob->gl_offs - 1)
204 return GLOB_NOSPACE; 203 return GLOB_NOSPACE;
205 204
206 bufnext = patbuf; 205 bufnext = patbuf;
207 bufend = bufnext + MAXPATHLEN - 1; 206 bufend = bufnext + PATH_MAX - 1;
208 if (flags & GLOB_NOESCAPE) 207 if (flags & GLOB_NOESCAPE)
209 while (bufnext < bufend && (c = *patnext++) != EOS) 208 while (bufnext < bufend && (c = *patnext++) != EOS)
210 *bufnext++ = c; 209 *bufnext++ = c;
@@ -261,7 +260,7 @@ globexp2(const Char *ptr, const Char *pattern, glob_t *pglob,
261 int i, rv; 260 int i, rv;
262 Char *lm, *ls; 261 Char *lm, *ls;
263 const Char *pe, *pm, *pl; 262 const Char *pe, *pm, *pl;
264 Char patbuf[MAXPATHLEN]; 263 Char patbuf[PATH_MAX];
265 264
266 /* copy part up to the brace */ 265 /* copy part up to the brace */
267 for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++) 266 for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++)
@@ -472,10 +471,11 @@ static int
472glob0(const Char *pattern, glob_t *pglob, struct glob_lim *limitp) 471glob0(const Char *pattern, glob_t *pglob, struct glob_lim *limitp)
473{ 472{
474 const Char *qpatnext; 473 const Char *qpatnext;
475 int c, err, oldpathc; 474 int c, err;
476 Char *bufnext, patbuf[MAXPATHLEN]; 475 size_t oldpathc;
476 Char *bufnext, patbuf[PATH_MAX];
477 477
478 qpatnext = globtilde(pattern, patbuf, MAXPATHLEN, pglob); 478 qpatnext = globtilde(pattern, patbuf, PATH_MAX, pglob);
479 oldpathc = pglob->gl_pathc; 479 oldpathc = pglob->gl_pathc;
480 bufnext = patbuf; 480 bufnext = patbuf;
481 481
@@ -545,7 +545,7 @@ glob0(const Char *pattern, glob_t *pglob, struct glob_lim *limitp)
545 qprintf("glob0:", patbuf); 545 qprintf("glob0:", patbuf);
546#endif 546#endif
547 547
548 if ((err = glob1(patbuf, patbuf+MAXPATHLEN-1, pglob, limitp)) != 0) 548 if ((err = glob1(patbuf, patbuf+PATH_MAX-1, pglob, limitp)) != 0)
549 return(err); 549 return(err);
550 550
551 /* 551 /*
@@ -566,9 +566,9 @@ glob0(const Char *pattern, glob_t *pglob, struct glob_lim *limitp)
566 if ((pglob->gl_flags & GLOB_KEEPSTAT)) { 566 if ((pglob->gl_flags & GLOB_KEEPSTAT)) {
567 /* Keep the paths and stat info synced during sort */ 567 /* Keep the paths and stat info synced during sort */
568 struct glob_path_stat *path_stat; 568 struct glob_path_stat *path_stat;
569 int i; 569 size_t i;
570 int n = pglob->gl_pathc - oldpathc; 570 size_t n = pglob->gl_pathc - oldpathc;
571 int o = pglob->gl_offs + oldpathc; 571 size_t o = pglob->gl_offs + oldpathc;
572 572
573 if ((path_stat = calloc(n, sizeof(*path_stat))) == NULL) 573 if ((path_stat = calloc(n, sizeof(*path_stat))) == NULL)
574 return GLOB_NOSPACE; 574 return GLOB_NOSPACE;
@@ -609,13 +609,13 @@ compare_gps(const void *_p, const void *_q)
609static int 609static int
610glob1(Char *pattern, Char *pattern_last, glob_t *pglob, struct glob_lim *limitp) 610glob1(Char *pattern, Char *pattern_last, glob_t *pglob, struct glob_lim *limitp)
611{ 611{
612 Char pathbuf[MAXPATHLEN]; 612 Char pathbuf[PATH_MAX];
613 613
614 /* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */ 614 /* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */
615 if (*pattern == EOS) 615 if (*pattern == EOS)
616 return(0); 616 return(0);
617 return(glob2(pathbuf, pathbuf+MAXPATHLEN-1, 617 return(glob2(pathbuf, pathbuf+PATH_MAX-1,
618 pathbuf, pathbuf+MAXPATHLEN-1, 618 pathbuf, pathbuf+PATH_MAX-1,
619 pattern, pattern_last, pglob, limitp)); 619 pattern, pattern_last, pglob, limitp));
620} 620}
621 621
@@ -639,8 +639,6 @@ glob2(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last,
639 for (anymeta = 0;;) { 639 for (anymeta = 0;;) {
640 if (*pattern == EOS) { /* End of pattern? */ 640 if (*pattern == EOS) { /* End of pattern? */
641 *pathend = EOS; 641 *pathend = EOS;
642 if (g_lstat(pathbuf, &sb, pglob))
643 return(0);
644 642
645 if ((pglob->gl_flags & GLOB_LIMIT) && 643 if ((pglob->gl_flags & GLOB_LIMIT) &&
646 limitp->glim_stat++ >= GLOB_LIMIT_STAT) { 644 limitp->glim_stat++ >= GLOB_LIMIT_STAT) {
@@ -649,6 +647,8 @@ glob2(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last,
649 *pathend = EOS; 647 *pathend = EOS;
650 return(GLOB_NOSPACE); 648 return(GLOB_NOSPACE);
651 } 649 }
650 if (g_lstat(pathbuf, &sb, pglob))
651 return(0);
652 652
653 if (((pglob->gl_flags & GLOB_MARK) && 653 if (((pglob->gl_flags & GLOB_MARK) &&
654 pathend[-1] != SEP) && (S_ISDIR(sb.st_mode) || 654 pathend[-1] != SEP) && (S_ISDIR(sb.st_mode) ||
@@ -700,7 +700,7 @@ glob3(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last,
700 struct dirent *dp; 700 struct dirent *dp;
701 DIR *dirp; 701 DIR *dirp;
702 int err; 702 int err;
703 char buf[MAXPATHLEN]; 703 char buf[PATH_MAX];
704 704
705 /* 705 /*
706 * The readdirfunc declaration can't be prototyped, because it is 706 * The readdirfunc declaration can't be prototyped, because it is
@@ -760,7 +760,7 @@ glob3(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last,
760 break; 760 break;
761 } 761 }
762 762
763 if (!match(pathend, pattern, restpattern, GLOB_LIMIT_RECUR)) { 763 if (!match(pathend, pattern, restpattern)) {
764 *pathend = EOS; 764 *pathend = EOS;
765 continue; 765 continue;
766 } 766 }
@@ -797,38 +797,33 @@ globextend(const Char *path, glob_t *pglob, struct glob_lim *limitp,
797 struct stat *sb) 797 struct stat *sb)
798{ 798{
799 char **pathv; 799 char **pathv;
800 ssize_t i; 800 size_t i, newn, len;
801 size_t newn, len;
802 char *copy = NULL; 801 char *copy = NULL;
803 const Char *p; 802 const Char *p;
804 struct stat **statv; 803 struct stat **statv;
805 804
806 newn = 2 + pglob->gl_pathc + pglob->gl_offs; 805 newn = 2 + pglob->gl_pathc + pglob->gl_offs;
807 if (pglob->gl_offs >= INT_MAX || 806 if (pglob->gl_offs >= SSIZE_MAX ||
808 pglob->gl_pathc >= INT_MAX || 807 pglob->gl_pathc >= SSIZE_MAX ||
809 newn >= INT_MAX || 808 newn >= SSIZE_MAX ||
810 SIZE_MAX / sizeof(*pathv) <= newn || 809 SIZE_MAX / sizeof(*pathv) <= newn ||
811 SIZE_MAX / sizeof(*statv) <= newn) { 810 SIZE_MAX / sizeof(*statv) <= newn) {
812 nospace: 811 nospace:
813 for (i = pglob->gl_offs; i < (ssize_t)(newn - 2); i++) { 812 for (i = pglob->gl_offs; i < newn - 2; i++) {
814 if (pglob->gl_pathv && pglob->gl_pathv[i]) 813 if (pglob->gl_pathv && pglob->gl_pathv[i])
815 free(pglob->gl_pathv[i]); 814 free(pglob->gl_pathv[i]);
816 if ((pglob->gl_flags & GLOB_KEEPSTAT) != 0 && 815 if ((pglob->gl_flags & GLOB_KEEPSTAT) != 0 &&
817 pglob->gl_pathv && pglob->gl_pathv[i]) 816 pglob->gl_pathv && pglob->gl_pathv[i])
818 free(pglob->gl_statv[i]); 817 free(pglob->gl_statv[i]);
819 } 818 }
820 if (pglob->gl_pathv) { 819 free(pglob->gl_pathv);
821 free(pglob->gl_pathv); 820 pglob->gl_pathv = NULL;
822 pglob->gl_pathv = NULL; 821 free(pglob->gl_statv);
823 } 822 pglob->gl_statv = NULL;
824 if (pglob->gl_statv) {
825 free(pglob->gl_statv);
826 pglob->gl_statv = NULL;
827 }
828 return(GLOB_NOSPACE); 823 return(GLOB_NOSPACE);
829 } 824 }
830 825
831 pathv = realloc(pglob->gl_pathv, newn * sizeof(*pathv)); 826 pathv = reallocarray(pglob->gl_pathv, newn, sizeof(*pathv));
832 if (pathv == NULL) 827 if (pathv == NULL)
833 goto nospace; 828 goto nospace;
834 if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) { 829 if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) {
@@ -840,7 +835,7 @@ globextend(const Char *path, glob_t *pglob, struct glob_lim *limitp,
840 pglob->gl_pathv = pathv; 835 pglob->gl_pathv = pathv;
841 836
842 if ((pglob->gl_flags & GLOB_KEEPSTAT) != 0) { 837 if ((pglob->gl_flags & GLOB_KEEPSTAT) != 0) {
843 statv = realloc(pglob->gl_statv, newn * sizeof(*statv)); 838 statv = reallocarray(pglob->gl_statv, newn, sizeof(*statv));
844 if (statv == NULL) 839 if (statv == NULL)
845 goto nospace; 840 goto nospace;
846 if (pglob->gl_statv == NULL && pglob->gl_offs > 0) { 841 if (pglob->gl_statv == NULL && pglob->gl_offs > 0) {
@@ -894,17 +889,24 @@ globextend(const Char *path, glob_t *pglob, struct glob_lim *limitp,
894 889
895/* 890/*
896 * pattern matching function for filenames. Each occurrence of the * 891 * pattern matching function for filenames. Each occurrence of the *
897 * pattern causes a recursion level. 892 * pattern causes an iteration.
893 *
894 * Note, this function differs from the original as per the discussion
895 * here: https://research.swtch.com/glob
896 *
897 * Basically we removed the recursion and made it use the algorithm
898 * from Russ Cox to not go quadratic on cases like a file called
899 * ("a" x 100) . "x" matched against a pattern like "a*a*a*a*a*a*a*y".
898 */ 900 */
899static int 901static int
900match(Char *name, Char *pat, Char *patend, int recur) 902match(Char *name, Char *pat, Char *patend)
901{ 903{
902 int ok, negate_range; 904 int ok, negate_range;
903 Char c, k; 905 Char c, k;
906 Char *nextp = NULL;
907 Char *nextn = NULL;
904 908
905 if (recur-- == 0) 909loop:
906 return(GLOB_NOSPACE);
907
908 while (pat < patend) { 910 while (pat < patend) {
909 c = *pat++; 911 c = *pat++;
910 switch (c & M_MASK) { 912 switch (c & M_MASK) {
@@ -913,19 +915,19 @@ match(Char *name, Char *pat, Char *patend, int recur)
913 pat++; /* eat consecutive '*' */ 915 pat++; /* eat consecutive '*' */
914 if (pat == patend) 916 if (pat == patend)
915 return(1); 917 return(1);
916 do { 918 if (*name == EOS)
917 if (match(name, pat, patend, recur)) 919 return(0);
918 return(1); 920 nextn = name + 1;
919 } while (*name++ != EOS); 921 nextp = pat - 1;
920 return(0); 922 break;
921 case M_ONE: 923 case M_ONE:
922 if (*name++ == EOS) 924 if (*name++ == EOS)
923 return(0); 925 goto fail;
924 break; 926 break;
925 case M_SET: 927 case M_SET:
926 ok = 0; 928 ok = 0;
927 if ((k = *name++) == EOS) 929 if ((k = *name++) == EOS)
928 return(0); 930 goto fail;
929 if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS) 931 if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS)
930 ++pat; 932 ++pat;
931 while (((c = *pat++) & M_MASK) != M_END) { 933 while (((c = *pat++) & M_MASK) != M_END) {
@@ -944,36 +946,43 @@ match(Char *name, Char *pat, Char *patend, int recur)
944 ok = 1; 946 ok = 1;
945 } 947 }
946 if (ok == negate_range) 948 if (ok == negate_range)
947 return(0); 949 goto fail;
948 break; 950 break;
949 default: 951 default:
950 if (*name++ != c) 952 if (*name++ != c)
951 return(0); 953 goto fail;
952 break; 954 break;
953 } 955 }
954 } 956 }
955 return(*name == EOS); 957 if (*name == EOS)
958 return(1);
959
960fail:
961 if (nextn) {
962 pat = nextp;
963 name = nextn;
964 goto loop;
965 }
966 return(0);
956} 967}
957 968
958/* Free allocated data belonging to a glob_t structure. */ 969/* Free allocated data belonging to a glob_t structure. */
959void 970void
960globfree(glob_t *pglob) 971globfree(glob_t *pglob)
961{ 972{
962 int i; 973 size_t i;
963 char **pp; 974 char **pp;
964 975
965 if (pglob->gl_pathv != NULL) { 976 if (pglob->gl_pathv != NULL) {
966 pp = pglob->gl_pathv + pglob->gl_offs; 977 pp = pglob->gl_pathv + pglob->gl_offs;
967 for (i = pglob->gl_pathc; i--; ++pp) 978 for (i = pglob->gl_pathc; i--; ++pp)
968 if (*pp) 979 free(*pp);
969 free(*pp);
970 free(pglob->gl_pathv); 980 free(pglob->gl_pathv);
971 pglob->gl_pathv = NULL; 981 pglob->gl_pathv = NULL;
972 } 982 }
973 if (pglob->gl_statv != NULL) { 983 if (pglob->gl_statv != NULL) {
974 for (i = 0; i < pglob->gl_pathc; i++) { 984 for (i = 0; i < pglob->gl_pathc; i++) {
975 if (pglob->gl_statv[i] != NULL) 985 free(pglob->gl_statv[i]);
976 free(pglob->gl_statv[i]);
977 } 986 }
978 free(pglob->gl_statv); 987 free(pglob->gl_statv);
979 pglob->gl_statv = NULL; 988 pglob->gl_statv = NULL;
@@ -983,7 +992,7 @@ globfree(glob_t *pglob)
983static DIR * 992static DIR *
984g_opendir(Char *str, glob_t *pglob) 993g_opendir(Char *str, glob_t *pglob)
985{ 994{
986 char buf[MAXPATHLEN]; 995 char buf[PATH_MAX];
987 996
988 if (!*str) 997 if (!*str)
989 strlcpy(buf, ".", sizeof buf); 998 strlcpy(buf, ".", sizeof buf);
@@ -1001,7 +1010,7 @@ g_opendir(Char *str, glob_t *pglob)
1001static int 1010static int
1002g_lstat(Char *fn, struct stat *sb, glob_t *pglob) 1011g_lstat(Char *fn, struct stat *sb, glob_t *pglob)
1003{ 1012{
1004 char buf[MAXPATHLEN]; 1013 char buf[PATH_MAX];
1005 1014
1006 if (g_Ctoc(fn, buf, sizeof(buf))) 1015 if (g_Ctoc(fn, buf, sizeof(buf)))
1007 return(-1); 1016 return(-1);
@@ -1013,7 +1022,7 @@ g_lstat(Char *fn, struct stat *sb, glob_t *pglob)
1013static int 1022static int
1014g_stat(Char *fn, struct stat *sb, glob_t *pglob) 1023g_stat(Char *fn, struct stat *sb, glob_t *pglob)
1015{ 1024{
1016 char buf[MAXPATHLEN]; 1025 char buf[PATH_MAX];
1017 1026
1018 if (g_Ctoc(fn, buf, sizeof(buf))) 1027 if (g_Ctoc(fn, buf, sizeof(buf)))
1019 return(-1); 1028 return(-1);
@@ -1033,7 +1042,7 @@ g_strchr(const Char *str, int ch)
1033} 1042}
1034 1043
1035static int 1044static int
1036g_Ctoc(const Char *str, char *buf, u_int len) 1045g_Ctoc(const Char *str, char *buf, size_t len)
1037{ 1046{
1038 1047
1039 while (len--) { 1048 while (len--) {