diff --git a/NEWS b/NEWS index c63549f1237..80e71e8f25d 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,9 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.3.0beta2 +- FFI: + . Fix leaking definitions when using FFI::cdef()->new(...). (ilutov) + - Streams: . Fixed bug GH-11735 (Use-after-free when unregistering user stream wrapper from itself). (ilutov) diff --git a/ext/ffi/ffi.c b/ext/ffi/ffi.c index 275a1df25c8..48813b17434 100644 --- a/ext/ffi/ffi.c +++ b/ext/ffi/ffi.c @@ -3773,11 +3773,14 @@ ZEND_METHOD(FFI, new) /* {{{ */ FFI_G(symbols) = NULL; FFI_G(tags) = NULL; } + bool clean_symbols = FFI_G(symbols) == NULL; + bool clean_tags = FFI_G(tags) == NULL; FFI_G(default_type_attr) = 0; if (zend_ffi_parse_type(ZSTR_VAL(type_def), ZSTR_LEN(type_def), &dcl) == FAILURE) { zend_ffi_type_dtor(dcl.type); +<<<<<<< HEAD if (is_static_call) { if (FFI_G(tags)) { zend_hash_destroy(FFI_G(tags)); @@ -3789,6 +3792,17 @@ ZEND_METHOD(FFI, new) /* {{{ */ efree(FFI_G(symbols)); FFI_G(symbols) = NULL; } +======= + if (clean_tags && FFI_G(tags)) { + zend_hash_destroy(FFI_G(tags)); + efree(FFI_G(tags)); + FFI_G(tags) = NULL; + } + if (clean_symbols && FFI_G(symbols)) { + zend_hash_destroy(FFI_G(symbols)); + efree(FFI_G(symbols)); + FFI_G(symbols) = NULL; +>>>>>>> PHP-8.2 } return; } @@ -3798,6 +3812,7 @@ ZEND_METHOD(FFI, new) /* {{{ */ is_const = 1; } +<<<<<<< HEAD if (is_static_call) { if (FFI_G(tags)) { zend_ffi_tags_cleanup(&dcl); @@ -3807,6 +3822,15 @@ ZEND_METHOD(FFI, new) /* {{{ */ efree(FFI_G(symbols)); FFI_G(symbols) = NULL; } +======= + if (clean_tags && FFI_G(tags)) { + zend_ffi_tags_cleanup(&dcl); + } + if (clean_symbols && FFI_G(symbols)) { + zend_hash_destroy(FFI_G(symbols)); + efree(FFI_G(symbols)); + FFI_G(symbols) = NULL; +>>>>>>> PHP-8.2 } FFI_G(symbols) = NULL; FFI_G(tags) = NULL; @@ -3925,11 +3949,14 @@ ZEND_METHOD(FFI, cast) /* {{{ */ FFI_G(symbols) = NULL; FFI_G(tags) = NULL; } + bool clean_symbols = FFI_G(symbols) == NULL; + bool clean_tags = FFI_G(tags) == NULL; FFI_G(default_type_attr) = 0; if (zend_ffi_parse_type(ZSTR_VAL(type_def), ZSTR_LEN(type_def), &dcl) == FAILURE) { zend_ffi_type_dtor(dcl.type); +<<<<<<< HEAD if (is_static_call) { if (FFI_G(tags)) { zend_hash_destroy(FFI_G(tags)); @@ -3941,6 +3968,17 @@ ZEND_METHOD(FFI, cast) /* {{{ */ efree(FFI_G(symbols)); FFI_G(symbols) = NULL; } +======= + if (clean_tags && FFI_G(tags)) { + zend_hash_destroy(FFI_G(tags)); + efree(FFI_G(tags)); + FFI_G(tags) = NULL; + } + if (clean_symbols && FFI_G(symbols)) { + zend_hash_destroy(FFI_G(symbols)); + efree(FFI_G(symbols)); + FFI_G(symbols) = NULL; +>>>>>>> PHP-8.2 } return; } @@ -3950,6 +3988,7 @@ ZEND_METHOD(FFI, cast) /* {{{ */ is_const = 1; } +<<<<<<< HEAD if (is_static_call) { if (FFI_G(tags)) { zend_ffi_tags_cleanup(&dcl); @@ -3959,6 +3998,15 @@ ZEND_METHOD(FFI, cast) /* {{{ */ efree(FFI_G(symbols)); FFI_G(symbols) = NULL; } +======= + if (clean_tags && FFI_G(tags)) { + zend_ffi_tags_cleanup(&dcl); + } + if (clean_symbols && FFI_G(symbols)) { + zend_hash_destroy(FFI_G(symbols)); + efree(FFI_G(symbols)); + FFI_G(symbols) = NULL; +>>>>>>> PHP-8.2 } FFI_G(symbols) = NULL; FFI_G(tags) = NULL; @@ -4099,11 +4147,14 @@ ZEND_METHOD(FFI, type) /* {{{ */ FFI_G(symbols) = NULL; FFI_G(tags) = NULL; } + bool clean_symbols = FFI_G(symbols) == NULL; + bool clean_tags = FFI_G(tags) == NULL; FFI_G(default_type_attr) = 0; if (zend_ffi_parse_type(ZSTR_VAL(type_def), ZSTR_LEN(type_def), &dcl) == FAILURE) { zend_ffi_type_dtor(dcl.type); +<<<<<<< HEAD if (is_static_call) { if (FFI_G(tags)) { zend_hash_destroy(FFI_G(tags)); @@ -4124,10 +4175,28 @@ ZEND_METHOD(FFI, type) /* {{{ */ zend_ffi_tags_cleanup(&dcl); } if (FFI_G(symbols)) { +======= + if (clean_tags && FFI_G(tags)) { + zend_hash_destroy(FFI_G(tags)); + efree(FFI_G(tags)); + FFI_G(tags) = NULL; + } + if (clean_symbols && FFI_G(symbols)) { +>>>>>>> PHP-8.2 zend_hash_destroy(FFI_G(symbols)); efree(FFI_G(symbols)); FFI_G(symbols) = NULL; } + return; + } + + if (clean_tags && FFI_G(tags)) { + zend_ffi_tags_cleanup(&dcl); + } + if (clean_symbols && FFI_G(symbols)) { + zend_hash_destroy(FFI_G(symbols)); + efree(FFI_G(symbols)); + FFI_G(symbols) = NULL; } FFI_G(symbols) = NULL; FFI_G(tags) = NULL; diff --git a/ext/ffi/tests/cdef_new.phpt b/ext/ffi/tests/cdef_new.phpt new file mode 100644 index 00000000000..ca3cba5d459 --- /dev/null +++ b/ext/ffi/tests/cdef_new.phpt @@ -0,0 +1,14 @@ +--TEST-- +Definitions should not leak when using FFI::cdef()->new(...) +--EXTENSIONS-- +ffi +--FILE-- +new('struct Example { uint32_t x; }'); +var_dump($struct); +?> +--EXPECT-- +object(FFI\CData:struct Example)#2 (1) { + ["x"]=> + int(0) +}