Skip to content

Commit d8c2ff6

Browse files
committed
Fix type inference and SCCP with typed references
We can't assume that the return value will be the same as the RHS if typed references are involved.
1 parent 0391c55 commit d8c2ff6

File tree

3 files changed

+28
-4
lines changed

3 files changed

+28
-4
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
--TEST--
2+
Result of assigning to typed reference
3+
--FILE--
4+
<?php
5+
6+
class Test {
7+
public ?string $prop;
8+
}
9+
function test() {
10+
$obj = new Test;
11+
$ref =& $obj->prop;
12+
var_dump($ref = 0);
13+
}
14+
test();
15+
16+
?>
17+
--EXPECT--
18+
string(1) "0"

ext/opcache/Optimizer/sccp.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1013,14 +1013,15 @@ static void sccp_visit_instr(scdf_ctx *scdf, zend_op *opline, zend_ssa_op *ssa_o
10131013
switch (opline->opcode) {
10141014
case ZEND_ASSIGN:
10151015
/* The value of op1 is irrelevant here, because we are overwriting it
1016-
* -- unless it can be a reference, in which case we propagate a BOT. */
1016+
* -- unless it can be a reference, in which case we propagate a BOT.
1017+
* The result is also BOT in this case, because it might be a typed reference. */
10171018
if (IS_BOT(op1) && (ctx->scdf.ssa->var_info[ssa_op->op1_use].type & MAY_BE_REF)) {
10181019
SET_RESULT_BOT(op1);
1020+
SET_RESULT_BOT(result);
10191021
} else {
10201022
SET_RESULT(op1, op2);
1023+
SET_RESULT(result, op2);
10211024
}
1022-
1023-
SET_RESULT(result, op2);
10241025
return;
10251026
case ZEND_TYPE_CHECK:
10261027
/* We may be able to evaluate TYPE_CHECK based on type inference info,

ext/opcache/Optimizer/zend_inference.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2879,7 +2879,12 @@ static zend_always_inline int _zend_update_type_info(
28792879
COPY_SSA_OBJ_TYPE(ssa_op->op2_use, ssa_op->op1_def);
28802880
}
28812881
if (ssa_op->result_def >= 0) {
2882-
UPDATE_SSA_TYPE(tmp & ~MAY_BE_REF, ssa_op->result_def);
2882+
if (tmp & MAY_BE_REF) {
2883+
/* Assignment to typed reference may change type.
2884+
* Be conservative and don't assume anything. */
2885+
tmp = MAY_BE_RC1|MAY_BE_RCN|MAY_BE_ANY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF;
2886+
}
2887+
UPDATE_SSA_TYPE(tmp, ssa_op->result_def);
28832888
COPY_SSA_OBJ_TYPE(ssa_op->op2_use, ssa_op->result_def);
28842889
}
28852890
break;

0 commit comments

Comments
 (0)