From 4d8503a2122ec7b3489878d09b17fb5f29bc92b0 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 8fa1471845..bcd560c8db 100644 --- a/NEWS +++ b/NEWS @@ -37,6 +37,8 @@ expected). (Stas) - Fixed bug #52891 (Wrong data inserted with mysqli/mysqlnd when using mysqli_stmt_bind_param and value> PHP_INT_MAX). (Andrey) +- 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 #52849 (GNU MP invalid version match). (Adam) - Fixed bug #52843 (Segfault when optional parameters are not passed in to mssql_connect). (Felipe) 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 b91fcd0787..291655027f 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -347,6 +347,9 @@ zval *zend_std_read_property(zval *object, zval *member, int type TSRMLS_DC) /* !guard->in_get) { /* have getter - try with it! */ Z_ADDREF_P(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; @@ -445,22 +448,22 @@ static void zend_std_write_property(zval *object, zval *member, zval *value TSRM } } } else { - int setter_done = 0; zend_guard *guard = NULL; if (zobj->ce->__set && zend_get_property_guard(zobj, property_info, member, &guard) == SUCCESS && !guard->in_set) { Z_ADDREF_P(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 */ @@ -643,6 +646,9 @@ static void zend_std_unset_property(zval *object, zval *member TSRMLS_DC) /* {{{ !guard->in_unset) { /* have unseter - try with it! */ Z_ADDREF_P(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; @@ -1169,6 +1175,9 @@ static int zend_std_has_property(zval *object, zval *member, int has_set_exists /* have issetter - try with it! */ Z_ADDREF_P(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