]> granicus.if.org Git - php/commitdiff
Fixed reference support (references to references are not allowed)
authorDmitry Stogov <dmitry@zend.com>
Thu, 14 Aug 2014 13:00:01 +0000 (17:00 +0400)
committerDmitry Stogov <dmitry@zend.com>
Thu, 14 Aug 2014 13:00:01 +0000 (17:00 +0400)
Zend/zend_object_handlers.c

index ff8d99addc34e5072d7e1761dda58788590a7a1d..6f0dc7811ee768405194845e3849feeb156654a7 100644 (file)
@@ -593,10 +593,24 @@ found:
                                                ZVAL_COPY_VALUE(&garbage, Z_REFVAL_P(variable_ptr)); /* old value should be destroyed */
 
                                                /* To check: can't *variable_ptr be some system variable like error_zval here? */
-                                               ZVAL_COPY_VALUE(Z_REFVAL_P(variable_ptr), value);
-                                               if (Z_REFCOUNTED_P(value) && Z_REFCOUNT_P(value) > 0) {
-                                                       zval_copy_ctor(Z_REFVAL_P(variable_ptr));
+                                               if (UNEXPECTED(Z_REFCOUNTED_P(value))) {
+                                                       if (EXPECTED(!Z_ISREF_P(value))) {
+                                                               Z_ADDREF_P(value);
+                                                       } else {
+                                                               if (Z_REFCOUNT_P(value) == 1) {
+                                                                       ZVAL_UNREF(value);
+                                                               } else {
+                                                                       value = Z_REFVAL_P(value);
+                                                               }
+                                                               if (Z_REFCOUNTED_P(value)) {
+                                                                       if (UNEXPECTED(Z_REFVAL_P(variable_ptr) == value)) {
+                                                                               goto exit;
+                                                                       }
+                                                                       Z_ADDREF_P(value);
+                                                               }
+                                                       }
                                                }
+                                               ZVAL_COPY_VALUE(Z_REFVAL_P(variable_ptr), value);
                                                zval_ptr_dtor(&garbage);
                                        } else {
                                                zval garbage;