Skip to content

Commit

Permalink
Fixed bug #76901
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
nikic committed Sep 19, 2018
1 parent ab6c45f commit 294fb83
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 7 deletions.
4 changes: 4 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
18 changes: 18 additions & 0 deletions Zend/tests/bug76901.phpt
Original file line number Diff line number Diff line change
@@ -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)
11 changes: 4 additions & 7 deletions Zend/zend_builtin_functions.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 294fb83

Please sign in to comment.