From a26e92e4fbac2325696964150776ad952bad56c8 Mon Sep 17 00:00:00 2001 From: Calvin Buckley Date: Wed, 27 Nov 2024 16:13:06 -0400 Subject: [PATCH 1/7] Add reallocarray to utility functions From OpenBSD, dependency of newer versions of glob. --- configure.ac | 3 ++- main/php.h | 8 ++++++ main/reallocarray.c | 59 ++++++++++++++++++++++++++++++++++++++++++ win32/build/config.w32 | 2 +- 4 files changed, 70 insertions(+), 2 deletions(-) create mode 100644 main/reallocarray.c diff --git a/configure.ac b/configure.ac index 01d9ded69b920..fc0fb11ae6b5b 100644 --- a/configure.ac +++ b/configure.ac @@ -689,7 +689,7 @@ AS_VAR_IF([php_cv_func_copy_file_range], [yes], [AC_DEFINE([HAVE_COPY_FILE_RANGE], [1], [Define to 1 if you have the 'copy_file_range' function.])]) -AC_REPLACE_FUNCS([strlcat strlcpy explicit_bzero getopt]) +AC_REPLACE_FUNCS([strlcat strlcpy reallocarray explicit_bzero getopt]) AC_FUNC_ALLOCA PHP_TIME_R_TYPE @@ -1638,6 +1638,7 @@ PHP_ADD_SOURCES([main], m4_normalize([ php_ticks.c php_variables.c reentrancy.c + reallocarray.c rfc1867.c safe_bcmp.c SAPI.c diff --git a/main/php.h b/main/php.h index 5c0b89c328375..32f4622be16de 100644 --- a/main/php.h +++ b/main/php.h @@ -172,6 +172,14 @@ END_EXTERN_C() #define explicit_bzero php_explicit_bzero #endif +#ifndef HAVE_REALLOCARRAY +BEGIN_EXTERN_C() +PHPAPI void *php_reallocarray(void *optr, size_t nmemb, size_t size); +END_EXTERN_C() +#undef reallocarray +#define reallocarray php_reallocarray +#endif + BEGIN_EXTERN_C() PHPAPI int php_safe_bcmp(const zend_string *a, const zend_string *b); END_EXTERN_C() diff --git a/main/reallocarray.c b/main/reallocarray.c new file mode 100644 index 0000000000000..20a31789424ff --- /dev/null +++ b/main/reallocarray.c @@ -0,0 +1,59 @@ +/* + +----------------------------------------------------------------------+ + | Copyright (c) The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | https://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: | + +----------------------------------------------------------------------+ +*/ + +#include "php.h" + +#ifdef USE_REALLOCARRAY_PHP_IMPL +/* $OpenBSD: reallocarray.c,v 1.3 2015/09/13 08:31:47 guenther Exp $ */ +/* + * Copyright (c) 2008 Otto Moerbeek + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include + +/* + * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX + * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW + */ +#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4)) + +PHPAPI void * +php_reallocarray(void *optr, size_t nmemb, size_t size) +{ + if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && + nmemb > 0 && SIZE_MAX / nmemb < size) { + errno = ENOMEM; + return NULL; + } + return realloc(optr, size * nmemb); +} + +#endif /* !HAVE_REALLOCARRAY */ diff --git a/win32/build/config.w32 b/win32/build/config.w32 index dd33e595a2ee9..bb3bceb40dbd4 100644 --- a/win32/build/config.w32 +++ b/win32/build/config.w32 @@ -284,7 +284,7 @@ if (VS_TOOLSET && VCVERS >= 1914) { //AC_DEFINE('ZEND_DVAL_TO_LVAL_CAST_OK', 1); ADD_SOURCES("main", "main.c snprintf.c spprintf.c getopt.c fopen_wrappers.c \ - php_ini_builder.c \ + php_ini_builder.c reallocarray.c \ php_scandir.c php_ini.c SAPI.c rfc1867.c php_content_types.c strlcpy.c \ strlcat.c reentrancy.c php_variables.c php_ticks.c network.c \ php_open_temporary_file.c output.c internal_functions.c \ From 3aafb045d3ab51c20480209dc8fac9c4e8c20065 Mon Sep 17 00:00:00 2001 From: Calvin Buckley Date: Tue, 26 Nov 2024 13:58:08 -0400 Subject: [PATCH 2/7] Update OpenBSD glob implementation for Windows We're considering making this used as a glob implementation on POSIX as well, but first, we should rebase it from the latest version of OpenBSD. This also adds a new internal header (charclass.h) for glob. See conversation in GH-15564. Co-authored-by: Christoph M. Becker --- main/php.h | 2 + win32/charclass.h | 29 +++ win32/glob.c | 526 +++++++++++++++++++++++++++++++++------------- win32/glob.h | 40 ++-- 4 files changed, 434 insertions(+), 163 deletions(-) create mode 100644 win32/charclass.h diff --git a/main/php.h b/main/php.h index 32f4622be16de..36f123c45605d 100644 --- a/main/php.h +++ b/main/php.h @@ -178,6 +178,8 @@ PHPAPI void *php_reallocarray(void *optr, size_t nmemb, size_t size); END_EXTERN_C() #undef reallocarray #define reallocarray php_reallocarray +#define HAVE_REALLOCARRAY 1 +#define USE_REALLOCARRAY_PHP_IMPL 1 #endif BEGIN_EXTERN_C() diff --git a/win32/charclass.h b/win32/charclass.h new file mode 100644 index 0000000000000..1d1ec07951160 --- /dev/null +++ b/win32/charclass.h @@ -0,0 +1,29 @@ +/* + * Public domain, 2008, Todd C. Miller + * + * $OpenBSD: charclass.h,v 1.3 2020/10/13 04:42:28 guenther Exp $ + */ + +/* + * POSIX character class support for fnmatch() and glob(). + */ +static const struct cclass { + const char *name; + int (*isctype)(int); +} cclasses[] = { + { "alnum", isalnum }, + { "alpha", isalpha }, + { "blank", isblank }, + { "cntrl", iscntrl }, + { "digit", isdigit }, + { "graph", isgraph }, + { "lower", islower }, + { "print", isprint }, + { "punct", ispunct }, + { "space", isspace }, + { "upper", isupper }, + { "xdigit", isxdigit }, + { NULL, NULL } +}; + +#define NCCLASSES (sizeof(cclasses) / sizeof(cclasses[0]) - 1) diff --git a/win32/glob.c b/win32/glob.c index 5dd0f4661acbe..f1e75de7344b2 100644 --- a/win32/glob.c +++ b/win32/glob.c @@ -13,11 +13,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -58,6 +54,7 @@ * gl_matchc: * Number of matches in the current invocation of glob. */ + #ifdef PHP_WIN32 #if _MSC_VER < 1800 # define _POSIX_ @@ -69,6 +66,17 @@ # define ARG_MAX 14500 # endif #endif +# ifndef PATH_MAX +# define PATH_MAX MAXPATHLEN +# endif +/* Windows defines SIZE_MAX but not SSIZE_MAX */ +# ifndef SSIZE_MAX +# ifdef _WIN64 +# define SSIZE_MAX _I64_MAX +# else +# define SSIZE_MAX INT_MAX +# endif +# endif #endif #include "php.h" @@ -83,10 +91,14 @@ #endif #include #include "glob.h" +#include +#include #include #include #include +#include "charclass.h" + #define DOLLAR '$' #define DOT '.' #define EOS '\0' @@ -134,34 +146,58 @@ typedef char Char; #define M_ONE META('?') #define M_RNG META('-') #define M_SET META('[') +#define M_CLASS META(':') #define ismeta(c) (((c)&M_QUOTE) != 0) +#define GLOB_LIMIT_MALLOC 65536 +#define GLOB_LIMIT_STAT 2048 +#define GLOB_LIMIT_READDIR 16384 + +struct glob_lim { + size_t glim_malloc; + size_t glim_stat; + size_t glim_readdir; +}; + +struct glob_path_stat { + char *gps_path; + zend_stat_t *gps_stat; +}; + static int compare(const void *, const void *); -static int g_Ctoc(const Char *, char *, u_int); +static int compare_gps(const void *, const void *); +static int g_Ctoc(const Char *, char *, size_t); static int g_lstat(Char *, zend_stat_t *, glob_t *); static DIR *g_opendir(Char *, glob_t *); -static Char *g_strchr(Char *, int); +static Char *g_strchr(const Char *, int); +static int g_strncmp(const Char *, const char *, size_t); static int g_stat(Char *, zend_stat_t *, glob_t *); -static int glob0(const Char *, glob_t *); -static int glob1(Char *, Char *, glob_t *, size_t *); +static int glob0(const Char *, glob_t *, struct glob_lim *); +static int glob1(Char *, Char *, glob_t *, struct glob_lim *); static int glob2(Char *, Char *, Char *, Char *, Char *, Char *, - glob_t *, size_t *); -static int glob3(Char *, Char *, Char *, Char *, Char *, Char *, - Char *, Char *, glob_t *, size_t *); -static int globextend(const Char *, glob_t *, size_t *); -static const Char *globtilde(const Char *, Char *, size_t, glob_t *); -static int globexp1(const Char *, glob_t *); -static int globexp2(const Char *, const Char *, glob_t *, int *); + glob_t *, struct glob_lim *); +static int glob3(Char *, Char *, Char *, Char *, Char *, + Char *, Char *, glob_t *, struct glob_lim *); +static int globextend(const Char *, glob_t *, struct glob_lim *, + zend_stat_t *); +static const Char * + globtilde(const Char *, Char *, size_t, glob_t *); +static int globexp1(const Char *, glob_t *, struct glob_lim *); +static int globexp2(const Char *, const Char *, glob_t *, + struct glob_lim *); static int match(Char *, Char *, Char *); #ifdef DEBUG static void qprintf(const char *, Char *); #endif -PHPAPI int glob(const char *pattern, int flags, int (*errfunc)(const char *, int), glob_t *pglob) +PHPAPI int +glob(const char *pattern, int flags, int (*errfunc)(const char *, int), + glob_t *pglob) { - const uint8_t *patnext; + const u_char *patnext; int c; - Char *bufnext, *bufend, patbuf[MAXPATHLEN]; + Char *bufnext, *bufend, patbuf[PATH_MAX]; + struct glob_lim limit = { 0, 0, 0 }; #ifdef PHP_WIN32 /* Force skipping escape sequences on windows @@ -170,10 +206,11 @@ PHPAPI int glob(const char *pattern, int flags, int (*errfunc)(const char *, int flags |= GLOB_NOESCAPE; #endif - patnext = (uint8_t *) pattern; + patnext = (u_char *) pattern; if (!(flags & GLOB_APPEND)) { pglob->gl_pathc = 0; pglob->gl_pathv = NULL; + pglob->gl_statv = NULL; if (!(flags & GLOB_DOOFFS)) pglob->gl_offs = 0; } @@ -181,8 +218,15 @@ PHPAPI int glob(const char *pattern, int flags, int (*errfunc)(const char *, int pglob->gl_errfunc = errfunc; pglob->gl_matchc = 0; + if (strnlen(pattern, PATH_MAX) == PATH_MAX) + return(GLOB_NOMATCH); + + if (pglob->gl_offs >= SSIZE_MAX || pglob->gl_pathc >= SSIZE_MAX || + pglob->gl_pathc >= SSIZE_MAX - pglob->gl_offs - 1) + return GLOB_NOSPACE; + bufnext = patbuf; - bufend = bufnext + MAXPATHLEN - 1; + bufend = bufnext + PATH_MAX - 1; if (flags & GLOB_NOESCAPE) while (bufnext < bufend && (c = *patnext++) != EOS) *bufnext++ = c; @@ -201,9 +245,9 @@ PHPAPI int glob(const char *pattern, int flags, int (*errfunc)(const char *, int *bufnext = EOS; if (flags & GLOB_BRACE) - return globexp1(patbuf, pglob); + return globexp1(patbuf, pglob, &limit); else - return glob0(patbuf, pglob); + return glob0(patbuf, pglob, &limit); } /* @@ -211,20 +255,19 @@ PHPAPI int glob(const char *pattern, int flags, int (*errfunc)(const char *, int * invoke the standard globbing routine to glob the rest of the magic * characters */ -static int globexp1(const Char *pattern,glob_t *pglob) +static int +globexp1(const Char *pattern, glob_t *pglob, struct glob_lim *limitp) { const Char* ptr = pattern; - int rv; /* Protect a single {}, for find(1), like csh */ if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS) - return glob0(pattern, pglob); + return glob0(pattern, pglob, limitp); - while ((ptr = (const Char *) g_strchr((Char *) ptr, LBRACE)) != NULL) - if (!globexp2(ptr, pattern, pglob, &rv)) - return rv; + if ((ptr = (const Char *) g_strchr(ptr, LBRACE)) != NULL) + return globexp2(ptr, pattern, pglob, limitp); - return glob0(pattern, pglob); + return glob0(pattern, pglob, limitp); } @@ -233,12 +276,14 @@ static int globexp1(const Char *pattern,glob_t *pglob) * If it succeeds then it invokes globexp1 with the new pattern. * 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) +static int +globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, + struct glob_lim *limitp) { - int i; + int i, rv; Char *lm, *ls; const Char *pe, *pm, *pl; - Char patbuf[MAXPATHLEN]; + Char patbuf[PATH_MAX]; /* copy part up to the brace */ for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++) @@ -268,10 +313,8 @@ static int 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); - return 0; - } + if (i != 0 || *pe == EOS) + return glob0(patbuf, pglob, limitp); for (i = 0, pl = pm = ptr; pm <= pe; pm++) { const Char *pb; @@ -319,7 +362,9 @@ static int globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv #ifdef DEBUG qprintf("globexp2:", patbuf); #endif - *rv = globexp1(patbuf, pglob); + rv = globexp1(patbuf, pglob, limitp); + if (rv && rv != GLOB_NOMATCH) + return rv; /* move after the comma, to the next string */ pl = pm + 1; @@ -330,7 +375,6 @@ static int globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv break; } } - *rv = 0; return 0; } @@ -339,10 +383,12 @@ static int globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv /* * expand tilde from the passwd file. */ -static const Char *globtilde(const Char *pattern, Char *patbuf, size_t patbuf_len, glob_t *pglob) +static const Char * +globtilde(const Char *pattern, Char *patbuf, size_t patbuf_len, glob_t *pglob) { #ifndef PHP_WIN32 - struct passwd *pwd; + struct passwd pwstore, *pwd = NULL; + char pwbuf[_PW_BUF_LEN]; #endif char *h; const Char *p; @@ -354,7 +400,7 @@ static const Char *globtilde(const Char *pattern, Char *patbuf, size_t patbuf_le /* Copy up to the end of the string or / */ eb = &patbuf[patbuf_len - 1]; for (p = pattern + 1, h = (char *) patbuf; - h < (char *)eb && *p && *p != SLASH; *h++ = (char) *p++) + h < (char *)eb && *p && *p != SLASH; *h++ = *p++) ; *h = EOS; @@ -365,26 +411,30 @@ static const Char *globtilde(const Char *pattern, Char *patbuf, size_t patbuf_le #endif if (((char *) patbuf)[0] == EOS) { +#ifndef PHP_WIN32 /* * handle a plain ~ or ~/ by expanding $HOME * first and then trying the password file */ - if ((h = getenv("HOME")) == NULL) { -#ifndef PHP_WIN32 - if ((pwd = getpwuid(getuid())) == NULL) + if (issetugid() != 0 || (h = getenv("HOME")) == NULL) { + getpwuid_r(getuid(), &pwstore, pwbuf, sizeof(pwbuf), + &pwd); + if (pwd == NULL) return pattern; else h = pwd->pw_dir; + } #else - return pattern; + return pattern; #endif - } } else { /* * Expand a ~user */ #ifndef PHP_WIN32 - if ((pwd = getpwnam((char*) patbuf)) == NULL) + getpwnam_r((char *)patbuf, &pwstore, pwbuf, sizeof(pwbuf), + &pwd); + if (pwd == NULL) return pattern; else h = pwd->pw_dir; @@ -405,6 +455,47 @@ static const Char *globtilde(const Char *pattern, Char *patbuf, size_t patbuf_le return patbuf; } +static int +g_strncmp(const Char *s1, const char *s2, size_t n) +{ + int rv = 0; + + while (n--) { + rv = *(Char *)s1 - *(const unsigned char *)s2++; + if (rv) + break; + if (*s1++ == '\0') + break; + } + return rv; +} + +static int +g_charclass(const Char **patternp, Char **bufnextp) +{ + const Char *pattern = *patternp + 1; + Char *bufnext = *bufnextp; + const Char *colon; + const struct cclass *cc; + size_t len; + + if ((colon = g_strchr(pattern, ':')) == NULL || colon[1] != ']') + return 1; /* not a character class */ + + len = (size_t)(colon - pattern); + for (cc = cclasses; cc->name != NULL; cc++) { + if (!g_strncmp(pattern, cc->name, len) && cc->name[len] == '\0') + break; + } + if (cc->name == NULL) + return -1; /* invalid character class */ + *bufnext++ = M_CLASS; + *bufnext++ = (Char)(cc - &cclasses[0]); + *bufnextp = bufnext; + *patternp += len + 3; + + return 0; +} /* * The main glob() routine: compiles the pattern (optionally processing @@ -413,14 +504,15 @@ static const Char *globtilde(const Char *pattern, Char *patbuf, size_t patbuf_le * if things went well, nonzero if errors occurred. It is not an error * to find no matches. */ -static int glob0( const Char *pattern, glob_t *pglob) +static int +glob0(const Char *pattern, glob_t *pglob, struct glob_lim *limitp) { const Char *qpatnext; - int c, err, oldpathc; - Char *bufnext, patbuf[MAXPATHLEN]; - size_t limit = 0; + int c, err; + size_t oldpathc; + Char *bufnext, patbuf[PATH_MAX]; - qpatnext = globtilde(pattern, patbuf, MAXPATHLEN, pglob); + qpatnext = globtilde(pattern, patbuf, PATH_MAX, pglob); oldpathc = pglob->gl_pathc; bufnext = patbuf; @@ -432,7 +524,7 @@ static int glob0( const Char *pattern, glob_t *pglob) if (c == NOT) ++qpatnext; if (*qpatnext == EOS || - g_strchr((Char *) qpatnext+1, RBRACKET) == NULL) { + g_strchr(qpatnext+1, RBRACKET) == NULL) { *bufnext++ = LBRACKET; if (c == NOT) --qpatnext; @@ -443,9 +535,23 @@ static int glob0( const Char *pattern, glob_t *pglob) *bufnext++ = M_NOT; c = *qpatnext++; do { + if (c == LBRACKET && *qpatnext == ':') { + do { + err = g_charclass(&qpatnext, + &bufnext); + if (err) + break; + c = *qpatnext++; + } while (c == LBRACKET && *qpatnext == ':'); + if (err == -1 && + !(pglob->gl_flags & GLOB_NOCHECK)) + return GLOB_NOMATCH; + if (c == RBRACKET) + break; + } *bufnext++ = CHAR(c); if (*qpatnext == RANGE && - (c = qpatnext[1]) != RBRACKET) { + (c = qpatnext[1]) != RBRACKET) { *bufnext++ = M_RNG; *bufnext++ = CHAR(c); qpatnext += 2; @@ -476,7 +582,7 @@ static int glob0( const Char *pattern, glob_t *pglob) qprintf("glob0:", patbuf); #endif - if ((err = glob1(patbuf, patbuf+MAXPATHLEN-1, pglob, &limit)) != 0) + if ((err = glob1(patbuf, patbuf+PATH_MAX-1, pglob, limitp)) != 0) return(err); /* @@ -487,37 +593,67 @@ static int glob0( const Char *pattern, glob_t *pglob) */ 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)); + ((pglob->gl_flags & GLOB_NOMAGIC) && + !(pglob->gl_flags & GLOB_MAGCHAR))) + return(globextend(pattern, pglob, limitp, NULL)); 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)) { + if ((pglob->gl_flags & GLOB_KEEPSTAT)) { + /* Keep the paths and stat info synced during sort */ + struct glob_path_stat *path_stat; + size_t i; + size_t n = pglob->gl_pathc - oldpathc; + size_t o = pglob->gl_offs + oldpathc; + + if ((path_stat = calloc(n, sizeof(*path_stat))) == NULL) + return GLOB_NOSPACE; + for (i = 0; i < n; i++) { + path_stat[i].gps_path = pglob->gl_pathv[o + i]; + path_stat[i].gps_stat = pglob->gl_statv[o + i]; + } + qsort(path_stat, n, sizeof(*path_stat), compare_gps); + for (i = 0; i < n; i++) { + pglob->gl_pathv[o + i] = path_stat[i].gps_path; + pglob->gl_statv[o + i] = path_stat[i].gps_stat; + } + free(path_stat); + } else { + qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc, + pglob->gl_pathc - oldpathc, sizeof(char *), + compare); + } + } return(0); } -static int compare(const void *p, const void *q) +static int +compare(const void *p, const void *q) { return(strcmp(*(char **)p, *(char **)q)); } static int -glob1(pattern, pattern_last, pglob, limitp) - Char *pattern, *pattern_last; - glob_t *pglob; - size_t *limitp; +compare_gps(const void *_p, const void *_q) { - Char pathbuf[MAXPATHLEN]; + const struct glob_path_stat *p = (const struct glob_path_stat *)_p; + const struct glob_path_stat *q = (const struct glob_path_stat *)_q; + + return(strcmp(p->gps_path, q->gps_path)); +} + +static int +glob1(Char *pattern, Char *pattern_last, glob_t *pglob, struct glob_lim *limitp) +{ + Char pathbuf[PATH_MAX]; /* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */ if (*pattern == EOS) return(0); - return(glob2(pathbuf, pathbuf+MAXPATHLEN-1, - pathbuf, pathbuf+MAXPATHLEN-1, - pattern, pattern_last, pglob, limitp)); + return(glob2(pathbuf, pathbuf+PATH_MAX-1, + pathbuf, pathbuf+PATH_MAX-1, + pattern, pattern_last, pglob, limitp)); } /* @@ -525,10 +661,11 @@ glob1(pattern, pattern_last, pglob, limitp) * of recursion for each segment in the pattern that contains one or more * meta characters. */ -static int glob2(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, Char *pattern, - Char *pattern_last, glob_t *pglob, size_t *limitp) +static int +glob2(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, + Char *pattern, Char *pattern_last, glob_t *pglob, struct glob_lim *limitp) { - zend_stat_t sb = {0}; + zend_stat_t sb; Char *p, *q; int anymeta; @@ -539,21 +676,29 @@ static int glob2(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend for (anymeta = 0;;) { if (*pattern == EOS) { /* End of pattern? */ *pathend = EOS; + + if ((pglob->gl_flags & GLOB_LIMIT) && + limitp->glim_stat++ >= GLOB_LIMIT_STAT) { + errno = 0; + *pathend++ = SEP; + *pathend = EOS; + return(GLOB_NOSPACE); + } if (g_lstat(pathbuf, &sb, pglob)) return(0); if (((pglob->gl_flags & GLOB_MARK) && - !IS_SLASH(pathend[-1])) && (S_ISDIR(sb.st_mode) || - (S_ISLNK(sb.st_mode) && - (g_stat(pathbuf, &sb, pglob) == 0) && - S_ISDIR(sb.st_mode)))) { + pathend[-1] != SEP) && (S_ISDIR(sb.st_mode) || + (S_ISLNK(sb.st_mode) && + (g_stat(pathbuf, &sb, pglob) == 0) && + S_ISDIR(sb.st_mode)))) { if (pathend+1 > pathend_last) return (1); *pathend++ = SEP; *pathend = EOS; } ++pglob->gl_matchc; - return(globextend(pathbuf, pglob, limitp)); + return(globextend(pathbuf, pglob, limitp, &sb)); } /* Find end of next segment, copy tentatively to pathend. */ @@ -578,18 +723,21 @@ static int glob2(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend } else /* Need expansion, recurse. */ return(glob3(pathbuf, pathbuf_last, pathend, - pathend_last, pattern, pattern_last, - p, pattern_last, pglob, limitp)); + pathend_last, pattern, p, pattern_last, + pglob, limitp)); } /* NOTREACHED */ } -static int glob3(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, Char *pattern, Char *pattern_last, - Char *restpattern, Char *restpattern_last, glob_t *pglob, size_t *limitp) +static int +glob3(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, + Char *pattern, Char *restpattern, Char *restpattern_last, glob_t *pglob, + struct glob_lim *limitp) { - register struct dirent *dp; + struct dirent *dp; DIR *dirp; int err; + char buf[PATH_MAX]; /* * The readdirfunc declaration can't be prototyped, because it is @@ -597,7 +745,7 @@ static int glob3(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend * and dirent.h as taking pointers to differently typed opaque * structures. */ - struct dirent *(*readdirfunc)(); + struct dirent *(*readdirfunc)(void *); if (pathend > pathend_last) return (1); @@ -607,11 +755,10 @@ static int glob3(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend if ((dirp = g_opendir(pathbuf, pglob)) == NULL) { /* TODO: don't call for ENOENT or ENOTDIR? */ if (pglob->gl_errfunc) { - char buf[MAXPATHLEN]; if (g_Ctoc(pathbuf, buf, sizeof(buf))) return(GLOB_ABORTED); if (pglob->gl_errfunc(buf, errno) || - pglob->gl_flags & GLOB_ERR) + pglob->gl_flags & GLOB_ERR) return(GLOB_ABORTED); } return(0); @@ -623,16 +770,25 @@ static int glob3(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend if (pglob->gl_flags & GLOB_ALTDIRFUNC) readdirfunc = pglob->gl_readdir; else - readdirfunc = readdir; + readdirfunc = (struct dirent *(*)(void *))readdir; while ((dp = (*readdirfunc)(dirp))) { - register uint8_t *sc; - register Char *dc; + u_char *sc; + Char *dc; + + if ((pglob->gl_flags & GLOB_LIMIT) && + limitp->glim_readdir++ >= GLOB_LIMIT_READDIR) { + errno = 0; + *pathend++ = SEP; + *pathend = EOS; + err = GLOB_NOSPACE; + break; + } /* Initial DOT must be matched literally. */ if (dp->d_name[0] == DOT && *pattern != DOT) continue; dc = pathend; - sc = (uint8_t *) dp->d_name; + sc = (u_char *) dp->d_name; while (dc < pathend_last && (*dc++ = *sc++) != EOS) ; if (dc >= pathend_last) { @@ -646,7 +802,7 @@ static int glob3(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend continue; } err = glob2(pathbuf, pathbuf_last, --dc, pathend_last, - restpattern, restpattern_last, pglob, limitp); + restpattern, restpattern_last, pglob, limitp); if (err) break; } @@ -673,37 +829,81 @@ static int glob3(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend * Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and * gl_pathv points to (gl_offs + gl_pathc + 1) items. */ -static int globextend(const Char *path, glob_t *pglob, size_t *limitp) +static int +globextend(const Char *path, glob_t *pglob, struct glob_lim *limitp, + zend_stat_t *sb) { - register char **pathv; - u_int newsize, len; - char *copy; + char **pathv; + size_t i, newn, len; + char *copy = NULL; const Char *p; - - newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs); - pathv = pglob->gl_pathv ? realloc((char *)pglob->gl_pathv, newsize) : - malloc(newsize); - if (pathv == NULL) { - if (pglob->gl_pathv) { - free(pglob->gl_pathv); - pglob->gl_pathv = NULL; + zend_stat_t **statv; + + newn = 2 + pglob->gl_pathc + pglob->gl_offs; + if (pglob->gl_offs >= SSIZE_MAX || + pglob->gl_pathc >= SSIZE_MAX || + newn >= SSIZE_MAX || + SIZE_MAX / sizeof(*pathv) <= newn || + SIZE_MAX / sizeof(*statv) <= newn) { + nospace: + for (i = pglob->gl_offs; i < newn - 2; i++) { + if (pglob->gl_pathv && pglob->gl_pathv[i]) + free(pglob->gl_pathv[i]); + if ((pglob->gl_flags & GLOB_KEEPSTAT) != 0 && + pglob->gl_pathv && pglob->gl_pathv[i]) + free(pglob->gl_statv[i]); } + free(pglob->gl_pathv); + pglob->gl_pathv = NULL; + free(pglob->gl_statv); + pglob->gl_statv = NULL; return(GLOB_NOSPACE); } + pathv = reallocarray(pglob->gl_pathv, newn, sizeof(*pathv)); + if (pathv == NULL) + goto nospace; if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) { - register int i; /* first time around -- clear initial gl_offs items */ pathv += pglob->gl_offs; - for (i = pglob->gl_offs; --i >= 0; ) + for (i = pglob->gl_offs; i > 0; i--) *--pathv = NULL; } pglob->gl_pathv = pathv; + if ((pglob->gl_flags & GLOB_KEEPSTAT) != 0) { + statv = reallocarray(pglob->gl_statv, newn, sizeof(*statv)); + if (statv == NULL) + goto nospace; + if (pglob->gl_statv == NULL && pglob->gl_offs > 0) { + /* first time around -- clear initial gl_offs items */ + statv += pglob->gl_offs; + for (i = pglob->gl_offs; i > 0; i--) + *--statv = NULL; + } + pglob->gl_statv = statv; + if (sb == NULL) + statv[pglob->gl_offs + pglob->gl_pathc] = NULL; + else { + limitp->glim_malloc += sizeof(**statv); + if ((pglob->gl_flags & GLOB_LIMIT) && + limitp->glim_malloc >= GLOB_LIMIT_MALLOC) { + errno = 0; + return(GLOB_NOSPACE); + } + if ((statv[pglob->gl_offs + pglob->gl_pathc] = + malloc(sizeof(**statv))) == NULL) + goto copy_error; + memcpy(statv[pglob->gl_offs + pglob->gl_pathc], sb, + sizeof(*sb)); + } + statv[pglob->gl_offs + pglob->gl_pathc + 1] = NULL; + } + for (p = path; *p++;) ; - len = (u_int)(p - path); - *limitp += len; + len = (size_t)(p - path); + limitp->glim_malloc += len; if ((copy = malloc(len)) != NULL) { if (g_Ctoc(path, copy, len)) { free(copy); @@ -714,87 +914,125 @@ static int globextend(const Char *path, glob_t *pglob, size_t *limitp) pathv[pglob->gl_offs + pglob->gl_pathc] = NULL; if ((pglob->gl_flags & GLOB_LIMIT) && - newsize + *limitp >= ARG_MAX) { + (newn * sizeof(*pathv)) + limitp->glim_malloc > + GLOB_LIMIT_MALLOC) { errno = 0; return(GLOB_NOSPACE); } - + copy_error: return(copy == NULL ? GLOB_NOSPACE : 0); } /* * pattern matching function for filenames. Each occurrence of the * - * pattern causes a recursion level. + * pattern causes an iteration. + * + * Note, this function differs from the original as per the discussion + * here: https://research.swtch.com/glob + * + * Basically we removed the recursion and made it use the algorithm + * from Russ Cox to not go quadratic on cases like a file called + * ("a" x 100) . "x" matched against a pattern like "a*a*a*a*a*a*a*y". */ -static int match(Char *name, Char *pat, Char *patend) +static int +match(Char *name, Char *pat, Char *patend) { int ok, negate_range; Char c, k; + Char *nextp = NULL; + Char *nextn = NULL; +loop: while (pat < patend) { c = *pat++; switch (c & M_MASK) { case M_ALL: + while (pat < patend && (*pat & M_MASK) == M_ALL) + pat++; /* eat consecutive '*' */ if (pat == patend) return(1); - do - if (match(name, pat, patend)) - return(1); - while (*name++ != EOS) - ; - return(0); + if (*name == EOS) + return(0); + nextn = name + 1; + nextp = pat - 1; + break; case M_ONE: if (*name++ == EOS) - return(0); + goto fail; break; case M_SET: ok = 0; if ((k = *name++) == EOS) - return(0); + goto fail; if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS) ++pat; - while (((c = *pat++) & M_MASK) != M_END) + while (((c = *pat++) & M_MASK) != M_END) { + if ((c & M_MASK) == M_CLASS) { + Char idx = *pat & M_MASK; + if (idx < NCCLASSES && + cclasses[idx].isctype(k)) + ok = 1; + ++pat; + } if ((*pat & M_MASK) == M_RNG) { if (c <= k && k <= pat[1]) ok = 1; pat += 2; } else if (c == k) ok = 1; + } if (ok == negate_range) - return(0); + goto fail; break; default: if (*name++ != c) - return(0); + goto fail; break; } } - return(*name == EOS); + if (*name == EOS) + return(1); + +fail: + if (nextn) { + pat = nextp; + name = nextn; + goto loop; + } + return(0); } /* Free allocated data belonging to a glob_t structure. */ -PHPAPI void globfree(glob_t *pglob) +PHPAPI void +globfree(glob_t *pglob) { - register int i; - register char **pp; + size_t i; + char **pp; if (pglob->gl_pathv != NULL) { pp = pglob->gl_pathv + pglob->gl_offs; for (i = pglob->gl_pathc; i--; ++pp) - if (*pp) - free(*pp); + free(*pp); free(pglob->gl_pathv); pglob->gl_pathv = NULL; } + if (pglob->gl_statv != NULL) { + for (i = 0; i < pglob->gl_pathc; i++) { + free(pglob->gl_statv[i]); + } + free(pglob->gl_statv); + pglob->gl_statv = NULL; + } } -static DIR * g_opendir(Char *str, glob_t *pglob) +static DIR * +g_opendir(Char *str, glob_t *pglob) { - char buf[MAXPATHLEN]; + char buf[PATH_MAX]; if (!*str) - strlcpy(buf, ".", sizeof(buf)); + strlcpy(buf, ".", sizeof buf); else { if (g_Ctoc(str, buf, sizeof(buf))) return(NULL); @@ -806,9 +1044,10 @@ static DIR * g_opendir(Char *str, glob_t *pglob) return(opendir(buf)); } -static int g_lstat(Char *fn, zend_stat_t *sb, glob_t *pglob) +static int +g_lstat(Char *fn, zend_stat_t *sb, glob_t *pglob) { - char buf[MAXPATHLEN]; + char buf[PATH_MAX]; if (g_Ctoc(fn, buf, sizeof(buf))) return(-1); @@ -817,9 +1056,10 @@ static int g_lstat(Char *fn, zend_stat_t *sb, glob_t *pglob) return(php_sys_lstat(buf, sb)); } -static int g_stat(Char *fn, zend_stat_t *sb, glob_t *pglob) +static int +g_stat(Char *fn, zend_stat_t *sb, glob_t *pglob) { - char buf[MAXPATHLEN]; + char buf[PATH_MAX]; if (g_Ctoc(fn, buf, sizeof(buf))) return(-1); @@ -828,20 +1068,22 @@ static int g_stat(Char *fn, zend_stat_t *sb, glob_t *pglob) return(php_sys_stat(buf, sb)); } -static Char *g_strchr(Char *str, int ch) +static Char * +g_strchr(const Char *str, int ch) { do { if (*str == ch) - return (str); + return ((Char *)str); } while (*str++); return (NULL); } -static int g_Ctoc(const Char *str, char *buf, u_int len) +static int +g_Ctoc(const Char *str, char *buf, size_t len) { while (len--) { - if ((*buf++ = (char) *str++) == EOS) + if ((*buf++ = *str++) == EOS) return (0); } return (1); @@ -849,9 +1091,9 @@ static int g_Ctoc(const Char *str, char *buf, u_int len) #ifdef DEBUG static void -qprintf(char *str, Char *s) +qprintf(const char *str, Char *s) { - register Char *p; + Char *p; (void)printf("%s:\n", str); for (p = s; *p; p++) diff --git a/win32/glob.h b/win32/glob.h index 42cf2f9d71dda..1e922b05b2f19 100644 --- a/win32/glob.h +++ b/win32/glob.h @@ -1,5 +1,5 @@ -/* OpenBSD: glob.h,v 1.7 2002/02/17 19:42:21 millert Exp */ -/* NetBSD: glob.h,v 1.5 1994/10/26 00:55:56 cgd Exp */ +/* $OpenBSD: glob.h,v 1.14 2019/02/04 16:45:40 millert Exp $ */ +/* $NetBSD: glob.h,v 1.5 1994/10/26 00:55:56 cgd Exp $ */ /* * Copyright (c) 1989, 1993 @@ -16,11 +16,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -49,11 +45,12 @@ #include "Zend/zend_stream.h" typedef struct { - int gl_pathc; /* Count of total paths so far. */ - int gl_matchc; /* Count of paths matching pattern. */ - int gl_offs; /* Reserved at beginning of gl_pathv. */ + size_t gl_pathc; /* Count of total paths so far. */ + size_t gl_matchc; /* Count of paths matching pattern. */ + size_t gl_offs; /* Reserved at beginning of gl_pathv. */ int gl_flags; /* Copy of flags parameter to glob. */ char **gl_pathv; /* List of paths matching pattern. */ + zend_stat_t **gl_statv; /* Stat entries corresponding to gl_pathv */ /* Copy of errfunc parameter to glob. */ int (*gl_errfunc)(const char *, int); @@ -63,19 +60,24 @@ typedef struct { * and lstat(2). */ void (*gl_closedir)(void *); - struct dirent *(*gl_readdir)(void *); + struct dirent *(*gl_readdir)(void *); void *(*gl_opendir)(const char *); int (*gl_lstat)(const char *, zend_stat_t *); int (*gl_stat)(const char *, zend_stat_t *); } glob_t; -/* Flags */ #define GLOB_APPEND 0x0001 /* Append to output from previous call. */ #define GLOB_DOOFFS 0x0002 /* Use gl_offs. */ #define GLOB_ERR 0x0004 /* Return on error. */ #define GLOB_MARK 0x0008 /* Append / to matching directories. */ #define GLOB_NOCHECK 0x0010 /* Return pattern itself if nothing matches. */ #define GLOB_NOSORT 0x0020 /* Don't sort. */ +#define GLOB_NOESCAPE 0x1000 /* Disable backslash escaping. */ + +#define GLOB_NOSPACE (-1) /* Malloc call failed. */ +#define GLOB_ABORTED (-2) /* Unignored error. */ +#define GLOB_NOMATCH (-3) /* No match and GLOB_NOCHECK not set. */ +#define GLOB_NOSYS (-4) /* Function not supported. */ #ifndef _POSIX_SOURCE #define GLOB_ALTDIRFUNC 0x0040 /* Use alternately specified directory funcs. */ @@ -84,19 +86,15 @@ typedef struct { #define GLOB_NOMAGIC 0x0200 /* GLOB_NOCHECK without magic chars (csh). */ #define GLOB_QUOTE 0x0400 /* Quote special chars with \. */ #define GLOB_TILDE 0x0800 /* Expand tilde names from the passwd file. */ -#define GLOB_NOESCAPE 0x1000 /* Disable backslash escaping. */ #define GLOB_LIMIT 0x2000 /* Limit pattern match output to ARG_MAX */ +#define GLOB_KEEPSTAT 0x4000 /* Retain stat data for paths in gl_statv. */ +#define GLOB_ABEND GLOB_ABORTED /* backward compatibility */ #endif -/* Error values returned by glob(3) */ -#define GLOB_NOSPACE (-1) /* Malloc call failed. */ -#define GLOB_ABORTED (-2) /* Unignored error. */ -#define GLOB_NOMATCH (-3) /* No match and GLOB_NOCHECK not set. */ -#define GLOB_NOSYS (-4) /* Function not supported. */ -#define GLOB_ABEND GLOB_ABORTED - BEGIN_EXTERN_C() -PHPAPI int glob(const char *, int, int (*)(const char *, int), glob_t *); +PHPAPI int glob(const char *__restrict, int, int (*)(const char *, int), + glob_t *__restrict); PHPAPI void globfree(glob_t *); END_EXTERN_C() + #endif /* !_GLOB_H_ */ From cd73ebd0f233b3d5eed12bbcee1b6670e6bc6b7f Mon Sep 17 00:00:00 2001 From: Calvin Buckley Date: Fri, 6 Dec 2024 14:43:18 -0400 Subject: [PATCH 3/7] remove tab at end --- win32/glob.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/win32/glob.h b/win32/glob.h index 1e922b05b2f19..0975c507388d5 100644 --- a/win32/glob.h +++ b/win32/glob.h @@ -60,7 +60,7 @@ typedef struct { * and lstat(2). */ void (*gl_closedir)(void *); - struct dirent *(*gl_readdir)(void *); + struct dirent *(*gl_readdir)(void *); void *(*gl_opendir)(const char *); int (*gl_lstat)(const char *, zend_stat_t *); int (*gl_stat)(const char *, zend_stat_t *); From 681d8601f9b2d66df6849b8281332f8b3458fc2a Mon Sep 17 00:00:00 2001 From: Calvin Buckley Date: Fri, 6 Dec 2024 14:43:50 -0400 Subject: [PATCH 4/7] Convert to standard C99 type --- win32/glob.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/win32/glob.c b/win32/glob.c index f1e75de7344b2..19ded09ce347e 100644 --- a/win32/glob.c +++ b/win32/glob.c @@ -194,7 +194,7 @@ PHPAPI int glob(const char *pattern, int flags, int (*errfunc)(const char *, int), glob_t *pglob) { - const u_char *patnext; + const uint8_t *patnext; int c; Char *bufnext, *bufend, patbuf[PATH_MAX]; struct glob_lim limit = { 0, 0, 0 }; @@ -206,7 +206,7 @@ glob(const char *pattern, int flags, int (*errfunc)(const char *, int), flags |= GLOB_NOESCAPE; #endif - patnext = (u_char *) pattern; + patnext = (uint8_t *) pattern; if (!(flags & GLOB_APPEND)) { pglob->gl_pathc = 0; pglob->gl_pathv = NULL; @@ -772,7 +772,7 @@ glob3(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, else readdirfunc = (struct dirent *(*)(void *))readdir; while ((dp = (*readdirfunc)(dirp))) { - u_char *sc; + uint8_t *sc; Char *dc; if ((pglob->gl_flags & GLOB_LIMIT) && @@ -788,7 +788,7 @@ glob3(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, if (dp->d_name[0] == DOT && *pattern != DOT) continue; dc = pathend; - sc = (u_char *) dp->d_name; + sc = (uint8_t *) dp->d_name; while (dc < pathend_last && (*dc++ = *sc++) != EOS) ; if (dc >= pathend_last) { From b161035c9b9bc8c09ecdb8a0e8d6c6f5c30dda72 Mon Sep 17 00:00:00 2001 From: Calvin Buckley Date: Mon, 9 Dec 2024 12:22:37 -0400 Subject: [PATCH 5/7] Change four spaces to tabs OpenBSD uses tabs for indentation, but four spaces to align i.e. continuations of lines. In PHP, we apparently just use tabs, so do that for code bodies and function declarations. --- win32/glob.c | 93 ++++++++++++++++++++++++++-------------------------- 1 file changed, 46 insertions(+), 47 deletions(-) diff --git a/win32/glob.c b/win32/glob.c index 19ded09ce347e..2021bc64af16c 100644 --- a/win32/glob.c +++ b/win32/glob.c @@ -175,16 +175,15 @@ static int g_stat(Char *, zend_stat_t *, glob_t *); static int glob0(const Char *, glob_t *, struct glob_lim *); static int glob1(Char *, Char *, glob_t *, struct glob_lim *); static int glob2(Char *, Char *, Char *, Char *, Char *, Char *, - glob_t *, struct glob_lim *); + glob_t *, struct glob_lim *); static int glob3(Char *, Char *, Char *, Char *, Char *, - Char *, Char *, glob_t *, struct glob_lim *); + Char *, Char *, glob_t *, struct glob_lim *); static int globextend(const Char *, glob_t *, struct glob_lim *, - zend_stat_t *); -static const Char * - globtilde(const Char *, Char *, size_t, glob_t *); + zend_stat_t *); +static const Char *globtilde(const Char *, Char *, size_t, glob_t *); static int globexp1(const Char *, glob_t *, struct glob_lim *); static int globexp2(const Char *, const Char *, glob_t *, - struct glob_lim *); + struct glob_lim *); static int match(Char *, Char *, Char *); #ifdef DEBUG static void qprintf(const char *, Char *); @@ -192,7 +191,7 @@ static void qprintf(const char *, Char *); PHPAPI int glob(const char *pattern, int flags, int (*errfunc)(const char *, int), - glob_t *pglob) + glob_t *pglob) { const uint8_t *patnext; int c; @@ -222,7 +221,7 @@ glob(const char *pattern, int flags, int (*errfunc)(const char *, int), return(GLOB_NOMATCH); if (pglob->gl_offs >= SSIZE_MAX || pglob->gl_pathc >= SSIZE_MAX || - pglob->gl_pathc >= SSIZE_MAX - pglob->gl_offs - 1) + pglob->gl_pathc >= SSIZE_MAX - pglob->gl_offs - 1) return GLOB_NOSPACE; bufnext = patbuf; @@ -278,7 +277,7 @@ globexp1(const Char *pattern, glob_t *pglob, struct glob_lim *limitp) */ static int globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, - struct glob_lim *limitp) + struct glob_lim *limitp) { int i, rv; Char *lm, *ls; @@ -400,7 +399,7 @@ globtilde(const Char *pattern, Char *patbuf, size_t patbuf_len, glob_t *pglob) /* Copy up to the end of the string or / */ eb = &patbuf[patbuf_len - 1]; for (p = pattern + 1, h = (char *) patbuf; - h < (char *)eb && *p && *p != SLASH; *h++ = *p++) + h < (char *)eb && *p && *p != SLASH; *h++ = *p++) ; *h = EOS; @@ -418,7 +417,7 @@ globtilde(const Char *pattern, Char *patbuf, size_t patbuf_len, glob_t *pglob) */ if (issetugid() != 0 || (h = getenv("HOME")) == NULL) { getpwuid_r(getuid(), &pwstore, pwbuf, sizeof(pwbuf), - &pwd); + &pwd); if (pwd == NULL) return pattern; else @@ -433,7 +432,7 @@ globtilde(const Char *pattern, Char *patbuf, size_t patbuf_len, glob_t *pglob) */ #ifndef PHP_WIN32 getpwnam_r((char *)patbuf, &pwstore, pwbuf, sizeof(pwbuf), - &pwd); + &pwd); if (pwd == NULL) return pattern; else @@ -524,7 +523,7 @@ glob0(const Char *pattern, glob_t *pglob, struct glob_lim *limitp) if (c == NOT) ++qpatnext; if (*qpatnext == EOS || - g_strchr(qpatnext+1, RBRACKET) == NULL) { + g_strchr(qpatnext+1, RBRACKET) == NULL) { *bufnext++ = LBRACKET; if (c == NOT) --qpatnext; @@ -538,20 +537,20 @@ glob0(const Char *pattern, glob_t *pglob, struct glob_lim *limitp) if (c == LBRACKET && *qpatnext == ':') { do { err = g_charclass(&qpatnext, - &bufnext); + &bufnext); if (err) break; c = *qpatnext++; } while (c == LBRACKET && *qpatnext == ':'); if (err == -1 && - !(pglob->gl_flags & GLOB_NOCHECK)) + !(pglob->gl_flags & GLOB_NOCHECK)) return GLOB_NOMATCH; if (c == RBRACKET) break; } *bufnext++ = CHAR(c); if (*qpatnext == RANGE && - (c = qpatnext[1]) != RBRACKET) { + (c = qpatnext[1]) != RBRACKET) { *bufnext++ = M_RNG; *bufnext++ = CHAR(c); qpatnext += 2; @@ -593,8 +592,8 @@ glob0(const Char *pattern, glob_t *pglob, struct glob_lim *limitp) */ if (pglob->gl_pathc == oldpathc) { if ((pglob->gl_flags & GLOB_NOCHECK) || - ((pglob->gl_flags & GLOB_NOMAGIC) && - !(pglob->gl_flags & GLOB_MAGCHAR))) + ((pglob->gl_flags & GLOB_NOMAGIC) && + !(pglob->gl_flags & GLOB_MAGCHAR))) return(globextend(pattern, pglob, limitp, NULL)); else return(GLOB_NOMATCH); @@ -621,8 +620,8 @@ glob0(const Char *pattern, glob_t *pglob, struct glob_lim *limitp) free(path_stat); } else { qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc, - pglob->gl_pathc - oldpathc, sizeof(char *), - compare); + pglob->gl_pathc - oldpathc, sizeof(char *), + compare); } } return(0); @@ -652,8 +651,8 @@ glob1(Char *pattern, Char *pattern_last, glob_t *pglob, struct glob_lim *limitp) if (*pattern == EOS) return(0); return(glob2(pathbuf, pathbuf+PATH_MAX-1, - pathbuf, pathbuf+PATH_MAX-1, - pattern, pattern_last, pglob, limitp)); + pathbuf, pathbuf+PATH_MAX-1, + pattern, pattern_last, pglob, limitp)); } /* @@ -663,7 +662,7 @@ glob1(Char *pattern, Char *pattern_last, glob_t *pglob, struct glob_lim *limitp) */ static int glob2(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, - Char *pattern, Char *pattern_last, glob_t *pglob, struct glob_lim *limitp) + Char *pattern, Char *pattern_last, glob_t *pglob, struct glob_lim *limitp) { zend_stat_t sb; Char *p, *q; @@ -678,7 +677,7 @@ glob2(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, *pathend = EOS; if ((pglob->gl_flags & GLOB_LIMIT) && - limitp->glim_stat++ >= GLOB_LIMIT_STAT) { + limitp->glim_stat++ >= GLOB_LIMIT_STAT) { errno = 0; *pathend++ = SEP; *pathend = EOS; @@ -688,10 +687,10 @@ glob2(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, return(0); if (((pglob->gl_flags & GLOB_MARK) && - pathend[-1] != SEP) && (S_ISDIR(sb.st_mode) || - (S_ISLNK(sb.st_mode) && - (g_stat(pathbuf, &sb, pglob) == 0) && - S_ISDIR(sb.st_mode)))) { + pathend[-1] != SEP) && (S_ISDIR(sb.st_mode) || + (S_ISLNK(sb.st_mode) && + (g_stat(pathbuf, &sb, pglob) == 0) && + S_ISDIR(sb.st_mode)))) { if (pathend+1 > pathend_last) return (1); *pathend++ = SEP; @@ -723,16 +722,16 @@ glob2(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, } else /* Need expansion, recurse. */ return(glob3(pathbuf, pathbuf_last, pathend, - pathend_last, pattern, p, pattern_last, - pglob, limitp)); + pathend_last, pattern, p, pattern_last, + pglob, limitp)); } /* NOTREACHED */ } static int glob3(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, - Char *pattern, Char *restpattern, Char *restpattern_last, glob_t *pglob, - struct glob_lim *limitp) + Char *pattern, Char *restpattern, Char *restpattern_last, glob_t *pglob, + struct glob_lim *limitp) { struct dirent *dp; DIR *dirp; @@ -758,7 +757,7 @@ glob3(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, if (g_Ctoc(pathbuf, buf, sizeof(buf))) return(GLOB_ABORTED); if (pglob->gl_errfunc(buf, errno) || - pglob->gl_flags & GLOB_ERR) + pglob->gl_flags & GLOB_ERR) return(GLOB_ABORTED); } return(0); @@ -776,7 +775,7 @@ glob3(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, Char *dc; if ((pglob->gl_flags & GLOB_LIMIT) && - limitp->glim_readdir++ >= GLOB_LIMIT_READDIR) { + limitp->glim_readdir++ >= GLOB_LIMIT_READDIR) { errno = 0; *pathend++ = SEP; *pathend = EOS; @@ -802,7 +801,7 @@ glob3(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, continue; } err = glob2(pathbuf, pathbuf_last, --dc, pathend_last, - restpattern, restpattern_last, pglob, limitp); + restpattern, restpattern_last, pglob, limitp); if (err) break; } @@ -831,7 +830,7 @@ glob3(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, */ static int globextend(const Char *path, glob_t *pglob, struct glob_lim *limitp, - zend_stat_t *sb) + zend_stat_t *sb) { char **pathv; size_t i, newn, len; @@ -841,16 +840,16 @@ globextend(const Char *path, glob_t *pglob, struct glob_lim *limitp, newn = 2 + pglob->gl_pathc + pglob->gl_offs; if (pglob->gl_offs >= SSIZE_MAX || - pglob->gl_pathc >= SSIZE_MAX || - newn >= SSIZE_MAX || - SIZE_MAX / sizeof(*pathv) <= newn || - SIZE_MAX / sizeof(*statv) <= newn) { + pglob->gl_pathc >= SSIZE_MAX || + newn >= SSIZE_MAX || + SIZE_MAX / sizeof(*pathv) <= newn || + SIZE_MAX / sizeof(*statv) <= newn) { nospace: for (i = pglob->gl_offs; i < newn - 2; i++) { if (pglob->gl_pathv && pglob->gl_pathv[i]) free(pglob->gl_pathv[i]); if ((pglob->gl_flags & GLOB_KEEPSTAT) != 0 && - pglob->gl_pathv && pglob->gl_pathv[i]) + pglob->gl_pathv && pglob->gl_pathv[i]) free(pglob->gl_statv[i]); } free(pglob->gl_pathv); @@ -887,15 +886,15 @@ globextend(const Char *path, glob_t *pglob, struct glob_lim *limitp, else { limitp->glim_malloc += sizeof(**statv); if ((pglob->gl_flags & GLOB_LIMIT) && - limitp->glim_malloc >= GLOB_LIMIT_MALLOC) { + limitp->glim_malloc >= GLOB_LIMIT_MALLOC) { errno = 0; return(GLOB_NOSPACE); } if ((statv[pglob->gl_offs + pglob->gl_pathc] = - malloc(sizeof(**statv))) == NULL) + malloc(sizeof(**statv))) == NULL) goto copy_error; memcpy(statv[pglob->gl_offs + pglob->gl_pathc], sb, - sizeof(*sb)); + sizeof(*sb)); } statv[pglob->gl_offs + pglob->gl_pathc + 1] = NULL; } @@ -914,8 +913,8 @@ globextend(const Char *path, glob_t *pglob, struct glob_lim *limitp, pathv[pglob->gl_offs + pglob->gl_pathc] = NULL; if ((pglob->gl_flags & GLOB_LIMIT) && - (newn * sizeof(*pathv)) + limitp->glim_malloc > - GLOB_LIMIT_MALLOC) { + (newn * sizeof(*pathv)) + limitp->glim_malloc > + GLOB_LIMIT_MALLOC) { errno = 0; return(GLOB_NOSPACE); } @@ -971,7 +970,7 @@ match(Char *name, Char *pat, Char *patend) if ((c & M_MASK) == M_CLASS) { Char idx = *pat & M_MASK; if (idx < NCCLASSES && - cclasses[idx].isctype(k)) + cclasses[idx].isctype(k)) ok = 1; ++pat; } From 64ff22595c7124912e090bedc7c17a5599b36f96 Mon Sep 17 00:00:00 2001 From: Calvin Buckley Date: Mon, 9 Dec 2024 12:26:52 -0400 Subject: [PATCH 6/7] Put function definitions associated with body on one line Matches the style of glob before, OpenBSD must have changed this to match their convention, but this is closer to PHP convention. --- win32/glob.c | 69 ++++++++++++++++------------------------------------ 1 file changed, 21 insertions(+), 48 deletions(-) diff --git a/win32/glob.c b/win32/glob.c index 2021bc64af16c..0a36c24d10534 100644 --- a/win32/glob.c +++ b/win32/glob.c @@ -189,9 +189,7 @@ static int match(Char *, Char *, Char *); static void qprintf(const char *, Char *); #endif -PHPAPI int -glob(const char *pattern, int flags, int (*errfunc)(const char *, int), - glob_t *pglob) +PHPAPI int glob(const char *pattern, int flags, int (*errfunc)(const char *, int), glob_t *pglob) { const uint8_t *patnext; int c; @@ -254,8 +252,7 @@ glob(const char *pattern, int flags, int (*errfunc)(const char *, int), * invoke the standard globbing routine to glob the rest of the magic * characters */ -static int -globexp1(const Char *pattern, glob_t *pglob, struct glob_lim *limitp) +static int globexp1(const Char *pattern, glob_t *pglob, struct glob_lim *limitp) { const Char* ptr = pattern; @@ -275,9 +272,7 @@ globexp1(const Char *pattern, glob_t *pglob, struct glob_lim *limitp) * If it succeeds then it invokes globexp1 with the new pattern. * 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, - struct glob_lim *limitp) +static int globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, struct glob_lim *limitp) { int i, rv; Char *lm, *ls; @@ -382,8 +377,7 @@ globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, /* * expand tilde from the passwd file. */ -static const Char * -globtilde(const Char *pattern, Char *patbuf, size_t patbuf_len, glob_t *pglob) +static const Char *globtilde(const Char *pattern, Char *patbuf, size_t patbuf_len, glob_t *pglob) { #ifndef PHP_WIN32 struct passwd pwstore, *pwd = NULL; @@ -454,8 +448,7 @@ globtilde(const Char *pattern, Char *patbuf, size_t patbuf_len, glob_t *pglob) return patbuf; } -static int -g_strncmp(const Char *s1, const char *s2, size_t n) +static int g_strncmp(const Char *s1, const char *s2, size_t n) { int rv = 0; @@ -469,8 +462,7 @@ g_strncmp(const Char *s1, const char *s2, size_t n) return rv; } -static int -g_charclass(const Char **patternp, Char **bufnextp) +static int g_charclass(const Char **patternp, Char **bufnextp) { const Char *pattern = *patternp + 1; Char *bufnext = *bufnextp; @@ -503,8 +495,7 @@ g_charclass(const Char **patternp, Char **bufnextp) * if things went well, nonzero if errors occurred. It is not an error * to find no matches. */ -static int -glob0(const Char *pattern, glob_t *pglob, struct glob_lim *limitp) +static int glob0(const Char *pattern, glob_t *pglob, struct glob_lim *limitp) { const Char *qpatnext; int c, err; @@ -627,14 +618,12 @@ glob0(const Char *pattern, glob_t *pglob, struct glob_lim *limitp) return(0); } -static int -compare(const void *p, const void *q) +static int compare(const void *p, const void *q) { return(strcmp(*(char **)p, *(char **)q)); } -static int -compare_gps(const void *_p, const void *_q) +static int compare_gps(const void *_p, const void *_q) { const struct glob_path_stat *p = (const struct glob_path_stat *)_p; const struct glob_path_stat *q = (const struct glob_path_stat *)_q; @@ -642,8 +631,7 @@ compare_gps(const void *_p, const void *_q) return(strcmp(p->gps_path, q->gps_path)); } -static int -glob1(Char *pattern, Char *pattern_last, glob_t *pglob, struct glob_lim *limitp) +static int glob1(Char *pattern, Char *pattern_last, glob_t *pglob, struct glob_lim *limitp) { Char pathbuf[PATH_MAX]; @@ -660,9 +648,7 @@ glob1(Char *pattern, Char *pattern_last, glob_t *pglob, struct glob_lim *limitp) * of recursion for each segment in the pattern that contains one or more * meta characters. */ -static int -glob2(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, - Char *pattern, Char *pattern_last, glob_t *pglob, struct glob_lim *limitp) +static int glob2(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, Char *pattern, Char *pattern_last, glob_t *pglob, struct glob_lim *limitp) { zend_stat_t sb; Char *p, *q; @@ -728,10 +714,7 @@ glob2(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, /* NOTREACHED */ } -static int -glob3(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, - Char *pattern, Char *restpattern, Char *restpattern_last, glob_t *pglob, - struct glob_lim *limitp) +static int glob3(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, Char *pattern, Char *restpattern, Char *restpattern_last, glob_t *pglob, struct glob_lim *limitp) { struct dirent *dp; DIR *dirp; @@ -828,9 +811,7 @@ glob3(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, * Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and * gl_pathv points to (gl_offs + gl_pathc + 1) items. */ -static int -globextend(const Char *path, glob_t *pglob, struct glob_lim *limitp, - zend_stat_t *sb) +static int globextend(const Char *path, glob_t *pglob, struct glob_lim *limitp, zend_stat_t *sb) { char **pathv; size_t i, newn, len; @@ -934,8 +915,7 @@ globextend(const Char *path, glob_t *pglob, struct glob_lim *limitp, * from Russ Cox to not go quadratic on cases like a file called * ("a" x 100) . "x" matched against a pattern like "a*a*a*a*a*a*a*y". */ -static int -match(Char *name, Char *pat, Char *patend) +static int match(Char *name, Char *pat, Char *patend) { int ok, negate_range; Char c, k; @@ -1003,8 +983,7 @@ match(Char *name, Char *pat, Char *patend) } /* Free allocated data belonging to a glob_t structure. */ -PHPAPI void -globfree(glob_t *pglob) +PHPAPI void globfree(glob_t *pglob) { size_t i; char **pp; @@ -1025,8 +1004,7 @@ globfree(glob_t *pglob) } } -static DIR * -g_opendir(Char *str, glob_t *pglob) +static DIR *g_opendir(Char *str, glob_t *pglob) { char buf[PATH_MAX]; @@ -1043,8 +1021,7 @@ g_opendir(Char *str, glob_t *pglob) return(opendir(buf)); } -static int -g_lstat(Char *fn, zend_stat_t *sb, glob_t *pglob) +static int g_lstat(Char *fn, zend_stat_t *sb, glob_t *pglob) { char buf[PATH_MAX]; @@ -1055,8 +1032,7 @@ g_lstat(Char *fn, zend_stat_t *sb, glob_t *pglob) return(php_sys_lstat(buf, sb)); } -static int -g_stat(Char *fn, zend_stat_t *sb, glob_t *pglob) +static int g_stat(Char *fn, zend_stat_t *sb, glob_t *pglob) { char buf[PATH_MAX]; @@ -1067,8 +1043,7 @@ g_stat(Char *fn, zend_stat_t *sb, glob_t *pglob) return(php_sys_stat(buf, sb)); } -static Char * -g_strchr(const Char *str, int ch) +static Char *g_strchr(const Char *str, int ch) { do { if (*str == ch) @@ -1077,8 +1052,7 @@ g_strchr(const Char *str, int ch) return (NULL); } -static int -g_Ctoc(const Char *str, char *buf, size_t len) +static int g_Ctoc(const Char *str, char *buf, size_t len) { while (len--) { @@ -1089,8 +1063,7 @@ g_Ctoc(const Char *str, char *buf, size_t len) } #ifdef DEBUG -static void -qprintf(const char *str, Char *s) +static void qprintf(const char *str, Char *s) { Char *p; From ce4c8334a266b40ce5b365acaa847b2a6c05e1bd Mon Sep 17 00:00:00 2001 From: Calvin Buckley Date: Wed, 18 Dec 2024 11:17:08 -0400 Subject: [PATCH 7/7] Move realloc array into win32/glob.c We only need it on Windows, and we want to convert this file to ZendMM later anyways, which has its own equivalent. This also reverts commit a26e92e4fbac2325696964150776ad952bad56c8. --- configure.ac | 3 +-- main/php.h | 10 ------- main/reallocarray.c | 59 ------------------------------------------ win32/build/config.w32 | 2 +- win32/glob.c | 41 +++++++++++++++++++++++++++++ 5 files changed, 43 insertions(+), 72 deletions(-) delete mode 100644 main/reallocarray.c diff --git a/configure.ac b/configure.ac index fc0fb11ae6b5b..01d9ded69b920 100644 --- a/configure.ac +++ b/configure.ac @@ -689,7 +689,7 @@ AS_VAR_IF([php_cv_func_copy_file_range], [yes], [AC_DEFINE([HAVE_COPY_FILE_RANGE], [1], [Define to 1 if you have the 'copy_file_range' function.])]) -AC_REPLACE_FUNCS([strlcat strlcpy reallocarray explicit_bzero getopt]) +AC_REPLACE_FUNCS([strlcat strlcpy explicit_bzero getopt]) AC_FUNC_ALLOCA PHP_TIME_R_TYPE @@ -1638,7 +1638,6 @@ PHP_ADD_SOURCES([main], m4_normalize([ php_ticks.c php_variables.c reentrancy.c - reallocarray.c rfc1867.c safe_bcmp.c SAPI.c diff --git a/main/php.h b/main/php.h index 36f123c45605d..5c0b89c328375 100644 --- a/main/php.h +++ b/main/php.h @@ -172,16 +172,6 @@ END_EXTERN_C() #define explicit_bzero php_explicit_bzero #endif -#ifndef HAVE_REALLOCARRAY -BEGIN_EXTERN_C() -PHPAPI void *php_reallocarray(void *optr, size_t nmemb, size_t size); -END_EXTERN_C() -#undef reallocarray -#define reallocarray php_reallocarray -#define HAVE_REALLOCARRAY 1 -#define USE_REALLOCARRAY_PHP_IMPL 1 -#endif - BEGIN_EXTERN_C() PHPAPI int php_safe_bcmp(const zend_string *a, const zend_string *b); END_EXTERN_C() diff --git a/main/reallocarray.c b/main/reallocarray.c deleted file mode 100644 index 20a31789424ff..0000000000000 --- a/main/reallocarray.c +++ /dev/null @@ -1,59 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | Copyright (c) The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 3.01 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available through the world-wide-web at the following url: | - | https://www.php.net/license/3_01.txt | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Author: | - +----------------------------------------------------------------------+ -*/ - -#include "php.h" - -#ifdef USE_REALLOCARRAY_PHP_IMPL -/* $OpenBSD: reallocarray.c,v 1.3 2015/09/13 08:31:47 guenther Exp $ */ -/* - * Copyright (c) 2008 Otto Moerbeek - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include -#include -#include - -/* - * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX - * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW - */ -#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4)) - -PHPAPI void * -php_reallocarray(void *optr, size_t nmemb, size_t size) -{ - if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && - nmemb > 0 && SIZE_MAX / nmemb < size) { - errno = ENOMEM; - return NULL; - } - return realloc(optr, size * nmemb); -} - -#endif /* !HAVE_REALLOCARRAY */ diff --git a/win32/build/config.w32 b/win32/build/config.w32 index bb3bceb40dbd4..dd33e595a2ee9 100644 --- a/win32/build/config.w32 +++ b/win32/build/config.w32 @@ -284,7 +284,7 @@ if (VS_TOOLSET && VCVERS >= 1914) { //AC_DEFINE('ZEND_DVAL_TO_LVAL_CAST_OK', 1); ADD_SOURCES("main", "main.c snprintf.c spprintf.c getopt.c fopen_wrappers.c \ - php_ini_builder.c reallocarray.c \ + php_ini_builder.c \ php_scandir.c php_ini.c SAPI.c rfc1867.c php_content_types.c strlcpy.c \ strlcat.c reentrancy.c php_variables.c php_ticks.c network.c \ php_open_temporary_file.c output.c internal_functions.c \ diff --git a/win32/glob.c b/win32/glob.c index 0a36c24d10534..8a04b8de18c24 100644 --- a/win32/glob.c +++ b/win32/glob.c @@ -164,6 +164,47 @@ struct glob_path_stat { zend_stat_t *gps_stat; }; +/* + * XXX: This is temporary to avoid having reallocarray be imported and part of + * PHP's public API. Since it's only needed here and on Windows, we can just + * put it here for now. Convert this file to ZendMM and remove this function + * when that's complete. + */ + +/* $OpenBSD: reallocarray.c,v 1.3 2015/09/13 08:31:47 guenther Exp $ */ +/* + * Copyright (c) 2008 Otto Moerbeek + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX + * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW + */ +#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4)) + +static void * +reallocarray(void *optr, size_t nmemb, size_t size) +{ + if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && + nmemb > 0 && SIZE_MAX / nmemb < size) { + errno = ENOMEM; + return NULL; + } + return realloc(optr, size * nmemb); +} + static int compare(const void *, const void *); static int compare_gps(const void *, const void *); static int g_Ctoc(const Char *, char *, size_t);