From 294fb83ee84b76479a62e4ed37d5523c1208ad7c Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Wed, 19 Sep 2018 09:37:04 +0200 Subject: Fixed bug #76901 get_method() may modify the object pointer passed to it if method forwarding is used. In this case we do not want to modify the passed zval, so make sure that we copy the object into a temporary first. --- NEWS | 4 ++++ Zend/tests/bug76901.phpt | 18 ++++++++++++++++++ Zend/zend_builtin_functions.c | 11 ++++------- 3 files changed, 26 insertions(+), 7 deletions(-) create mode 100644 Zend/tests/bug76901.phpt diff --git a/NEWS b/NEWS index 0e5daeacd6..1add82df49 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,10 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? 2018, PHP 7.1.23 +- Core: + . Fixed bug #76901 (method_exists on SPL iterator passthrough method corrupts + memory). (Nikita) + - CURL: . Fixed bug #76480 (Use curl_multi_wait() so that timeouts are respected). (Pierrick) diff --git a/Zend/tests/bug76901.phpt b/Zend/tests/bug76901.phpt new file mode 100644 index 0000000000..8d567d9e0c --- /dev/null +++ b/Zend/tests/bug76901.phpt @@ -0,0 +1,18 @@ +--TEST-- +Bug #76901: method_exists on SPL iterator passthrough method corrupts memory +--FILE-- +offsetGet(0)); + } +} + +?> +--EXPECT-- +int(1) +int(1) +int(1) diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index 184b352ec8..f792756a11 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -1400,13 +1400,10 @@ ZEND_FUNCTION(method_exists) if (zend_hash_exists(&ce->function_table, lcname)) { zend_string_release(lcname); RETURN_TRUE; - } else { - union _zend_function *func = NULL; - - if (Z_TYPE_P(klass) == IS_OBJECT - && Z_OBJ_HT_P(klass)->get_method != NULL - && (func = Z_OBJ_HT_P(klass)->get_method(&Z_OBJ_P(klass), method_name, NULL)) != NULL - ) { + } else if (Z_TYPE_P(klass) == IS_OBJECT && Z_OBJ_HT_P(klass)->get_method != NULL) { + zend_object *obj = Z_OBJ_P(klass); + zend_function *func = Z_OBJ_HT_P(klass)->get_method(&obj, method_name, NULL); + if (func != NULL) { if (func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) { /* Returns true to the fake Closure's __invoke */ RETVAL_BOOL(func->common.scope == zend_ce_closure -- cgit v1.2.1