summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Zend/tests/class_constant_to_reference_cached.phpt31
-rw-r--r--Zend/zend_execute.c2
-rw-r--r--Zend/zend_vm_def.h5
-rw-r--r--Zend/zend_vm_execute.h15
4 files changed, 40 insertions, 13 deletions
diff --git a/Zend/tests/class_constant_to_reference_cached.phpt b/Zend/tests/class_constant_to_reference_cached.phpt
new file mode 100644
index 0000000000..b752226aba
--- /dev/null
+++ b/Zend/tests/class_constant_to_reference_cached.phpt
@@ -0,0 +1,31 @@
+--TEST--
+Conversion of a class constant to a reference after it has been cached
+--FILE--
+<?php
+
+class Test {
+ const TEST = 'TEST';
+
+ private $prop;
+
+ public function readConst() {
+ $this->prop = self::TEST;
+ }
+}
+
+$obj = new Test;
+$obj->readConst();
+unset($obj);
+var_dump(Test::TEST);
+
+eval('class Test2 extends Test {}');
+
+$obj = new Test;
+$obj->readConst();
+unset($obj);
+var_dump(Test::TEST);
+
+?>
+--EXPECT--
+string(4) "TEST"
+string(4) "TEST"
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c
index e0653f9b63..9cc0f3a4cf 100644
--- a/Zend/zend_execute.c
+++ b/Zend/zend_execute.c
@@ -724,7 +724,7 @@ 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) {
- ZVAL_DEREF(value);
+ 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 cba6e77d2b..5042c065ba 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -3631,15 +3631,14 @@ ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, VAR|CONST|UNUSED, CONST)
} else {
ce = Z_CE_P(EX_VAR(opline->op1.var));
if ((value = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce)) != NULL) {
+ ZVAL_DEREF(value);
ZVAL_DUP(EX_VAR(opline->result.var), value);
goto constant_fetch_end;
}
}
if (EXPECTED((value = zend_hash_find(&ce->constants_table, Z_STR_P(opline->op2.zv))) != NULL)) {
- if (Z_ISREF_P(value)) {
- value = Z_REFVAL_P(value);
- }
+ ZVAL_DEREF(value);
if (Z_CONSTANT_P(value)) {
zend_class_entry *old_scope = EG(scope);
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index 2e7184e30d..5b5c69923a 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -3903,15 +3903,14 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_CONST_CONST_HANDLER(ZEND_OPCO
} else {
ce = Z_CE_P(EX_VAR(opline->op1.var));
if ((value = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce)) != NULL) {
+ ZVAL_DEREF(value);
ZVAL_DUP(EX_VAR(opline->result.var), value);
goto constant_fetch_end;
}
}
if (EXPECTED((value = zend_hash_find(&ce->constants_table, Z_STR_P(opline->op2.zv))) != NULL)) {
- if (Z_ISREF_P(value)) {
- value = Z_REFVAL_P(value);
- }
+ ZVAL_DEREF(value);
if (Z_CONSTANT_P(value)) {
zend_class_entry *old_scope = EG(scope);
@@ -15346,15 +15345,14 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE
} else {
ce = Z_CE_P(EX_VAR(opline->op1.var));
if ((value = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce)) != NULL) {
+ ZVAL_DEREF(value);
ZVAL_DUP(EX_VAR(opline->result.var), value);
goto constant_fetch_end;
}
}
if (EXPECTED((value = zend_hash_find(&ce->constants_table, Z_STR_P(opline->op2.zv))) != NULL)) {
- if (Z_ISREF_P(value)) {
- value = Z_REFVAL_P(value);
- }
+ ZVAL_DEREF(value);
if (Z_CONSTANT_P(value)) {
zend_class_entry *old_scope = EG(scope);
@@ -24557,15 +24555,14 @@ static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPC
} else {
ce = Z_CE_P(EX_VAR(opline->op1.var));
if ((value = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(opline->op2.zv), ce)) != NULL) {
+ ZVAL_DEREF(value);
ZVAL_DUP(EX_VAR(opline->result.var), value);
goto constant_fetch_end;
}
}
if (EXPECTED((value = zend_hash_find(&ce->constants_table, Z_STR_P(opline->op2.zv))) != NULL)) {
- if (Z_ISREF_P(value)) {
- value = Z_REFVAL_P(value);
- }
+ ZVAL_DEREF(value);
if (Z_CONSTANT_P(value)) {
zend_class_entry *old_scope = EG(scope);