diff --git a/Zend/Optimizer/sccp.c b/Zend/Optimizer/sccp.c index 30fafe00791..94dfd4c3177 100644 --- a/Zend/Optimizer/sccp.c +++ b/Zend/Optimizer/sccp.c @@ -992,14 +992,15 @@ static void sccp_visit_instr(scdf_ctx *scdf, zend_op *opline, zend_ssa_op *ssa_o switch (opline->opcode) { case ZEND_ASSIGN: /* The value of op1 is irrelevant here, because we are overwriting it - * -- unless it can be a reference, in which case we propagate a BOT. */ + * -- unless it can be a reference, in which case we propagate a BOT. + * The result is also BOT in this case, because it might be a typed reference. */ if (IS_BOT(op1) && (ctx->scdf.ssa->var_info[ssa_op->op1_use].type & MAY_BE_REF)) { SET_RESULT_BOT(op1); + SET_RESULT_BOT(result); } else { SET_RESULT(op1, op2); + SET_RESULT(result, op2); } - - SET_RESULT(result, op2); return; case ZEND_TYPE_CHECK: /* We may be able to evaluate TYPE_CHECK based on type inference info, diff --git a/Zend/Optimizer/zend_inference.c b/Zend/Optimizer/zend_inference.c index 2418f19333f..e5a16f25690 100644 --- a/Zend/Optimizer/zend_inference.c +++ b/Zend/Optimizer/zend_inference.c @@ -2916,7 +2916,12 @@ static zend_always_inline int _zend_update_type_info( COPY_SSA_OBJ_TYPE(ssa_op->op2_use, ssa_op->op1_def); } if (ssa_op->result_def >= 0) { - UPDATE_SSA_TYPE(tmp & ~MAY_BE_REF, ssa_op->result_def); + if (tmp & MAY_BE_REF) { + /* Assignment to typed reference may change type. + * Be conservative and don't assume anything. */ + 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; + } + UPDATE_SSA_TYPE(tmp, ssa_op->result_def); COPY_SSA_OBJ_TYPE(ssa_op->op2_use, ssa_op->result_def); } break; diff --git a/Zend/tests/assign_typed_ref_result.phpt b/Zend/tests/assign_typed_ref_result.phpt new file mode 100644 index 00000000000..9075db50376 --- /dev/null +++ b/Zend/tests/assign_typed_ref_result.phpt @@ -0,0 +1,18 @@ +--TEST-- +Result of assigning to typed reference +--FILE-- +prop; + var_dump($ref = 0); +} +test(); + +?> +--EXPECT-- +string(1) "0"