From dc7a83f9a276b68d211aa60c32fe1c9938472d31 Mon Sep 17 00:00:00 2001 From: bwoebi Date: Sun, 24 Feb 2013 00:17:22 +0100 Subject: [PATCH 1/2] Fixed bug #64280 --- Zend/tests/bug64280.phpt | 13 +++++++++++++ Zend/tests/bug64280_1.phpt | 34 ++++++++++++++++++++++++++++++++++ Zend/zend_execute_API.c | 5 +++++ Zend/zend_globals.h | 11 +++++++---- main/main.c | 18 ++++++++++++++++++ php.ini-development | 5 +++++ php.ini-production | 5 +++++ 7 files changed, 87 insertions(+), 4 deletions(-) create mode 100644 Zend/tests/bug64280.phpt create mode 100644 Zend/tests/bug64280_1.phpt diff --git a/Zend/tests/bug64280.phpt b/Zend/tests/bug64280.phpt new file mode 100644 index 0000000000000..15c75b148a5d6 --- /dev/null +++ b/Zend/tests/bug64280.phpt @@ -0,0 +1,13 @@ +--TEST-- +Bug #64280 (__destruct loop segfaults) - Basic behaviour +--FILE-- + +--EXPECTF-- +Fatal error: Magic method or function too often called recursively in %s on line %d diff --git a/Zend/tests/bug64280_1.phpt b/Zend/tests/bug64280_1.phpt new file mode 100644 index 0000000000000..80d5da9f77a27 --- /dev/null +++ b/Zend/tests/bug64280_1.phpt @@ -0,0 +1,34 @@ +--TEST-- +Bug #64280 (__destruct loop segfaults) - tests ini entry "max_magic_calls" and combining magic methods/functions with functions +--INI-- +max_magic_calls = 20 +--FILE-- += EG(max_magic_calls)) { + zend_error_noreturn(E_ERROR, "Magic method or function too often called recursively"); + } + EX(prev_execute_data) = EG(current_execute_data); EG(current_execute_data) = &execute_data; @@ -1022,6 +1026,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS EG(scope) = current_scope; EG(This) = current_this; EG(current_execute_data) = EX(prev_execute_data); + --EG(magic_call_count); if (EG(exception)) { zend_throw_exception_internal(NULL TSRMLS_CC); diff --git a/Zend/zend_globals.h b/Zend/zend_globals.h index 58392c199bd58..d2bd89217d878 100644 --- a/Zend/zend_globals.h +++ b/Zend/zend_globals.h @@ -5,7 +5,7 @@ | Copyright (c) 1998-2013 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | - | that is bundled with this package in the file LICENSE, and is | + | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.zend.com/license/2_00.txt. | | If you did not receive a copy of the Zend license and are unable to | @@ -236,11 +236,14 @@ struct _zend_executor_globals { /* timeout support */ int timeout_seconds; + long magic_call_count; + long max_magic_calls; + int lambda_count; HashTable *ini_directives; HashTable *modified_ini_directives; - zend_ini_entry *error_reporting_ini_entry; + zend_ini_entry *error_reporting_ini_entry; zend_objects_store objects_store; zval *exception, *prev_exception; @@ -253,7 +256,7 @@ struct _zend_executor_globals { zend_property_info std_property_info; - zend_bool active; + zend_bool active; zend_op *start_op; @@ -297,7 +300,7 @@ struct _zend_php_scanner_globals { unsigned char *yy_limit; int yy_state; zend_stack state_stack; - + /* original (unfiltered) script */ unsigned char *script_org; size_t script_org_size; diff --git a/main/main.c b/main/main.c index be289c8060839..f294b3b5ac63b 100644 --- a/main/main.c +++ b/main/main.c @@ -453,6 +453,23 @@ static PHP_INI_MH(OnChangeMailForceExtra) } /* }}} */ +/* {{{ PHP_INI_MH + */ +static PHP_INI_MH(OnChangeMagicMaximumCalls) +{ + int intval = atoi(new_value); + /* strict minimum of 2, otherwise "normal" non recursive magic function calls may fail */ + if (intval > 1) { + if (!entry->orig_value || intval <= atoi(entry->orig_value)) { + OnUpdateLong(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC); + return SUCCESS; + } + } + zend_error(E_WARNING, "max_magic_calls ini-value has to be equal or less than php.ini value and greater than 1"); + return FAILURE; +} +/* }}} */ + /* defined in browscap.c */ PHP_INI_MH(OnChangeBrowscap); @@ -509,6 +526,7 @@ PHP_INI_BEGIN() STD_PHP_INI_BOOLEAN("short_open_tag", DEFAULT_SHORT_OPEN_TAG, PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateBool, short_tags, zend_compiler_globals, compiler_globals) STD_PHP_INI_BOOLEAN("sql.safe_mode", "0", PHP_INI_SYSTEM, OnUpdateBool, sql_safe_mode, php_core_globals, core_globals) STD_PHP_INI_BOOLEAN("track_errors", "0", PHP_INI_ALL, OnUpdateBool, track_errors, php_core_globals, core_globals) + STD_PHP_INI_ENTRY("max_magic_calls", "100", PHP_INI_ALL, OnChangeMagicMaximumCalls, max_magic_calls, zend_executor_globals, executor_globals) STD_PHP_INI_ENTRY("unserialize_callback_func", NULL, PHP_INI_ALL, OnUpdateString, unserialize_callback_func, php_core_globals, core_globals) STD_PHP_INI_ENTRY("serialize_precision", "17", PHP_INI_ALL, OnUpdateLongGEZero, serialize_precision, php_core_globals, core_globals) diff --git a/php.ini-development b/php.ini-development index 4ff4192f6f84e..d7e4c47350a9b 100644 --- a/php.ini-development +++ b/php.ini-development @@ -383,6 +383,11 @@ expose_php = On ; Note: This directive is hardcoded to 0 for the CLI SAPI max_execution_time = 30 +; Maximum nesting level of magic functions +; http://php.net/max-magic-calls +; Note: If you set it too high, PHP may crash +;max_magic_calls = 100 + ; Maximum amount of time each script may spend parsing request data. It's a good ; idea to limit this time on productions servers in order to eliminate unexpectedly ; long running scripts. diff --git a/php.ini-production b/php.ini-production index 814455bbbbbfe..c4dae7a649893 100644 --- a/php.ini-production +++ b/php.ini-production @@ -383,6 +383,11 @@ expose_php = On ; Note: This directive is hardcoded to 0 for the CLI SAPI max_execution_time = 30 +; Maximum nesting level of magic functions +; http://php.net/max-magic-calls +; Note: If you set it too high, PHP may crash +;max_magic_calls = 100 + ; Maximum amount of time each script may spend parsing request data. It's a good ; idea to limit this time on productions servers in order to eliminate unexpectedly ; long running scripts. From 8689267c9965560603a2edaa4e5d592b7ad92dfe Mon Sep 17 00:00:00 2001 From: bwoebi Date: Mon, 25 Feb 2013 22:22:04 +0100 Subject: [PATCH 2/2] Changed ini-setting name to max_implicit_function_calls and set default value to 1000 --- Zend/tests/bug64280_1.phpt | 4 ++-- Zend/zend_execute_API.c | 6 +++--- Zend/zend_globals.h | 4 ++-- main/main.c | 6 +++--- php.ini-development | 6 +++--- php.ini-production | 6 +++--- 6 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Zend/tests/bug64280_1.phpt b/Zend/tests/bug64280_1.phpt index 80d5da9f77a27..81efb8c565f83 100644 --- a/Zend/tests/bug64280_1.phpt +++ b/Zend/tests/bug64280_1.phpt @@ -19,7 +19,7 @@ function f() { } f(); --EXPECTF-- -Warning: max_magic_calls ini-value has to be equal or less than php.ini value and greater than 1 in %s on line %d +Warning: max_implicit_function_calls ini-value has to be equal or less than php.ini value and greater than 1 in %s on line %d 1 2 3 @@ -31,4 +31,4 @@ Warning: max_magic_calls ini-value has to be equal or less than php.ini value an 9 10 -Fatal error: Magic method or function too often called recursively in %s on line %d +Fatal error: Method or function too often called recursively by implicit call in %s on line %d diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 55e853905ea84..8983fa4a5cee8 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -938,8 +938,8 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS EG(This) = NULL; } - if (EG(magic_call_count)++ >= EG(max_magic_calls)) { - zend_error_noreturn(E_ERROR, "Magic method or function too often called recursively"); + if (EG(implicit_fcall_count)++ >= EG(max_implicit_fcalls)) { + zend_error_noreturn(E_ERROR, "Method or function too often called recursively by implicit call"); } EX(prev_execute_data) = EG(current_execute_data); @@ -1026,7 +1026,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS EG(scope) = current_scope; EG(This) = current_this; EG(current_execute_data) = EX(prev_execute_data); - --EG(magic_call_count); + --EG(implicit_fcall_count); if (EG(exception)) { zend_throw_exception_internal(NULL TSRMLS_CC); diff --git a/Zend/zend_globals.h b/Zend/zend_globals.h index d2bd89217d878..b594d80730933 100644 --- a/Zend/zend_globals.h +++ b/Zend/zend_globals.h @@ -236,8 +236,8 @@ struct _zend_executor_globals { /* timeout support */ int timeout_seconds; - long magic_call_count; - long max_magic_calls; + long implicit_fcall_count; + long max_implicit_fcalls; int lambda_count; diff --git a/main/main.c b/main/main.c index f294b3b5ac63b..b156a4426dd14 100644 --- a/main/main.c +++ b/main/main.c @@ -455,7 +455,7 @@ static PHP_INI_MH(OnChangeMailForceExtra) /* {{{ PHP_INI_MH */ -static PHP_INI_MH(OnChangeMagicMaximumCalls) +static PHP_INI_MH(OnChangeMaxImplicitFcalls) { int intval = atoi(new_value); /* strict minimum of 2, otherwise "normal" non recursive magic function calls may fail */ @@ -465,7 +465,7 @@ static PHP_INI_MH(OnChangeMagicMaximumCalls) return SUCCESS; } } - zend_error(E_WARNING, "max_magic_calls ini-value has to be equal or less than php.ini value and greater than 1"); + zend_error(E_WARNING, "max_implicit_function_calls ini-value has to be equal or less than php.ini value and greater than 1"); return FAILURE; } /* }}} */ @@ -526,7 +526,7 @@ PHP_INI_BEGIN() STD_PHP_INI_BOOLEAN("short_open_tag", DEFAULT_SHORT_OPEN_TAG, PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateBool, short_tags, zend_compiler_globals, compiler_globals) STD_PHP_INI_BOOLEAN("sql.safe_mode", "0", PHP_INI_SYSTEM, OnUpdateBool, sql_safe_mode, php_core_globals, core_globals) STD_PHP_INI_BOOLEAN("track_errors", "0", PHP_INI_ALL, OnUpdateBool, track_errors, php_core_globals, core_globals) - STD_PHP_INI_ENTRY("max_magic_calls", "100", PHP_INI_ALL, OnChangeMagicMaximumCalls, max_magic_calls, zend_executor_globals, executor_globals) + STD_PHP_INI_ENTRY("max_implicit_function_calls", "1000", PHP_INI_ALL, OnChangeMaxImplicitFcalls, max_implicit_fcalls, zend_executor_globals, executor_globals) STD_PHP_INI_ENTRY("unserialize_callback_func", NULL, PHP_INI_ALL, OnUpdateString, unserialize_callback_func, php_core_globals, core_globals) STD_PHP_INI_ENTRY("serialize_precision", "17", PHP_INI_ALL, OnUpdateLongGEZero, serialize_precision, php_core_globals, core_globals) diff --git a/php.ini-development b/php.ini-development index d7e4c47350a9b..6ed6f727f3531 100644 --- a/php.ini-development +++ b/php.ini-development @@ -383,10 +383,10 @@ expose_php = On ; Note: This directive is hardcoded to 0 for the CLI SAPI max_execution_time = 30 -; Maximum nesting level of magic functions -; http://php.net/max-magic-calls +; Maximum nesting level of implicit function calls +; http://php.net/max-implicit-function-calls ; Note: If you set it too high, PHP may crash -;max_magic_calls = 100 +;max_implicit_function_calls = 1000 ; Maximum amount of time each script may spend parsing request data. It's a good ; idea to limit this time on productions servers in order to eliminate unexpectedly diff --git a/php.ini-production b/php.ini-production index c4dae7a649893..ffe7de025ec16 100644 --- a/php.ini-production +++ b/php.ini-production @@ -383,10 +383,10 @@ expose_php = On ; Note: This directive is hardcoded to 0 for the CLI SAPI max_execution_time = 30 -; Maximum nesting level of magic functions -; http://php.net/max-magic-calls +; Maximum nesting level of implicit function calls +; http://php.net/max-implicit-function-calls ; Note: If you set it too high, PHP may crash -;max_magic_calls = 100 +;max_implicit_function_calls = 1000 ; Maximum amount of time each script may spend parsing request data. It's a good ; idea to limit this time on productions servers in order to eliminate unexpectedly