From ef965fe3b75969acebd9b0fc2751fca07216780f Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Thu, 10 Oct 2024 23:31:27 +0200 Subject: [PATCH 1/3] 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. --- ext/ffi/ffi.c | 23 +++++++++++++++++++++++ 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 +------------------- 16 files changed, 41 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/ext/ffi/ffi.c b/ext/ffi/ffi.c index 38d413c504371..49c243fdfee1d 100644 --- a/ext/ffi/ffi.c +++ b/ext/ffi/ffi.c @@ -2968,6 +2968,29 @@ static zend_always_inline bool zend_ffi_validate_api_restriction(zend_execute_da } \ } while (0) +#ifdef PHP_WIN32 +#define NUM_MODULES 1024 +/* A rough approximation of dlysm(RTLD_DEFAULT) */ +static void *dlsym_loaded(char *symbol) +{ + HMODULE modules[NUM_MODULES]; + DWORD num, i; + void * addr; + if (!EnumProcessModules(GetCurrentProcess(), modules, sizeof modules, &num)) { + return NULL; + } + if (num >= NUM_MODULES) { + num = NUM_MODULES - 1; + } + for (i = 0; i < num; i++) { + addr = GetProcAddress(modules[i], symbol); + if (addr != NULL) break; + } + return addr; +} +# 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 33b974a37b183..f231170315f30 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 4730e2689e03b..3362e98b9fdfb 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 92aedc5435bb8..aae410de7b163 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 0677a2cf30053..efe92633f07a2 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 044c84ec097a3..8aedd0aa8aec9 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 81017b27d56cd..9542bdcb70c8b 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 8c7ce6cc2af70..66db0a573927a 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 2b6e449d36d6a..fe980f95c6517 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 386c62540c163..553cfe71bef0c 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 83929de7512b4..da499b1586f18 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 795e7bcaa5aa9..a13aaafe3aa98 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 63c020fb5393d..d5a9fc31e6eae 100644 --- a/ext/ffi/tests/utils.inc +++ b/ext/ffi/tests/utils.inc @@ -1,28 +1,10 @@ Date: Fri, 11 Oct 2024 00:40:39 +0200 Subject: [PATCH 2/3] fix --- ext/ffi/ffi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ext/ffi/ffi.c b/ext/ffi/ffi.c index 49c243fdfee1d..329871ec031fa 100644 --- a/ext/ffi/ffi.c +++ b/ext/ffi/ffi.c @@ -2969,7 +2969,7 @@ static zend_always_inline bool zend_ffi_validate_api_restriction(zend_execute_da } while (0) #ifdef PHP_WIN32 -#define NUM_MODULES 1024 +# define NUM_MODULES 1024 /* A rough approximation of dlysm(RTLD_DEFAULT) */ static void *dlsym_loaded(char *symbol) { @@ -2988,6 +2988,7 @@ static void *dlsym_loaded(char *symbol) } return addr; } +# undef DL_FETCH_SYMBOL # define DL_FETCH_SYMBOL(h, s) (h == NULL ? dlsym_loaded(s) : GetProcAddress(h, s)) #endif From 814e1ab03903a155bd365977536f6e66b773e9f9 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Fri, 11 Oct 2024 17:50:15 +0200 Subject: [PATCH 3/3] Use larger dynamic buffer if necessary --- ext/ffi/ffi.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/ext/ffi/ffi.c b/ext/ffi/ffi.c index 329871ec031fa..78118aedb4646 100644 --- a/ext/ffi/ffi.c +++ b/ext/ffi/ffi.c @@ -2969,23 +2969,33 @@ 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[NUM_MODULES]; - DWORD num, i; + HMODULE modules_static[NUM_MODULES], *modules = modules_static; + DWORD num = NUM_MODULES, i; void * addr; - if (!EnumProcessModules(GetCurrentProcess(), modules, sizeof modules, &num)) { + if (!EnumProcessModules(GetCurrentProcess(), modules, num * sizeof(HMODULE), &num)) { return NULL; } - if (num >= NUM_MODULES) { - num = NUM_MODULES - 1; + 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