diff --git a/ext/ffi/ffi.c b/ext/ffi/ffi.c index fc8bb9a1b09f..0f5e97cba57f 100644 --- a/ext/ffi/ffi.c +++ b/ext/ffi/ffi.c @@ -188,6 +188,10 @@ typedef struct _zend_ffi_ctype { zend_ffi_type *type; } zend_ffi_ctype; +/* This is a "mutable" copy of zend_empty_array that prevents asserts in attempts of iteration + * (see https://github.com/php/php-src/issues/9697) */ +static HashTable _empty_array; + static zend_class_entry *zend_ffi_exception_ce; static zend_class_entry *zend_ffi_parser_exception_ce; static zend_class_entry *zend_ffi_ce; @@ -4699,7 +4703,7 @@ static ZEND_COLD zend_function *zend_fake_get_method(zend_object **obj_ptr, zend static HashTable *zend_fake_get_properties(zend_object *obj) /* {{{ */ { - return (HashTable*)&zend_empty_array; + return &_empty_array; } /* }}} */ @@ -4935,6 +4939,10 @@ ZEND_MINIT_FUNCTION(ffi) REGISTER_INI_ENTRIES(); + memcpy(&_empty_array, &zend_empty_array, sizeof(HashTable)); + GC_SET_REFCOUNT(&_empty_array, 1); + GC_TYPE_INFO(&_empty_array) = GC_ARRAY; + FFI_G(is_cli) = strcmp(sapi_module.name, "cli") == 0; INIT_NS_CLASS_ENTRY(ce, "FFI", "Exception", NULL); diff --git a/ext/ffi/tests/gh9697-2.phpt b/ext/ffi/tests/gh9697-2.phpt new file mode 100644 index 000000000000..94745d6c7ec3 --- /dev/null +++ b/ext/ffi/tests/gh9697-2.phpt @@ -0,0 +1,20 @@ +--TEST-- +FFI: Test deprecated use of array helper functions on FFI classes doesn't crash +--SKIPIF-- + +--INI-- +ffi.enable=1 +--FILE-- + +--EXPECTF-- +bool(false) +bool(false) +bool(false) +bool(false)