]> granicus.if.org Git - php/commitdiff
Addref static vars when not copying private method
authorNikita Popov <nikita.ppv@gmail.com>
Thu, 29 Aug 2019 12:33:31 +0000 (14:33 +0200)
committerNikita Popov <nikita.ppv@gmail.com>
Thu, 29 Aug 2019 12:47:09 +0000 (14:47 +0200)
While we don't need to give this method separate static vars, we
do still need to perform an addref, as there will be a corresponding
delref in the dtor.

Zend/tests/static_variable_in_private_trait_method.phpt [new file with mode: 0644]
Zend/zend_inheritance.c

diff --git a/Zend/tests/static_variable_in_private_trait_method.phpt b/Zend/tests/static_variable_in_private_trait_method.phpt
new file mode 100644 (file)
index 0000000..0d842c8
--- /dev/null
@@ -0,0 +1,35 @@
+--TEST--
+Behavior of static variable in private trait method
+--FILE--
+<?php
+
+trait T {
+    private static function method() {
+        static $x;
+        if ($x === null) $x = new stdClass;
+        return $x;
+    }
+
+    public static function method2() {
+        return self::method();
+    }
+}
+
+class C {
+    use T;
+}
+
+var_dump(C::method2());
+
+class D extends C {
+    use T;
+}
+
+var_dump(D::method2());
+
+?>
+--EXPECT--
+object(stdClass)#1 (0) {
+}
+object(stdClass)#2 (0) {
+}
index f79f295f8120577b4f244218e68b51426f5fc38a..9c8acca865666ff1ea10f7bf03db7655f19603c8 100644 (file)
@@ -96,11 +96,19 @@ static zend_always_inline zend_function *zend_duplicate_function(zend_function *
                        (*func->op_array.refcount)++;
                }
                if (is_interface
-                || EXPECTED(!func->op_array.static_variables)
-                || (func->op_array.fn_flags & ZEND_ACC_PRIVATE)) {
+                || EXPECTED(!func->op_array.static_variables)) {
                        /* reuse the same op_array structure */
                        return func;
                }
+               if (func->op_array.fn_flags & ZEND_ACC_PRIVATE) {
+                       /* For private methods we reuse the same op_array structure even if
+                        * static variables are used, because it will not end up being used
+                        * anyway. However we still need to addref as the dtor will delref. */
+                       if (!(GC_FLAGS(func->op_array.static_variables) & IS_ARRAY_IMMUTABLE)) {
+                               GC_ADDREF(func->op_array.static_variables);
+                       }
+                       return func;
+               }
                return zend_duplicate_user_function(func);
        }
 }