From 05c5e5dfde91955263469daa2dd5afcbb5199d17 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 21 Oct 2019 14:52:26 +0300 Subject: [PATCH] Fixed bug #78512 (Cannot make preload work) --- NEWS | 3 +++ ext/opcache/ZendAccelerator.c | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index 056c7739a0b6..636058dd0875 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -4565,6 +4565,11 @@ static int accel_finish_startup(void) zend_accel_error(ACCEL_LOG_FATAL, "Preloading failed to waitpid(%d)", pid); return FAILURE; } + + if (ZCSG(preload_script)) { + preload_load(); + } + zend_shared_alloc_unlock(); if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { return SUCCESS; From 1c9bfcb6a766d4062f2dd1e594b30831d59cc36c Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Tue, 22 Oct 2019 11:33:00 +0200 Subject: [PATCH] Fix #78716: Function name mangling is wrong for some parameter types We have to cater to function parameter alignment when calculating the parameter size. --- NEWS | 4 ++++ ext/ffi/ffi.c | 2 +- ext/ffi/tests/callconv.phpt | 30 +++++++++++++++--------------- ext/ffi/tests/callconv_x86.dll | Bin 8704 -> 8704 bytes 4 files changed, 20 insertions(+), 16 deletions(-) diff --git a/ext/ffi/ffi.c b/ext/ffi/ffi.c index 1d6f84b6b223..1edba157a171 100644 --- a/ext/ffi/ffi.c +++ b/ext/ffi/ffi.c @@ -775,7 +775,7 @@ static size_t zend_ffi_arg_size(zend_ffi_type *type) /* {{{ */ size_t arg_size = 0; ZEND_HASH_FOREACH_PTR(type->func.args, arg_type) { - arg_size += ZEND_FFI_TYPE(arg_type)->size; + arg_size += MAX(ZEND_FFI_TYPE(arg_type)->size, sizeof(size_t)); } ZEND_HASH_FOREACH_END(); return arg_size; } diff --git a/ext/ffi/tests/callconv.phpt b/ext/ffi/tests/callconv.phpt index aa481de2249c..233c73f11010 100644 --- a/ext/ffi/tests/callconv.phpt +++ b/ext/ffi/tests/callconv.phpt @@ -9,32 +9,32 @@ if (PHP_INT_SIZE != 4) die("skip this test is for 32bit platforms only"); --FILE-- cdecl_func(1, 2.3); -$ffi1->stdcall_func(4, 5.6); -$ffi1->fastcall_func(7, 8.9); +$ffi1->cdecl_func(1, 2.3, 'a'); +$ffi1->stdcall_func(4, 5.6, 'b'); +$ffi1->fastcall_func(7, 8.9, 'c'); file_put_contents($headername, "#define FFI_LIB \"$dllname\"\n$header"); $ffi2 = FFI::load($headername); -$ffi2->cdecl_func(2, 3.4); -$ffi2->stdcall_func(5, 6.7); -$ffi2->fastcall_func(8, 9.1); +$ffi2->cdecl_func(2, 3.4, 'a'); +$ffi2->stdcall_func(5, 6.7, 'b'); +$ffi2->fastcall_func(8, 9.1, 'c'); ?> --EXPECT-- -cdecl: 1, 2.300000 -stdcall: 4, 5.600000 -fastcall: 7, 8.900000 -cdecl: 2, 3.400000 -stdcall: 5, 6.700000 -fastcall: 8, 9.100000 +cdecl: 1, 2.300000, a +stdcall: 4, 5.600000, b +fastcall: 7, 8.900000, c +cdecl: 2, 3.400000, a +stdcall: 5, 6.700000, b +fastcall: 8, 9.100000, c --CLEAN-- Date: Tue, 22 Oct 2019 17:52:56 +0300 Subject: [PATCH] Allow loading FFI bindings through ffi.preload directive --- Zend/zend_compile.h | 3 + ext/ffi/ffi.c | 101 ++++++++++++++++++++++++++++------ ext/ffi/php_ffi.h | 1 + ext/ffi/tests/302.phpt | 15 +++++ ext/opcache/ZendAccelerator.c | 31 +++++++---- 5 files changed, 124 insertions(+), 27 deletions(-) create mode 100644 ext/ffi/tests/302.phpt diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 499d0d64b641..c21554e4641e 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -1094,6 +1094,9 @@ END_EXTERN_C() /* disable jumptable optimization for switch statements */ #define ZEND_COMPILE_NO_JUMPTABLES (1<<16) +/* this flag is set when compiler invoked during preloading in separate process */ +#define ZEND_COMPILE_PRELOAD_IN_CHILD (1<<17) + /* The default value for CG(compiler_options) */ #define ZEND_COMPILE_DEFAULT ZEND_COMPILE_HANDLE_OP_ARRAY diff --git a/ext/ffi/ffi.c b/ext/ffi/ffi.c index 1edba157a171..4b7144e11ccc 100644 --- a/ext/ffi/ffi.c +++ b/ext/ffi/ffi.c @@ -3083,15 +3083,13 @@ static zend_ffi_type *zend_ffi_remember_type(zend_ffi_type *type) /* {{{ */ } /* }}} */ -ZEND_METHOD(FFI, load) /* {{{ */ +static zend_ffi *zend_ffi_load(const char *filename, zend_bool preload) /* {{{ */ { - zend_string *fn; struct stat buf; int fd; - char *filename, *code, *code_pos, *scope_name, *lib; + char *code, *code_pos, *scope_name, *lib; size_t code_size, scope_name_len; zend_ffi *ffi; - zend_bool preload = (CG(compiler_options) & ZEND_COMPILE_PRELOAD) != 0; DL_HANDLE handle = NULL; zend_ffi_scope *scope = NULL; zend_string *name; @@ -3099,19 +3097,13 @@ ZEND_METHOD(FFI, load) /* {{{ */ zend_ffi_tag *tag; void *addr; - ZEND_FFI_VALIDATE_API_RESTRICTION(); - ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_STR(fn) - ZEND_PARSE_PARAMETERS_END(); - - filename = ZSTR_VAL(fn); if (stat(filename, &buf) != 0) { if (preload) { zend_error(E_WARNING, "FFI: failed pre-loading '%s', file doesn't exist", filename); } else { zend_throw_error(zend_ffi_exception_ce, "Failed loading '%s', file doesn't exist", filename); } - return; + return NULL; } if ((buf.st_mode & S_IFMT) != S_IFREG) { @@ -3120,7 +3112,7 @@ ZEND_METHOD(FFI, load) /* {{{ */ } else { zend_throw_error(zend_ffi_exception_ce, "Failed loading '%s', not a regular file", filename); } - return; + return NULL; } code_size = buf.st_size; @@ -3134,7 +3126,7 @@ ZEND_METHOD(FFI, load) /* {{{ */ } efree(code); close(fd); - return; + return NULL; } close(fd); code[code_size] = 0; @@ -3153,7 +3145,7 @@ ZEND_METHOD(FFI, load) /* {{{ */ if (!code_pos) { efree(code); FFI_G(persistent) = 0; - return; + return NULL; } code_size -= code_pos - code; @@ -3318,7 +3310,11 @@ ZEND_METHOD(FFI, load) /* {{{ */ } } - ffi = (zend_ffi*)zend_ffi_new(zend_ffi_ce); + if (EG(objects_store).object_buckets) { + ffi = (zend_ffi*)zend_ffi_new(zend_ffi_ce); + } else { + ffi = ecalloc(1, sizeof(zend_ffi)); + } ffi->symbols = scope->symbols; ffi->tags = scope->tags; ffi->persistent = 1; @@ -3333,7 +3329,7 @@ ZEND_METHOD(FFI, load) /* {{{ */ FFI_G(symbols) = NULL; FFI_G(tags) = NULL; - RETURN_OBJ(&ffi->std); + return ffi; cleanup: efree(code); @@ -3348,6 +3344,30 @@ ZEND_METHOD(FFI, load) /* {{{ */ FFI_G(tags) = NULL; } FFI_G(persistent) = 0; + return NULL; +} +/* }}} */ + +ZEND_METHOD(FFI, load) /* {{{ */ +{ + zend_string *fn; + zend_ffi *ffi; + + ZEND_FFI_VALIDATE_API_RESTRICTION(); + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_STR(fn) + ZEND_PARSE_PARAMETERS_END(); + + if (CG(compiler_options) & ZEND_COMPILE_PRELOAD_IN_CHILD) { + zend_throw_error(zend_ffi_exception_ce, "FFI::load() doesn't work in conjunction with \"opcache.pelaod_user\". Use \"ffi.preload\" instead."); + return; + } + + ffi = zend_ffi_load(ZSTR_VAL(fn), (CG(compiler_options) & ZEND_COMPILE_PRELOAD) != 0); + + if (ffi) { + RETURN_OBJ(&ffi->std); + } } /* }}} */ @@ -4813,8 +4833,51 @@ static ZEND_INI_DISP(zend_ffi_enable_displayer_cb) /* {{{ */ ZEND_INI_BEGIN() ZEND_INI_ENTRY3_EX("ffi.enable", "preload", ZEND_INI_SYSTEM, OnUpdateFFIEnable, NULL, NULL, NULL, zend_ffi_enable_displayer_cb) + STD_ZEND_INI_ENTRY("ffi.preload", NULL, ZEND_INI_SYSTEM, OnUpdateString, preload, zend_ffi_globals, ffi_globals) ZEND_INI_END() +static int zend_ffi_preload(char *preload) /* {{{ */ +{ + zend_ffi *ffi; + char *s = NULL, *e, *filename; + + e = preload; + while (*e) { + switch (*e) { + case ZEND_PATHS_SEPARATOR: + if (s) { + filename = estrndup(s, e-s); + ffi = zend_ffi_load(filename, 1); + efree(filename); + if (!ffi) { + return FAILURE; + } + efree(ffi); + s = NULL; + } + break; + default: + if (!s) { + s = e; + } + break; + } + e++; + } + if (s) { + filename = estrndup(s, e-s); + ffi = zend_ffi_load(filename, 1); + efree(filename); + if (!ffi) { + return FAILURE; + } + efree(ffi); + } + + return SUCCESS; +} +/* }}} */ + /* {{{ ZEND_MINIT_FUNCTION */ ZEND_MINIT_FUNCTION(ffi) @@ -4976,6 +5039,12 @@ ZEND_MINIT_FUNCTION(ffi) zend_ffi_ctype_handlers.get_properties = zend_fake_get_properties; zend_ffi_ctype_handlers.get_gc = zend_fake_get_gc; + if (FFI_G(preload)) { + if (zend_ffi_preload(FFI_G(preload)) != SUCCESS) { + return FAILURE; + } + } + return SUCCESS; } /* }}} */ diff --git a/ext/ffi/php_ffi.h b/ext/ffi/php_ffi.h index 0f511fccf05c..b9f01d6e96f4 100644 --- a/ext/ffi/php_ffi.h +++ b/ext/ffi/php_ffi.h @@ -38,6 +38,7 @@ ZEND_BEGIN_MODULE_GLOBALS(ffi) HashTable types; /* preloading */ + char *preload; HashTable *scopes; /* list of preloaded scopes */ /* callbacks */ diff --git a/ext/ffi/tests/302.phpt b/ext/ffi/tests/302.phpt new file mode 100644 index 000000000000..cb0d73d56880 --- /dev/null +++ b/ext/ffi/tests/302.phpt @@ -0,0 +1,15 @@ +--TEST-- +FFI 302: FFI preloading +--SKIPIF-- + + +--INI-- +ffi.enable=1 +ffi.preload={PWD}/300.h +--FILE-- +printf("Hello World from %s!\n", "PHP"); +?> +--EXPECT-- +Hello World from PHP! diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index 636058dd0875..704e1c38d9b7 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -4140,14 +4140,17 @@ static void preload_load(void) if (EG(class_table)) { EG(persistent_classes_count) = EG(class_table)->nNumUsed; } - CG(map_ptr_last) = ZCSG(map_ptr_last); + if (CG(map_ptr_last) != ZCSG(map_ptr_last)) { + CG(map_ptr_last) = ZCSG(map_ptr_last); + CG(map_ptr_size) = ZEND_MM_ALIGNED_SIZE_EX(CG(map_ptr_last) + 1, 4096); + CG(map_ptr_base) = perealloc(CG(map_ptr_base), CG(map_ptr_size) * sizeof(void*), 1); + } } static int accel_preload(const char *config) { zend_file_handle file_handle; int ret; - uint32_t orig_compiler_options; char *orig_open_basedir; size_t orig_map_ptr_last; zval *zv; @@ -4159,14 +4162,6 @@ static int accel_preload(const char *config) preload_orig_compile_file = accelerator_orig_compile_file; accelerator_orig_compile_file = preload_compile_file; - orig_compiler_options = CG(compiler_options); - CG(compiler_options) |= ZEND_COMPILE_PRELOAD; - CG(compiler_options) |= ZEND_COMPILE_HANDLE_OP_ARRAY; -// CG(compiler_options) |= ZEND_COMPILE_IGNORE_INTERNAL_CLASSES; - CG(compiler_options) |= ZEND_COMPILE_DELAYED_BINDING; - CG(compiler_options) |= ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION; -// CG(compiler_options) |= ZEND_COMPILE_IGNORE_OTHER_FILES; - orig_map_ptr_last = CG(map_ptr_last); /* Compile and execute proloading script */ @@ -4207,7 +4202,6 @@ static int accel_preload(const char *config) ret = FAILURE; } zend_end_try(); - CG(compiler_options) = orig_compiler_options; PG(open_basedir) = orig_open_basedir; accelerator_orig_compile_file = preload_orig_compile_file; ZCG(enabled) = 1; @@ -4500,6 +4494,7 @@ static int accel_finish_startup(void) char *(*orig_getenv)(char *name, size_t name_len TSRMLS_DC) = sapi_module.getenv; size_t (*orig_ub_write)(const char *str, size_t str_length) = sapi_module.ub_write; void (*orig_flush)(void *server_context) = sapi_module.flush; + uint32_t orig_compiler_options = CG(compiler_options); #ifdef ZEND_SIGNALS zend_bool old_reset_signals = SIGG(reset); #endif @@ -4595,6 +4590,18 @@ static int accel_finish_startup(void) sapi_module.ub_write = preload_ub_write; sapi_module.flush = preload_flush; +#ifndef ZEND_WIN32 + if (in_child) { + CG(compiler_options) |= ZEND_COMPILE_PRELOAD_IN_CHILD; + } +#endif + CG(compiler_options) |= ZEND_COMPILE_PRELOAD; + CG(compiler_options) |= ZEND_COMPILE_HANDLE_OP_ARRAY; + CG(compiler_options) |= ZEND_COMPILE_IGNORE_INTERNAL_CLASSES; + CG(compiler_options) |= ZEND_COMPILE_DELAYED_BINDING; + CG(compiler_options) |= ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION; + CG(compiler_options) |= ZEND_COMPILE_IGNORE_OTHER_FILES; + zend_interned_strings_switch_storage(1); #ifdef ZEND_SIGNALS @@ -4648,6 +4655,8 @@ static int accel_finish_startup(void) SIGG(reset) = old_reset_signals; #endif + CG(compiler_options) = orig_compiler_options; + sapi_module.activate = orig_activate; sapi_module.deactivate = orig_deactivate; sapi_module.register_server_variables = orig_register_server_variables; From 598bf7f5d5f9c76fd003590083c98736eb7702ab Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Tue, 22 Oct 2019 17:53:34 +0200 Subject: [PATCH] Fix typo --- ext/ffi/ffi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/ffi/ffi.c b/ext/ffi/ffi.c index 4b7144e11ccc..17e8a8409d1f 100644 --- a/ext/ffi/ffi.c +++ b/ext/ffi/ffi.c @@ -3359,7 +3359,7 @@ ZEND_METHOD(FFI, load) /* {{{ */ ZEND_PARSE_PARAMETERS_END(); if (CG(compiler_options) & ZEND_COMPILE_PRELOAD_IN_CHILD) { - zend_throw_error(zend_ffi_exception_ce, "FFI::load() doesn't work in conjunction with \"opcache.pelaod_user\". Use \"ffi.preload\" instead."); + zend_throw_error(zend_ffi_exception_ce, "FFI::load() doesn't work in conjunction with \"opcache.preload_user\". Use \"ffi.preload\" instead."); return; } From dcd772325d0f7702a525f03c7d5dd04bf96d8e18 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Wed, 23 Oct 2019 07:49:13 +0200 Subject: [PATCH] add new ffi.preload option in php.ini and display ini entries in MINFO --- ext/ffi/ffi.c | 2 ++ php.ini-development | 3 +++ php.ini-production | 3 +++ 3 files changed, 8 insertions(+) diff --git a/ext/ffi/ffi.c b/ext/ffi/ffi.c index 17e8a8409d1f..39bf2f82bf09 100644 --- a/ext/ffi/ffi.c +++ b/ext/ffi/ffi.c @@ -5077,6 +5077,8 @@ ZEND_MINFO_FUNCTION(ffi) php_info_print_table_start(); php_info_print_table_header(2, "FFI support", "enabled"); php_info_print_table_end(); + + DISPLAY_INI_ENTRIES(); } /* }}} */ diff --git a/php.ini-development b/php.ini-development index 3aefcd071db4..3f0c90cfca89 100644 --- a/php.ini-development +++ b/php.ini-development @@ -1945,3 +1945,6 @@ ldap.max_links = -1 ; "false" - always disabled ; "true" - always enabled ;ffi.enable=preload + +; List of headers files to preload +;ffi.preload= diff --git a/php.ini-production b/php.ini-production index 8dc9a32e0026..867de11c60d4 100644 --- a/php.ini-production +++ b/php.ini-production @@ -1947,3 +1947,6 @@ ldap.max_links = -1 ; "false" - always disabled ; "true" - always enabled ;ffi.enable=preload + +; List of headers files to preload +;ffi.preload= From fea8c5481bfae651167d90393ddae89e591b0d55 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Wed, 23 Oct 2019 17:18:11 +0300 Subject: [PATCH] Added suppot for glob() wildcard matching in ffi.preload directive --- ext/ffi/ffi.c | 93 +++++++++++++++++++++++++++++++++++++----- ext/ffi/tests/303.phpt | 15 +++++++ php.ini-development | 2 +- php.ini-production | 2 +- 4 files changed, 99 insertions(+), 13 deletions(-) create mode 100644 ext/ffi/tests/303.phpt diff --git a/ext/ffi/ffi.c b/ext/ffi/ffi.c index e2476653f72f..ca6e7c4ef523 100644 --- a/ext/ffi/ffi.c +++ b/ext/ffi/ffi.c @@ -35,6 +35,14 @@ #include #include +#ifdef HAVE_GLOB +#ifdef PHP_WIN32 +#include "win32/glob.h" +#else +#include +#endif +#endif + ZEND_DECLARE_MODULE_GLOBALS(ffi) typedef enum _zend_ffi_tag_kind { @@ -4836,10 +4844,50 @@ ZEND_INI_BEGIN() STD_ZEND_INI_ENTRY("ffi.preload", NULL, ZEND_INI_SYSTEM, OnUpdateString, preload, zend_ffi_globals, ffi_globals) ZEND_INI_END() +static int zend_ffi_preload_glob(const char *filename) /* {{{ */ +{ +#ifdef HAVE_GLOB + glob_t globbuf; + int ret; + unsigned int i; + + memset(&globbuf, 0, sizeof(glob_t)); + + ret = glob(filename, 0, NULL, &globbuf); +#ifdef GLOB_NOMATCH + if (ret == GLOB_NOMATCH || !globbuf.gl_pathc) { +#else + if (!globbuf.gl_pathc) { +#endif + /* pass */ + } else { + for(i=0 ; i + +--INI-- +ffi.enable=1 +ffi.preload={PWD}/300*.h +--FILE-- +printf("Hello World from %s!\n", "PHP"); +?> +--EXPECT-- +Hello World from PHP! diff --git a/php.ini-development b/php.ini-development index 3f0c90cfca89..f44c541a7a10 100644 --- a/php.ini-development +++ b/php.ini-development @@ -1946,5 +1946,5 @@ ldap.max_links = -1 ; "true" - always enabled ;ffi.enable=preload -; List of headers files to preload +; List of headers files to preload, wilcards allowed. ;ffi.preload= diff --git a/php.ini-production b/php.ini-production index 867de11c60d4..b7f2536fd992 100644 --- a/php.ini-production +++ b/php.ini-production @@ -1948,5 +1948,5 @@ ldap.max_links = -1 ; "true" - always enabled ;ffi.enable=preload -; List of headers files to preload +; List of headers files to preload, wilcards allowed. ;ffi.preload= From 69b608cf13f24f7859e564254263fa789e722211 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Thu, 24 Oct 2019 07:43:49 +0200 Subject: [PATCH] typo and better wording --- php.ini-development | 2 +- php.ini-production | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/php.ini-development b/php.ini-development index f44c541a7a10..5bd274016041 100644 --- a/php.ini-development +++ b/php.ini-development @@ -1946,5 +1946,5 @@ ldap.max_links = -1 ; "true" - always enabled ;ffi.enable=preload -; List of headers files to preload, wilcards allowed. +; List of headers files to preload, wildcard patterns allowed. ;ffi.preload= diff --git a/php.ini-production b/php.ini-production index b7f2536fd992..beea6b26500f 100644 --- a/php.ini-production +++ b/php.ini-production @@ -1948,5 +1948,5 @@ ldap.max_links = -1 ; "true" - always enabled ;ffi.enable=preload -; List of headers files to preload, wilcards allowed. +; List of headers files to preload, wildcard patterns allowed. ;ffi.preload=