Skip to content

FFI Incompatible types when assigning to type 'void(*)()' from type 'void(*)()' #9090

Description

@adsr

Description

It appears we're unable to assign a function pointer via FFI:

$ cat ffibug.c 
#include <stdio.h>

void func() {
    printf("hello\n");
}

void (*func_ptr)() = NULL;

void call_func() {
    if (func_ptr != NULL) func_ptr();
}
$ gcc -shared -fPIC -o libffibug.so ffibug.c
$ php -v
PHP 8.2.0-dev (cli) (built: Jul 19 2022 20:25:19) (NTS DEBUG)
Copyright (c) The PHP Group
Zend Engine v4.2.0-dev, Copyright (c) Zend Technologies
$ php -a
Interactive shell

php > $ffi = FFI::cdef('void func(); void (*func_ptr)(); void call_func();', __DIR__ . '/libffibug.so');
php > $ffi->call_func();
php > $ffi->func_ptr = $ffi->func;

Warning: Uncaught FFI\Exception: Incompatible types when assigning to type 'void(*)()' from type 'void(*)()' in php shell code:1
Stack trace:
#0 {main}
  thrown in php shell code on line 1
php > 

The following patch seems to fix:

diff --git a/ext/ffi/ffi.c b/ext/ffi/ffi.c
index cb82c3a3c3..3cd568826f 100644
--- a/ext/ffi/ffi.c
+++ b/ext/ffi/ffi.c
@@ -267,7 +267,8 @@ static bool zend_ffi_is_compatible_type(zend_ffi_type *dst_type, zend_ffi_type *
 				dst_type = ZEND_FFI_TYPE(dst_type->pointer.type);
 				src_type = ZEND_FFI_TYPE(src_type->pointer.type);
 				if (dst_type->kind == ZEND_FFI_TYPE_VOID ||
-				    src_type->kind == ZEND_FFI_TYPE_VOID) {
+				    src_type->kind == ZEND_FFI_TYPE_VOID ||
+				    src_type->kind == dst_type->kind) {
 				    return 1;
 				}
 			} else if (dst_type->kind == ZEND_FFI_TYPE_ARRAY &&
$ php -a
Interactive shell

php > $ffi = FFI::cdef('void func(); void (*func_ptr)(); void call_func();', __DIR__ . '/libffibug.so');
php > $ffi->call_func();
php > $ffi->func_ptr = $ffi->func;
php > $ffi->call_func();
hello
php > 
$ 

I'm not familiar with FFI internals so could use a review. FFI tests continue to pass at least. If it looks ok I can follow up with a PR + phpt.

PHP Version

HEAD

Operating System

Debian testing

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions