From db991bc0f13caecbfd505e8ca155a91d0c97b1be Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Fri, 11 Oct 2024 17:50:15 +0200 Subject: [PATCH] FFI: support symbol lookup without specifying lib on Windows MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This works similar to `dlsym(RTLD_DEFAULT, …)` with the caveat that symbols on Windows may not be unique, and are usually qualified by the module they are exported from. That means that wrong symbols may be fetched, potentially causing serious issues; therefore this usage is not recommended for production purposes, but is a nice simplification for quick experiments and the ext/ffi test suite. Closes GH-16351. --- UPGRADING | 5 +++++ ext/ffi/ffi.c | 34 ++++++++++++++++++++++++++++++++++ ext/ffi/tests/100.phpt | 7 +++---- ext/ffi/tests/101.phpt | 7 +++---- ext/ffi/tests/200.phpt | 4 ++-- ext/ffi/tests/300-win32.h.in | 4 ---- ext/ffi/tests/301-win32.phpt | 29 ----------------------------- ext/ffi/tests/301.phpt | 2 -- ext/ffi/tests/bug77632b.phpt | 6 ++---- ext/ffi/tests/bug78714.phpt | 3 +-- ext/ffi/tests/bug79096.phpt | 12 +----------- ext/ffi/tests/bug79177.phpt | 12 +----------- ext/ffi/tests/bug79532.phpt | 13 +------------ ext/ffi/tests/bug80847.phpt | 11 +---------- ext/ffi/tests/bug_gh9090.phpt | 11 +---------- ext/ffi/tests/gh11934b.phpt | 12 +----------- ext/ffi/tests/utils.inc | 20 +------------------- 17 files changed, 57 insertions(+), 135 deletions(-) delete mode 100644 ext/ffi/tests/300-win32.h.in delete mode 100644 ext/ffi/tests/301-win32.phpt diff --git a/UPGRADING b/UPGRADING index 110080e2ee4..6a7a54f7174 100644 --- a/UPGRADING +++ b/UPGRADING @@ -116,6 +116,11 @@ PHP 8.5 UPGRADE NOTES PHP_RELEASE_VERSION are now always numbers. Previously, they have been strings for buildconf builds. +* FFI: + . It is no longer necessary to specify the library when using FFI::cdef() + and FFI::load(). However, this convenience feature should not be used in + production. + ======================================== 13. Other Changes ======================================== diff --git a/ext/ffi/ffi.c b/ext/ffi/ffi.c index 2648162ae9c..dc044885c02 100644 --- a/ext/ffi/ffi.c +++ b/ext/ffi/ffi.c @@ -2974,6 +2974,40 @@ static zend_always_inline bool zend_ffi_validate_api_restriction(zend_execute_da } \ } while (0) +#ifdef PHP_WIN32 +# ifndef DWORD_MAX +# define DWORD_MAX ULONG_MAX +# endif +# define NUM_MODULES 1024 +/* A rough approximation of dlysm(RTLD_DEFAULT) */ +static void *dlsym_loaded(char *symbol) +{ + HMODULE modules_static[NUM_MODULES], *modules = modules_static; + DWORD num = NUM_MODULES, i; + void * addr; + if (!EnumProcessModules(GetCurrentProcess(), modules, num * sizeof(HMODULE), &num)) { + return NULL; + } + if (num >= NUM_MODULES && num <= DWORD_MAX / sizeof(HMODULE)) { + modules = emalloc(num *sizeof(HMODULE)); + if (!EnumProcessModules(GetCurrentProcess(), modules, num * sizeof(HMODULE), &num)) { + efree(modules); + return NULL; + } + } + for (i = 0; i < num; i++) { + addr = GetProcAddress(modules[i], symbol); + if (addr != NULL) break; + } + if (modules != modules_static) { + efree(modules); + } + return addr; +} +# undef DL_FETCH_SYMBOL +# define DL_FETCH_SYMBOL(h, s) (h == NULL ? dlsym_loaded(s) : GetProcAddress(h, s)) +#endif + ZEND_METHOD(FFI, cdef) /* {{{ */ { zend_string *code = NULL; diff --git a/ext/ffi/tests/100.phpt b/ext/ffi/tests/100.phpt index 33b974a37b1..f231170315f 100644 --- a/ext/ffi/tests/100.phpt +++ b/ext/ffi/tests/100.phpt @@ -3,10 +3,9 @@ FFI 100: PHP symbols --EXTENSIONS-- ffi --SKIPIF-- - get_zend_version())[0])); //var_dump(trim(FFI::string($zend->get_zend_version()))); var_dump($zend->zend_printf); diff --git a/ext/ffi/tests/101.phpt b/ext/ffi/tests/101.phpt index 4730e2689e0..3362e98b9fd 100644 --- a/ext/ffi/tests/101.phpt +++ b/ext/ffi/tests/101.phpt @@ -3,10 +3,9 @@ FFI 101: PHP symbols (function address) --EXTENSIONS-- ffi --SKIPIF-- - get_zend_version; var_dump(trim(explode("\n",$f())[0])); //var_dump(trim(FFI::string($zend->get_zend_version()))); diff --git a/ext/ffi/tests/200.phpt b/ext/ffi/tests/200.phpt index 92aedc5435b..aae410de7b1 100644 --- a/ext/ffi/tests/200.phpt +++ b/ext/ffi/tests/200.phpt @@ -6,7 +6,7 @@ ffi ---INI-- -ffi.enable=1 ---FILE-- -php_printf("Hello World from %s!\n", "PHP"); -?> ---CLEAN-- - ---EXPECT-- -Hello World from PHP! diff --git a/ext/ffi/tests/301.phpt b/ext/ffi/tests/301.phpt index 0677a2cf300..efe92633f07 100644 --- a/ext/ffi/tests/301.phpt +++ b/ext/ffi/tests/301.phpt @@ -2,8 +2,6 @@ FFI 301: FFI loading --EXTENSIONS-- ffi ---SKIPIF-- - --INI-- ffi.enable=1 --FILE-- diff --git a/ext/ffi/tests/bug77632b.phpt b/ext/ffi/tests/bug77632b.phpt index 044c84ec097..8aedd0aa8ae 100644 --- a/ext/ffi/tests/bug77632b.phpt +++ b/ext/ffi/tests/bug77632b.phpt @@ -4,9 +4,8 @@ Bug #77632 (FFI function pointers with variadics) ffi --SKIPIF-- zend_printf)(...$args); $args2 = ["Hello, %s from zend_printf\n", "world"]; diff --git a/ext/ffi/tests/bug78714.phpt b/ext/ffi/tests/bug78714.phpt index 81017b27d56..9542bdcb70c 100644 --- a/ext/ffi/tests/bug78714.phpt +++ b/ext/ffi/tests/bug78714.phpt @@ -6,9 +6,8 @@ ffi ffi.enable=1 --FILE-- get_zend_version()), 0, 4) . "\n"; ?> --EXPECT-- diff --git a/ext/ffi/tests/bug79096.phpt b/ext/ffi/tests/bug79096.phpt index 8c7ce6cc2af..66db0a57392 100644 --- a/ext/ffi/tests/bug79096.phpt +++ b/ext/ffi/tests/bug79096.phpt @@ -5,7 +5,6 @@ ffi zend_test --FILE-- bug79096(); var_dump($struct); ?> diff --git a/ext/ffi/tests/bug79177.phpt b/ext/ffi/tests/bug79177.phpt index 2b6e449d36d..fe980f95c65 100644 --- a/ext/ffi/tests/bug79177.phpt +++ b/ext/ffi/tests/bug79177.phpt @@ -5,22 +5,12 @@ ffi zend_test --FILE-- bug79177_cb = function() { throw new \RuntimeException('Not allowed'); }; diff --git a/ext/ffi/tests/bug79532.phpt b/ext/ffi/tests/bug79532.phpt index 386c62540c1..553cfe71bef 100644 --- a/ext/ffi/tests/bug79532.phpt +++ b/ext/ffi/tests/bug79532.phpt @@ -5,22 +5,11 @@ ffi zend_test --FILE-- new("off_t[3]"); $ffi->bug79532($array, 3); var_dump($array); diff --git a/ext/ffi/tests/bug80847.phpt b/ext/ffi/tests/bug80847.phpt index 83929de7512..da499b1586f 100644 --- a/ext/ffi/tests/bug80847.phpt +++ b/ext/ffi/tests/bug80847.phpt @@ -9,7 +9,6 @@ if (PHP_OS_FAMILY == 'Windows' && ((1 << 31) > 0)) die('xfail libffi doesn\'t pr ?> --FILE-- new('bug80847_02'); $x->a->b = 42; $x->a->c = 42.5; diff --git a/ext/ffi/tests/bug_gh9090.phpt b/ext/ffi/tests/bug_gh9090.phpt index 795e7bcaa5a..a13aaafe3aa 100644 --- a/ext/ffi/tests/bug_gh9090.phpt +++ b/ext/ffi/tests/bug_gh9090.phpt @@ -6,7 +6,6 @@ zend_test --FILE-- gh11934b_ffi_var_test_cdata->cdata = 2; var_dump($ffi->gh11934b_ffi_var_test_cdata); $source = $ffi->new('int'); diff --git a/ext/ffi/tests/utils.inc b/ext/ffi/tests/utils.inc index 63c020fb539..d5a9fc31e6e 100644 --- a/ext/ffi/tests/utils.inc +++ b/ext/ffi/tests/utils.inc @@ -1,28 +1,10 @@