Nothing Special   »   [go: up one dir, main page]

Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
adsr opened this issue Jul 22, 2022 · 3 comments
Closed

Comments

@adsr
Copy link
Contributor
adsr commented Jul 22, 2022

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

@cmb69
Copy link
Member
cmb69 commented Jul 22, 2022

Hmm, I think we could do that, but that would allow to assign any function pointer to any other. So we would not only ignore the return and parameter types, but also the calling convention. That would seriously undermine the type safety of FFI. To wit:

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

void func(char *str) {
    printf("hello %s\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(char *); void (*func_ptr)(); void call_func();', __DIR__ . '/libffibug.so');
php > $ffi->func_ptr = $ffi->func;
php > $ffi->call_func();

Segmentation fault (core dumped)

If we want to support function pointer compatibility (what looks sensible), we should also check the details (src_type->func and dst_type->func).

@adsr
Copy link
Contributor Author
adsr commented Jul 22, 2022

Yes good idea @cmb69. I'll submit a PR incorporating that.

@adsr
Copy link
Contributor Author
adsr commented Jul 22, 2022

#9107

adsr added a commit to adsr/php-src that referenced this issue Jul 25, 2022
adsr added a commit to adsr/php-src that referenced this issue Jul 27, 2022
@cmb69 cmb69 closed this as completed in 8cf9c2f Jul 27, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants