summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@php.net>2008-10-17 10:25:56 +0000
committerDmitry Stogov <dmitry@php.net>2008-10-17 10:25:56 +0000
commit739c75b05077a08176a12b77db1d72aa17b2971d (patch)
tree8791083cd8736c1efbf3cfe2e2467b0316a3c22f
parent0621602408f75d01a213bdd0fb61d311457ea280 (diff)
downloadphp-git-739c75b05077a08176a12b77db1d72aa17b2971d.tar.gz
Fixed bug #46308 (Invalid write when changing property from inside getter)
-rw-r--r--NEWS2
-rw-r--r--Zend/tests/bug46308.phpt33
-rw-r--r--Zend/zend_object_handlers.c8
3 files changed, 43 insertions, 0 deletions
diff --git a/NEWS b/NEWS
index d15dab5137..e4e1afe306 100644
--- 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
index 0000000000..37227385c7
--- /dev/null
+++ b/Zend/tests/bug46308.phpt
@@ -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
diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c
index 42b687eff7..044f21b92f 100644
--- a/Zend/zend_object_handlers.c
+++ b/Zend/zend_object_handlers.c
@@ -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) {