Skip to content

Commit b8e946b

Browse files
committed
- Fixed bug #62384 (Attempting to invoke a Closure more than once causes segfaul)
1 parent 055ecbc commit b8e946b

File tree

2 files changed

+31
-0
lines changed

2 files changed

+31
-0
lines changed

ext/reflection/php_reflection.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2747,6 +2747,16 @@ ZEND_METHOD(reflection_method, invokeArgs)
27472747
fcc.calling_scope = obj_ce;
27482748
fcc.called_scope = intern->ce;
27492749
fcc.object_ptr = object;
2750+
2751+
/*
2752+
* Closure::__invoke() actually expects a copy of zend_function, so that it
2753+
* frees it after the invoking.
2754+
*/
2755+
if (obj_ce == zend_ce_closure && object &&
2756+
strlen(mptr->common.function_name) == sizeof(ZEND_INVOKE_FUNC_NAME)-1 &&
2757+
memcmp(mptr->common.function_name, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1) == 0) {
2758+
fcc.function_handler = _copy_function(mptr TSRMLS_CC);
2759+
}
27502760

27512761
result = zend_call_function(&fci, &fcc TSRMLS_CC);
27522762

ext/reflection/tests/bug62384.phpt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
--TEST--
2+
Bug #62384 (Attempting to invoke a Closure more than once causes segfaul)
3+
--FILE--
4+
<?php
5+
6+
$closure1 = function($val){ return $val; };
7+
$closure2 = function($val){ return $val; };
8+
9+
$reflection_class = new ReflectionClass($closure1);
10+
$reflection_method = $reflection_class->getMethod('__invoke');
11+
12+
$arguments1 = array('hello');
13+
$arguments2 = array('world');
14+
15+
var_dump($reflection_method->invokeArgs($closure1, $arguments1));
16+
var_dump($reflection_method->invokeArgs($closure2, $arguments2));
17+
18+
?>
19+
--EXPECT--
20+
string(5) "hello"
21+
string(5) "world"

0 commit comments

Comments
 (0)