]> granicus.if.org Git - php/commitdiff
Handle NULL caller_call_opline
authorNikita Popov <nikita.ppv@gmail.com>
Mon, 23 Mar 2020 16:10:54 +0000 (17:10 +0100)
committerNikita Popov <nikita.ppv@gmail.com>
Mon, 23 Mar 2020 16:12:01 +0000 (17:12 +0100)
This can happen if there is an EXIT in the call arguments, in which
case the DO_CALL opcode may be eliminated as unreachable.

ext/opcache/Optimizer/dfa_pass.c
ext/opcache/Optimizer/sccp.c
ext/opcache/Optimizer/zend_call_graph.c
ext/opcache/Optimizer/zend_inference.c

index 3bff500de19fd32b9e971839a1f6ccb3cedc5a63..01baadd1e7311fd3004dd33f3e6cf6469e8aaca2 100644 (file)
@@ -301,8 +301,10 @@ static void zend_ssa_remove_nops(zend_op_array *op_array, zend_ssa *ssa, zend_op
                        while (call_info) {
                                call_info->caller_init_opline -=
                                        shiftlist[call_info->caller_init_opline - op_array->opcodes];
-                               call_info->caller_call_opline -=
-                                       shiftlist[call_info->caller_call_opline - op_array->opcodes];
+                               if (call_info->caller_call_opline) {
+                                       call_info->caller_call_opline -=
+                                               shiftlist[call_info->caller_call_opline - op_array->opcodes];
+                               }
                                call_info = call_info->next_callee;
                        }
                }
@@ -388,7 +390,8 @@ int zend_dfa_optimize_calls(zend_op_array *op_array, zend_ssa *ssa)
                zend_call_info *call_info = func_info->callee_info;
 
                do {
-                       if (call_info->caller_call_opline->opcode == ZEND_DO_ICALL
+                       if (call_info->caller_call_opline
+                        && call_info->caller_call_opline->opcode == ZEND_DO_ICALL
                         && call_info->callee_func
                         && ZSTR_LEN(call_info->callee_func->common.function_name) == sizeof("in_array")-1
                         && memcmp(ZSTR_VAL(call_info->callee_func->common.function_name), "in_array", sizeof("in_array")-1) == 0
index 1ec3a5153241d9b7fce572de60d597bc6034be16..53549a620809f3eccf1145a2c45bd442b1037ec2 100644 (file)
@@ -1251,7 +1251,8 @@ static void sccp_visit_instr(scdf_ctx *scdf, zend_op *opline, zend_ssa_op *ssa_o
                        }
 
                        call = ctx->call_map[opline - ctx->scdf.op_array->opcodes];
-                       if (IS_TOP(op1) || !call || call->caller_call_opline->opcode != ZEND_DO_ICALL) {
+                       if (IS_TOP(op1) || !call || !call->caller_call_opline
+                                       || call->caller_call_opline->opcode != ZEND_DO_ICALL) {
                                return;
                        }
 
index 4dde2982804119ecf72c827b8189b88e0b2a4ed8..109fc723535ed84037efca12f4343ba7dd1bd96f 100644 (file)
@@ -171,6 +171,10 @@ int zend_analyze_calls(zend_arena **arena, zend_script *script, uint32_t build_f
                                        call_info->num_args = -1;
                                }
                                break;
+                       case ZEND_EXIT:
+                               /* In this case the DO_CALL opcode may have been dropped
+                                * and caller_call_opline will be NULL. */
+                               break;
                }
                opline++;
        }
@@ -280,7 +284,9 @@ zend_call_info **zend_build_call_map(zend_arena **arena, zend_func_info *info, z
        for (call = info->callee_info; call; call = call->next_callee) {
                int i;
                map[call->caller_init_opline - op_array->opcodes] = call;
-               map[call->caller_call_opline - op_array->opcodes] = call;
+               if (call->caller_call_opline) {
+                       map[call->caller_call_opline - op_array->opcodes] = call;
+               }
                for (i = 0; i < call->num_args; i++) {
                        if (call->arg_info[i].opline) {
                                map[call->arg_info[i].opline - op_array->opcodes] = call;
index 7bddb827052c19d7368f4489f5bab2770e0dd998..a60ecef888d7a940bb6429b79f3142d47a6196a8 100644 (file)
@@ -4145,7 +4145,7 @@ void zend_inference_check_recursive_dependencies(zend_op_array *op_array)
        memset(worklist, 0, sizeof(zend_ulong) * worklist_len);
        call_info = info->callee_info;
        while (call_info) {
-               if (call_info->recursive &&
+               if (call_info->recursive && call_info->caller_call_opline &&
                    info->ssa.ops[call_info->caller_call_opline - op_array->opcodes].result_def >= 0) {
                        zend_bitset_incl(worklist, info->ssa.ops[call_info->caller_call_opline - op_array->opcodes].result_def);
                }