diff options
author | Nikita Popov <nikita.ppv@gmail.com> | 2021-03-18 15:40:48 +0100 |
---|---|---|
committer | Nikita Popov <nikita.ppv@gmail.com> | 2021-03-19 10:49:15 +0100 |
commit | 2d0e2733c8a0010df9f45693d536531a7a725bdf (patch) | |
tree | 715b953768f04d3240c57b14bd8d9c5218af4ada /Zend/Optimizer/zend_call_graph.c | |
parent | 6689bedd1796380f882fdecc6dcf8da1ff885c2b (diff) | |
download | php-git-2d0e2733c8a0010df9f45693d536531a7a725bdf.tar.gz |
Support prototypes in call graph
Even if we don't know the exact method being called, include it
in the call graph with the is_prototype flag. In particular, we
can still make use of return types from prototype methods, as
PHP 8 makes LSP violations a hard error.
Most other places are adjusted to skip calls with !is_prototype.
Maybe some of them would be fine, but ignoring them is conservative.
Diffstat (limited to 'Zend/Optimizer/zend_call_graph.c')
-rw-r--r-- | Zend/Optimizer/zend_call_graph.c | 11 |
1 files changed, 7 insertions, 4 deletions
diff --git a/Zend/Optimizer/zend_call_graph.c b/Zend/Optimizer/zend_call_graph.c index b0f3247cd7..fb24a8d40f 100644 --- a/Zend/Optimizer/zend_call_graph.c +++ b/Zend/Optimizer/zend_call_graph.c @@ -65,8 +65,7 @@ ZEND_API int zend_analyze_calls(zend_arena **arena, zend_script *script, uint32_ call_stack[call] = call_info; func = zend_optimizer_get_called_func( script, op_array, opline, &is_prototype); - /* TODO: Support prototypes? */ - if (func && !is_prototype) { + if (func) { call_info = zend_arena_calloc(arena, 1, sizeof(zend_call_info) + (sizeof(zend_send_arg_info) * ((int)opline->extended_value - 1))); call_info->caller_op_array = op_array; call_info->caller_init_opline = opline; @@ -74,6 +73,7 @@ ZEND_API int zend_analyze_calls(zend_arena **arena, zend_script *script, uint32_ call_info->callee_func = func; call_info->num_args = opline->extended_value; call_info->next_callee = func_info->callee_info; + call_info->is_prototype = is_prototype; func_info->callee_info = call_info; if (build_flags & ZEND_CALL_TREE) { @@ -194,7 +194,11 @@ static void zend_analyze_recursion(zend_call_graph *call_graph) op_array = call_graph->op_arrays[i]; func_info = call_graph->func_infos + i; call_info = func_info->caller_info; - while (call_info) { + for (; call_info; call_info = call_info->next_caller) { + if (call_info->is_prototype) { + /* Might be calling an overridden child method and not actually recursive. */ + continue; + } if (call_info->caller_op_array == op_array) { call_info->recursive = 1; func_info->flags |= ZEND_FUNC_RECURSIVE | ZEND_FUNC_RECURSIVE_DIRECTLY; @@ -205,7 +209,6 @@ static void zend_analyze_recursion(zend_call_graph *call_graph) func_info->flags |= ZEND_FUNC_RECURSIVE | ZEND_FUNC_RECURSIVE_INDIRECTLY; } } - call_info = call_info->next_caller; } } |