From 01e081cfa7384d2d40a1a32e30437834834baf44 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Fri, 1 Oct 2010 09:49:20 +0000 Subject: [PATCH] Fixed bug #52879 (Objects unreferenced in __get, __set, __isset or __unset can be freed too early). (mail_ben_schmidt at yahoo dot com dot au, Dmitry) --- NEWS | 2 ++ Zend/tests/bug52879.phpt | 16 ++++++++++++++++ Zend/zend_object_handlers.c | 17 +++++++++++++---- 3 files changed, 31 insertions(+), 4 deletions(-) create mode 100644 Zend/tests/bug52879.phpt diff --git a/NEWS b/NEWS index 93fa9ccb83..c00f86205a 100644 --- a/NEWS +++ b/NEWS @@ -6,6 +6,8 @@ - Fixed bug #52929 (Segfault in filter_var with FILTER_VALIDATE_EMAIL with large amount of data). (Adam) +- Fixed bug #52879 (Objects unreferenced in __get, __set, __isset or __unset + can be freed too early). (mail_ben_schmidt at yahoo dot com dot au, Dmitry) - Fixed bug #52772 (var_dump() doesn't check for the existence of get_class_name before calling it). (Kalle, Gustavo) - Fixed bug #52546 (pdo_dblib segmentation fault when iterating MONEY values). diff --git a/Zend/tests/bug52879.phpt b/Zend/tests/bug52879.phpt new file mode 100644 index 0000000000..0193be4b45 --- /dev/null +++ b/Zend/tests/bug52879.phpt @@ -0,0 +1,16 @@ +--TEST-- +Bug #52879 (Objects unreferenced in __get, __set, __isset or __unset can be freed too early) +--FILE-- +myRef = $value; + } +} +$myGlobal=new MyClass($myGlobal); +$myGlobal->myRef=&$myGlobal; +$myGlobal->myNonExistentProperty="ok\n"; +echo $myGlobal; +--EXPECT-- +ok diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index 8679daf6b6..271c79f8df 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -329,6 +329,9 @@ zval *zend_std_read_property(zval *object, zval *member, int type TSRMLS_DC) !guard->in_get) { /* have getter - try with it! */ ZVAL_ADDREF(object); + if (PZVAL_IS_REF(object)) { + SEPARATE_ZVAL(&object); + } guard->in_get = 1; /* prevent circular getting */ rv = zend_std_call_getter(object, member TSRMLS_CC); guard->in_get = 0; @@ -418,22 +421,22 @@ static void zend_std_write_property(zval *object, zval *member, zval *value TSRM } } } else { - int setter_done = 0; zend_guard *guard; if (zobj->ce->__set && zend_get_property_guard(zobj, property_info, member, &guard) == SUCCESS && !guard->in_set) { ZVAL_ADDREF(object); + if (PZVAL_IS_REF(object)) { + SEPARATE_ZVAL(&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) { + } else if (property_info) { zval **foo; /* if we assign referenced variable, we should separate it */ @@ -611,6 +614,9 @@ static void zend_std_unset_property(zval *object, zval *member TSRMLS_DC) !guard->in_unset) { /* have unseter - try with it! */ ZVAL_ADDREF(object); + if (PZVAL_IS_REF(object)) { + SEPARATE_ZVAL(&object); + } guard->in_unset = 1; /* prevent circular unsetting */ zend_std_call_unsetter(object, member TSRMLS_CC); guard->in_unset = 0; @@ -1042,6 +1048,9 @@ static int zend_std_has_property(zval *object, zval *member, int has_set_exists /* have issetter - try with it! */ ZVAL_ADDREF(object); + if (PZVAL_IS_REF(object)) { + SEPARATE_ZVAL(&object); + } guard->in_isset = 1; /* prevent circular getting */ rv = zend_std_call_issetter(object, member TSRMLS_CC); if (rv) { -- 2.40.0