]> granicus.if.org Git - php/commitdiff
Only compute callback name in error cases
authorNikita Popov <nikita.ppv@gmail.com>
Sun, 25 Jun 2017 16:45:59 +0000 (18:45 +0200)
committerNikita Popov <nikita.ppv@gmail.com>
Sun, 25 Jun 2017 16:45:59 +0000 (18:45 +0200)
Mostly the callback name is only used to report an error. Try to
avoid calculating it if no error occurred.

12 files changed:
Zend/zend_builtin_functions.c
Zend/zend_execute_API.c
ext/interbase/ibase_events.c
ext/ldap/ldap.c
ext/oci8/oci8_interface.c
ext/pcntl/pcntl.c
ext/pcre/php_pcre.c
ext/pdo_sqlite/sqlite_driver.c
ext/readline/readline.c
ext/session/session.c
ext/sqlite3/sqlite3.c
ext/standard/basic_functions.c

index 2850821ebd3197548610b4eda9c9d9aff8ccedf8..150603f879540c930d202986b9aa65d558479d5e 100644 (file)
@@ -1593,7 +1593,6 @@ ZEND_FUNCTION(trigger_error)
 ZEND_FUNCTION(set_error_handler)
 {
        zval *error_handler;
-       zend_string *error_handler_name = NULL;
        zend_long error_type = E_ALL;
 
        if (zend_parse_parameters(ZEND_NUM_ARGS(), "z|l", &error_handler, &error_type) == FAILURE) {
@@ -1601,13 +1600,13 @@ ZEND_FUNCTION(set_error_handler)
        }
 
        if (Z_TYPE_P(error_handler) != IS_NULL) { /* NULL == unset */
-               if (!zend_is_callable(error_handler, 0, &error_handler_name)) {
+               if (!zend_is_callable(error_handler, 0, NULL)) {
+                       zend_string *error_handler_name = zend_get_callable_name(error_handler);
                        zend_error(E_WARNING, "%s() expects the argument (%s) to be a valid callback",
                                           get_active_function_name(), error_handler_name?ZSTR_VAL(error_handler_name):"unknown");
                        zend_string_release(error_handler_name);
                        return;
                }
-               zend_string_release(error_handler_name);
        }
 
        if (Z_TYPE(EG(user_error_handler)) != IS_UNDEF) {
@@ -1662,20 +1661,19 @@ ZEND_FUNCTION(restore_error_handler)
 ZEND_FUNCTION(set_exception_handler)
 {
        zval *exception_handler;
-       zend_string *exception_handler_name = NULL;
 
        if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &exception_handler) == FAILURE) {
                return;
        }
 
        if (Z_TYPE_P(exception_handler) != IS_NULL) { /* NULL == unset */
-               if (!zend_is_callable(exception_handler, 0, &exception_handler_name)) {
+               if (!zend_is_callable(exception_handler, 0, NULL)) {
+               zend_string *exception_handler_name = zend_get_callable_name(exception_handler);
                        zend_error(E_WARNING, "%s() expects the argument (%s) to be a valid callback",
                                           get_active_function_name(), exception_handler_name?ZSTR_VAL(exception_handler_name):"unknown");
                        zend_string_release(exception_handler_name);
                        return;
                }
-               zend_string_release(exception_handler_name);
        }
 
        if (Z_TYPE(EG(user_exception_handler)) != IS_UNDEF) {
index fec7f73f5758fff665c94263dbaa6046648eb40b..ae0dd8f972ea2f6b8bc52b932996a57bf5d0e2c7 100644 (file)
@@ -703,19 +703,18 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) /
        }
 
        if (!fci_cache || !fci_cache->initialized) {
-               zend_string *callable_name;
                char *error = NULL;
 
                if (!fci_cache) {
                        fci_cache = &fci_cache_local;
                }
 
-               if (!zend_is_callable_ex(&fci->function_name, fci->object, IS_CALLABLE_CHECK_SILENT, &callable_name, fci_cache, &error)) {
+               if (!zend_is_callable_ex(&fci->function_name, fci->object, IS_CALLABLE_CHECK_SILENT, NULL, fci_cache, &error)) {
                        if (error) {
+                               zend_string *callable_name
+                                       = zend_get_callable_name_ex(&fci->function_name, fci->object);
                                zend_error(E_WARNING, "Invalid callback %s, %s", ZSTR_VAL(callable_name), error);
                                efree(error);
-                       }
-                       if (callable_name) {
                                zend_string_release(callable_name);
                        }
                        if (EG(current_execute_data) == &dummy_execute_data) {
@@ -730,16 +729,12 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) /
                        zend_error(E_DEPRECATED, "%s", error);
                        efree(error);
                        if (UNEXPECTED(EG(exception))) {
-                               if (callable_name) {
-                                       zend_string_release(callable_name);
-                               }
                                if (EG(current_execute_data) == &dummy_execute_data) {
                                        EG(current_execute_data) = dummy_execute_data.prev_execute_data;
                                }
                                return FAILURE;
                        }
                }
-               zend_string_release(callable_name);
        }
 
        func = fci_cache->function_handler;
index 36eca398fd3c740c8b3b8d27e4955d0d652a1831..001c43ddedb035f9edd602b7005e5b09f87689ba 100644 (file)
@@ -264,7 +264,6 @@ PHP_FUNCTION(ibase_set_event_handler)
         * link resource id (int) as arguments. The value returned from the function is
         * used to determine if the event handler should remain set.
         */
-       zend_string *cb_name;
        zval *args, *cb_arg;
        ibase_db_link *ib_link;
        ibase_event *event;
@@ -318,12 +317,12 @@ PHP_FUNCTION(ibase_set_event_handler)
        }
 
        /* get the callback */
-       if (!zend_is_callable(cb_arg, 0, &cb_name)) {
+       if (!zend_is_callable(cb_arg, 0, NULL)) {
+               zend_string *cb_name = zend_get_callable_name(cb_arg);
                _php_ibase_module_error("Callback argument %s is not a callable function", ZSTR_VAL(cb_name));
                zend_string_release(cb_name);
                RETURN_FALSE;
        }
-       zend_string_release(cb_name);
 
        /* allocate the event resource */
        event = (ibase_event *) safe_emalloc(sizeof(ibase_event), 1, 0);
index d17719a28526986db88051b7eee8e44467883f68..717b8e7a46063733e92a59e540dafe6ecc2d2ddd 100644 (file)
@@ -2783,7 +2783,6 @@ PHP_FUNCTION(ldap_set_rebind_proc)
 {
        zval *link, *callback;
        ldap_linkdata *ld;
-       zend_string *callback_name;
 
        if (zend_parse_parameters(ZEND_NUM_ARGS(), "rz", &link, &callback) != SUCCESS) {
                RETURN_FALSE;
@@ -2804,12 +2803,12 @@ PHP_FUNCTION(ldap_set_rebind_proc)
        }
 
        /* callable? */
-       if (!zend_is_callable(callback, 0, &callback_name)) {
+       if (!zend_is_callable(callback, 0, NULL)) {
+               zend_string *callback_name = zend_get_callable_name(callback);
                php_error_docref(NULL, E_WARNING, "Two arguments expected for '%s' to be a valid callback", ZSTR_VAL(callback_name));
                zend_string_release(callback_name);
                RETURN_FALSE;
        }
-       zend_string_release(callback_name);
 
        /* register rebind procedure */
        if (Z_ISUNDEF(ld->rebindproc)) {
index 59bdb9cc85d6e1d7fffa7e7c2334d0f30dc037ab..71905675189af8198c0f3de2bb9ee505280ddb93 100644 (file)
@@ -49,20 +49,18 @@ PHP_FUNCTION(oci_register_taf_callback)
        zval *z_connection;
        php_oci_connection *connection;
        zval *callback;
-       zend_string *callback_name;
 
        if (zend_parse_parameters(ZEND_NUM_ARGS(), "r|z!", &z_connection, &callback) == FAILURE) {
                return;
        }
 
        if (callback) {
-               if (!zend_is_callable(callback, 0, &callback_name)) {
+               if (!zend_is_callable(callback, 0, NULL)) {
+                       zend_string *callback_name = zend_get_callable_name(callback);
                        php_error_docref(NULL, E_WARNING, "function '%s' is not callable", ZSTR_VAL(callback_name));
                        zend_string_release(callback_name);
                        RETURN_FALSE;
                }
-
-               zend_string_release(callback_name);
        }
 
        PHP_OCI_ZVAL_TO_CONNECTION(z_connection, connection);
index fd8c5067381e5815cb863e8308cfd8f6a640b030..d82fed294a2c661fcb5c9355a152d355e64bb348 100644 (file)
@@ -990,7 +990,6 @@ PHP_FUNCTION(pcntl_exec)
 PHP_FUNCTION(pcntl_signal)
 {
        zval *handle;
-       zend_string *func_name;
        zend_long signo;
        zend_bool restart_syscalls = 1;
 
@@ -1031,13 +1030,13 @@ PHP_FUNCTION(pcntl_signal)
                RETURN_TRUE;
        }
 
-       if (!zend_is_callable(handle, 0, &func_name)) {
+       if (!zend_is_callable(handle, 0, NULL)) {
+               zend_string *func_name = zend_get_callable_name(handle);
                PCNTL_G(last_error) = EINVAL;
                php_error_docref(NULL, E_WARNING, "%s is not a callable function name error", ZSTR_VAL(func_name));
                zend_string_release(func_name);
                RETURN_FALSE;
        }
-       zend_string_release(func_name);
 
        /* Add the function name to our signal table */
        if (zend_hash_index_update(&PCNTL_G(php_signal_table), signo, handle)) {
index 615c83ae65383e842c7ef0174991647e9c1a305f..131f096f47a9ec6493a89cb3ccd568ea80242c04 100644 (file)
@@ -2037,7 +2037,6 @@ static PHP_FUNCTION(preg_replace_callback)
 {
        zval *regex, *replace, *subject, *zcount = NULL;
        zend_long limit = -1;
-       zend_string     *callback_name;
        int replace_count;
        zend_fcall_info fci;
        zend_fcall_info_cache fcc;
@@ -2052,13 +2051,13 @@ static PHP_FUNCTION(preg_replace_callback)
                Z_PARAM_ZVAL_DEREF(zcount)
        ZEND_PARSE_PARAMETERS_END();
 
-       if (!zend_is_callable_ex(replace, NULL, 0, &callback_name, &fcc, NULL)) {
+       if (!zend_is_callable_ex(replace, NULL, 0, NULL, &fcc, NULL)) {
+               zend_string     *callback_name = zend_get_callable_name(replace);
                php_error_docref(NULL, E_WARNING, "Requires argument 2, '%s', to be a valid callback", ZSTR_VAL(callback_name));
                zend_string_release(callback_name);
                ZVAL_STR(return_value, zval_get_string(subject));
                return;
        }
-       zend_string_release(callback_name);
 
        fci.size = sizeof(fci);
        fci.object = NULL;
@@ -2079,7 +2078,6 @@ static PHP_FUNCTION(preg_replace_callback_array)
        zval regex, zv, *replace, *subject, *pattern, *zcount = NULL;
        zend_long limit = -1;
        zend_string *str_idx;
-       zend_string *callback_name;
        int replace_count = 0;
        zend_fcall_info fci;
        zend_fcall_info_cache fcc;
@@ -2105,7 +2103,8 @@ static PHP_FUNCTION(preg_replace_callback_array)
                        RETURN_NULL();
                }
 
-               if (!zend_is_callable_ex(replace, NULL, 0, &callback_name, &fcc, NULL)) {
+               if (!zend_is_callable_ex(replace, NULL, 0, NULL, &fcc, NULL)) {
+                       zend_string *callback_name = zend_get_callable_name(replace);
                        php_error_docref(NULL, E_WARNING, "'%s' is not a valid callback", ZSTR_VAL(callback_name));
                        zend_string_release(callback_name);
                        zval_ptr_dtor(&regex);
@@ -2113,7 +2112,6 @@ static PHP_FUNCTION(preg_replace_callback_array)
                        ZVAL_COPY(return_value, subject);
                        return;
                }
-               zend_string_release(callback_name);
 
                ZVAL_COPY_VALUE(&fci.function_name, replace);
 
index fed9dbed2f4c5ba9416d9b2f2324bf2ac80a505e..3d32f232e834b1ea71d90cbf28ac9e0cc45d5335 100644 (file)
@@ -515,7 +515,6 @@ static PHP_METHOD(SQLite, sqliteCreateFunction)
        size_t func_name_len;
        zend_long argc = -1;
        zend_long flags = 0;
-       zend_string *cbname = NULL;
        pdo_dbh_t *dbh;
        pdo_sqlite_db_handle *H;
        int ret;
@@ -531,12 +530,12 @@ static PHP_METHOD(SQLite, sqliteCreateFunction)
        dbh = Z_PDO_DBH_P(getThis());
        PDO_CONSTRUCT_CHECK;
 
-       if (!zend_is_callable(callback, 0, &cbname)) {
+       if (!zend_is_callable(callback, 0, NULL)) {
+               zend_string *cbname = zend_get_callable_name(callback);
                php_error_docref(NULL, E_WARNING, "function '%s' is not callable", ZSTR_VAL(cbname));
                zend_string_release(cbname);
                RETURN_FALSE;
        }
-       zend_string_release(cbname);
 
        H = (pdo_sqlite_db_handle *)dbh->driver_data;
 
@@ -588,7 +587,6 @@ static PHP_METHOD(SQLite, sqliteCreateAggregate)
        char *func_name;
        size_t func_name_len;
        zend_long argc = -1;
-       zend_string *cbname = NULL;
        pdo_dbh_t *dbh;
        pdo_sqlite_db_handle *H;
        int ret;
@@ -604,18 +602,19 @@ static PHP_METHOD(SQLite, sqliteCreateAggregate)
        dbh = Z_PDO_DBH_P(getThis());
        PDO_CONSTRUCT_CHECK;
 
-       if (!zend_is_callable(step_callback, 0, &cbname)) {
+       if (!zend_is_callable(step_callback, 0, NULL)) {
+               zend_string *cbname = zend_get_callable_name(step_callback);
                php_error_docref(NULL, E_WARNING, "function '%s' is not callable", ZSTR_VAL(cbname));
                zend_string_release(cbname);
                RETURN_FALSE;
        }
-       zend_string_release(cbname);
-       if (!zend_is_callable(fini_callback, 0, &cbname)) {
+
+       if (!zend_is_callable(fini_callback, 0, NULL)) {
+               zend_string *cbname = zend_get_callable_name(fini_callback);
                php_error_docref(NULL, E_WARNING, "function '%s' is not callable", ZSTR_VAL(cbname));
                zend_string_release(cbname);
                RETURN_FALSE;
        }
-       zend_string_release(cbname);
 
        H = (pdo_sqlite_db_handle *)dbh->driver_data;
 
@@ -651,7 +650,6 @@ static PHP_METHOD(SQLite, sqliteCreateCollation)
        zval *callback;
        char *collation_name;
        size_t collation_name_len;
-       zend_string *cbname = NULL;
        pdo_dbh_t *dbh;
        pdo_sqlite_db_handle *H;
        int ret;
@@ -664,12 +662,12 @@ static PHP_METHOD(SQLite, sqliteCreateCollation)
        dbh = Z_PDO_DBH_P(getThis());
        PDO_CONSTRUCT_CHECK;
 
-       if (!zend_is_callable(callback, 0, &cbname)) {
+       if (!zend_is_callable(callback, 0, NULL)) {
+               zend_string *cbname = zend_get_callable_name(callback);
                php_error_docref(NULL, E_WARNING, "function '%s' is not callable", ZSTR_VAL(cbname));
                zend_string_release(cbname);
                RETURN_FALSE;
        }
-       zend_string_release(cbname);
 
        H = (pdo_sqlite_db_handle *)dbh->driver_data;
 
index 53a4c9e9abf182dde70b2489b72ba563298f15df..3f0d9223180654429299134508ab132fe8804461 100644 (file)
@@ -507,7 +507,7 @@ static char **_readline_completion_cb(const char *text, int start, int end)
                                        return NULL;
                                }
                                matches[0] = strdup("");
-                               matches[1] = '\0';
+                               matches[1] = NULL;
                        }
                }
        }
@@ -522,19 +522,18 @@ static char **_readline_completion_cb(const char *text, int start, int end)
 
 PHP_FUNCTION(readline_completion_function)
 {
-       zval *arg = NULL;
-       zend_string *name = NULL;
+       zval *arg;
 
        if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "z", &arg)) {
                RETURN_FALSE;
        }
 
-       if (!zend_is_callable(arg, 0, &name)) {
+       if (!zend_is_callable(arg, 0, NULL)) {
+               zend_string *name = zend_get_callable_name(arg);
                php_error_docref(NULL, E_WARNING, "%s is not callable", ZSTR_VAL(name));
                zend_string_release(name);
                RETURN_FALSE;
        }
-       zend_string_release(name);
 
        zval_ptr_dtor(&_readline_completion);
        ZVAL_COPY(&_readline_completion, arg);
@@ -570,7 +569,6 @@ static void php_rl_callback_handler(char *the_line)
 PHP_FUNCTION(readline_callback_handler_install)
 {
        zval *callback;
-       zend_string *name = NULL;
        char *prompt;
        size_t prompt_len;
 
@@ -578,12 +576,12 @@ PHP_FUNCTION(readline_callback_handler_install)
                return;
        }
 
-       if (!zend_is_callable(callback, 0, &name)) {
+       if (!zend_is_callable(callback, 0, NULL)) {
+               zend_string *name = zend_get_callable_name(callback);
                php_error_docref(NULL, E_WARNING, "%s is not callable", ZSTR_VAL(name));
                zend_string_release(name);
                RETURN_FALSE;
        }
-       zend_string_release(name);
 
        if (Z_TYPE(_prepped_callback) != IS_UNDEF) {
                rl_callback_handler_remove();
index c51d51b46faf6eb2af41de5b69f3865820c11d47..7bc3a49abfdc17d4b8ea2b7d6923f3806b58ce8f 100644 (file)
@@ -1830,7 +1830,6 @@ static PHP_FUNCTION(session_set_save_handler)
 {
        zval *args = NULL;
        int i, num_args, argc = ZEND_NUM_ARGS();
-       zend_string *name;
        zend_string *ini_name, *ini_val;
 
        if (PS(session_status) == php_session_active) {
@@ -1960,12 +1959,12 @@ static PHP_FUNCTION(session_set_save_handler)
 
        /* At this point argc can only be between 6 and PS_NUM_APIS */
        for (i = 0; i < argc; i++) {
-               if (!zend_is_callable(&args[i], 0, &name)) {
+               if (!zend_is_callable(&args[i], 0, NULL)) {
+                       zend_string *name = zend_get_callable_name(&args[i]);
                        php_error_docref(NULL, E_WARNING, "Argument %d is not a valid callback", i+1);
                        zend_string_release(name);
                        RETURN_FALSE;
                }
-               zend_string_release(name);
        }
 
        if (PS(mod) && PS(mod) != &ps_mod_user) {
index b56c2388d91bd2a251e7fa68a618cd635b0313c7..04c98d836d63b5089640192915498bc6f4576431 100644 (file)
@@ -907,7 +907,6 @@ PHP_METHOD(sqlite3, createFunction)
        char *sql_func;
        size_t sql_func_len;
        zval *callback_func;
-       zend_string *callback_name;
        zend_long sql_func_num_args = -1;
        zend_long flags = 0;
        db_obj = Z_SQLITE3_DB_P(object);
@@ -922,12 +921,12 @@ PHP_METHOD(sqlite3, createFunction)
                RETURN_FALSE;
        }
 
-       if (!zend_is_callable(callback_func, 0, &callback_name)) {
+       if (!zend_is_callable(callback_func, 0, NULL)) {
+               zend_string *callback_name = zend_get_callable_name(callback_func);
                php_sqlite3_error(db_obj, "Not a valid callback function %s", ZSTR_VAL(callback_name));
                zend_string_release(callback_name);
                RETURN_FALSE;
        }
-       zend_string_release(callback_name);
 
        func = (php_sqlite3_func *)ecalloc(1, sizeof(*func));
 
@@ -956,7 +955,6 @@ PHP_METHOD(sqlite3, createAggregate)
        zval *object = getThis();
        php_sqlite3_func *func;
        char *sql_func;
-       zend_string *callback_name;
        size_t sql_func_len;
        zval *step_callback, *fini_callback;
        zend_long sql_func_num_args = -1;
@@ -972,19 +970,19 @@ PHP_METHOD(sqlite3, createAggregate)
                RETURN_FALSE;
        }
 
-       if (!zend_is_callable(step_callback, 0, &callback_name)) {
+       if (!zend_is_callable(step_callback, 0, NULL)) {
+               zend_string *callback_name = zend_get_callable_name(step_callback);
                php_sqlite3_error(db_obj, "Not a valid callback function %s", ZSTR_VAL(callback_name));
                zend_string_release(callback_name);
                RETURN_FALSE;
        }
-       zend_string_release(callback_name);
 
-       if (!zend_is_callable(fini_callback, 0, &callback_name)) {
+       if (!zend_is_callable(fini_callback, 0, NULL)) {
+               zend_string *callback_name = zend_get_callable_name(fini_callback);
                php_sqlite3_error(db_obj, "Not a valid callback function %s", ZSTR_VAL(callback_name));
                zend_string_release(callback_name);
                RETURN_FALSE;
        }
-       zend_string_release(callback_name);
 
        func = (php_sqlite3_func *)ecalloc(1, sizeof(*func));
 
@@ -1014,7 +1012,6 @@ PHP_METHOD(sqlite3, createCollation)
        zval *object = getThis();
        php_sqlite3_collation *collation;
        char *collation_name;
-       zend_string *callback_name;
        size_t collation_name_len;
        zval *callback_func;
        db_obj = Z_SQLITE3_DB_P(object);
@@ -1029,12 +1026,12 @@ PHP_METHOD(sqlite3, createCollation)
                RETURN_FALSE;
        }
 
-       if (!zend_is_callable(callback_func, 0, &callback_name)) {
+       if (!zend_is_callable(callback_func, 0, NULL)) {
+               zend_string *callback_name = zend_get_callable_name(callback_func);
                php_sqlite3_error(db_obj, "Not a valid callback function %s", ZSTR_VAL(callback_name));
                zend_string_release(callback_name);
                RETURN_FALSE;
        }
-       zend_string_release(callback_name);
 
        collation = (php_sqlite3_collation *)ecalloc(1, sizeof(*collation));
        if (sqlite3_create_collation(db_obj->db, collation_name, SQLITE_UTF8, collation, php_sqlite3_callback_compare) == SQLITE_OK) {
index 8f73153bbaf3f02edac09c36149fec2cf60a1a74..383e988090af1ff24c1161cca35c69f73742ce2b 100644 (file)
@@ -4976,19 +4976,13 @@ static int user_shutdown_function_call(zval *zv) /* {{{ */
 {
     php_shutdown_function_entry *shutdown_function_entry = Z_PTR_P(zv);
        zval retval;
-       zend_string *function_name;
 
-       if (!zend_is_callable(&shutdown_function_entry->arguments[0], 0, &function_name)) {
-               if (function_name) {
-                       php_error(E_WARNING, "(Registered shutdown functions) Unable to call %s() - function does not exist", ZSTR_VAL(function_name));
-                       zend_string_release(function_name);
-               } else {
-                       php_error(E_WARNING, "(Registered shutdown functions) Unable to call - function does not exist");
-               }
-               return 0;
-       }
-       if (function_name) {
+       if (!zend_is_callable(&shutdown_function_entry->arguments[0], 0, NULL)) {
+               zend_string *function_name
+                       = zend_get_callable_name(&shutdown_function_entry->arguments[0]);
+               php_error(E_WARNING, "(Registered shutdown functions) Unable to call %s() - function does not exist", ZSTR_VAL(function_name));
                zend_string_release(function_name);
+               return 0;
        }
 
        if (call_user_function(EG(function_table), NULL,
@@ -5102,7 +5096,6 @@ PHPAPI void php_free_shutdown_functions(void) /* {{{ */
 PHP_FUNCTION(register_shutdown_function)
 {
        php_shutdown_function_entry shutdown_function_entry;
-       zend_string *callback_name = NULL;
        int i;
 
        shutdown_function_entry.arg_count = ZEND_NUM_ARGS();
@@ -5119,13 +5112,12 @@ PHP_FUNCTION(register_shutdown_function)
        }
 
        /* Prevent entering of anything but valid callback (syntax check only!) */
-       if (!zend_is_callable(&shutdown_function_entry.arguments[0], 0, &callback_name)) {
-               if (callback_name) {
-                       php_error_docref(NULL, E_WARNING, "Invalid shutdown callback '%s' passed", ZSTR_VAL(callback_name));
-               } else {
-                       php_error_docref(NULL, E_WARNING, "Invalid shutdown callback passed");
-               }
+       if (!zend_is_callable(&shutdown_function_entry.arguments[0], 0, NULL)) {
+               zend_string *callback_name
+                       = zend_get_callable_name(&shutdown_function_entry.arguments[0]);
+               php_error_docref(NULL, E_WARNING, "Invalid shutdown callback '%s' passed", ZSTR_VAL(callback_name));
                efree(shutdown_function_entry.arguments);
+               zend_string_release(callback_name);
                RETVAL_FALSE;
        } else {
                if (!BG(user_shutdown_function_names)) {
@@ -5138,9 +5130,6 @@ PHP_FUNCTION(register_shutdown_function)
                }
                zend_hash_next_index_insert_mem(BG(user_shutdown_function_names), &shutdown_function_entry, sizeof(php_shutdown_function_entry));
        }
-       if (callback_name) {
-               zend_string_release(callback_name);
-       }
 }
 /* }}} */