diff options
author | Nikita Popov <nikita.ppv@gmail.com> | 2018-09-19 09:37:04 +0200 |
---|---|---|
committer | Nikita Popov <nikita.ppv@gmail.com> | 2018-09-19 09:37:04 +0200 |
commit | 294fb83ee84b76479a62e4ed37d5523c1208ad7c (patch) | |
tree | 2a97de67c347171d0c80199f19e72d7a961e65ba | |
parent | ab6c45f5249d077463c1876d7cf09a11f04240fa (diff) | |
download | php-git-294fb83ee84b76479a62e4ed37d5523c1208ad7c.tar.gz |
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.
-rw-r--r-- | NEWS | 4 | ||||
-rw-r--r-- | Zend/tests/bug76901.phpt | 18 | ||||
-rw-r--r-- | Zend/zend_builtin_functions.c | 11 |
3 files changed, 26 insertions, 7 deletions
@@ -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-- +<?php + +$it = new ArrayIterator([1, 2, 3]); +$it = new IteratorIterator($it); +foreach ($it as $v) { + if (method_exists($it, 'offsetGet')) { + var_dump($it->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 |