Skip to content

Commit 04b35a4

Browse files
authored
Fix segfault caused by weak references to FFI objects (#12488)
Thank you!
1 parent 83a505e commit 04b35a4

File tree

5 files changed

+119
-0
lines changed

5 files changed

+119
-0
lines changed

ext/ffi/ffi.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "php_scandir.h"
2525
#include "zend_exceptions.h"
2626
#include "zend_closures.h"
27+
#include "zend_weakrefs.h"
2728
#include "main/SAPI.h"
2829
#include "ffi_arginfo.h"
2930

@@ -2143,6 +2144,10 @@ static void zend_ffi_ctype_free_obj(zend_object *object) /* {{{ */
21432144
zend_ffi_ctype *ctype = (zend_ffi_ctype*)object;
21442145

21452146
zend_ffi_type_dtor(ctype->type);
2147+
2148+
if (UNEXPECTED(GC_FLAGS(object) & IS_OBJ_WEAKLY_REFERENCED)) {
2149+
zend_weakrefs_notify(object);
2150+
}
21462151
}
21472152
/* }}} */
21482153

@@ -2369,6 +2374,10 @@ static void zend_ffi_free_obj(zend_object *object) /* {{{ */
23692374
zend_hash_destroy(ffi->tags);
23702375
efree(ffi->tags);
23712376
}
2377+
2378+
if (UNEXPECTED(GC_FLAGS(object) & IS_OBJ_WEAKLY_REFERENCED)) {
2379+
zend_weakrefs_notify(object);
2380+
}
23722381
}
23732382
/* }}} */
23742383

@@ -2377,6 +2386,10 @@ static void zend_ffi_cdata_free_obj(zend_object *object) /* {{{ */
23772386
zend_ffi_cdata *cdata = (zend_ffi_cdata*)object;
23782387

23792388
zend_ffi_cdata_dtor(cdata);
2389+
2390+
if (UNEXPECTED(GC_FLAGS(object) & IS_OBJ_WEAKLY_REFERENCED)) {
2391+
zend_weakrefs_notify(object);
2392+
}
23802393
}
23812394
/* }}} */
23822395

ext/ffi/tests/weak_reference_001.phpt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
--TEST--
2+
Weak reference to \FFI
3+
--EXTENSIONS--
4+
ffi
5+
--INI--
6+
ffi.enable=1
7+
--FILE--
8+
<?php
9+
$ffi = \FFI::cdef('');
10+
$ref = \WeakReference::create($ffi);
11+
var_dump($ref->get() === $ffi);
12+
unset($ffi);
13+
var_dump($ref->get() === null);
14+
?>
15+
--EXPECTF--
16+
bool(true)
17+
bool(true)

ext/ffi/tests/weak_reference_002.phpt

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
--TEST--
2+
Weak reference to \FFI\CData
3+
--EXTENSIONS--
4+
ffi
5+
--INI--
6+
ffi.enable=1
7+
--FILE--
8+
<?php
9+
$cdata_value = \FFI::new('int');
10+
$cdata_array = \FFI::new('int[1]');
11+
$cdata_free = \FFI::new('int[1]', false);
12+
\FFI::free($cdata_free);
13+
14+
$ref_value = \WeakReference::create($cdata_value);
15+
$ref_array = \WeakReference::create($cdata_array);
16+
$ref_free = \WeakReference::create($cdata_free);
17+
18+
var_dump($ref_value->get() === $cdata_value);
19+
var_dump($ref_array->get() === $cdata_array);
20+
var_dump($ref_free->get() === $cdata_free);
21+
22+
unset($cdata_value);
23+
unset($cdata_array);
24+
unset($cdata_free);
25+
26+
var_dump($ref_value->get() === null);
27+
var_dump($ref_array->get() === null);
28+
var_dump($ref_free->get() === null);
29+
?>
30+
--EXPECTF--
31+
bool(true)
32+
bool(true)
33+
bool(true)
34+
bool(true)
35+
bool(true)
36+
bool(true)

ext/ffi/tests/weak_reference_003.phpt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
--TEST--
2+
Weak reference to \FFI\CType
3+
--EXTENSIONS--
4+
ffi
5+
--INI--
6+
ffi.enable=1
7+
--FILE--
8+
<?php
9+
$ctype = \FFI::type('int');
10+
$ref = \WeakReference::create($ctype);
11+
var_dump($ref->get() === $ctype);
12+
unset($ctype);
13+
var_dump($ref->get() === null);
14+
?>
15+
--EXPECTF--
16+
bool(true)
17+
bool(true)

ext/ffi/tests/weak_reference_004.phpt

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
--TEST--
2+
Using FFI Types for keys of a WeakMap
3+
--EXTENSIONS--
4+
ffi
5+
--INI--
6+
ffi.enable=1
7+
--FILE--
8+
<?php
9+
$map = new WeakMap();
10+
11+
$ffi = \FFI::cdef('');
12+
$cdata_value = \FFI::new('int');
13+
$cdata_array = \FFI::new('int[1]');
14+
$cdata_free = \FFI::new('int[1]', false);
15+
\FFI::free($cdata_free);
16+
$ctype = \FFI::type('int');
17+
18+
$map[$ffi] = 'ffi';
19+
$map[$cdata_value] = 'cdata_value';
20+
$map[$cdata_array] = 'cdata_array';
21+
$map[$cdata_free] = 'cdata_free';
22+
$map[$ctype] = 'ctype';
23+
24+
var_dump(count($map) === 5);
25+
26+
unset($ffi);
27+
unset($cdata_value);
28+
unset($cdata_array);
29+
unset($cdata_free);
30+
unset($ctype);
31+
32+
var_dump(count($map) === 0);
33+
?>
34+
--EXPECTF--
35+
bool(true)
36+
bool(true)

0 commit comments

Comments
 (0)