Skip to content

Commit 34f1266

Browse files
committed
Handle NULL caller_call_opline
This can happen if there is an EXIT in the call arguments, in which case the DO_CALL opcode may be eliminated as unreachable.
1 parent ba404f2 commit 34f1266

File tree

4 files changed

+16
-6
lines changed

4 files changed

+16
-6
lines changed

ext/opcache/Optimizer/dfa_pass.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -301,8 +301,10 @@ static void zend_ssa_remove_nops(zend_op_array *op_array, zend_ssa *ssa, zend_op
301301
while (call_info) {
302302
call_info->caller_init_opline -=
303303
shiftlist[call_info->caller_init_opline - op_array->opcodes];
304-
call_info->caller_call_opline -=
305-
shiftlist[call_info->caller_call_opline - op_array->opcodes];
304+
if (call_info->caller_call_opline) {
305+
call_info->caller_call_opline -=
306+
shiftlist[call_info->caller_call_opline - op_array->opcodes];
307+
}
306308
call_info = call_info->next_callee;
307309
}
308310
}
@@ -388,7 +390,8 @@ int zend_dfa_optimize_calls(zend_op_array *op_array, zend_ssa *ssa)
388390
zend_call_info *call_info = func_info->callee_info;
389391

390392
do {
391-
if (call_info->caller_call_opline->opcode == ZEND_DO_ICALL
393+
if (call_info->caller_call_opline
394+
&& call_info->caller_call_opline->opcode == ZEND_DO_ICALL
392395
&& call_info->callee_func
393396
&& ZSTR_LEN(call_info->callee_func->common.function_name) == sizeof("in_array")-1
394397
&& memcmp(ZSTR_VAL(call_info->callee_func->common.function_name), "in_array", sizeof("in_array")-1) == 0

ext/opcache/Optimizer/sccp.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1251,7 +1251,8 @@ static void sccp_visit_instr(scdf_ctx *scdf, zend_op *opline, zend_ssa_op *ssa_o
12511251
}
12521252

12531253
call = ctx->call_map[opline - ctx->scdf.op_array->opcodes];
1254-
if (IS_TOP(op1) || !call || call->caller_call_opline->opcode != ZEND_DO_ICALL) {
1254+
if (IS_TOP(op1) || !call || !call->caller_call_opline
1255+
|| call->caller_call_opline->opcode != ZEND_DO_ICALL) {
12551256
return;
12561257
}
12571258

ext/opcache/Optimizer/zend_call_graph.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,10 @@ int zend_analyze_calls(zend_arena **arena, zend_script *script, uint32_t build_f
171171
call_info->num_args = -1;
172172
}
173173
break;
174+
case ZEND_EXIT:
175+
/* In this case the DO_CALL opcode may have been dropped
176+
* and caller_call_opline will be NULL. */
177+
break;
174178
}
175179
opline++;
176180
}
@@ -280,7 +284,9 @@ zend_call_info **zend_build_call_map(zend_arena **arena, zend_func_info *info, z
280284
for (call = info->callee_info; call; call = call->next_callee) {
281285
int i;
282286
map[call->caller_init_opline - op_array->opcodes] = call;
283-
map[call->caller_call_opline - op_array->opcodes] = call;
287+
if (call->caller_call_opline) {
288+
map[call->caller_call_opline - op_array->opcodes] = call;
289+
}
284290
for (i = 0; i < call->num_args; i++) {
285291
if (call->arg_info[i].opline) {
286292
map[call->arg_info[i].opline - op_array->opcodes] = call;

ext/opcache/Optimizer/zend_inference.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4145,7 +4145,7 @@ void zend_inference_check_recursive_dependencies(zend_op_array *op_array)
41454145
memset(worklist, 0, sizeof(zend_ulong) * worklist_len);
41464146
call_info = info->callee_info;
41474147
while (call_info) {
4148-
if (call_info->recursive &&
4148+
if (call_info->recursive && call_info->caller_call_opline &&
41494149
info->ssa.ops[call_info->caller_call_opline - op_array->opcodes].result_def >= 0) {
41504150
zend_bitset_incl(worklist, info->ssa.ops[call_info->caller_call_opline - op_array->opcodes].result_def);
41514151
}

0 commit comments

Comments
 (0)