From e03480bfabce62916d57013d27069e3f46fc7730 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Fri, 12 Aug 2016 16:23:40 +0800 Subject: [PATCH] Fixed bug #72813 (Segfault with __get returned by ref) This should be safe change, as we don't dereference value and member after calling setter/getter. And compare to adding unref codes, this is much cheaper. --- NEWS | 1 + Zend/tests/bug72813.phpt | 43 +++++++++++++++++++++++++++++++++++++ Zend/zend_object_handlers.c | 10 --------- 3 files changed, 44 insertions(+), 10 deletions(-) create mode 100644 Zend/tests/bug72813.phpt diff --git a/NEWS b/NEWS index 92cc7ce517..d031042485 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,7 @@ PHP NEWS ?? ??? 2016 PHP 7.0.11 - Core: + . Fixed bug #72813 (Segfault with __get returned by ref). (Laruence) . Fixed bug #72767 (PHP Segfaults when trying to expand an infinite operator). (Nikita) diff --git a/Zend/tests/bug72813.phpt b/Zend/tests/bug72813.phpt new file mode 100644 index 0000000000..85ba066adb --- /dev/null +++ b/Zend/tests/bug72813.phpt @@ -0,0 +1,43 @@ +--TEST-- +Bug #72813 (Segfault with __get returned by ref) +--FILE-- + 'text', 'b' => 1]; + + public function &__get($prop) + { + return $this->props[$prop]; + } + + public function __set($prop, $value) + { + if ($prop === 'b') $value = [$value]; + $this->props[$prop] = $value; + } + + public function getProperties() + { + return [$this->props]; + } +} + +$obj = new Test; +$obj->b = $obj->b; +print_r($obj->getProperties()); +?> +--EXPECT-- +Array +( + [0] => Array + ( + [a] => text + [b] => Array + ( + [0] => 1 + ) + + ) + +) diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index ba3e84bf7d..70dab660b3 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -197,11 +197,7 @@ static void zend_std_call_getter(zval *object, zval *member, zval *retval) /* {{ it should return whether the call was successful or not */ - if (Z_REFCOUNTED_P(member)) Z_ADDREF_P(member); - zend_call_method_with_1_params(object, ce, &ce->__get, ZEND_GET_FUNC_NAME, retval, member); - - zval_ptr_dtor(member); } /* }}} */ @@ -211,9 +207,6 @@ static int zend_std_call_setter(zval *object, zval *member, zval *value) /* {{{ int result; zend_class_entry *ce = Z_OBJCE_P(object); - if (Z_REFCOUNTED_P(member)) Z_ADDREF_P(member); - if (Z_REFCOUNTED_P(value)) Z_ADDREF_P(value); - /* __set handler is called with two arguments: property name value to be set @@ -222,9 +215,6 @@ static int zend_std_call_setter(zval *object, zval *member, zval *value) /* {{{ */ zend_call_method_with_2_params(object, ce, &ce->__set, ZEND_SET_FUNC_NAME, &retval, member, value); - zval_ptr_dtor(member); - zval_ptr_dtor(value); - if (Z_TYPE(retval) != IS_UNDEF) { result = i_zend_is_true(&retval) ? SUCCESS : FAILURE; zval_ptr_dtor(&retval); -- 2.40.0