Changeset View
Changeset View
Standalone View
Standalone View
lib/libc/gen/glob.c
Show First 20 Lines • Show All 86 Lines • ▼ Show 20 Lines | |||||
#include <pwd.h> | #include <pwd.h> | ||||
#include <stdint.h> | #include <stdint.h> | ||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <string.h> | #include <string.h> | ||||
#include <unistd.h> | #include <unistd.h> | ||||
#include <wchar.h> | #include <wchar.h> | ||||
#include "block_abi.h" | |||||
#include "collate.h" | #include "collate.h" | ||||
/* errblock_t */ | |||||
typedef DECLARE_BLOCK(int, errblock_t, const char *, int); | |||||
/* | /* | ||||
* glob(3) expansion limits. Stop the expansion if any of these limits | * glob(3) expansion limits. Stop the expansion if any of these limits | ||||
* is reached. This caps the runtime in the face of DoS attacks. See | * is reached. This caps the runtime in the face of DoS attacks. See | ||||
* also CVE-2010-2632 | * also CVE-2010-2632 | ||||
*/ | */ | ||||
#define GLOB_LIMIT_BRACE 128 /* number of brace calls */ | #define GLOB_LIMIT_BRACE 128 /* number of brace calls */ | ||||
#define GLOB_LIMIT_PATH 65536 /* number of path elements */ | #define GLOB_LIMIT_PATH 65536 /* number of path elements */ | ||||
#define GLOB_LIMIT_READDIR 16384 /* number of readdirs */ | #define GLOB_LIMIT_READDIR 16384 /* number of readdirs */ | ||||
▲ Show 20 Lines • Show All 79 Lines • ▼ Show 20 Lines | |||||
static int globexp1(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 *, int *, | ||||
struct glob_limit *); | struct glob_limit *); | ||||
static int match(Char *, Char *, Char *); | static int match(Char *, Char *, Char *); | ||||
#ifdef DEBUG | #ifdef DEBUG | ||||
static void qprintf(const char *, Char *); | static void qprintf(const char *, Char *); | ||||
#endif | #endif | ||||
int | static int | ||||
glob(const char * __restrict pattern, int flags, | _glob_common(const char * __restrict pattern, int flags, | ||||
int (*errfunc)(const char *, int), glob_t * __restrict pglob) | glob_t * __restrict pglob) | ||||
{ | { | ||||
struct glob_limit limit = { 0, 0, 0, 0, 0 }; | struct glob_limit limit = { 0, 0, 0, 0, 0 }; | ||||
const char *patnext; | const char *patnext; | ||||
Char *bufnext, *bufend, patbuf[MAXPATHLEN], prot; | Char *bufnext, *bufend, patbuf[MAXPATHLEN], prot; | ||||
mbstate_t mbs; | mbstate_t mbs; | ||||
wchar_t wc; | wchar_t wc; | ||||
size_t clen; | size_t clen; | ||||
patnext = pattern; | patnext = pattern; | ||||
if (!(flags & GLOB_APPEND)) { | if (!(flags & GLOB_APPEND)) { | ||||
pglob->gl_pathc = 0; | pglob->gl_pathc = 0; | ||||
pglob->gl_pathv = NULL; | pglob->gl_pathv = NULL; | ||||
if (!(flags & GLOB_DOOFFS)) | if (!(flags & GLOB_DOOFFS)) | ||||
pglob->gl_offs = 0; | pglob->gl_offs = 0; | ||||
} | } | ||||
if (flags & GLOB_LIMIT) { | if (flags & GLOB_LIMIT) { | ||||
limit.l_path_lim = pglob->gl_matchc; | limit.l_path_lim = pglob->gl_matchc; | ||||
if (limit.l_path_lim == 0) | if (limit.l_path_lim == 0) | ||||
limit.l_path_lim = GLOB_LIMIT_PATH; | limit.l_path_lim = GLOB_LIMIT_PATH; | ||||
} | } | ||||
pglob->gl_flags = flags & ~GLOB_MAGCHAR; | |||||
pglob->gl_errfunc = errfunc; | |||||
pglob->gl_matchc = 0; | pglob->gl_matchc = 0; | ||||
bufnext = patbuf; | bufnext = patbuf; | ||||
bufend = bufnext + MAXPATHLEN - 1; | bufend = bufnext + MAXPATHLEN - 1; | ||||
if (flags & GLOB_NOESCAPE) { | if (flags & GLOB_NOESCAPE) { | ||||
memset(&mbs, 0, sizeof(mbs)); | memset(&mbs, 0, sizeof(mbs)); | ||||
while (bufend - bufnext >= MB_CUR_MAX) { | while (bufend - bufnext >= MB_CUR_MAX) { | ||||
clen = mbrtowc(&wc, patnext, MB_LEN_MAX, &mbs); | clen = mbrtowc(&wc, patnext, MB_LEN_MAX, &mbs); | ||||
Show All 28 Lines | _glob_common(const char * __restrict pattern, int flags, | ||||
*bufnext = EOS; | *bufnext = EOS; | ||||
if (flags & GLOB_BRACE) | if (flags & GLOB_BRACE) | ||||
return (globexp1(patbuf, pglob, &limit)); | return (globexp1(patbuf, pglob, &limit)); | ||||
else | else | ||||
return (glob0(patbuf, pglob, &limit)); | return (glob0(patbuf, pglob, &limit)); | ||||
} | } | ||||
int | |||||
glob(const char * __restrict pattern, int flags, | |||||
int (*errfunc)(const char *, int), glob_t * __restrict pglob) | |||||
{ | |||||
pglob->gl_flags = flags & ~(GLOB_MAGCHAR | _GLOB_ERRBLK); | |||||
pglob->gl_errfunc = errfunc; | |||||
return (_glob_common(pattern, flags, pglob)); | |||||
} | |||||
int | |||||
glob_b(const char * __restrict pattern, int flags, errblock_t errblock, | |||||
glob_t * __restrict pglob) | |||||
{ | |||||
pglob->gl_flags = flags & ~GLOB_MAGCHAR; | |||||
pglob->gl_flags |= _GLOB_ERRBLK; | |||||
pglob->gl_errblk = (void *)errblock; | |||||
return (_glob_common(pattern, flags, pglob)); | |||||
} | |||||
/* | /* | ||||
* Expand recursively a glob {} pattern. When there is no more expansion | * Expand recursively a glob {} pattern. When there is no more expansion | ||||
* invoke the standard globbing routine to glob the rest of the magic | * invoke the standard globbing routine to glob the rest of the magic | ||||
* characters | * characters | ||||
*/ | */ | ||||
static int | static int | ||||
globexp1(const Char *pattern, glob_t *pglob, struct glob_limit *limit) | globexp1(const Char *pattern, glob_t *pglob, struct glob_limit *limit) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 375 Lines • ▼ Show 20 Lines | |||||
glob3(Char *pathbuf, Char *pathend, Char *pathend_last, | glob3(Char *pathbuf, Char *pathend, Char *pathend_last, | ||||
Char *pattern, Char *restpattern, | Char *pattern, Char *restpattern, | ||||
glob_t *pglob, struct glob_limit *limit) | glob_t *pglob, struct glob_limit *limit) | ||||
{ | { | ||||
struct dirent *dp; | struct dirent *dp; | ||||
DIR *dirp; | DIR *dirp; | ||||
int err; | int err; | ||||
char buf[MAXPATHLEN]; | char buf[MAXPATHLEN]; | ||||
int (*errfunc)(const char *, int); | |||||
/* | /* | ||||
* The readdirfunc declaration can't be prototyped, because it is | * The readdirfunc declaration can't be prototyped, because it is | ||||
* assigned, below, to two functions which are prototyped in glob.h | * assigned, below, to two functions which are prototyped in glob.h | ||||
* and dirent.h as taking pointers to differently typed opaque | * and dirent.h as taking pointers to differently typed opaque | ||||
* structures. | * structures. | ||||
*/ | */ | ||||
struct dirent *(*readdirfunc)(); | struct dirent *(*readdirfunc)(); | ||||
if (pathend > pathend_last) | if (pathend > pathend_last) | ||||
return (GLOB_ABORTED); | return (GLOB_ABORTED); | ||||
*pathend = EOS; | *pathend = EOS; | ||||
errno = 0; | errno = 0; | ||||
if ((dirp = g_opendir(pathbuf, pglob)) == NULL) { | if ((dirp = g_opendir(pathbuf, pglob)) == NULL) { | ||||
/* TODO: don't call for ENOENT or ENOTDIR? */ | /* TODO: don't call for ENOENT or ENOTDIR? */ | ||||
if (pglob->gl_errfunc) { | if (pglob->gl_errfunc) { | ||||
if (g_Ctoc(pathbuf, buf, sizeof(buf))) | if (g_Ctoc(pathbuf, buf, sizeof(buf))) | ||||
return (GLOB_ABORTED); | return (GLOB_ABORTED); | ||||
if (pglob->gl_errfunc(buf, errno) || | printf("glob3: %p %d\n", buf, errno); | ||||
if (pglob->gl_flags & _GLOB_ERRBLK) | |||||
errfunc = (int (*)(const char *, int)) | |||||
GET_BLOCK_FUNCTION(pglob->gl_errblk); | |||||
else | |||||
errfunc = pglob->gl_errfunc; | |||||
if ((*errfunc)(buf, errno) || | |||||
pglob->gl_flags & GLOB_ERR) | pglob->gl_flags & GLOB_ERR) | ||||
return (GLOB_ABORTED); | return (GLOB_ABORTED); | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
err = 0; | err = 0; | ||||
▲ Show 20 Lines • Show All 290 Lines • Show Last 20 Lines |