diff --git a/Zend/tests/bug41026.phpt b/Zend/tests/bug41026.phpt index 0dde757d84cec..36d8ba4c634cb 100644 --- a/Zend/tests/bug41026.phpt +++ b/Zend/tests/bug41026.phpt @@ -12,7 +12,7 @@ class try_class static public function on_shutdown () { - printf ("CHECKPOINT\n"); /* never reached */ + printf ("CHECKPOINT\n"); } } @@ -22,5 +22,4 @@ echo "Done\n"; ?> --EXPECT-- Done - -Fatal error: Registered shutdown function self::on_shutdown() cannot be called, function does not exist in Unknown on line 0 +CHECKPOINT diff --git a/ext/session/session.c b/ext/session/session.c index 2a1ddbbfa174b..e6799642fde0f 100644 --- a/ext/session/session.c +++ b/ext/session/session.c @@ -2047,13 +2047,18 @@ PHP_FUNCTION(session_set_save_handler) if (register_shutdown) { /* create shutdown function */ php_shutdown_function_entry shutdown_function_entry; - ZVAL_STRING(&shutdown_function_entry.function_name, "session_register_shutdown"); - shutdown_function_entry.arg_count = 0; - shutdown_function_entry.arguments = NULL; + zval callable; + zend_result result; + + ZVAL_STRING(&callable, "session_register_shutdown"); + result = zend_fcall_info_init(&callable, 0, &shutdown_function_entry.fci, + &shutdown_function_entry.fci_cache, NULL, NULL); + + ZEND_ASSERT(result == SUCCESS); /* add shutdown function, removing the old one if it exists */ if (!register_user_shutdown_function("session_shutdown", sizeof("session_shutdown") - 1, &shutdown_function_entry)) { - zval_ptr_dtor(&shutdown_function_entry.function_name); + zval_ptr_dtor(&callable); php_error_docref(NULL, E_WARNING, "Unable to register session shutdown function"); RETURN_FALSE; } @@ -2654,6 +2659,8 @@ PHP_FUNCTION(session_status) PHP_FUNCTION(session_register_shutdown) { php_shutdown_function_entry shutdown_function_entry; + zval callable; + zend_result result; ZEND_PARSE_PARAMETERS_NONE(); @@ -2663,13 +2670,14 @@ PHP_FUNCTION(session_register_shutdown) * function after calling session_set_save_handler(), which expects * the session still to be available. */ + ZVAL_STRING(&callable, "session_write_close"); + result = zend_fcall_info_init(&callable, 0, &shutdown_function_entry.fci, + &shutdown_function_entry.fci_cache, NULL, NULL); - ZVAL_STRING(&shutdown_function_entry.function_name, "session_write_close"); - shutdown_function_entry.arg_count = 0; - shutdown_function_entry.arguments = NULL; + ZEND_ASSERT(result == SUCCESS); if (!append_user_shutdown_function(&shutdown_function_entry)) { - zval_ptr_dtor(&shutdown_function_entry.function_name); + zval_ptr_dtor(&callable); /* Unable to register shutdown function, presumably because of lack * of memory, so flush the session now. It would be done in rshutdown diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index 81a6cd4d734aa..d4ab282b0bb86 100755 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -1664,14 +1664,10 @@ PHP_FUNCTION(forward_static_call_array) void user_shutdown_function_dtor(zval *zv) /* {{{ */ { - int i; php_shutdown_function_entry *shutdown_function_entry = Z_PTR_P(zv); - zval_ptr_dtor(&shutdown_function_entry->function_name); - for (i = 0; i < shutdown_function_entry->arg_count; i++) { - zval_ptr_dtor(&shutdown_function_entry->arguments[i]); - } - efree(shutdown_function_entry->arguments); + zval_ptr_dtor(&shutdown_function_entry->fci.function_name); + zend_fcall_info_args_clear(&shutdown_function_entry->fci, true); efree(shutdown_function_entry); } /* }}} */ @@ -1685,24 +1681,16 @@ void user_tick_function_dtor(user_tick_function_entry *tick_function_entry) /* { static int user_shutdown_function_call(zval *zv) /* {{{ */ { - php_shutdown_function_entry *shutdown_function_entry = Z_PTR_P(zv); + php_shutdown_function_entry *shutdown_function_entry = Z_PTR_P(zv); zval retval; + zend_result call_status; - if (!zend_is_callable(&shutdown_function_entry->function_name, 0, NULL)) { - zend_string *function_name = zend_get_callable_name(&shutdown_function_entry->function_name); - zend_throw_error(NULL, "Registered shutdown function %s() cannot be called, function does not exist", ZSTR_VAL(function_name)); - zend_string_release(function_name); - return 0; - } + /* set retval zval for FCI struct */ + shutdown_function_entry->fci.retval = &retval; + call_status = zend_call_function(&shutdown_function_entry->fci, &shutdown_function_entry->fci_cache); + ZEND_ASSERT(call_status == SUCCESS); + zval_ptr_dtor(&retval); - if (call_user_function(NULL, NULL, - &shutdown_function_entry->function_name, - &retval, - shutdown_function_entry->arg_count, - shutdown_function_entry->arguments) == SUCCESS) - { - zval_ptr_dtor(&retval); - } return 0; } /* }}} */ @@ -1761,8 +1749,7 @@ PHPAPI void php_call_shutdown_functions(void) /* {{{ */ if (BG(user_shutdown_function_names)) { zend_try { zend_hash_apply(BG(user_shutdown_function_names), user_shutdown_function_call); - } - zend_end_try(); + } zend_end_try(); } } /* }}} */ @@ -1786,23 +1773,20 @@ PHPAPI void php_free_shutdown_functions(void) /* {{{ */ PHP_FUNCTION(register_shutdown_function) { php_shutdown_function_entry entry; - zend_fcall_info fci; - zend_fcall_info_cache fcc; - zval *args; - int arg_count = 0; + zval *params; + uint32_t param_count; + bool status; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "f*", &fci, &fcc, &args, &arg_count) == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_START(1, -1) + Z_PARAM_FUNC(entry.fci, entry.fci_cache) + Z_PARAM_VARIADIC('+', params, param_count); + ZEND_PARSE_PARAMETERS_END(); - ZVAL_COPY(&entry.function_name, &fci.function_name); - entry.arguments = (zval *) safe_emalloc(sizeof(zval), arg_count, 0); - entry.arg_count = arg_count; - for (int i = 0; i < arg_count; i++) { - ZVAL_COPY(&entry.arguments[i], &args[i]); - } + Z_TRY_ADDREF(entry.fci.function_name); + zend_fcall_info_argp(&entry.fci, param_count, params); - append_user_shutdown_function(&entry); + status = append_user_shutdown_function(&entry); + ZEND_ASSERT(status); } /* }}} */ diff --git a/ext/standard/basic_functions.h b/ext/standard/basic_functions.h index 18ddd667818d7..f692c14cdc82c 100644 --- a/ext/standard/basic_functions.h +++ b/ext/standard/basic_functions.h @@ -143,9 +143,8 @@ PHPAPI double php_get_nan(void); PHPAPI double php_get_inf(void); typedef struct _php_shutdown_function_entry { - zval function_name; - zval *arguments; - int arg_count; + zend_fcall_info fci; + zend_fcall_info_cache fci_cache; } php_shutdown_function_entry; PHPAPI extern bool register_user_shutdown_function(const char *function_name, size_t function_len, php_shutdown_function_entry *shutdown_function_entry); diff --git a/ext/standard/tests/general_functions/010.phpt b/ext/standard/tests/general_functions/010.phpt index af722ea583c63..08c941331f543 100644 --- a/ext/standard/tests/general_functions/010.phpt +++ b/ext/standard/tests/general_functions/010.phpt @@ -12,7 +12,7 @@ class test { } try { - register_shutdown_function(array("test","__call")); + var_dump(register_shutdown_function(array("test","__call"))); } catch (TypeError $exception) { echo $exception->getMessage() . "\n"; }