@@ -214,6 +214,7 @@ static ZEND_FUNCTION(ffi_trampoline);
214
214
static ZEND_COLD void zend_ffi_return_unsupported (zend_ffi_type * type );
215
215
static ZEND_COLD void zend_ffi_pass_unsupported (zend_ffi_type * type );
216
216
static ZEND_COLD void zend_ffi_assign_incompatible (zval * arg , zend_ffi_type * type );
217
+ static bool zend_ffi_is_compatible_type (zend_ffi_type * dst_type , zend_ffi_type * src_type );
217
218
218
219
#if FFI_CLOSURES
219
220
static void * zend_ffi_create_callback (zend_ffi_type * type , zval * value );
@@ -255,6 +256,39 @@ static zend_object *zend_ffi_cdata_new(zend_class_entry *class_type) /* {{{ */
255
256
}
256
257
/* }}} */
257
258
259
+ static bool zend_ffi_func_ptr_are_compatible (zend_ffi_type * dst_type , zend_ffi_type * src_type ) /* {{{ */
260
+ {
261
+ uint32_t dst_argc , src_argc , i ;
262
+ zend_ffi_type * dst_arg , * src_arg ;
263
+
264
+ ZEND_ASSERT (dst_type -> kind == ZEND_FFI_TYPE_FUNC );
265
+ ZEND_ASSERT (src_type -> kind == ZEND_FFI_TYPE_FUNC );
266
+
267
+ /* Ensure compatible ret_type */
268
+ if (!zend_ffi_is_compatible_type (dst_type -> func .ret_type , src_type -> func .ret_type )) {
269
+ return 0 ;
270
+ }
271
+
272
+ /* Ensure same arg count */
273
+ dst_argc = dst_type -> func .args ? zend_hash_num_elements (dst_type -> func .args ) : 0 ;
274
+ src_argc = src_type -> func .args ? zend_hash_num_elements (src_type -> func .args ) : 0 ;
275
+ if (dst_argc != src_argc ) {
276
+ return 0 ;
277
+ }
278
+
279
+ /* Ensure compatible args */
280
+ for (i = 0 ; i < dst_argc ; i ++ ) {
281
+ dst_arg = zend_hash_index_find_ptr (dst_type -> func .args , i );
282
+ src_arg = zend_hash_index_find_ptr (src_type -> func .args , i );
283
+ if (!zend_ffi_is_compatible_type (ZEND_FFI_TYPE (dst_arg ), ZEND_FFI_TYPE (src_arg ))) {
284
+ return 0 ;
285
+ }
286
+ }
287
+
288
+ return 1 ;
289
+ }
290
+ /* }}} */
291
+
258
292
static bool zend_ffi_is_compatible_type (zend_ffi_type * dst_type , zend_ffi_type * src_type ) /* {{{ */
259
293
{
260
294
while (1 ) {
@@ -269,6 +303,9 @@ static bool zend_ffi_is_compatible_type(zend_ffi_type *dst_type, zend_ffi_type *
269
303
if (dst_type -> kind == ZEND_FFI_TYPE_VOID ||
270
304
src_type -> kind == ZEND_FFI_TYPE_VOID ) {
271
305
return 1 ;
306
+ } else if (dst_type -> kind == ZEND_FFI_TYPE_FUNC &&
307
+ src_type -> kind == ZEND_FFI_TYPE_FUNC ) {
308
+ return zend_ffi_func_ptr_are_compatible (dst_type , src_type );
272
309
}
273
310
} else if (dst_type -> kind == ZEND_FFI_TYPE_ARRAY &&
274
311
(dst_type -> array .length == src_type -> array .length ||
0 commit comments