diff options
-rw-r--r-- | ext/standard/dl.c | 10 | ||||
-rw-r--r-- | main/php_ini.c | 17 | ||||
-rw-r--r-- | win32/winutil.c | 37 | ||||
-rw-r--r-- | win32/winutil.h | 2 |
4 files changed, 66 insertions, 0 deletions
diff --git a/ext/standard/dl.c b/ext/standard/dl.c index 226474efbf..ddc87a40d0 100644 --- a/ext/standard/dl.c +++ b/ext/standard/dl.c @@ -167,6 +167,16 @@ PHPAPI int php_load_extension(char *filename, int type, int start_now) efree(err1); } +#ifdef PHP_WIN32 + if (!php_win32_image_compatible(libpath, NULL, &err1)) { + php_error_docref(NULL, error_type, err1); + efree(err1); + efree(libpath); + DL_UNLOAD(handle); + return FAILURE; + } +#endif + efree(libpath); get_module = (zend_module_entry *(*)(void)) DL_FETCH_SYMBOL(handle, "get_module"); diff --git a/main/php_ini.c b/main/php_ini.c index 7d4e916432..f4c61820ae 100644 --- a/main/php_ini.c +++ b/main/php_ini.c @@ -339,6 +339,13 @@ static void php_load_zend_extension_cb(void *arg) #endif if (IS_ABSOLUTE_PATH(filename, length)) { +#ifdef PHP_WIN32 + char *err; + if (!php_win32_image_compatible(filename, NULL, &err)) { + php_error(E_CORE_WARNING, err); + return FAILURE; + } +#endif zend_load_extension(filename); } else { DL_HANDLE handle; @@ -384,6 +391,16 @@ static void php_load_zend_extension_cb(void *arg) efree(err1); } +#ifdef PHP_WIN32 + if (!php_win32_image_compatible(libpath, NULL, &err1)) { + php_error(E_CORE_WARNING, err1); + efree(err1); + efree(libpath); + DL_UNLOAD(handle); + return FAILURE; + } +#endif + zend_load_extension_handle(handle, libpath); efree(libpath); } diff --git a/win32/winutil.c b/win32/winutil.c index 366a48bb11..18f890fb33 100644 --- a/win32/winutil.c +++ b/win32/winutil.c @@ -22,6 +22,8 @@ #include "codepage.h" #include <bcrypt.h> #include <lmcons.h> +#include <imagehlp.h> + PHP_WINUTIL_API char *php_win32_error_to_msg(HRESULT error) {/*{{{*/ @@ -435,3 +437,38 @@ PHP_WINUTIL_API char *php_win32_get_username(void) return uname; }/*}}}*/ + +PHP_WINUTIL_API BOOL php_win32_image_compatible(const char *name, const char *path, char **err) +{/*{{{*/ + PLOADED_IMAGE img = ImageLoad(name, NULL); + + if (!img) { + DWORD _err = GetLastError(); + char *err_txt = php_win32_error_to_msg(_err); + spprintf(err, 0, "Failed to load %s, %s", name, err_txt); + free(err_txt); + return FALSE; + } + + DWORD major = img->FileHeader->OptionalHeader.MajorLinkerVersion; + DWORD minor = img->FileHeader->OptionalHeader.MinorLinkerVersion; + + /* VS 2015, 2017 and 2019 are binary compatible, but only forward compatible. + It should be fine, if we load a module linked with an older one into + the core linked with the newer one, but not the otherway round. + Otherwise, if the linker major version is not same, it is an error, as + per the current knowledge. + + This check is to be extended as new VS versions come out. */ + if (14 == major && PHP_LINKER_MINOR < minor + || PHP_LINKER_MAJOR != major) { + spprintf(err, 0, "Can't load module '%s' as it's linked with %u.%u, but the core is linked with %d.%d", name, major, minor, PHP_LINKER_MAJOR, PHP_LINKER_MINOR); + ImageUnload(img); + return FALSE; + } + + ImageUnload(img); + + return TRUE; +}/*}}}*/ + diff --git a/win32/winutil.h b/win32/winutil.h index 2899a71292..594f2d8d63 100644 --- a/win32/winutil.h +++ b/win32/winutil.h @@ -55,4 +55,6 @@ PHP_WINUTIL_API int php_win32_code_to_errno(unsigned long w32Err); PHP_WINUTIL_API char *php_win32_get_username(void); +PHP_WINUTIL_API BOOL php_win32_image_compatible(const char *img, const char *path, char **err); + #endif |