diff --git a/configure.ac b/configure.ac index 2dfb06dd023e0..d874a40a951c9 100644 --- a/configure.ac +++ b/configure.ac @@ -689,7 +689,7 @@ if test "$ac_cv_func_getaddrinfo" = yes; then AC_DEFINE(HAVE_GETADDRINFO,1,[Define if you have the getaddrinfo function]) fi -AC_REPLACE_FUNCS(strlcat strlcpy explicit_bzero getopt) +AC_REPLACE_FUNCS(strlcat strlcpy explicit_bzero getopt reallocarray) AC_FUNC_ALLOCA PHP_TIME_R_TYPE PHP_CHECK_IN_ADDR_T @@ -1616,7 +1616,7 @@ PHP_ADD_SOURCES(main, main.c snprintf.c spprintf.c \ php_ini_builder.c \ php_ini.c SAPI.c rfc1867.c php_content_types.c strlcpy.c \ strlcat.c explicit_bzero.c reentrancy.c php_variables.c php_ticks.c \ - network.c php_open_temporary_file.c php_odbc_utils.c safe_bcmp.c \ + network.c php_open_temporary_file.c php_odbc_utils.c safe_bcmp.c reallocarray.c \ output.c getopt.c php_syslog.c, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1) PHP_ADD_SOURCES_X(main, fastcgi.c, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1, PHP_FASTCGI_OBJS, no) diff --git a/main/php.h b/main/php.h index 9009ba032d3bd..27eb72389d2c7 100644 --- a/main/php.h +++ b/main/php.h @@ -179,6 +179,14 @@ END_EXTERN_C() #define explicit_bzero php_explicit_bzero #endif +#ifndef HAVE_REALLOCARRAY +BEGIN_EXTERN_C() +PHPAPI void* php_reallocarray(void *p, size_t nmb, size_t siz); +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..beee4bfa09705 --- /dev/null +++ b/main/reallocarray.c @@ -0,0 +1,41 @@ +/* + +----------------------------------------------------------------------+ + | 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: David Carlier | + +----------------------------------------------------------------------+ +*/ + +#include "php.h" + +#ifndef HAVE_REALLOCARRAY + +#include + +PHPAPI void* php_reallocarray(void *p, size_t nmb, size_t siz) +{ + size_t r; +#ifndef _WIN32 + if (__builtin_mul_overflow(nmb, siz, &r)) { +#else + + r = siz * nmb; + if (siz != 0 && r / siz != nmb) { +#endif + // EOVERFLOW may have been, arguably, more appropriate + // but this is what other implementations set + errno = ENOMEM; + return NULL; + } + + return realloc(p, r); +} +#endif diff --git a/sapi/fpm/fpm/fpm_arrays.h b/sapi/fpm/fpm/fpm_arrays.h index 82c7cbc09e1e0..454ff31204b2d 100644 --- a/sapi/fpm/fpm/fpm_arrays.h +++ b/sapi/fpm/fpm/fpm_arrays.h @@ -6,6 +6,8 @@ #include #include +#include "php.h" + struct fpm_array_s { void *data; size_t sz; @@ -84,7 +86,7 @@ static inline void *fpm_array_push(struct fpm_array_s *a) /* {{{ */ if (a->used == a->allocated) { size_t new_allocated = a->allocated ? a->allocated * 2 : 20; - void *new_ptr = realloc(a->data, a->sz * new_allocated); + void *new_ptr = reallocarray(a->data, a->sz, new_allocated); if (!new_ptr) { return 0;