]> granicus.if.org Git - php/commitdiff
Fix #74922 - Try to resolve constants when importing trait properties
authorPedro Magalhães <mail@pmmaga.net>
Wed, 27 Sep 2017 00:31:03 +0000 (01:31 +0100)
committerNikita Popov <nikita.ppv@gmail.com>
Thu, 2 Nov 2017 20:06:27 +0000 (21:06 +0100)
NEWS
Zend/tests/traits/bug74922.phpt [new file with mode: 0644]
Zend/tests/traits/bug74922a.phpt [new file with mode: 0644]
Zend/tests/traits/bug74922b.inc [new file with mode: 0644]
Zend/tests/traits/bug74922b.phpt [new file with mode: 0644]
Zend/tests/traits/bug74922c.phpt [new file with mode: 0644]
Zend/zend_inheritance.c

diff --git a/NEWS b/NEWS
index 35b828e359ae04d23e53e6a6175b903e1543c9e6..d3ad412982b0fc3c449d32dcd7546482acb1ca83 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -14,6 +14,8 @@ PHP                                                                        NEWS
     (andrewnester)
   . Fixed bug #69954 (broken links and unused config items in distributed ini
     files). (petk)
+  . Fixed bug #74922 (Composed class has fatal error with duplicate, equal const
+    properties). (pmmaga)
 
 - BCMath:
   . Fixed bug #66364 (BCMath bcmul ignores scale parameter). (cmb)
diff --git a/Zend/tests/traits/bug74922.phpt b/Zend/tests/traits/bug74922.phpt
new file mode 100644 (file)
index 0000000..16272b8
--- /dev/null
@@ -0,0 +1,16 @@
+--TEST--
+Bug #74922 (Composed class has fatal error with duplicate, equal const properties)
+--FILE--
+<?php
+
+const VALUE = true;
+
+trait Foo {public $var = VALUE;}
+trait Bar {public $var = VALUE;}
+class Baz {use Foo, Bar;}
+
+echo "DONE";
+
+?>
+--EXPECT--
+DONE
diff --git a/Zend/tests/traits/bug74922a.phpt b/Zend/tests/traits/bug74922a.phpt
new file mode 100644 (file)
index 0000000..40617bc
--- /dev/null
@@ -0,0 +1,16 @@
+--TEST--
+Bug #74922 (Composed class has fatal error with duplicate, equal const properties)
+--FILE--
+<?php
+
+const VALUE = true;
+
+trait Foo {public $var = VALUE;}
+trait Bar {public $var = true;}
+class Baz {use Foo, Bar;}
+
+echo "DONE";
+
+?>
+--EXPECT--
+DONE
diff --git a/Zend/tests/traits/bug74922b.inc b/Zend/tests/traits/bug74922b.inc
new file mode 100644 (file)
index 0000000..b64ee21
--- /dev/null
@@ -0,0 +1,9 @@
+<?php
+
+namespace Bug74922;
+
+const FOO = 'foo';
+
+trait T1 {
+    public $var = FOO;
+}
diff --git a/Zend/tests/traits/bug74922b.phpt b/Zend/tests/traits/bug74922b.phpt
new file mode 100644 (file)
index 0000000..9a0f235
--- /dev/null
@@ -0,0 +1,15 @@
+--TEST--
+Bug #74922 (Composed class has fatal error with duplicate, equal const properties)
+--FILE--
+<?php
+
+require('bug74922b.inc');
+
+trait T2 {public $var = Bug74922\FOO;}
+class Baz {use Bug74922\T1, T2;}
+
+echo "DONE";
+
+?>
+--EXPECT--
+DONE
diff --git a/Zend/tests/traits/bug74922c.phpt b/Zend/tests/traits/bug74922c.phpt
new file mode 100644 (file)
index 0000000..367bbf4
--- /dev/null
@@ -0,0 +1,20 @@
+--TEST--
+Bug #74922 (Composed class has fatal error with duplicate, equal const properties)
+--FILE--
+<?php
+
+trait T {
+    public $x = self::X;
+}
+trait T2 {
+    public $x = self::X;
+}
+class C {
+    use T, T2;
+    const X = 42;
+}
+var_dump((new C)->x);
+
+?>
+--EXPECT--
+int(42)
index a9c468493d349e4b521b641b0b99fe7c1f18d8f0..b9794b0d62c9a53e3375d4b48f81c09acf736046 100644 (file)
@@ -1584,19 +1584,32 @@ static void zend_do_traits_property_binding(zend_class_entry *ce) /* {{{ */
                                        zend_hash_del(&ce->properties_info, prop_name);
                                        flags |= ZEND_ACC_CHANGED;
                                } else {
+                                       not_compatible = 1;
+                                       
                                        if ((coliding_prop->flags & (ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC))
                                                == (flags & (ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC))) {
-                                               /* flags are identical, now the value needs to be checked */
+                                               /* the flags are identical, thus, the properties may be compatible */
+                                               zval op1, op2;
+
                                                if (flags & ZEND_ACC_STATIC) {
-                                                       not_compatible = fast_is_not_identical_function(&ce->default_static_members_table[coliding_prop->offset],
-                                                                                         &ce->traits[i]->default_static_members_table[property_info->offset]);
+                                                       ZVAL_COPY_OR_DUP(&op1, &ce->default_static_members_table[coliding_prop->offset]);
+                                                       ZVAL_COPY_OR_DUP(&op2, &ce->traits[i]->default_static_members_table[property_info->offset]);
                                                } else {
-                                                       not_compatible = fast_is_not_identical_function(&ce->default_properties_table[OBJ_PROP_TO_NUM(coliding_prop->offset)],
-                                                                                         &ce->traits[i]->default_properties_table[OBJ_PROP_TO_NUM(property_info->offset)]);
+                                                       ZVAL_COPY_OR_DUP(&op1, &ce->default_properties_table[OBJ_PROP_TO_NUM(coliding_prop->offset)]);
+                                                       ZVAL_COPY_OR_DUP(&op2, &ce->traits[i]->default_properties_table[OBJ_PROP_TO_NUM(property_info->offset)]);
                                                }
-                                       } else {
-                                               /* the flags are not identical, thus, we assume properties are not compatible */
-                                               not_compatible = 1;
+
+                                               /* if any of the values is a constant, we try to resolve it */
+                                               if (UNEXPECTED(Z_TYPE(op1) == IS_CONSTANT_AST)) {
+                                                       zval_update_constant_ex(&op1, ce);
+                                               }
+                                               if (UNEXPECTED(Z_TYPE(op2) == IS_CONSTANT_AST)) {
+                                                       zval_update_constant_ex(&op2, ce);
+                                               }
+
+                                               not_compatible = fast_is_not_identical_function(&op1, &op2);
+                                               zval_ptr_dtor_nogc(&op1);
+                                               zval_ptr_dtor_nogc(&op2);
                                        }
 
                                        if (not_compatible) {