From f870cd858954b3fddf9a9d7a229a8db2723b2791 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Fri, 17 Oct 2008 10:26:16 +0000 Subject: [PATCH] Fixed bug #46308 (Invalid write when changing property from inside getter) --- Zend/tests/bug46308.phpt | 33 +++++++++++++++++++++++++++++++++ Zend/zend_object_handlers.c | 8 ++++++++ 2 files changed, 41 insertions(+) create mode 100644 Zend/tests/bug46308.phpt 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-- +bar; +echo "ok\n"; +?> +--EXPECT-- +ok diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index fddf991c13..6144b2a632 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -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) { -- 2.50.1