Skip to content

Commit 01b91cb

Browse files
committed
Merge branch 'PHP-8.0' into PHP-8.1
2 parents 1c0dc2a + 2397e76 commit 01b91cb

File tree

3 files changed

+54
-3
lines changed

3 files changed

+54
-3
lines changed

NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ PHP NEWS
1717
. Fixed bug GH-8289 (Exceptions thrown within a yielded from iterator are
1818
not rethrown into the generator). (Bob)
1919

20+
- FFI:
21+
. Fixed bug GH-8433 (Assigning function pointers to structs in FFI leaks).
22+
(Bob)
23+
2024
- FPM:
2125
. Fixed bug #76003 (FPM /status reports wrong number of active processe).
2226
(Jakub Zelenka)

ext/ffi/ffi.c

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -863,6 +863,14 @@ static void zend_ffi_callback_hash_dtor(zval *zv) /* {{{ */
863863
if (callback_data->fcc.function_handler->common.fn_flags & ZEND_ACC_CLOSURE) {
864864
OBJ_RELEASE(ZEND_CLOSURE_OBJECT(callback_data->fcc.function_handler));
865865
}
866+
for (int i = 0; i < callback_data->arg_count; ++i) {
867+
if (callback_data->arg_types[i]->type == FFI_TYPE_STRUCT) {
868+
efree(callback_data->arg_types[i]);
869+
}
870+
}
871+
if (callback_data->ret_type->type == FFI_TYPE_STRUCT) {
872+
efree(callback_data->ret_type);
873+
}
866874
efree(callback_data);
867875
}
868876
/* }}} */
@@ -916,6 +924,8 @@ static void zend_ffi_callback_trampoline(ffi_cif* cif, void* ret, void** args, v
916924
if (ret_type->kind != ZEND_FFI_TYPE_VOID) {
917925
zend_ffi_zval_to_cdata(ret, ret_type, &retval);
918926
}
927+
928+
zval_ptr_dtor(&retval);
919929
}
920930
/* }}} */
921931

@@ -966,6 +976,11 @@ static void *zend_ffi_create_callback(zend_ffi_type *type, zval *value) /* {{{ *
966976
callback_data->arg_types[n] = zend_ffi_get_type(arg_type);
967977
if (!callback_data->arg_types[n]) {
968978
zend_ffi_pass_unsupported(arg_type);
979+
for (int i = 0; i < n; ++i) {
980+
if (callback_data->arg_types[i]->type == FFI_TYPE_STRUCT) {
981+
efree(callback_data->arg_types[i]);
982+
}
983+
}
969984
efree(callback_data);
970985
ffi_closure_free(callback);
971986
return NULL;
@@ -976,20 +991,32 @@ static void *zend_ffi_create_callback(zend_ffi_type *type, zval *value) /* {{{ *
976991
callback_data->ret_type = zend_ffi_get_type(ZEND_FFI_TYPE(type->func.ret_type));
977992
if (!callback_data->ret_type) {
978993
zend_ffi_return_unsupported(type->func.ret_type);
994+
for (int i = 0; i < callback_data->arg_count; ++i) {
995+
if (callback_data->arg_types[i]->type == FFI_TYPE_STRUCT) {
996+
efree(callback_data->arg_types[i]);
997+
}
998+
}
979999
efree(callback_data);
9801000
ffi_closure_free(callback);
9811001
return NULL;
9821002
}
9831003

9841004
if (ffi_prep_cif(&callback_data->cif, type->func.abi, callback_data->arg_count, callback_data->ret_type, callback_data->arg_types) != FFI_OK) {
9851005
zend_throw_error(zend_ffi_exception_ce, "Cannot prepare callback CIF");
986-
efree(callback_data);
987-
ffi_closure_free(callback);
988-
return NULL;
1006+
goto free_on_failure;
9891007
}
9901008

9911009
if (ffi_prep_closure_loc(callback, &callback_data->cif, zend_ffi_callback_trampoline, callback_data, code) != FFI_OK) {
9921010
zend_throw_error(zend_ffi_exception_ce, "Cannot prepare callback");
1011+
free_on_failure: ;
1012+
for (int i = 0; i < callback_data->arg_count; ++i) {
1013+
if (callback_data->arg_types[i]->type == FFI_TYPE_STRUCT) {
1014+
efree(callback_data->arg_types[i]);
1015+
}
1016+
}
1017+
if (callback_data->ret_type->type == FFI_TYPE_STRUCT) {
1018+
efree(callback_data->ret_type);
1019+
}
9931020
efree(callback_data);
9941021
ffi_closure_free(callback);
9951022
return NULL;

ext/ffi/tests/gh8433.phpt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
--TEST--
2+
GH-8433 (Assigning function pointers to structs in FFI leaks memory)
3+
--FILE--
4+
<?php
5+
6+
$ffi = FFI::cdef("typedef struct { int a; } bar;");
7+
$x = $ffi->new("bar(*)(void)");
8+
FFI::addr($x)[0] = function() use ($ffi) {
9+
$bar = $ffi->new("bar");
10+
$bar->a = 2;
11+
return $bar;
12+
};
13+
var_dump($x());
14+
15+
?>
16+
--EXPECTF--
17+
object(FFI\CData:struct <anonymous>)#%d (1) {
18+
["a"]=>
19+
int(2)
20+
}

0 commit comments

Comments
 (0)