Skip to content

Commit bf29ee6

Browse files
committed
Add reallocarray implementation.
In a similar model as _safe_*alloc api but for the `userland` it guards against overflow before (re)allocation, usage concealed in fpm for now. Modern Linux and most of BSD already have it. Closes #8871.
1 parent 3b92a96 commit bf29ee6

File tree

4 files changed

+54
-3
lines changed

4 files changed

+54
-3
lines changed

configure.ac

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -689,7 +689,7 @@ if test "$ac_cv_func_getaddrinfo" = yes; then
689689
AC_DEFINE(HAVE_GETADDRINFO,1,[Define if you have the getaddrinfo function])
690690
fi
691691

692-
AC_REPLACE_FUNCS(strlcat strlcpy explicit_bzero getopt)
692+
AC_REPLACE_FUNCS(strlcat strlcpy explicit_bzero getopt reallocarray)
693693
AC_FUNC_ALLOCA
694694
PHP_TIME_R_TYPE
695695
PHP_CHECK_IN_ADDR_T
@@ -1616,7 +1616,7 @@ PHP_ADD_SOURCES(main, main.c snprintf.c spprintf.c \
16161616
php_ini_builder.c \
16171617
php_ini.c SAPI.c rfc1867.c php_content_types.c strlcpy.c \
16181618
strlcat.c explicit_bzero.c reentrancy.c php_variables.c php_ticks.c \
1619-
network.c php_open_temporary_file.c php_odbc_utils.c safe_bcmp.c \
1619+
network.c php_open_temporary_file.c php_odbc_utils.c safe_bcmp.c reallocarray.c \
16201620
output.c getopt.c php_syslog.c, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1)
16211621

16221622
PHP_ADD_SOURCES_X(main, fastcgi.c, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1, PHP_FASTCGI_OBJS, no)

main/php.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,14 @@ END_EXTERN_C()
179179
#define explicit_bzero php_explicit_bzero
180180
#endif
181181

182+
#ifndef HAVE_REALLOCARRAY
183+
BEGIN_EXTERN_C()
184+
PHPAPI void* php_reallocarray(void *p, size_t nmb, size_t siz);
185+
END_EXTERN_C()
186+
#undef reallocarray
187+
#define reallocarray php_reallocarray
188+
#endif
189+
182190
BEGIN_EXTERN_C()
183191
PHPAPI int php_safe_bcmp(const zend_string *a, const zend_string *b);
184192
END_EXTERN_C()

main/reallocarray.c

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
+----------------------------------------------------------------------+
3+
| Copyright (c) The PHP Group |
4+
+----------------------------------------------------------------------+
5+
| This source file is subject to version 3.01 of the PHP license, |
6+
| that is bundled with this package in the file LICENSE, and is |
7+
| available through the world-wide-web at the following url: |
8+
| https://www.php.net/license/3_01.txt |
9+
| If you did not receive a copy of the PHP license and are unable to |
10+
| obtain it through the world-wide-web, please send a note to |
11+
| license@php.net so we can mail you a copy immediately. |
12+
+----------------------------------------------------------------------+
13+
| Author: David Carlier <devnexen@gmail.com> |
14+
+----------------------------------------------------------------------+
15+
*/
16+
17+
#include "php.h"
18+
19+
#ifndef HAVE_REALLOCARRAY
20+
21+
#include <string.h>
22+
23+
PHPAPI void* php_reallocarray(void *p, size_t nmb, size_t siz)
24+
{
25+
size_t r;
26+
#ifndef _WIN32
27+
if (__builtin_mul_overflow(nmb, siz, &r)) {
28+
#else
29+
30+
r = siz * nmb;
31+
if (siz != 0 && r / siz != nmb) {
32+
#endif
33+
// EOVERFLOW may have been, arguably, more appropriate
34+
// but this is what other implementations set
35+
errno = ENOMEM;
36+
return NULL;
37+
}
38+
39+
return realloc(p, r);
40+
}
41+
#endif

sapi/fpm/fpm/fpm_arrays.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
#include <stdlib.h>
77
#include <string.h>
88

9+
#include "php.h"
10+
911
struct fpm_array_s {
1012
void *data;
1113
size_t sz;
@@ -84,7 +86,7 @@ static inline void *fpm_array_push(struct fpm_array_s *a) /* {{{ */
8486

8587
if (a->used == a->allocated) {
8688
size_t new_allocated = a->allocated ? a->allocated * 2 : 20;
87-
void *new_ptr = realloc(a->data, a->sz * new_allocated);
89+
void *new_ptr = reallocarray(a->data, a->sz, new_allocated);
8890

8991
if (!new_ptr) {
9092
return 0;

0 commit comments

Comments
 (0)