Skip to content

Commit a9fb8ce

Browse files
committed
wip
1 parent dea69c3 commit a9fb8ce

File tree

8 files changed

+3113
-13
lines changed

8 files changed

+3113
-13
lines changed

Zend/Optimizer/zend_func_info.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,7 @@ static uint32_t zend_range_info(const zend_call_info *call_info, const zend_ssa
7777
}
7878
if ((t1 & ((MAY_BE_ANY|MAY_BE_UNDEF)-MAY_BE_DOUBLE))
7979
&& (t2 & ((MAY_BE_ANY|MAY_BE_UNDEF)-MAY_BE_DOUBLE))) {
80-
if ((t3 & MAY_BE_ANY) != MAY_BE_DOUBLE) {
81-
tmp |= MAY_BE_ARRAY_OF_LONG;
82-
}
80+
tmp |= MAY_BE_ARRAY_OF_LONG;
8381
}
8482
if (tmp & MAY_BE_ARRAY_OF_ANY) {
8583
tmp |= MAY_BE_ARRAY_PACKED;

Zend/Optimizer/zend_optimizer.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1332,6 +1332,26 @@ static void zend_redo_pass_two_ex(zend_op_array *op_array, zend_ssa *ssa)
13321332
}
13331333
break;
13341334
}
1335+
#ifdef ZEND_VERIFY_TYPE_INFERENCE
1336+
if (ssa_op->op1_use >= 0) {
1337+
opline->op1_use_type = ssa->var_info[ssa_op->op1_use].type;
1338+
}
1339+
if (ssa_op->op2_use >= 0) {
1340+
opline->op2_use_type = ssa->var_info[ssa_op->op2_use].type;
1341+
}
1342+
if (ssa_op->result_use >= 0) {
1343+
opline->result_use_type = ssa->var_info[ssa_op->result_use].type;
1344+
}
1345+
if (ssa_op->op1_def >= 0) {
1346+
opline->op1_def_type = ssa->var_info[ssa_op->op1_def].type;
1347+
}
1348+
if (ssa_op->op2_def >= 0) {
1349+
opline->op2_def_type = ssa->var_info[ssa_op->op2_def].type;
1350+
}
1351+
if (ssa_op->result_def >= 0) {
1352+
opline->result_def_type = ssa->var_info[ssa_op->result_def].type;
1353+
}
1354+
#endif
13351355
zend_vm_set_opcode_handler_ex(opline, op1_info, op2_info, res_info);
13361356
opline++;
13371357
}

Zend/tests/gh10168/wrong_assign_to_variable.phpt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
--TEST--
22
GH-10168: Wrong assign to variable
3+
--SKIPIF--
4+
<?php
5+
if (defined('ZEND_VERIFY_TYPE_INFERENCE')) die('skip Destructor side-effects violate type inference');
6+
?>
37
--FILE--
48
<?php
59

Zend/zend_execute.c

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5439,31 +5439,53 @@ static void zend_verify_inference_def(zend_execute_data *execute_data, const zen
54395439
zend_verify_type_inference(EX_VAR(opline->op1.var), opline->op1_def_type, opline->op1_type, execute_data, opline, "op1_def");
54405440
}
54415441
if (opline->op2_def_type
5442-
&& (opline->op2_type & (IS_TMP_VAR|IS_VAR|IS_CV))) {
5442+
&& (opline->op2_type & (IS_TMP_VAR|IS_VAR|IS_CV))
5443+
/* ZEND_FE_FETCH_R[W] does not define a result in the last iteration. */
5444+
&& opline->opcode != ZEND_FE_FETCH_R
5445+
&& opline->opcode != ZEND_FE_FETCH_RW) {
54435446
zend_verify_type_inference(EX_VAR(opline->op2.var), opline->op2_def_type, opline->op2_type, execute_data, opline, "op2_def");
54445447
}
54455448
if (opline->result_def_type
54465449
&& (opline->result_type & (IS_TMP_VAR|IS_VAR|IS_CV))
54475450
&& opline->opcode != ZEND_ROPE_INIT
54485451
&& opline->opcode != ZEND_ROPE_ADD
5449-
// Some jump opcode handlers don't set result when it's never read
5452+
/* Some jump opcode handlers don't set result when it's never read. */
54505453
&& opline->opcode != ZEND_JMP_SET
54515454
&& opline->opcode != ZEND_JMP_NULL
54525455
&& opline->opcode != ZEND_COALESCE
5453-
&& opline->opcode != ZEND_ASSERT_CHECK) {
5456+
&& opline->opcode != ZEND_ASSERT_CHECK
5457+
/* Smart branches may not declare result. */
5458+
&& !zend_is_smart_branch(opline)
5459+
/* Calls only initialize result when returning from the called function. */
5460+
&& opline->opcode != ZEND_DO_FCALL
5461+
&& opline->opcode != ZEND_DO_ICALL
5462+
&& opline->opcode != ZEND_DO_UCALL
5463+
&& opline->opcode != ZEND_DO_FCALL_BY_NAME
5464+
/* ZEND_FE_FETCH_R[W] does not define a result in the last iteration. */
5465+
&& opline->opcode != ZEND_FE_FETCH_R
5466+
&& opline->opcode != ZEND_FE_FETCH_RW) {
54545467
zend_verify_type_inference(EX_VAR(opline->result.var), opline->result_def_type, opline->result_type, execute_data, opline, "result_def");
5468+
5469+
/* Verify return value in the context of caller. */
5470+
if ((opline->opcode == ZEND_RETURN || opline->opcode == ZEND_RETURN_BY_REF)
5471+
&& execute_data->prev_execute_data
5472+
&& execute_data->prev_execute_data->func
5473+
&& ZEND_USER_CODE(execute_data->prev_execute_data->func->type)) {
5474+
zend_execute_data *prev_execute_data = execute_data->prev_execute_data;
5475+
const zend_op *opline = execute_data->prev_execute_data->opline;
5476+
zend_verify_type_inference(ZEND_CALL_VAR(prev_execute_data, opline->result.var), opline->result_def_type, opline->result_type, prev_execute_data, opline, "result_def");
5477+
}
54555478
}
54565479
}
54575480

54585481
# define ZEND_VERIFY_INFERENCE_USE() zend_verify_inference_use(execute_data, OPLINE);
5459-
# define ZEND_VERIFY_INFERENCE_DEF() zend_verify_inference_def(execute_data, OPLINE);
5482+
# define ZEND_VERIFY_INFERENCE_DEF(execute_data, opline) zend_verify_inference_def(execute_data, opline);
54605483
#else
54615484
# define ZEND_VERIFY_INFERENCE_USE()
54625485
# define ZEND_VERIFY_INFERENCE_DEF()
54635486
#endif
54645487

54655488
#define ZEND_VM_NEXT_OPCODE_EX(check_exception, skip) \
5466-
ZEND_VERIFY_INFERENCE_DEF() \
54675489
CHECK_SYMBOL_TABLES() \
54685490
if (check_exception) { \
54695491
OPLINE = EX(opline) + (skip); \

0 commit comments

Comments
 (0)