From: Nikita Popov Date: Thu, 29 May 2014 09:17:33 +0000 (+0200) Subject: Improve class constant fetch fix X-Git-Tag: POST_PHPNG_MERGE~243 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=47e85b1b354bae083e51bce7396d1a2ac1c77161;p=php Improve class constant fetch fix Dereference the cached constant for Test::TEST as well (and not just self::TEST). Also improve the phpt file to test this case as well - previously this only manifested with opcache enabled, due to literal sharing. Additionally the Z_TYPE_P != IS_REFERENCE assertion is now moved into the TMP_VAR fetching code (as it applies to more than just property assignments.) --- diff --git a/Zend/tests/class_constant_to_reference_cached.phpt b/Zend/tests/class_constant_to_reference_cached.phpt index b752226aba..5bfbc61dd0 100644 --- a/Zend/tests/class_constant_to_reference_cached.phpt +++ b/Zend/tests/class_constant_to_reference_cached.phpt @@ -13,17 +13,16 @@ class Test { } } -$obj = new Test; -$obj->readConst(); -unset($obj); -var_dump(Test::TEST); +function doTest() { + $obj = new Test; + $obj->readConst(); + unset($obj); + var_dump(Test::TEST); +} +doTest(); eval('class Test2 extends Test {}'); - -$obj = new Test; -$obj->readConst(); -unset($obj); -var_dump(Test::TEST); +doTest(); ?> --EXPECT-- diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 9cc0f3a4cf..ae66364aa9 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -147,8 +147,10 @@ ZEND_API zval* zend_get_compiled_variable_value(const zend_execute_data *execute static zend_always_inline zval *_get_zval_ptr_tmp(zend_uint var, const zend_execute_data *execute_data, zend_free_op *should_free TSRMLS_DC) { zval *ret = EX_VAR(var); - should_free->var = ret; + + ZEND_ASSERT(Z_TYPE_P(ret) != IS_REFERENCE); + return ret; } @@ -724,7 +726,6 @@ static inline void zend_assign_to_object(zval *retval, zval *object_ptr, zval *p /* separate our value if necessary */ if (value_type == IS_TMP_VAR) { - ZEND_ASSERT(Z_TYPE_P(value) != IS_REFERENCE); ZVAL_COPY_VALUE(&tmp, value); value = &tmp; } else if (value_type == IS_CONST) { diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 5042c065ba..c27570c9df 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -3614,6 +3614,7 @@ ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, VAR|CONST|UNUSED, CONST) if (OP1_TYPE == IS_CONST) { if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { value = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); + ZVAL_DEREF(value); ZVAL_DUP(EX_VAR(opline->result.var), value); goto constant_fetch_end; } else if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) { diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 5b5c69923a..4534be8639 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -3886,6 +3886,7 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_CONST_CONST_HANDLER(ZEND_OPCO if (IS_CONST == IS_CONST) { if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { value = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); + ZVAL_DEREF(value); ZVAL_DUP(EX_VAR(opline->result.var), value); goto constant_fetch_end; } else if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) { @@ -15328,6 +15329,7 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE if (IS_VAR == IS_CONST) { if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { value = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); + ZVAL_DEREF(value); ZVAL_DUP(EX_VAR(opline->result.var), value); goto constant_fetch_end; } else if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) { @@ -24538,6 +24540,7 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPC if (IS_UNUSED == IS_CONST) { if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { value = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); + ZVAL_DEREF(value); ZVAL_DUP(EX_VAR(opline->result.var), value); goto constant_fetch_end; } else if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op1.zv))) {