mirror of
https://github.com/php/php-src.git
synced 2025-08-15 21:48:51 +02:00
Merge branch 'PHP-8.2'
* PHP-8.2: Reset EG(trampoline).op_array.last_var that FFI may modify
This commit is contained in:
commit
f1333bc9fe
2 changed files with 49 additions and 0 deletions
|
@ -1313,6 +1313,12 @@ ZEND_API zend_function *zend_get_call_trampoline_func(const zend_class_entry *ce
|
|||
ZEND_MAP_PTR_INIT(func->run_time_cache, (void**)dummy);
|
||||
func->scope = fbc->common.scope;
|
||||
/* reserve space for arguments, local and temporary variables */
|
||||
/* EG(trampoline) is reused from other places, like FFI (e.g. zend_ffi_cdata_get_closure()) where
|
||||
* it is used as an internal function. It may set fields that don't belong to common, thus
|
||||
* modifying zend_op_array specific data, most significantly last_var. We need to reset this
|
||||
* value so that it doesn't contain garbage when the engine allocates space for the next stack
|
||||
* frame. This didn't cause any issues until now due to "lucky" structure layout. */
|
||||
func->last_var = 0;
|
||||
func->T = (fbc->type == ZEND_USER_FUNCTION)? MAX(fbc->op_array.last_var + fbc->op_array.T, 2) : 2;
|
||||
func->filename = (fbc->type == ZEND_USER_FUNCTION)? fbc->op_array.filename : ZSTR_EMPTY_ALLOC();
|
||||
func->line_start = (fbc->type == ZEND_USER_FUNCTION)? fbc->op_array.line_start : 0;
|
||||
|
|
43
ext/ffi/tests/trampoline_reset.phpt
Normal file
43
ext/ffi/tests/trampoline_reset.phpt
Normal file
|
@ -0,0 +1,43 @@
|
|||
--TEST--
|
||||
Memory corruption when mixing __callStatic() and FFI
|
||||
--EXTENSIONS--
|
||||
ffi
|
||||
--SKIPIF--
|
||||
<?php
|
||||
try {
|
||||
$libc = FFI::cdef("int printf(const char *format, ...);", "libc.so.6");
|
||||
} catch (Throwable $_) {
|
||||
die('skip libc.so.6 not available');
|
||||
}
|
||||
?>
|
||||
--INI--
|
||||
ffi.enable=1
|
||||
--FILE--
|
||||
<?php
|
||||
class Test
|
||||
{
|
||||
public static function __callStatic($name, $args)
|
||||
{
|
||||
echo "$name called\n";
|
||||
}
|
||||
}
|
||||
|
||||
$header = '
|
||||
typedef struct _IO_FILE FILE;
|
||||
extern FILE *stdout;
|
||||
int fprintf(FILE *, const char *, ...);
|
||||
int fflush(FILE *);
|
||||
';
|
||||
$ffi = FFI::cdef($header, 'libc.so.6');
|
||||
|
||||
Test::foo();
|
||||
Test::bar();
|
||||
$ffi->fprintf($ffi->stdout, "FFI\n");
|
||||
$ffi->fflush($ffi->stdout);
|
||||
Test::baz();
|
||||
?>
|
||||
--EXPECT--
|
||||
foo called
|
||||
bar called
|
||||
FFI
|
||||
baz called
|
Loading…
Add table
Add a link
Reference in a new issue