}
/* }}} */
-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 &&
((fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) ||
fcc->function_handler->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY ||
}
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) /* {{{ */
check_func:
ret = zend_is_callable_check_func(check_flags, callable, fcc, strict_class, error);
if (fcc == &fcc_local) {
- free_fcc(fcc);
+ zend_release_fcall_info_cache(fcc);
}
return ret;
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;
if (fcc == &fcc_local) {
- free_fcc(fcc);
+ zend_release_fcall_info_cache(fcc);
}
return 1;
}
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));
}
- free_fcc(&fcc);
+ zend_release_fcall_info_cache(&fcc);
return 1;
}
return 0;
#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(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);
BG(user_compare_fci_cache) = empty_fcall_info_cache; \
#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_cache) = old_user_compare_fci_cache; \
);
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_cache) = orig_array_walk_fci_cache;
RETURN_TRUE;
);
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_cache) = orig_array_walk_fci_cache;
RETURN_TRUE;
if (zend_hash_num_elements(htbl) == 0) {
ZVAL_COPY_VALUE(return_value, &result);
+ zend_release_fcall_info_cache(&fci_cache);
return;
}
}
} ZEND_HASH_FOREACH_END();
+ zend_release_fcall_info_cache(&fci_cache);
RETVAL_ZVAL(&result, 1, 1);
}
/* }}} */
array_init(return_value);
if (zend_hash_num_elements(Z_ARRVAL_P(array)) == 0) {
+ zend_release_fcall_info_cache(&fci_cache);
return;
}
}
zval_add_ref(operand);
} ZEND_HASH_FOREACH_END();
+
+ zend_release_fcall_info_cache(&fci_cache);
}
/* }}} */
/* Short-circuit: if no callback and only one array, just return it. */
if (!ZEND_FCI_INITIALIZED(fci) || !maxlen) {
ZVAL_COPY(return_value, &arrays[0]);
+ zend_release_fcall_info_cache(&fci_cache);
return;
}
zend_hash_index_add_new(Z_ARRVAL_P(return_value), num_key, &result);
}
} ZEND_HASH_FOREACH_END();
+
+ zend_release_fcall_info_cache(&fci_cache);
} else {
uint32_t *array_pos = (HashPosition *)ecalloc(n_arrays, sizeof(HashPosition));
}
efree(params);
+ zend_release_fcall_info_cache(&fci_cache);
}
efree(array_pos);
}
--- /dev/null
+--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===