From 4195a4a7916068e167670219110caf39b1a5052c Mon Sep 17 00:00:00 2001 From: Calvin Buckley Date: Fri, 10 Jan 2025 12:24:00 -0400 Subject: [PATCH 1/4] Initial ZendMM conversion of glob Removes the vendored OpenBSD reallocarray and changes libc memory management to ZendMM. Not sure if non-persistent is the right call, I think glob users use it then call globfree ASAP within a request, but it might be preferable to use persistent allocations. --- configure.ac | 1 - main/php_glob.c | 73 ++++++++++--------------------------------------- 2 files changed, 15 insertions(+), 59 deletions(-) diff --git a/configure.ac b/configure.ac index 61d1c350a82be..5363d36955f8e 100644 --- a/configure.ac +++ b/configure.ac @@ -572,7 +572,6 @@ AC_CHECK_FUNCS(m4_normalize([ poll pthread_jit_write_protect_np putenv - reallocarray scandir setenv setitimer diff --git a/main/php_glob.c b/main/php_glob.c index 8757ec0783f6d..7e2743848e95e 100644 --- a/main/php_glob.c +++ b/main/php_glob.c @@ -172,49 +172,6 @@ struct glob_path_stat { zend_stat_t *gps_stat; }; -#ifndef HAVE_REALLOCARRAY -/* - * 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); -} -#endif - static int compare(const void *, const void *); static int compare_gps(const void *, const void *); static int g_Ctoc(const Char *, char *, size_t); @@ -652,7 +609,7 @@ static int glob0(const Char *pattern, php_glob_t *pglob, struct glob_lim *limitp size_t n = pglob->gl_pathc - oldpathc; size_t o = pglob->gl_offs + oldpathc; - if ((path_stat = calloc(n, sizeof(*path_stat))) == NULL) + if ((path_stat = ecalloc(n, sizeof(*path_stat))) == NULL) return PHP_GLOB_NOSPACE; for (i = 0; i < n; i++) { path_stat[i].gps_path = pglob->gl_pathv[o + i]; @@ -663,7 +620,7 @@ static int glob0(const Char *pattern, php_glob_t *pglob, struct glob_lim *limitp pglob->gl_pathv[o + i] = path_stat[i].gps_path; pglob->gl_statv[o + i] = path_stat[i].gps_stat; } - free(path_stat); + efree(path_stat); } else { qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc, pglob->gl_pathc - oldpathc, sizeof(char *), @@ -883,19 +840,19 @@ static int globextend(const Char *path, php_glob_t *pglob, struct glob_lim *limi nospace: for (i = pglob->gl_offs; i < newn - 2; i++) { if (pglob->gl_pathv && pglob->gl_pathv[i]) - free(pglob->gl_pathv[i]); + efree(pglob->gl_pathv[i]); if ((pglob->gl_flags & PHP_GLOB_KEEPSTAT) != 0 && pglob->gl_pathv && pglob->gl_pathv[i]) - free(pglob->gl_statv[i]); + efree(pglob->gl_statv[i]); } - free(pglob->gl_pathv); + efree(pglob->gl_pathv); pglob->gl_pathv = NULL; - free(pglob->gl_statv); + efree(pglob->gl_statv); pglob->gl_statv = NULL; return(PHP_GLOB_NOSPACE); } - pathv = reallocarray(pglob->gl_pathv, newn, sizeof(*pathv)); + pathv = safe_erealloc_rel(pglob->gl_pathv, newn, sizeof(*pathv), 0); if (pathv == NULL) goto nospace; if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) { @@ -907,7 +864,7 @@ static int globextend(const Char *path, php_glob_t *pglob, struct glob_lim *limi pglob->gl_pathv = pathv; if ((pglob->gl_flags & PHP_GLOB_KEEPSTAT) != 0) { - statv = reallocarray(pglob->gl_statv, newn, sizeof(*statv)); + statv = safe_erealloc_rel(pglob->gl_statv, newn, sizeof(*statv), 0); if (statv == NULL) goto nospace; if (pglob->gl_statv == NULL && pglob->gl_offs > 0) { @@ -927,7 +884,7 @@ static int globextend(const Char *path, php_glob_t *pglob, struct glob_lim *limi return(PHP_GLOB_NOSPACE); } if ((statv[pglob->gl_offs + pglob->gl_pathc] = - malloc(sizeof(**statv))) == NULL) + emalloc(sizeof(**statv))) == NULL) goto copy_error; memcpy(statv[pglob->gl_offs + pglob->gl_pathc], sb, sizeof(*sb)); @@ -939,9 +896,9 @@ static int globextend(const Char *path, php_glob_t *pglob, struct glob_lim *limi ; len = (size_t)(p - path); limitp->glim_malloc += len; - if ((copy = malloc(len)) != NULL) { + if ((copy = emalloc(len)) != NULL) { if (g_Ctoc(path, copy, len)) { - free(copy); + efree(copy); return(PHP_GLOB_NOSPACE); } pathv[pglob->gl_offs + pglob->gl_pathc++] = copy; @@ -1046,15 +1003,15 @@ PHPAPI void php_globfree(php_glob_t *pglob) if (pglob->gl_pathv != NULL) { pp = pglob->gl_pathv + pglob->gl_offs; for (i = pglob->gl_pathc; i--; ++pp) - free(*pp); - free(pglob->gl_pathv); + efree(*pp); + efree(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]); + efree(pglob->gl_statv[i]); } - free(pglob->gl_statv); + efree(pglob->gl_statv); pglob->gl_statv = NULL; } } From 7bc29b0c1c5298bfaae0e7147b63b1ba764ec653 Mon Sep 17 00:00:00 2001 From: Calvin Buckley Date: Mon, 20 Jan 2025 12:55:36 -0400 Subject: [PATCH 2/4] ZendMM is infalliable, skip checks --- main/php_glob.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/main/php_glob.c b/main/php_glob.c index 7e2743848e95e..37fdcfb9746f2 100644 --- a/main/php_glob.c +++ b/main/php_glob.c @@ -609,8 +609,7 @@ static int glob0(const Char *pattern, php_glob_t *pglob, struct glob_lim *limitp size_t n = pglob->gl_pathc - oldpathc; size_t o = pglob->gl_offs + oldpathc; - if ((path_stat = ecalloc(n, sizeof(*path_stat))) == NULL) - return PHP_GLOB_NOSPACE; + path_stat = ecalloc(n, sizeof(*path_stat)); 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]; @@ -853,8 +852,6 @@ static int globextend(const Char *path, php_glob_t *pglob, struct glob_lim *limi } pathv = safe_erealloc_rel(pglob->gl_pathv, newn, sizeof(*pathv), 0); - if (pathv == NULL) - goto nospace; if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) { /* first time around -- clear initial gl_offs items */ pathv += pglob->gl_offs; @@ -883,9 +880,8 @@ static int globextend(const Char *path, php_glob_t *pglob, struct glob_lim *limi errno = 0; return(PHP_GLOB_NOSPACE); } - if ((statv[pglob->gl_offs + pglob->gl_pathc] = - emalloc(sizeof(**statv))) == NULL) - goto copy_error; + statv[pglob->gl_offs + pglob->gl_pathc] = + emalloc(sizeof(**statv)); memcpy(statv[pglob->gl_offs + pglob->gl_pathc], sb, sizeof(*sb)); } @@ -896,13 +892,12 @@ static int globextend(const Char *path, php_glob_t *pglob, struct glob_lim *limi ; len = (size_t)(p - path); limitp->glim_malloc += len; - if ((copy = emalloc(len)) != NULL) { - if (g_Ctoc(path, copy, len)) { - efree(copy); - return(PHP_GLOB_NOSPACE); - } - pathv[pglob->gl_offs + pglob->gl_pathc++] = copy; + copy = emalloc(len); + if (g_Ctoc(path, copy, len)) { + efree(copy); + return(PHP_GLOB_NOSPACE); } + pathv[pglob->gl_offs + pglob->gl_pathc++] = copy; pathv[pglob->gl_offs + pglob->gl_pathc] = NULL; if ((pglob->gl_flags & PHP_GLOB_LIMIT) && From 0293e7fd1f5f88b0c15df8ad455bd0e9361f492c Mon Sep 17 00:00:00 2001 From: Calvin Buckley Date: Tue, 20 May 2025 18:46:19 -0300 Subject: [PATCH 3/4] Don't use relay wrapper --- main/php_glob.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/main/php_glob.c b/main/php_glob.c index 37fdcfb9746f2..4dffd00a90f02 100644 --- a/main/php_glob.c +++ b/main/php_glob.c @@ -851,7 +851,7 @@ static int globextend(const Char *path, php_glob_t *pglob, struct glob_lim *limi return(PHP_GLOB_NOSPACE); } - pathv = safe_erealloc_rel(pglob->gl_pathv, newn, sizeof(*pathv), 0); + pathv = safe_erealloc(pglob->gl_pathv, newn, sizeof(*pathv), 0); if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) { /* first time around -- clear initial gl_offs items */ pathv += pglob->gl_offs; @@ -861,7 +861,7 @@ static int globextend(const Char *path, php_glob_t *pglob, struct glob_lim *limi pglob->gl_pathv = pathv; if ((pglob->gl_flags & PHP_GLOB_KEEPSTAT) != 0) { - statv = safe_erealloc_rel(pglob->gl_statv, newn, sizeof(*statv), 0); + statv = safe_erealloc(pglob->gl_statv, newn, sizeof(*statv), 0); if (statv == NULL) goto nospace; if (pglob->gl_statv == NULL && pglob->gl_offs > 0) { From 6a6041b9093ab62a2a7a379029531db09d87a363 Mon Sep 17 00:00:00 2001 From: Calvin Buckley Date: Tue, 20 May 2025 18:58:13 -0300 Subject: [PATCH 4/4] Remove unused label after refactor --- main/php_glob.c | 1 - 1 file changed, 1 deletion(-) diff --git a/main/php_glob.c b/main/php_glob.c index 4dffd00a90f02..09da11a6a7594 100644 --- a/main/php_glob.c +++ b/main/php_glob.c @@ -906,7 +906,6 @@ static int globextend(const Char *path, php_glob_t *pglob, struct glob_lim *limi errno = 0; return(PHP_GLOB_NOSPACE); } - copy_error: return(copy == NULL ? PHP_GLOB_NOSPACE : 0); }