From d8c2ff6486d178becbb71b774df8d7072e406fcf Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Tue, 28 Sep 2021 12:58:14 +0200 Subject: [PATCH] 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. --- Zend/tests/assign_typed_ref_result.phpt | 18 ++++++++++++++++++ ext/opcache/Optimizer/sccp.c | 7 ++++--- ext/opcache/Optimizer/zend_inference.c | 7 ++++++- 3 files changed, 28 insertions(+), 4 deletions(-) create mode 100644 Zend/tests/assign_typed_ref_result.phpt 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" diff --git a/ext/opcache/Optimizer/sccp.c b/ext/opcache/Optimizer/sccp.c index 361f56e8c2d..8c68099ec30 100644 --- a/ext/opcache/Optimizer/sccp.c +++ b/ext/opcache/Optimizer/sccp.c @@ -1013,14 +1013,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/ext/opcache/Optimizer/zend_inference.c b/ext/opcache/Optimizer/zend_inference.c index a224ce605ca..e005c8852cd 100644 --- a/ext/opcache/Optimizer/zend_inference.c +++ b/ext/opcache/Optimizer/zend_inference.c @@ -2879,7 +2879,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;