Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed bug #64280 #290

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions Zend/tests/bug64280.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
--TEST--
Bug #64280 (__destruct loop segfaults) - Basic behaviour
--FILE--
<?php
class getDestructed {
public function __destruct() {
new self;
}
}
$class = new getDestructed;
?>
--EXPECTF--
Fatal error: Magic method or function too often called recursively in %s on line %d
34 changes: 34 additions & 0 deletions Zend/tests/bug64280_1.phpt
Original file line number Diff line number Diff line change
@@ -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--
<?php
ini_set("max_magic_calls", 30);
ini_set("max_magic_calls", 10);
class getStringed {
public function __toString() {
global $count;
echo ++$count,"\n";
f();
}
}
function f() {
$class = new getStringed;
print $class;
}
f();
--EXPECTF--
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
4
5
6
7
8
9
10

Fatal error: Method or function too often called recursively by implicit call in %s on line %d
5 changes: 5 additions & 0 deletions Zend/zend_execute_API.c
Original file line number Diff line number Diff line change
Expand Up @@ -938,6 +938,10 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
EG(This) = NULL;
}

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);
EG(current_execute_data) = &execute_data;

Expand Down Expand Up @@ -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(implicit_fcall_count);

if (EG(exception)) {
zend_throw_exception_internal(NULL TSRMLS_CC);
Expand Down
11 changes: 7 additions & 4 deletions Zend/zend_globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 |
Expand Down Expand Up @@ -236,11 +236,14 @@ struct _zend_executor_globals {
/* timeout support */
int timeout_seconds;

long implicit_fcall_count;
long max_implicit_fcalls;

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;
Expand All @@ -253,7 +256,7 @@ struct _zend_executor_globals {

zend_property_info std_property_info;

zend_bool active;
zend_bool active;

zend_op *start_op;

Expand Down Expand Up @@ -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;
Expand Down
18 changes: 18 additions & 0 deletions main/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,23 @@ static PHP_INI_MH(OnChangeMailForceExtra)
}
/* }}} */

/* {{{ PHP_INI_MH
*/
static PHP_INI_MH(OnChangeMaxImplicitFcalls)
{
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_implicit_function_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);

Expand Down Expand Up @@ -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_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)
Expand Down
5 changes: 5 additions & 0 deletions php.ini-development
Original file line number Diff line number Diff line change
Expand Up @@ -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 implicit function calls
; http://php.net/max-implicit-function-calls
; Note: If you set it too high, PHP may crash
;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
; long running scripts.
Expand Down
5 changes: 5 additions & 0 deletions php.ini-production
Original file line number Diff line number Diff line change
Expand Up @@ -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 implicit function calls
; http://php.net/max-implicit-function-calls
; Note: If you set it too high, PHP may crash
;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
; long running scripts.
Expand Down