From 6db3cf2aa850b172b557a56d59a3dae78eead5f0 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Wed, 23 Oct 2019 09:35:32 +0200 Subject: fix preload, add more upstream patches for #78713 #78716 --- 1417352dda354c22db43a8d4dbaa967575e2720c.patch | 332 +++++++++++++++++++++++++ 1 file changed, 332 insertions(+) create mode 100644 1417352dda354c22db43a8d4dbaa967575e2720c.patch (limited to '1417352dda354c22db43a8d4dbaa967575e2720c.patch') diff --git a/1417352dda354c22db43a8d4dbaa967575e2720c.patch b/1417352dda354c22db43a8d4dbaa967575e2720c.patch new file mode 100644 index 0000000..5e4da11 --- /dev/null +++ b/1417352dda354c22db43a8d4dbaa967575e2720c.patch @@ -0,0 +1,332 @@ +From 1417352dda354c22db43a8d4dbaa967575e2720c Mon Sep 17 00:00:00 2001 +From: Dmitry Stogov +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; -- cgit