Skip to content

Commit 1fc85a3

Browse files
committed
Merge branch 'PHP-8.3'
* PHP-8.3: Fix GH-12905: FFI::new interacts badly with observers
2 parents b6a0e3d + 87c906c commit 1fc85a3

File tree

2 files changed

+56
-0
lines changed

2 files changed

+56
-0
lines changed

ext/ffi/ffi.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "zend_closures.h"
2727
#include "zend_weakrefs.h"
2828
#include "main/SAPI.h"
29+
#include "zend_observer.h"
2930

3031
#include <ffi.h>
3132

@@ -5373,6 +5374,25 @@ static zend_result zend_ffi_preload(char *preload) /* {{{ */
53735374
}
53745375
/* }}} */
53755376

5377+
/* The startup code for observers adds a temporary to each function for internal use.
5378+
* The "new", "cast", and "type" functions in FFI are both static and non-static.
5379+
* Only the static versions are in the function table and the non-static versions are not.
5380+
* This means the non-static versions will be skipped by the observers startup code.
5381+
* This function fixes that by incrementing the temporary count for the non-static versions.
5382+
*/
5383+
static zend_result (*prev_zend_post_startup_cb)(void);
5384+
static zend_result ffi_fixup_temporaries(void) {
5385+
if (ZEND_OBSERVER_ENABLED) {
5386+
++zend_ffi_new_fn.T;
5387+
++zend_ffi_cast_fn.T;
5388+
++zend_ffi_type_fn.T;
5389+
}
5390+
if (prev_zend_post_startup_cb) {
5391+
return prev_zend_post_startup_cb();
5392+
}
5393+
return SUCCESS;
5394+
}
5395+
53765396
/* {{{ ZEND_MINIT_FUNCTION */
53775397
ZEND_MINIT_FUNCTION(ffi)
53785398
{
@@ -5395,6 +5415,9 @@ ZEND_MINIT_FUNCTION(ffi)
53955415
memcpy(&zend_ffi_type_fn, zend_hash_str_find_ptr(&zend_ffi_ce->function_table, "type", sizeof("type")-1), sizeof(zend_internal_function));
53965416
zend_ffi_type_fn.fn_flags &= ~ZEND_ACC_STATIC;
53975417

5418+
prev_zend_post_startup_cb = zend_post_startup_cb;
5419+
zend_post_startup_cb = ffi_fixup_temporaries;
5420+
53985421
memcpy(&zend_ffi_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
53995422
zend_ffi_handlers.get_constructor = zend_fake_get_constructor;
54005423
zend_ffi_handlers.free_obj = zend_ffi_free_obj;

ext/ffi/tests/gh12905.phpt

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
--TEST--
2+
GH-12905 (FFI::new interacts badly with observers)
3+
--EXTENSIONS--
4+
ffi
5+
zend_test
6+
--SKIPIF--
7+
<?php
8+
try {
9+
$libc = FFI::cdef("int printf(const char *format, ...);", "libc.so.6");
10+
} catch (Throwable $_) {
11+
die('skip libc.so.6 not available');
12+
}
13+
?>
14+
--INI--
15+
ffi.enable=1
16+
zend_test.observer.enabled=1
17+
zend_test.observer.observe_all=1
18+
zend_test.observer.show_return_value=0
19+
--FILE--
20+
<?php
21+
$ffi = FFI::cdef("", "libc.so.6");
22+
$ffi->new("int");
23+
?>
24+
--EXPECTF--
25+
<!-- init '%sgh12905.php' -->
26+
<file '%sgh12905.php'>
27+
<!-- init FFI::cdef() -->
28+
<FFI::cdef>
29+
</FFI::cdef>
30+
<!-- init FFI::new() -->
31+
<FFI::new>
32+
</FFI::new>
33+
</file '%sgh12905.php'>

0 commit comments

Comments
 (0)