Skip to content

Commit 0a8518b

Browse files
committed
Reset user func trampoline values FFI may overwrite
1 parent 94d6bcb commit 0a8518b

File tree

2 files changed

+40
-0
lines changed

2 files changed

+40
-0
lines changed

Zend/zend_object_handlers.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1253,6 +1253,9 @@ ZEND_API zend_function *zend_get_call_trampoline_func(zend_class_entry *ce, zend
12531253
ZEND_MAP_PTR_INIT(func->run_time_cache, (void***)&dummy);
12541254
func->scope = fbc->common.scope;
12551255
/* reserve space for arguments, local and temporary variables */
1256+
/* last_var is overwritten by zend_ffi_cdata_get_closure() (overlapping
1257+
* internal function data) so we need to reset it */
1258+
func->last_var = 0;
12561259
func->T = (fbc->type == ZEND_USER_FUNCTION)? MAX(fbc->op_array.last_var + fbc->op_array.T, 2) : 2;
12571260
func->filename = (fbc->type == ZEND_USER_FUNCTION)? fbc->op_array.filename : ZSTR_EMPTY_ALLOC();
12581261
func->line_start = (fbc->type == ZEND_USER_FUNCTION)? fbc->op_array.line_start : 0;

ext/ffi/tests/trampoline_reset.phpt

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
--TEST--
2+
Test
3+
--EXTENSIONS--
4+
ffi
5+
--SKIPIF--
6+
<?php
7+
try {
8+
$libc = FFI::cdef("int printf(const char *format, ...);", "libc.so.6");
9+
} catch (Throwable $_) {
10+
die('skip libc.so.6 not available');
11+
}
12+
?>
13+
--INI--
14+
ffi.enable=1
15+
--FILE--
16+
<?php
17+
class Test
18+
{
19+
public static function __callStatic($name, $args)
20+
{
21+
echo "$name called\n";
22+
}
23+
}
24+
25+
Test::works1();
26+
Test::works2();
27+
28+
$ffi = FFI::cdef('int printf(const char *format, ...);', 'libc.so.6');
29+
$ffi->printf("Hello %s!\n", "world");
30+
31+
Test::breaks();
32+
?>
33+
--EXPECT--
34+
works1 called
35+
works2 called
36+
breaks called
37+
Hello world!

0 commit comments

Comments
 (0)