]> granicus.if.org Git - php/commitdiff
Fixed bug #46308 (Invalid write when changing property from inside getter)
authorDmitry Stogov <dmitry@php.net>
Fri, 17 Oct 2008 10:25:56 +0000 (10:25 +0000)
committerDmitry Stogov <dmitry@php.net>
Fri, 17 Oct 2008 10:25:56 +0000 (10:25 +0000)
NEWS
Zend/tests/bug46308.phpt [new file with mode: 0644]
Zend/zend_object_handlers.c

diff --git a/NEWS b/NEWS
index d15dab513770e8456f6c8fcf0ebfa202115fe8de..e4e1afe3063b0e445051c4498f3d485d66d1e19a 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -3,6 +3,8 @@ PHP                                                                        NEWS
 ?? Oct 2008, PHP 5.2.7RC2
 - Fixed bug #46319 (PHP sets default Content-Type header for HTTP 304
   response code, in cgi sapi). (Ilia)
+- Fixed bug #46308 (Invalid write when changing property from inside getter).
+  (Dmitry)
 - Fixed bug #46292 (PDO::setFetchMode() shouldn't requires the 2nd arg when 
   using FETCH_CLASSTYPE). (Felipe)
 - Fixed bug #46274, #46249 (pdo_pgsql always fill in NULL for empty BLOB and 
diff --git a/Zend/tests/bug46308.phpt b/Zend/tests/bug46308.phpt
new file mode 100644 (file)
index 0000000..3722738
--- /dev/null
@@ -0,0 +1,33 @@
+--TEST--
+Bug #46308 (Invalid write when changing property from inside getter)
+--FILE--
+<?php
+class main
+{
+   public static $dummy        = NULL ;
+   public static $dataAccessor = NULL ;
+}
+
+class dataAccessor
+{
+}
+
+class relay
+{
+   public function __get( $name )
+   {
+       main::$dataAccessor = new dataAccessor;
+   }
+}
+
+class dummy
+{
+}
+
+main::$dummy        = new dummy();
+main::$dataAccessor = new relay();
+main::$dataAccessor->bar;
+echo "ok\n";
+?>
+--EXPECT--
+ok
index 42b687eff7ca0446b110dd845f41e4bcfd1278f6..044f21b92fe8db1c3c0ab5558ee7e1d89a22b8a9 100644 (file)
@@ -328,6 +328,7 @@ zval *zend_std_read_property(zval *object, zval *member, int type TSRMLS_DC)
                    zend_get_property_guard(zobj, property_info, member, &guard) == SUCCESS &&
                    !guard->in_get) {
                        /* have getter - try with it! */
+                       ZVAL_ADDREF(object);
                        guard->in_get = 1; /* prevent circular getting */
                        rv = zend_std_call_getter(object, member TSRMLS_CC);
                        guard->in_get = 0;
@@ -352,6 +353,7 @@ zval *zend_std_read_property(zval *object, zval *member, int type TSRMLS_DC)
                        } else {
                                retval = &EG(uninitialized_zval_ptr);
                        }
+                       zval_ptr_dtor(&object);
                } else {
                        if (!silent) {
                                zend_error(E_NOTICE,"Undefined property: %s::$%s", zobj->ce->name, Z_STRVAL_P(member));
@@ -422,12 +424,14 @@ static void zend_std_write_property(zval *object, zval *member, zval *value TSRM
                if (zobj->ce->__set &&
                    zend_get_property_guard(zobj, property_info, member, &guard) == SUCCESS &&
                    !guard->in_set) {
+                       ZVAL_ADDREF(object);
                        guard->in_set = 1; /* prevent circular setting */
                        if (zend_std_call_setter(object, member, value TSRMLS_CC) != SUCCESS) {
                                /* for now, just ignore it - __set should take care of warnings, etc. */
                        }
                        setter_done = 1;
                        guard->in_set = 0;
+                       zval_ptr_dtor(&object);
                }
                if (!setter_done && property_info) {
                        zval **foo;
@@ -602,9 +606,11 @@ static void zend_std_unset_property(zval *object, zval *member TSRMLS_DC)
                    zend_get_property_guard(zobj, property_info, member, &guard) == SUCCESS &&
                    !guard->in_unset) {
                        /* have unseter - try with it! */
+                       ZVAL_ADDREF(object);
                        guard->in_unset = 1; /* prevent circular unsetting */
                        zend_std_call_unsetter(object, member TSRMLS_CC);
                        guard->in_unset = 0;
+                       zval_ptr_dtor(&object);
                }
        }
 
@@ -1020,6 +1026,7 @@ static int zend_std_has_property(zval *object, zval *member, int has_set_exists
                        zval *rv;
 
                        /* have issetter - try with it! */
+                       ZVAL_ADDREF(object);
                        guard->in_isset = 1; /* prevent circular getting */
                        rv = zend_std_call_issetter(object, member TSRMLS_CC);
                        if (rv) {
@@ -1037,6 +1044,7 @@ static int zend_std_has_property(zval *object, zval *member, int has_set_exists
                                }
                        }
                        guard->in_isset = 0;
+                       zval_ptr_dtor(&object);
                }
        } else {
                switch (has_set_exists) {