From a60e91b31351146caa1d0a15ff60c9029ea8654f Mon Sep 17 00:00:00 2001 From: Andrei Zmievski Date: Fri, 11 Feb 2000 21:14:42 +0000 Subject: [PATCH] (request_shutdown) Prevent infinite loop on shutdown if there is an error in shutdown function. (php_array_walk) Print a warning if the walk function doesn't exist. Split shutdown function call into a separate function that's called with zend_hash_apply() instead of as destructor to keep hash consistent. This fixes bug #3419. --- ext/standard/array.c | 10 ++++++---- ext/standard/basic_functions.c | 19 ++++++++++++++----- main/main.c | 9 +++++++-- main/php_globals.h | 1 + 4 files changed, 28 insertions(+), 11 deletions(-) diff --git a/ext/standard/array.c b/ext/standard/array.c index 0d47ed68e8..82bb9efff8 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -825,12 +825,14 @@ static int php_array_walk(HashTable *target_hash, zval **userdata) } /* Call the userland function */ - call_user_function_ex(CG(function_table), NULL, *BG(array_walk_func_name), - &retval_ptr, userdata ? 3 : 2, args, 0); + if (call_user_function_ex(CG(function_table), NULL, *BG(array_walk_func_name), + &retval_ptr, userdata ? 3 : 2, args, 0) == SUCCESS) { - if (retval_ptr) { zval_ptr_dtor(&retval_ptr); - } + } else + php_error(E_WARNING,"Unable to call %s() - function does not exist", + (*BG(array_walk_func_name))->value.str.val); + /* Clean up the key */ if (zend_hash_get_current_key_type(target_hash) == HASH_KEY_IS_STRING) efree(key->value.str.val); diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index 3e70b22f5d..f5c571a21a 100644 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -1045,25 +1045,34 @@ PHP_FUNCTION(call_user_method) void user_shutdown_function_dtor(php_shutdown_function_entry *shutdown_function_entry) { - pval retval; int i; - CLS_FETCH(); - if (call_user_function(CG(function_table), NULL, shutdown_function_entry->arguments[0], &retval, shutdown_function_entry->arg_count-1, shutdown_function_entry->arguments+1)==SUCCESS) { - pval_destructor(&retval); - } for (i=0; iarg_count; i++) { zval_ptr_dtor(&shutdown_function_entry->arguments[i]); } efree(shutdown_function_entry->arguments); } +int user_shutdown_function_call(php_shutdown_function_entry *shutdown_function_entry) +{ + zval retval; + CLS_FETCH(); + + if (call_user_function(CG(function_table), NULL, shutdown_function_entry->arguments[0], &retval, shutdown_function_entry->arg_count-1, shutdown_function_entry->arguments+1)==SUCCESS) { + zval_dtor(&retval); + } else + php_error(E_WARNING,"Unable to call %s() - function does not exist", + shutdown_function_entry->arguments[0]->value.str.val); + return 0; +} void php_call_shutdown_functions(void) { BLS_FETCH(); if (BG(user_shutdown_function_names)) { + zend_hash_apply(BG(user_shutdown_function_names), + (apply_func_t)user_shutdown_function_call); zend_hash_destroy(BG(user_shutdown_function_names)); efree(BG(user_shutdown_function_names)); } diff --git a/main/main.c b/main/main.c index b1a0898b58..ab769466cd 100644 --- a/main/main.c +++ b/main/main.c @@ -624,7 +624,8 @@ int php_request_startup(CLS_D ELS_DC PLS_DC SLS_DC) php_output_startup(); /* initialize global variables */ - PG(header_is_being_sent)=0; + PG(header_is_being_sent) = 0; + PG(already_in_shutdown) = 0; zend_activate(CLS_C ELS_CC); sapi_activate(SLS_C); @@ -658,11 +659,15 @@ void php_request_shutdown(void *dummy) CLS_FETCH(); ELS_FETCH(); SLS_FETCH(); + PLS_FETCH(); sapi_send_headers(); php_end_ob_buffering(SG(request_info).headers_only?0:1); - php_call_shutdown_functions(); + if (!PG(already_in_shutdown)) { + PG(already_in_shutdown) = 1; + php_call_shutdown_functions(); + } php_ini_rshutdown(); diff --git a/main/php_globals.h b/main/php_globals.h index b6e086ced3..441ecec0d3 100644 --- a/main/php_globals.h +++ b/main/php_globals.h @@ -97,6 +97,7 @@ struct _php_core_globals { long max_execution_time; unsigned char header_is_being_sent; + zend_bool already_in_shutdown; }; -- 2.40.0