Commit e228395787a for php.net
commit e228395787a13f2f9f5b474d6484c85e7ffa03c7
Author: Ilia Alshanetsky <ilia@ilia.ws>
Date: Fri Apr 3 11:27:52 2026 -0400
Use pemalloc/perealloc for persistent allocations
Replace direct malloc/realloc calls with OOM-safe pemalloc/perealloc
(persistent: true) counterparts.
Fixes GH-19200
Fixes GH-17013
Closes GH-21625
diff --git a/Zend/zend.c b/Zend/zend.c
index f4236053af3..f83389a96a6 100644
--- a/Zend/zend.c
+++ b/Zend/zend.c
@@ -1303,7 +1303,7 @@ ZEND_API void zend_append_version_info(const zend_extension *extension) /* {{{ *
snprintf(new_info, new_info_length, " with %s v%s, %s, by %s\n", extension->name, extension->version, extension->copyright, extension->author);
- zend_version_info = (char *) realloc(zend_version_info, zend_version_info_length+new_info_length + 1);
+ zend_version_info = (char *) perealloc(zend_version_info, zend_version_info_length+new_info_length + 1, true);
strncat(zend_version_info, new_info, new_info_length);
zend_version_info_length += new_info_length;
free(new_info);
diff --git a/Zend/zend_API.c b/Zend/zend_API.c
index c04217983b5..ccb770a9963 100644
--- a/Zend/zend_API.c
+++ b/Zend/zend_API.c
@@ -2504,19 +2504,19 @@ ZEND_API void zend_collect_module_handlers(void) /* {{{ */
dl_loaded_count++;
}
} ZEND_HASH_FOREACH_END();
- module_request_startup_handlers = (zend_module_entry**)realloc(
+ module_request_startup_handlers = (zend_module_entry**)perealloc(
module_request_startup_handlers,
sizeof(zend_module_entry*) *
(startup_count + 1 +
shutdown_count + 1 +
- post_deactivate_count + 1));
+ post_deactivate_count + 1), true);
module_request_startup_handlers[startup_count] = NULL;
module_request_shutdown_handlers = module_request_startup_handlers + startup_count + 1;
module_request_shutdown_handlers[shutdown_count] = NULL;
module_post_deactivate_handlers = module_request_shutdown_handlers + shutdown_count + 1;
module_post_deactivate_handlers[post_deactivate_count] = NULL;
/* Cannot reuse module_request_startup_handlers because it is freed in zend_destroy_modules, which happens before zend_unload_modules. */
- modules_dl_loaded = realloc(modules_dl_loaded, sizeof(zend_module_entry*) * (dl_loaded_count + 1));
+ modules_dl_loaded = perealloc(modules_dl_loaded, sizeof(zend_module_entry*) * (dl_loaded_count + 1), true);
modules_dl_loaded[dl_loaded_count] = NULL;
startup_count = 0;
@@ -2543,10 +2543,10 @@ ZEND_API void zend_collect_module_handlers(void) /* {{{ */
}
} ZEND_HASH_FOREACH_END();
- class_cleanup_handlers = (zend_class_entry**)realloc(
+ class_cleanup_handlers = (zend_class_entry**)perealloc(
class_cleanup_handlers,
sizeof(zend_class_entry*) *
- (class_count + 1));
+ (class_count + 1), true);
class_cleanup_handlers[class_count] = NULL;
if (class_count) {
@@ -3143,7 +3143,7 @@ ZEND_API zend_result zend_register_functions(zend_class_entry *scope, const zend
}
lowercase_name = zend_string_tolower_ex(internal_function->function_name, type == MODULE_PERSISTENT);
lowercase_name = zend_new_interned_string(lowercase_name);
- reg_function = malloc(sizeof(zend_internal_function));
+ reg_function = pemalloc(sizeof(zend_internal_function), true);
memcpy(reg_function, &function, sizeof(zend_internal_function));
if (zend_hash_add_ptr(target_function_table, lowercase_name, reg_function) == NULL) {
unload=1;
@@ -3161,8 +3161,8 @@ ZEND_API zend_result zend_register_functions(zend_class_entry *scope, const zend
zend_flf_capacity *= 2;
}
/* +1 for NULL terminator */
- zend_flf_handlers = realloc(zend_flf_handlers, (zend_flf_capacity + 1) * sizeof(void *));
- zend_flf_functions = realloc(zend_flf_functions, (zend_flf_capacity + 1) * sizeof(zend_function *));
+ zend_flf_handlers = perealloc(zend_flf_handlers, (zend_flf_capacity + 1) * sizeof(void *), true);
+ zend_flf_functions = perealloc(zend_flf_functions, (zend_flf_capacity + 1) * sizeof(zend_function *), true);
}
zend_flf_handlers[zend_flf_count] = flf_info->handler;
zend_flf_functions[zend_flf_count] = (zend_function *)reg_function;
@@ -3208,7 +3208,7 @@ ZEND_API zend_result zend_register_functions(zend_class_entry *scope, const zend
/* Treat return type as an extra argument */
num_args++;
- new_arg_info = malloc(sizeof(zend_arg_info) * num_args);
+ new_arg_info = pemalloc(sizeof(zend_arg_info) * num_args, true);
reg_function->arg_info = new_arg_info + 1;
for (i = 0; i < num_args; i++) {
zend_convert_internal_arg_info(&new_arg_info[i], &arg_info[i],
@@ -3493,7 +3493,7 @@ ZEND_API int zend_next_free_module(void) /* {{{ */
static zend_class_entry *do_register_internal_class(const zend_class_entry *orig_class_entry, uint32_t ce_flags) /* {{{ */
{
- zend_class_entry *class_entry = malloc(sizeof(zend_class_entry));
+ zend_class_entry *class_entry = pemalloc(sizeof(zend_class_entry), true);
zend_string *lowercase_name;
*class_entry = *orig_class_entry;
diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c
index bf4c84404a6..d70d08f5f1c 100644
--- a/Zend/zend_inheritance.c
+++ b/Zend/zend_inheritance.c
@@ -1595,11 +1595,7 @@ static void zend_do_inherit_interfaces(zend_class_entry *ce, const zend_class_en
ce_num = ce->num_interfaces;
- if (ce->type == ZEND_INTERNAL_CLASS) {
- ce->interfaces = (zend_class_entry **) realloc(ce->interfaces, sizeof(zend_class_entry *) * (ce_num + if_num));
- } else {
- ce->interfaces = (zend_class_entry **) erealloc(ce->interfaces, sizeof(zend_class_entry *) * (ce_num + if_num));
- }
+ ce->interfaces = (zend_class_entry **) perealloc(ce->interfaces, sizeof(zend_class_entry *) * (ce_num + if_num), ce->type == ZEND_INTERNAL_CLASS);
/* Inherit the interfaces, only if they're not already inherited by the class */
while (if_num--) {
@@ -2234,11 +2230,7 @@ ZEND_API void zend_do_implement_interface(zend_class_entry *ce, zend_class_entry
} ZEND_HASH_FOREACH_END();
} else {
if (ce->num_interfaces >= current_iface_num) {
- if (ce->type == ZEND_INTERNAL_CLASS) {
- ce->interfaces = (zend_class_entry **) realloc(ce->interfaces, sizeof(zend_class_entry *) * (++current_iface_num));
- } else {
- ce->interfaces = (zend_class_entry **) erealloc(ce->interfaces, sizeof(zend_class_entry *) * (++current_iface_num));
- }
+ ce->interfaces = (zend_class_entry **) perealloc(ce->interfaces, sizeof(zend_class_entry *) * (++current_iface_num), ce->type == ZEND_INTERNAL_CLASS);
}
ce->interfaces[ce->num_interfaces++] = iface;
diff --git a/ext/opcache/zend_accelerator_blacklist.c b/ext/opcache/zend_accelerator_blacklist.c
index 56a4ceb4dc4..ed03a82e9f3 100644
--- a/ext/opcache/zend_accelerator_blacklist.c
+++ b/ext/opcache/zend_accelerator_blacklist.c
@@ -225,7 +225,7 @@ static inline void zend_accel_blacklist_allocate(zend_blacklist *blacklist)
{
if (blacklist->pos == blacklist->size) {
blacklist->size += ZEND_BLACKLIST_BLOCK_SIZE;
- blacklist->entries = (zend_blacklist_entry *) realloc(blacklist->entries, sizeof(zend_blacklist_entry)*blacklist->size);
+ blacklist->entries = (zend_blacklist_entry *) perealloc(blacklist->entries, sizeof(zend_blacklist_entry)*blacklist->size, true);
}
}
diff --git a/main/network.c b/main/network.c
index f652cf555ff..90d1716b558 100644
--- a/main/network.c
+++ b/main/network.c
@@ -1459,7 +1459,7 @@ static struct hostent * gethostname_re (const char *host,struct hostent *hostbuf
if (*hstbuflen == 0) {
*hstbuflen = 1024;
- *tmphstbuf = (char *)malloc (*hstbuflen);
+ *tmphstbuf = (char *)pemalloc(*hstbuflen, true);
}
while (( res =
@@ -1467,7 +1467,7 @@ static struct hostent * gethostname_re (const char *host,struct hostent *hostbuf
&& (errno == ERANGE)) {
/* Enlarge the buffer. */
*hstbuflen *= 2;
- *tmphstbuf = (char *)realloc (*tmphstbuf,*hstbuflen);
+ *tmphstbuf = (char *)perealloc(*tmphstbuf, *hstbuflen, true);
}
if (res != 0) {
@@ -1485,7 +1485,7 @@ static struct hostent * gethostname_re (const char *host,struct hostent *hostbuf
if (*hstbuflen == 0) {
*hstbuflen = 1024;
- *tmphstbuf = (char *)malloc (*hstbuflen);
+ *tmphstbuf = (char *)pemalloc(*hstbuflen, true);
}
while ((NULL == ( hp =
@@ -1493,7 +1493,7 @@ static struct hostent * gethostname_re (const char *host,struct hostent *hostbuf
&& (errno == ERANGE)) {
/* Enlarge the buffer. */
*hstbuflen *= 2;
- *tmphstbuf = (char *)realloc (*tmphstbuf,*hstbuflen);
+ *tmphstbuf = (char *)perealloc(*tmphstbuf, *hstbuflen, true);
}
return hp;
}
@@ -1503,11 +1503,11 @@ static struct hostent * gethostname_re (const char *host,struct hostent *hostbuf
{
if (*hstbuflen == 0) {
*hstbuflen = sizeof(struct hostent_data);
- *tmphstbuf = (char *)malloc (*hstbuflen);
+ *tmphstbuf = (char *)pemalloc(*hstbuflen, true);
} else {
if (*hstbuflen < sizeof(struct hostent_data)) {
*hstbuflen = sizeof(struct hostent_data);
- *tmphstbuf = (char *)realloc(*tmphstbuf, *hstbuflen);
+ *tmphstbuf = (char *)perealloc(*tmphstbuf, *hstbuflen, true);
}
}
memset((void *)(*tmphstbuf),0,*hstbuflen);
diff --git a/main/php_ini.c b/main/php_ini.c
index 9925eafad1f..43e1c115e6e 100644
--- a/main/php_ini.c
+++ b/main/php_ini.c
@@ -694,7 +694,7 @@ void php_init_config(void)
if (total_l) {
size_t php_ini_scanned_files_len = (php_ini_scanned_files) ? strlen(php_ini_scanned_files) + 1 : 0;
- php_ini_scanned_files = (char *) realloc(php_ini_scanned_files, php_ini_scanned_files_len + total_l + 1);
+ php_ini_scanned_files = (char *) perealloc(php_ini_scanned_files, php_ini_scanned_files_len + total_l + 1, true);
if (!php_ini_scanned_files_len) {
*php_ini_scanned_files = '\0';
}
diff --git a/main/php_ini_builder.h b/main/php_ini_builder.h
index 0ad70b6f68a..9f73cba13cb 100644
--- a/main/php_ini_builder.h
+++ b/main/php_ini_builder.h
@@ -60,7 +60,7 @@ static inline char *php_ini_builder_finish(struct php_ini_builder *b)
static inline void php_ini_builder_realloc(struct php_ini_builder *b, size_t delta)
{
/* reserve enough space for the null terminator */
- b->value = realloc(b->value, b->length + delta + 1);
+ b->value = perealloc(b->value, b->length + delta + 1, true);
}
/**
diff --git a/sapi/phpdbg/phpdbg.c b/sapi/phpdbg/phpdbg.c
index 278e2657862..3c0d5e836dd 100644
--- a/sapi/phpdbg/phpdbg.c
+++ b/sapi/phpdbg/phpdbg.c
@@ -1199,9 +1199,9 @@ int main(int argc, char **argv) /* {{{ */
case 'z':
zend_extensions_len++;
if (zend_extensions_list) {
- zend_extensions_list = realloc(zend_extensions_list, sizeof(char*) * zend_extensions_len);
+ zend_extensions_list = perealloc(zend_extensions_list, sizeof(char*) * zend_extensions_len, true);
} else {
- zend_extensions_list = malloc(sizeof(char*) * zend_extensions_len);
+ zend_extensions_list = pemalloc(sizeof(char*) * zend_extensions_len, true);
}
zend_extensions_list[zend_extensions_len-1] = strdup(php_optarg);
break;
diff --git a/sapi/phpdbg/phpdbg_prompt.c b/sapi/phpdbg/phpdbg_prompt.c
index 9435e25ca00..692cda32c7e 100644
--- a/sapi/phpdbg/phpdbg_prompt.c
+++ b/sapi/phpdbg/phpdbg_prompt.c
@@ -215,9 +215,9 @@ static void phpdbg_line_init(char *cmd, struct phpdbg_init_state *state) {
if (state->in_code) {
if (state->code == NULL) {
- state->code = malloc(cmd_len + 1);
+ state->code = pemalloc(cmd_len + 1, true);
} else {
- state->code = realloc(state->code, state->code_len + cmd_len + 1);
+ state->code = perealloc(state->code, state->code_len + cmd_len + 1, true);
}
if (state->code) {