Skip to content

Commit e81751c

Browse files
committed
Fixed bug #78502
We need to make sure that the function is fully compiled before we calculate the stack size. There already was a check for directly recursive calls, but the same issue exists with indirectly recursive calls. I'm using DONE_PASS_TWO as the indication that the function is fully compiled.
1 parent df35d5c commit e81751c

File tree

2 files changed

+40
-8
lines changed

2 files changed

+40
-8
lines changed

Zend/tests/bug78502.phpt

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
--TEST--
2+
Bug #78502: Incorrect stack size calculation for indirectly recursive function call
3+
--FILE--
4+
<?php
5+
6+
$tree = [
7+
'name' => 'a',
8+
'quant' => 1,
9+
'children' => [
10+
['name' => 'b', 'quant' => 1],
11+
['name' => 'c', 'quant' => 1, 'children' => [
12+
['name' => 'd', 'quant' => 1],
13+
]],
14+
],
15+
];
16+
17+
function tree_map($tree, $recursive_attr, closure $callback){
18+
if(isset($tree[$recursive_attr])){
19+
$tree[$recursive_attr] = array_map(function($c) use($recursive_attr, $callback){
20+
return tree_map($c, $recursive_attr, $callback);
21+
}, $tree[$recursive_attr]);
22+
}
23+
return $callback($tree);
24+
}
25+
26+
tree_map($tree, 'children', function ($node) {});
27+
28+
?>
29+
===DONE===
30+
--EXPECT--
31+
===DONE===

Zend/zend_compile.c

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3321,6 +3321,12 @@ int zend_compile_func_ord(znode *result, zend_ast_list *args) /* {{{ */
33213321
}
33223322
/* }}} */
33233323

3324+
/* We can only calculate the stack size for functions that have been fully compiled, otherwise
3325+
* additional CV or TMP slots may still be added. This prevents the use of INIT_FCALL for
3326+
* directly or indirectly recursive function calls. */
3327+
static zend_bool fbc_is_finalized(zend_function *fbc) {
3328+
return !ZEND_USER_CODE(fbc->type) || (fbc->common.fn_flags & ZEND_ACC_DONE_PASS_TWO);
3329+
}
33243330

33253331
static int zend_try_compile_ct_bound_init_user_func(zend_ast *name_ast, uint32_t num_args) /* {{{ */
33263332
{
@@ -3336,9 +3342,7 @@ static int zend_try_compile_ct_bound_init_user_func(zend_ast *name_ast, uint32_t
33363342
lcname = zend_string_tolower(name);
33373343

33383344
fbc = zend_hash_find_ptr(CG(function_table), lcname);
3339-
if (!fbc
3340-
/* Don't use INIT_FCALL for recursive calls */
3341-
|| (fbc == (zend_function*)CG(active_op_array))
3345+
if (!fbc || !fbc_is_finalized(fbc)
33423346
|| (fbc->type == ZEND_INTERNAL_FUNCTION && (CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS))
33433347
|| (fbc->type == ZEND_USER_FUNCTION && (CG(compiler_options) & ZEND_COMPILE_IGNORE_USER_FUNCTIONS))
33443348
|| (fbc->type == ZEND_USER_FUNCTION && (CG(compiler_options) & ZEND_COMPILE_IGNORE_OTHER_FILES) && fbc->op_array.filename != CG(active_op_array)->filename)
@@ -3461,8 +3465,7 @@ static void zend_compile_assert(znode *result, zend_ast_list *args, zend_string
34613465

34623466
zend_emit_op(NULL, ZEND_ASSERT_CHECK, NULL, NULL);
34633467

3464-
/* Don't use INIT_FCALL for recursive calls */
3465-
if (fbc && fbc != (zend_function*)CG(active_op_array)) {
3468+
if (fbc && fbc_is_finalized(fbc)) {
34663469
name_node.op_type = IS_CONST;
34673470
ZVAL_STR_COPY(&name_node.u.constant, name);
34683471

@@ -3838,9 +3841,7 @@ void zend_compile_call(znode *result, zend_ast *ast, uint32_t type) /* {{{ */
38383841
return;
38393842
}
38403843

3841-
if (!fbc
3842-
/* Don't use INIT_FCALL for recursive calls */
3843-
|| (fbc == (zend_function*)CG(active_op_array))
3844+
if (!fbc || !fbc_is_finalized(fbc)
38443845
|| (fbc->type == ZEND_INTERNAL_FUNCTION && (CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS))
38453846
|| (fbc->type == ZEND_USER_FUNCTION && (CG(compiler_options) & ZEND_COMPILE_IGNORE_USER_FUNCTIONS))
38463847
|| (fbc->type == ZEND_USER_FUNCTION && (CG(compiler_options) & ZEND_COMPILE_IGNORE_OTHER_FILES) && fbc->op_array.filename != CG(active_op_array)->filename)

0 commit comments

Comments
 (0)