mirror of
https://github.com/php/php-src.git
synced 2025-08-16 14:08:47 +02:00
Fixed bug #74345
Export zend_release_fcall_info_cache(). It is only necessary to call it if the fcc may not have been used -- if it is passed to zend_call_function() and friends, then they will take care of freeing trampolines.
This commit is contained in:
parent
ed808c59e4
commit
abc457fe1d
4 changed files with 45 additions and 4 deletions
|
@ -2907,7 +2907,7 @@ static int zend_is_callable_check_class(zend_string *name, zend_class_entry *sco
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
static void free_fcc(zend_fcall_info_cache *fcc) {
|
ZEND_API void zend_release_fcall_info_cache(zend_fcall_info_cache *fcc) {
|
||||||
if (fcc->function_handler &&
|
if (fcc->function_handler &&
|
||||||
((fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) ||
|
((fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) ||
|
||||||
fcc->function_handler->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY ||
|
fcc->function_handler->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY ||
|
||||||
|
@ -2918,6 +2918,7 @@ static void free_fcc(zend_fcall_info_cache *fcc) {
|
||||||
}
|
}
|
||||||
zend_free_trampoline(fcc->function_handler);
|
zend_free_trampoline(fcc->function_handler);
|
||||||
}
|
}
|
||||||
|
fcc->function_handler = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static zend_always_inline int zend_is_callable_check_func(int check_flags, zval *callable, zend_fcall_info_cache *fcc, int strict_class, char **error) /* {{{ */
|
static zend_always_inline int zend_is_callable_check_func(int check_flags, zval *callable, zend_fcall_info_cache *fcc, int strict_class, char **error) /* {{{ */
|
||||||
|
@ -3283,7 +3284,7 @@ again:
|
||||||
check_func:
|
check_func:
|
||||||
ret = zend_is_callable_check_func(check_flags, callable, fcc, strict_class, error);
|
ret = zend_is_callable_check_func(check_flags, callable, fcc, strict_class, error);
|
||||||
if (fcc == &fcc_local) {
|
if (fcc == &fcc_local) {
|
||||||
free_fcc(fcc);
|
zend_release_fcall_info_cache(fcc);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
@ -3352,7 +3353,7 @@ check_func:
|
||||||
if (Z_OBJ_HANDLER_P(callable, get_closure) && Z_OBJ_HANDLER_P(callable, get_closure)(callable, &fcc->calling_scope, &fcc->function_handler, &fcc->object) == SUCCESS) {
|
if (Z_OBJ_HANDLER_P(callable, get_closure) && Z_OBJ_HANDLER_P(callable, get_closure)(callable, &fcc->calling_scope, &fcc->function_handler, &fcc->object) == SUCCESS) {
|
||||||
fcc->called_scope = fcc->calling_scope;
|
fcc->called_scope = fcc->calling_scope;
|
||||||
if (fcc == &fcc_local) {
|
if (fcc == &fcc_local) {
|
||||||
free_fcc(fcc);
|
zend_release_fcall_info_cache(fcc);
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -3394,7 +3395,7 @@ ZEND_API zend_bool zend_make_callable(zval *callable, zend_string **callable_nam
|
||||||
add_next_index_str(callable, zend_string_copy(fcc.calling_scope->name));
|
add_next_index_str(callable, zend_string_copy(fcc.calling_scope->name));
|
||||||
add_next_index_str(callable, zend_string_copy(fcc.function_handler->common.function_name));
|
add_next_index_str(callable, zend_string_copy(fcc.function_handler->common.function_name));
|
||||||
}
|
}
|
||||||
free_fcc(&fcc);
|
zend_release_fcall_info_cache(&fcc);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -302,6 +302,7 @@ ZEND_API ZEND_COLD void zend_wrong_param_count(void);
|
||||||
|
|
||||||
#define IS_CALLABLE_STRICT (IS_CALLABLE_CHECK_IS_STATIC)
|
#define IS_CALLABLE_STRICT (IS_CALLABLE_CHECK_IS_STATIC)
|
||||||
|
|
||||||
|
ZEND_API void zend_release_fcall_info_cache(zend_fcall_info_cache *fcc);
|
||||||
ZEND_API zend_string *zend_get_callable_name_ex(zval *callable, zend_object *object);
|
ZEND_API zend_string *zend_get_callable_name_ex(zval *callable, zend_object *object);
|
||||||
ZEND_API zend_string *zend_get_callable_name(zval *callable);
|
ZEND_API zend_string *zend_get_callable_name(zval *callable);
|
||||||
ZEND_API zend_bool zend_is_callable_ex(zval *callable, zend_object *object, uint32_t check_flags, zend_string **callable_name, zend_fcall_info_cache *fcc, char **error);
|
ZEND_API zend_bool zend_is_callable_ex(zval *callable, zend_object *object, uint32_t check_flags, zend_string **callable_name, zend_fcall_info_cache *fcc, char **error);
|
||||||
|
|
|
@ -1013,6 +1013,7 @@ static int php_array_user_compare(const void *a, const void *b) /* {{{ */
|
||||||
BG(user_compare_fci_cache) = empty_fcall_info_cache; \
|
BG(user_compare_fci_cache) = empty_fcall_info_cache; \
|
||||||
|
|
||||||
#define PHP_ARRAY_CMP_FUNC_RESTORE() \
|
#define PHP_ARRAY_CMP_FUNC_RESTORE() \
|
||||||
|
zend_release_fcall_info_cache(&BG(user_compare_fci_cache)); \
|
||||||
BG(user_compare_fci) = old_user_compare_fci; \
|
BG(user_compare_fci) = old_user_compare_fci; \
|
||||||
BG(user_compare_fci_cache) = old_user_compare_fci_cache; \
|
BG(user_compare_fci_cache) = old_user_compare_fci_cache; \
|
||||||
|
|
||||||
|
@ -1502,6 +1503,7 @@ PHP_FUNCTION(array_walk)
|
||||||
);
|
);
|
||||||
|
|
||||||
php_array_walk(array, userdata, 0);
|
php_array_walk(array, userdata, 0);
|
||||||
|
zend_release_fcall_info_cache(&BG(array_walk_fci_cache));
|
||||||
BG(array_walk_fci) = orig_array_walk_fci;
|
BG(array_walk_fci) = orig_array_walk_fci;
|
||||||
BG(array_walk_fci_cache) = orig_array_walk_fci_cache;
|
BG(array_walk_fci_cache) = orig_array_walk_fci_cache;
|
||||||
RETURN_TRUE;
|
RETURN_TRUE;
|
||||||
|
@ -1532,6 +1534,7 @@ PHP_FUNCTION(array_walk_recursive)
|
||||||
);
|
);
|
||||||
|
|
||||||
php_array_walk(array, userdata, 1);
|
php_array_walk(array, userdata, 1);
|
||||||
|
zend_release_fcall_info_cache(&BG(array_walk_fci_cache));
|
||||||
BG(array_walk_fci) = orig_array_walk_fci;
|
BG(array_walk_fci) = orig_array_walk_fci;
|
||||||
BG(array_walk_fci_cache) = orig_array_walk_fci_cache;
|
BG(array_walk_fci_cache) = orig_array_walk_fci_cache;
|
||||||
RETURN_TRUE;
|
RETURN_TRUE;
|
||||||
|
@ -6017,6 +6020,7 @@ PHP_FUNCTION(array_reduce)
|
||||||
|
|
||||||
if (zend_hash_num_elements(htbl) == 0) {
|
if (zend_hash_num_elements(htbl) == 0) {
|
||||||
ZVAL_COPY_VALUE(return_value, &result);
|
ZVAL_COPY_VALUE(return_value, &result);
|
||||||
|
zend_release_fcall_info_cache(&fci_cache);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6040,6 +6044,7 @@ PHP_FUNCTION(array_reduce)
|
||||||
}
|
}
|
||||||
} ZEND_HASH_FOREACH_END();
|
} ZEND_HASH_FOREACH_END();
|
||||||
|
|
||||||
|
zend_release_fcall_info_cache(&fci_cache);
|
||||||
RETVAL_ZVAL(&result, 1, 1);
|
RETVAL_ZVAL(&result, 1, 1);
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
@ -6069,6 +6074,7 @@ PHP_FUNCTION(array_filter)
|
||||||
|
|
||||||
array_init(return_value);
|
array_init(return_value);
|
||||||
if (zend_hash_num_elements(Z_ARRVAL_P(array)) == 0) {
|
if (zend_hash_num_elements(Z_ARRVAL_P(array)) == 0) {
|
||||||
|
zend_release_fcall_info_cache(&fci_cache);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6130,6 +6136,8 @@ PHP_FUNCTION(array_filter)
|
||||||
}
|
}
|
||||||
zval_add_ref(operand);
|
zval_add_ref(operand);
|
||||||
} ZEND_HASH_FOREACH_END();
|
} ZEND_HASH_FOREACH_END();
|
||||||
|
|
||||||
|
zend_release_fcall_info_cache(&fci_cache);
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
|
@ -6167,6 +6175,7 @@ PHP_FUNCTION(array_map)
|
||||||
/* Short-circuit: if no callback and only one array, just return it. */
|
/* Short-circuit: if no callback and only one array, just return it. */
|
||||||
if (!ZEND_FCI_INITIALIZED(fci) || !maxlen) {
|
if (!ZEND_FCI_INITIALIZED(fci) || !maxlen) {
|
||||||
ZVAL_COPY(return_value, &arrays[0]);
|
ZVAL_COPY(return_value, &arrays[0]);
|
||||||
|
zend_release_fcall_info_cache(&fci_cache);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6192,6 +6201,8 @@ PHP_FUNCTION(array_map)
|
||||||
zend_hash_index_add_new(Z_ARRVAL_P(return_value), num_key, &result);
|
zend_hash_index_add_new(Z_ARRVAL_P(return_value), num_key, &result);
|
||||||
}
|
}
|
||||||
} ZEND_HASH_FOREACH_END();
|
} ZEND_HASH_FOREACH_END();
|
||||||
|
|
||||||
|
zend_release_fcall_info_cache(&fci_cache);
|
||||||
} else {
|
} else {
|
||||||
uint32_t *array_pos = (HashPosition *)ecalloc(n_arrays, sizeof(HashPosition));
|
uint32_t *array_pos = (HashPosition *)ecalloc(n_arrays, sizeof(HashPosition));
|
||||||
|
|
||||||
|
@ -6284,6 +6295,7 @@ PHP_FUNCTION(array_map)
|
||||||
}
|
}
|
||||||
|
|
||||||
efree(params);
|
efree(params);
|
||||||
|
zend_release_fcall_info_cache(&fci_cache);
|
||||||
}
|
}
|
||||||
efree(array_pos);
|
efree(array_pos);
|
||||||
}
|
}
|
||||||
|
|
27
ext/standard/tests/array/bug74345.phpt
Normal file
27
ext/standard/tests/array/bug74345.phpt
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
--TEST--
|
||||||
|
Bug #74345: Call trampoline leaked if callback not invoked
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class Test {
|
||||||
|
public function __call($name, $args) {
|
||||||
|
echo "__call()\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$name = "foo" . ($x = "bar");
|
||||||
|
$cb = [new Test, $name];
|
||||||
|
array_map($cb, []);
|
||||||
|
array_map($cb, [], []);
|
||||||
|
array_filter([], $cb);
|
||||||
|
array_reduce([], $cb);
|
||||||
|
|
||||||
|
$array = [];
|
||||||
|
array_walk($array, $cb);
|
||||||
|
array_walk_recursive($array, $cb);
|
||||||
|
usort($array, $cb);
|
||||||
|
|
||||||
|
?>
|
||||||
|
===DONE===
|
||||||
|
--EXPECT--
|
||||||
|
===DONE===
|
Loading…
Add table
Add a link
Reference in a new issue