summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ext/standard/dl.c10
-rw-r--r--main/php_ini.c17
-rw-r--r--win32/winutil.c37
-rw-r--r--win32/winutil.h2
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