]> 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:26:16 +0000 (10:26 +0000)
committerDmitry Stogov <dmitry@php.net>
Fri, 17 Oct 2008 10:26:16 +0000 (10:26 +0000)
Zend/tests/bug46308.phpt [new file with mode: 0644]
Zend/zend_object_handlers.c

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 fddf991c133d24ccfe207466c7e126fe4044c67b..6144b2a632d8ae55c969b7f56b7e149f89217a85 100644 (file)
@@ -353,6 +353,7 @@ zval *zend_std_read_property(zval *object, zval *member, int type TSRMLS_DC) /*
                    zend_get_property_guard(zobj, property_info, member, &guard TSRMLS_CC) == SUCCESS &&
                    !guard->in_get) {
                        /* have getter - try with it! */
+                       Z_ADDREF_P(object);
                        guard->in_get = 1; /* prevent circular getting */
                        rv = zend_std_call_getter(object, member TSRMLS_CC);
                        guard->in_get = 0;
@@ -377,6 +378,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: %v::$%R", zobj->ce->name, Z_TYPE_P(member), Z_STRVAL_P(member));
@@ -447,12 +449,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 TSRMLS_CC) == SUCCESS &&
                    !guard->in_set) {
+                       Z_ADDREF_P(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;
@@ -628,9 +632,11 @@ static void zend_std_unset_property(zval *object, zval *member TSRMLS_DC) /* {{{
                    zend_get_property_guard(zobj, property_info, member, &guard TSRMLS_CC) == SUCCESS &&
                    !guard->in_unset) {
                        /* have unseter - try with it! */
+                       Z_ADDREF_P(object);
                        guard->in_unset = 1; /* prevent circular unsetting */
                        zend_std_call_unsetter(object, member TSRMLS_CC);
                        guard->in_unset = 0;
+                       zval_ptr_dtor(&object);
                }
        }
 
@@ -1146,6 +1152,7 @@ static int zend_std_has_property(zval *object, zval *member, int has_set_exists
                        zval *rv;
 
                        /* have issetter - try with it! */
+                       Z_ADDREF_P(object);
                        guard->in_isset = 1; /* prevent circular getting */
                        rv = zend_std_call_issetter(object, member TSRMLS_CC);
                        if (rv) {
@@ -1169,6 +1176,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) {