1) GLOB_BRACE was somewhat broken. First it repeatedly calls glob0() in
globexp1() recursive calls, but glob0() was not supposed to be called repeatedly in the original code. It finalize results by possible adding original pattern for no match case, may return GLOB_NOMATCH error and by sorting all things. Original pattern adding or GLOB_NOMATCH error can happens each time glob0() called repeatedly, and sorting happens for one item only, all things are never sorted. Second, f.e. "a{a" pattern does not match "a{a" file but match "a" file instead (just one example, there are many). Third, some errors (f.e. for limits or overflow) can be ignored by GLOB_BRACE code because it forces return (0). Add non-finalizing flag to glob0() and make globexp0() wrapper around recursively called globexp1() to finalize things like glob0() does. Reorganize braces code to work correctly. 2) Don't allow MB_CUR_MAX * strlen overallocation hits GLOB_LIMIT_STRING (ARG_MAX) limit, use final string length, not malloced space for it. 3) Revive DEBUG-ifdefed section.
This commit is contained in:
parent
1859c867df
commit
bd7a98506c
@ -128,8 +128,6 @@ struct glob_limit {
|
||||
#define RBRACE L'}'
|
||||
#define COMMA L','
|
||||
|
||||
#ifndef DEBUG
|
||||
|
||||
#define M_QUOTE 0x8000000000ULL
|
||||
#define M_PROTECT 0x4000000000ULL
|
||||
#define M_MASK 0xffffffffffULL
|
||||
@ -137,18 +135,6 @@ struct glob_limit {
|
||||
|
||||
typedef uint_fast64_t Char;
|
||||
|
||||
#else
|
||||
|
||||
#define M_QUOTE 0x80
|
||||
#define M_PROTECT 0x40
|
||||
#define M_MASK 0xff
|
||||
#define M_CHAR 0x7f
|
||||
|
||||
typedef char Char;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#define CHAR(c) ((Char)((c)&M_CHAR))
|
||||
#define META(c) ((Char)((c)|M_QUOTE))
|
||||
#define UNPROT(c) ((c) & ~M_PROTECT)
|
||||
@ -171,7 +157,7 @@ static const Char *g_strchr(const Char *, wchar_t);
|
||||
static Char *g_strcat(Char *, const Char *);
|
||||
#endif
|
||||
static int g_stat(Char *, struct stat *, glob_t *);
|
||||
static int glob0(const Char *, glob_t *, struct glob_limit *);
|
||||
static int glob0(const Char *, glob_t *, struct glob_limit *, int);
|
||||
static int glob1(Char *, glob_t *, struct glob_limit *);
|
||||
static int glob2(Char *, Char *, Char *, Char *, glob_t *,
|
||||
struct glob_limit *);
|
||||
@ -180,8 +166,9 @@ static int glob3(Char *, Char *, Char *, Char *, Char *, glob_t *,
|
||||
static int globextend(const Char *, glob_t *, struct glob_limit *, int);
|
||||
static const Char *
|
||||
globtilde(const Char *, Char *, size_t, glob_t *);
|
||||
static int globexp0(const Char *, glob_t *, struct glob_limit *);
|
||||
static int globexp1(const Char *, glob_t *, struct glob_limit *);
|
||||
static int globexp2(const Char *, const Char *, glob_t *, int *,
|
||||
static int globexp2(const Char *, const Char *, glob_t *,
|
||||
struct glob_limit *);
|
||||
static int match(Char *, Char *, Char *);
|
||||
#ifdef DEBUG
|
||||
@ -260,9 +247,49 @@ glob(const char * __restrict pattern, int flags,
|
||||
*bufnext = EOS;
|
||||
|
||||
if (flags & GLOB_BRACE)
|
||||
return (globexp1(patbuf, pglob, &limit));
|
||||
return (globexp0(patbuf, pglob, &limit));
|
||||
else
|
||||
return (glob0(patbuf, pglob, &limit));
|
||||
return (glob0(patbuf, pglob, &limit, 1));
|
||||
}
|
||||
|
||||
static int
|
||||
globexp0(const Char *pattern, glob_t *pglob, struct glob_limit *limit)
|
||||
{
|
||||
int rv;
|
||||
size_t oldpathc;
|
||||
|
||||
/* Protect a single {}, for find(1), like csh */
|
||||
if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS) {
|
||||
if ((pglob->gl_flags & GLOB_LIMIT) &&
|
||||
limit->l_brace_cnt++ >= GLOB_LIMIT_BRACE) {
|
||||
errno = 0;
|
||||
return (GLOB_NOSPACE);
|
||||
}
|
||||
return (glob0(pattern, pglob, limit, 1));
|
||||
}
|
||||
|
||||
oldpathc = pglob->gl_pathc;
|
||||
|
||||
if ((rv = globexp1(pattern, pglob, limit)) != 0)
|
||||
return rv;
|
||||
/*
|
||||
* If there was no match we are going to append the pattern
|
||||
* if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was specified
|
||||
* and the pattern did not contain any magic characters
|
||||
* GLOB_NOMAGIC is there just for compatibility with csh.
|
||||
*/
|
||||
if (pglob->gl_pathc == oldpathc) {
|
||||
if (((pglob->gl_flags & GLOB_NOCHECK) ||
|
||||
((pglob->gl_flags & GLOB_NOMAGIC) &&
|
||||
!(pglob->gl_flags & GLOB_MAGCHAR))))
|
||||
return (globextend(pattern, pglob, limit, 1));
|
||||
else
|
||||
return (GLOB_NOMATCH);
|
||||
}
|
||||
if (!(pglob->gl_flags & GLOB_NOSORT))
|
||||
qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc,
|
||||
pglob->gl_pathc - oldpathc, sizeof(char *), compare);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -273,24 +300,18 @@ glob(const char * __restrict pattern, int flags,
|
||||
static int
|
||||
globexp1(const Char *pattern, glob_t *pglob, struct glob_limit *limit)
|
||||
{
|
||||
const Char* ptr = pattern;
|
||||
int rv;
|
||||
const Char* ptr;
|
||||
|
||||
if ((pglob->gl_flags & GLOB_LIMIT) &&
|
||||
limit->l_brace_cnt++ >= GLOB_LIMIT_BRACE) {
|
||||
errno = 0;
|
||||
return (GLOB_NOSPACE);
|
||||
if ((ptr = g_strchr(pattern, LBRACE)) != NULL) {
|
||||
if ((pglob->gl_flags & GLOB_LIMIT) &&
|
||||
limit->l_brace_cnt++ >= GLOB_LIMIT_BRACE) {
|
||||
errno = 0;
|
||||
return (GLOB_NOSPACE);
|
||||
}
|
||||
return (globexp2(ptr, pattern, pglob, limit));
|
||||
}
|
||||
|
||||
/* Protect a single {}, for find(1), like csh */
|
||||
if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS)
|
||||
return glob0(pattern, pglob, limit);
|
||||
|
||||
while ((ptr = g_strchr(ptr, LBRACE)) != NULL)
|
||||
if (!globexp2(ptr, pattern, pglob, &rv, limit))
|
||||
return rv;
|
||||
|
||||
return glob0(pattern, pglob, limit);
|
||||
return (glob0(pattern, pglob, limit, 0));
|
||||
}
|
||||
|
||||
|
||||
@ -300,10 +321,10 @@ globexp1(const Char *pattern, glob_t *pglob, struct glob_limit *limit)
|
||||
* If it fails then it tries to glob the rest of the pattern and returns.
|
||||
*/
|
||||
static int
|
||||
globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv,
|
||||
globexp2(const Char *ptr, const Char *pattern, glob_t *pglob,
|
||||
struct glob_limit *limit)
|
||||
{
|
||||
int i;
|
||||
int i, rv;
|
||||
Char *lm, *ls;
|
||||
const Char *pe, *pm, *pm1, *pl;
|
||||
Char patbuf[MAXPATHLEN];
|
||||
@ -315,7 +336,7 @@ globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv,
|
||||
ls = lm;
|
||||
|
||||
/* Find the balanced brace */
|
||||
for (i = 0, pe = ++ptr; *pe; pe++)
|
||||
for (i = 0, pe = ++ptr; *pe != EOS; pe++)
|
||||
if (*pe == LBRACKET) {
|
||||
/* Ignore everything between [] */
|
||||
for (pm = pe++; *pe != RBRACKET && *pe != EOS; pe++)
|
||||
@ -337,10 +358,8 @@ globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv,
|
||||
}
|
||||
|
||||
/* Non matching braces; just glob the pattern */
|
||||
if (i != 0 || *pe == EOS) {
|
||||
*rv = glob0(patbuf, pglob, limit);
|
||||
return (0);
|
||||
}
|
||||
if (i != 0 || *pe == EOS)
|
||||
return (glob0(pattern, pglob, limit, 0));
|
||||
|
||||
for (i = 0, pl = pm = ptr; pm <= pe; pm++)
|
||||
switch (*pm) {
|
||||
@ -385,7 +404,9 @@ globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv,
|
||||
#ifdef DEBUG
|
||||
qprintf("globexp2:", patbuf);
|
||||
#endif
|
||||
*rv = globexp1(patbuf, pglob, limit);
|
||||
rv = globexp1(patbuf, pglob, limit);
|
||||
if (rv)
|
||||
return (rv);
|
||||
|
||||
/* move after the comma, to the next string */
|
||||
pl = pm + 1;
|
||||
@ -395,7 +416,6 @@ globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv,
|
||||
default:
|
||||
break;
|
||||
}
|
||||
*rv = 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -517,7 +537,8 @@ globtilde(const Char *pattern, Char *patbuf, size_t patbuf_len, glob_t *pglob)
|
||||
* if things went well, nonzero if errors occurred.
|
||||
*/
|
||||
static int
|
||||
glob0(const Char *pattern, glob_t *pglob, struct glob_limit *limit)
|
||||
glob0(const Char *pattern, glob_t *pglob, struct glob_limit *limit,
|
||||
int final)
|
||||
{
|
||||
const Char *qpatnext;
|
||||
int err;
|
||||
@ -587,23 +608,25 @@ glob0(const Char *pattern, glob_t *pglob, struct glob_limit *limit)
|
||||
if ((err = glob1(patbuf, pglob, limit)) != 0)
|
||||
return(err);
|
||||
|
||||
/*
|
||||
* If there was no match we are going to append the pattern
|
||||
* if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was specified
|
||||
* and the pattern did not contain any magic characters
|
||||
* GLOB_NOMAGIC is there just for compatibility with csh.
|
||||
*/
|
||||
if (pglob->gl_pathc == oldpathc) {
|
||||
if (((pglob->gl_flags & GLOB_NOCHECK) ||
|
||||
((pglob->gl_flags & GLOB_NOMAGIC) &&
|
||||
!(pglob->gl_flags & GLOB_MAGCHAR))))
|
||||
return (globextend(pattern, pglob, limit, 1));
|
||||
else
|
||||
return (GLOB_NOMATCH);
|
||||
if (final) {
|
||||
/*
|
||||
* If there was no match we are going to append the pattern
|
||||
* if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was specified
|
||||
* and the pattern did not contain any magic characters
|
||||
* GLOB_NOMAGIC is there just for compatibility with csh.
|
||||
*/
|
||||
if (pglob->gl_pathc == oldpathc) {
|
||||
if (((pglob->gl_flags & GLOB_NOCHECK) ||
|
||||
((pglob->gl_flags & GLOB_NOMAGIC) &&
|
||||
!(pglob->gl_flags & GLOB_MAGCHAR))))
|
||||
return (globextend(pattern, pglob, limit, 1));
|
||||
else
|
||||
return (GLOB_NOMATCH);
|
||||
}
|
||||
if (!(pglob->gl_flags & GLOB_NOSORT))
|
||||
qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc,
|
||||
pglob->gl_pathc - oldpathc, sizeof(char *), compare);
|
||||
}
|
||||
if (!(pglob->gl_flags & GLOB_NOSORT))
|
||||
qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc,
|
||||
pglob->gl_pathc - oldpathc, sizeof(char *), compare);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -856,18 +879,19 @@ globextend(const Char *path, glob_t *pglob, struct glob_limit *limit,
|
||||
len = MB_CUR_MAX * (size_t)(p - path); /* XXX overallocation */
|
||||
if (prot)
|
||||
len += (size_t)(p - path) - 1;
|
||||
limit->l_string_cnt += len;
|
||||
if ((pglob->gl_flags & GLOB_LIMIT) &&
|
||||
limit->l_string_cnt >= GLOB_LIMIT_STRING) {
|
||||
errno = 0;
|
||||
return (GLOB_NOSPACE);
|
||||
}
|
||||
if ((copy = malloc(len)) != NULL) {
|
||||
if (g_Ctoc(path, copy, len, prot)) {
|
||||
free(copy);
|
||||
errno = 0;
|
||||
return (GLOB_NOSPACE);
|
||||
}
|
||||
limit->l_string_cnt += strlen(copy) + 1;
|
||||
if ((pglob->gl_flags & GLOB_LIMIT) &&
|
||||
limit->l_string_cnt >= GLOB_LIMIT_STRING) {
|
||||
free(copy);
|
||||
errno = 0;
|
||||
return (GLOB_NOSPACE);
|
||||
}
|
||||
pathv[pglob->gl_offs + pglob->gl_pathc++] = copy;
|
||||
}
|
||||
pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
|
||||
@ -1046,15 +1070,17 @@ qprintf(const char *str, Char *s)
|
||||
{
|
||||
Char *p;
|
||||
|
||||
(void)printf("%s:\n", str);
|
||||
for (p = s; *p; p++)
|
||||
(void)printf("%c", CHAR(*p));
|
||||
(void)printf("\n");
|
||||
for (p = s; *p; p++)
|
||||
(void)printf("%c", *p & M_PROTECT ? '"' : ' ');
|
||||
(void)printf("\n");
|
||||
for (p = s; *p; p++)
|
||||
(void)printf("%c", ismeta(*p) ? '_' : ' ');
|
||||
(void)printf("\n");
|
||||
(void)printf("%s\n", str);
|
||||
if (s != NULL) {
|
||||
for (p = s; *p != EOS; p++)
|
||||
(void)printf("%c", (char)CHAR(*p));
|
||||
(void)printf("\n");
|
||||
for (p = s; *p != EOS; p++)
|
||||
(void)printf("%c", (isprot(*p) ? '\\' : ' '));
|
||||
(void)printf("\n");
|
||||
for (p = s; *p != EOS; p++)
|
||||
(void)printf("%c", (ismeta(*p) ? '_' : ' '));
|
||||
(void)printf("\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user