Skip to content

Commit dc56f73

Browse files
committed
PHP 8.4: Support for opcode-less exit
Copied over from the Xdebug implementation. Fixes #83: minimal fix for 8.4.0beta3
1 parent df1c52c commit dc56f73

File tree

1 file changed

+48
-2
lines changed

1 file changed

+48
-2
lines changed

srm_oparray.c

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1108,15 +1108,17 @@ int vld_find_jumps(zend_op_array *opa, unsigned int position, size_t *jump_count
11081108

11091109
#if PHP_VERSION_ID >= 80400
11101110
} else if (opcode.opcode == ZEND_JMP_FRAMELESS) {
1111-
jumps[0] = VLD_ZNODE_JMP_LINE(opcode.op2, position, base_address);
1112-
jumps[1] = position + 1;
1111+
jumps[0] = position + 1;
1112+
jumps[1] = VLD_ZNODE_JMP_LINE(opcode.op2, position, base_address);
11131113
*jump_count = 2;
11141114
return 1;
11151115
#endif
11161116

11171117
} else if (
11181118
opcode.opcode == ZEND_GENERATOR_RETURN ||
1119+
#if PHP_VERSION_ID < 80400
11191120
opcode.opcode == ZEND_EXIT ||
1121+
#endif
11201122
opcode.opcode == ZEND_THROW ||
11211123
#if PHP_VERSION_ID >= 80000
11221124
opcode.opcode == ZEND_MATCH_ERROR ||
@@ -1126,6 +1128,48 @@ int vld_find_jumps(zend_op_array *opa, unsigned int position, size_t *jump_count
11261128
jumps[0] = VLD_JMP_EXIT;
11271129
*jump_count = 1;
11281130
return 1;
1131+
} else if (
1132+
opcode.opcode == ZEND_INIT_FCALL
1133+
) {
1134+
zval *func_name = RT_CONSTANT(&opa->opcodes[position], opcode.op2);
1135+
if (zend_string_equals_literal(Z_PTR_P(func_name), "exit")) {
1136+
int level = 0;
1137+
uint32_t start = position + 1;
1138+
1139+
for (;;) {
1140+
switch (opa->opcodes[start].opcode) {
1141+
case ZEND_INIT_FCALL:
1142+
case ZEND_INIT_FCALL_BY_NAME:
1143+
case ZEND_INIT_NS_FCALL_BY_NAME:
1144+
case ZEND_INIT_DYNAMIC_CALL:
1145+
case ZEND_INIT_USER_CALL:
1146+
case ZEND_INIT_METHOD_CALL:
1147+
case ZEND_INIT_STATIC_METHOD_CALL:
1148+
#if PHP_VERSION_ID >= 80400
1149+
case ZEND_INIT_PARENT_PROPERTY_HOOK_CALL:
1150+
#endif
1151+
case ZEND_NEW:
1152+
level++;
1153+
break;
1154+
case ZEND_DO_FCALL:
1155+
case ZEND_DO_FCALL_BY_NAME:
1156+
case ZEND_DO_ICALL:
1157+
case ZEND_DO_UCALL:
1158+
if (level == 0) {
1159+
goto done;
1160+
}
1161+
level--;
1162+
break;
1163+
}
1164+
start++;
1165+
}
1166+
done:
1167+
ZEND_ASSERT(opa->opcodes[start].opcode == ZEND_DO_ICALL);
1168+
jumps[0] = VLD_JMP_EXIT;
1169+
*jump_count = 1;
1170+
return 1;
1171+
}
1172+
11291173
#if PHP_VERSION_ID >= 70200
11301174
} else if (
11311175
# if PHP_VERSION_ID >= 80000
@@ -1265,13 +1309,15 @@ void vld_analyse_branch(zend_op_array *opa, unsigned int position, vld_set *set,
12651309
break;
12661310
}
12671311

1312+
#if PHP_VERSION_ID < 80400
12681313
/* See if we have an exit instruction */
12691314
if (opa->opcodes[position].opcode == ZEND_EXIT) {
12701315
VLD_PRINT(1, "Exit found\n");
12711316
vld_set_add(branch_info->ends, position);
12721317
branch_info->branches[position].start_lineno = opa->opcodes[position].lineno;
12731318
break;
12741319
}
1320+
#endif
12751321
/* See if we have a return instruction */
12761322
if (
12771323
opa->opcodes[position].opcode == ZEND_RETURN

0 commit comments

Comments
 (0)