mirror of
https://github.com/php/php-src.git
synced 2025-08-16 14:08:47 +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);
|
ZEND_MAP_PTR_INIT(func->run_time_cache, (void**)dummy);
|
||||||
func->scope = fbc->common.scope;
|
func->scope = fbc->common.scope;
|
||||||
/* reserve space for arguments, local and temporary variables */
|
/* 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->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->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;
|
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