From 73d913519d710b58742bc0136c2063c146388d20 Mon Sep 17 00:00:00 2001 From: Randy Eckenrode Date: Wed, 10 Jul 2024 18:27:53 -0400 Subject: [PATCH 1/2] gmodule-dl: fix G_MODULE_BIND_LOCAL on Darwin According to POSIX, the default behavior of `dlopen` is unspecified when its flags include neither `RTLD_LOCAL` nor `RTLD_GLOBAL`. Consequently, different platforms have different default behavior. The default on Linux is `RTLD_LOCAL`, but the default on Darwin is `RTLD_GLOBAL`. By passing `0` to `dlopen`, this results in the opposite of the caller's intent when using `G_MODULE_BIND_LOCAL`. Passing `RTLD_LOCAL` for `G_MODULE_BIND_LOCAL` allows the correct behavior to be observed regardless of the platform's default. --- gmodule/gmodule-dl.c | 2 +- gmodule/tests/module-test.c | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/gmodule/gmodule-dl.c b/gmodule/gmodule-dl.c index 6d1c5fab7..871d71b5d 100644 --- a/gmodule/gmodule-dl.c +++ b/gmodule/gmodule-dl.c @@ -136,7 +136,7 @@ _g_module_open (const gchar *file_name, lock_dlerror (); handle = dlopen (file_name, - (bind_local ? 0 : RTLD_GLOBAL) | (bind_lazy ? RTLD_LAZY : RTLD_NOW)); + (bind_local ? RTLD_LOCAL : RTLD_GLOBAL) | (bind_lazy ? RTLD_LAZY : RTLD_NOW)); if (!handle) { const gchar *message = fetch_dlerror (TRUE); diff --git a/gmodule/tests/module-test.c b/gmodule/tests/module-test.c index d00656c75..1ecbaa4b7 100644 --- a/gmodule/tests/module-test.c +++ b/gmodule/tests/module-test.c @@ -233,6 +233,37 @@ test_module_invalid_libtool_archive (void) g_free (la_filename); } +static void +test_local_binding (void) +{ + gchar *plugin = NULL; + GModule *module_plugin = NULL, *module_self = NULL; + GError *error = NULL; + + gboolean found_symbol = FALSE; + gpointer symbol = NULL; + + g_test_summary ("Test that binding a library's symbols locally does not add them globally"); + + plugin = g_test_build_filename (G_TEST_BUILT, MODULE_FILENAME_PREFIX "moduletestplugin_a_" MODULE_TYPE, NULL); + + module_plugin = g_module_open_full (plugin, G_MODULE_BIND_LOCAL, &error); + g_assert_no_error (error); + g_assert_nonnull (module_plugin); + + module_self = g_module_open_full (NULL, 0, &error); + g_assert_no_error (error); + g_assert_nonnull (module_self); + + found_symbol = g_module_symbol (module_self, "gplugin_say_boo_func", &symbol); + g_assert_false (found_symbol); + g_assert_null (symbol); + + g_module_close (module_self); + g_module_close (module_plugin); + g_free (plugin); +} + int main (int argc, char *argv[]) { @@ -240,6 +271,7 @@ main (int argc, char *argv[]) g_test_add_func ("/module/basics", test_module_basics); g_test_add_func ("/module/invalid-libtool-archive", test_module_invalid_libtool_archive); + g_test_add_func ("/module/local-binding", test_local_binding); return g_test_run (); } From 3ab13ddc4ba680ab0e50fae242cc617d04c6575d Mon Sep 17 00:00:00 2001 From: Randy Eckenrode Date: Wed, 10 Jul 2024 22:55:18 -0400 Subject: [PATCH 2/2] gmodule: skip local-binding test on Windows --- gmodule/tests/module-test.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/gmodule/tests/module-test.c b/gmodule/tests/module-test.c index 1ecbaa4b7..782e96fdc 100644 --- a/gmodule/tests/module-test.c +++ b/gmodule/tests/module-test.c @@ -245,6 +245,11 @@ test_local_binding (void) g_test_summary ("Test that binding a library's symbols locally does not add them globally"); +#if defined(G_PLATFORM_WIN32) + g_test_skip ("G_MODULE_BIND_LOCAL is not supported on Windows."); + return; +#endif + plugin = g_test_build_filename (G_TEST_BUILT, MODULE_FILENAME_PREFIX "moduletestplugin_a_" MODULE_TYPE, NULL); module_plugin = g_module_open_full (plugin, G_MODULE_BIND_LOCAL, &error);