libnm, libnm-utils: error out if mixed libnm/libnm-util symbols are detected
authorDan Winship <danw@gnome.org>
Fri, 25 Jul 2014 21:50:14 +0000 (17:50 -0400)
committerDan Winship <danw@gnome.org>
Fri, 1 Aug 2014 18:34:40 +0000 (14:34 -0400)
If a program accidentally ends up linking in both libnm and libnm-util
(presumably via different dependencies), error out immediately.

.gitignore
libnm-core/nm-utils.c
libnm-util/nm-utils.c
libnm-util/tests/Makefile.am
libnm-util/tests/test-general.c
libnm-util/tests/test-libnm-linking.c [new file with mode: 0644]

index 0ad930a..2c3ccc4 100644 (file)
@@ -193,6 +193,7 @@ valgrind-*.log
 /libnm-util/tests/test-crypto
 /libnm-util/tests/test-settings-defaults
 /libnm-util/tests/test-general
+/libnm-util/tests/test-libnm-linking
 /libnm-util/tests/test-need-secrets
 /libnm-util/tests/test-secrets
 /libnm-util/tests/test-setting-8021x
index 9be9077..4c3a89f 100644 (file)
@@ -26,6 +26,7 @@
 #include <netinet/ether.h>
 #include <linux/if_infiniband.h>
 #include <uuid/uuid.h>
+#include <gmodule.h>
 
 #include "nm-utils.h"
 #include "nm-utils-private.h"
@@ -201,6 +202,18 @@ get_encodings_for_lang (const char *lang,
 
 /* init, deinit for libnm_util */
 
+static void __attribute__((constructor))
+_check_symbols (void)
+{
+       GModule *self;
+       gpointer func;
+
+       self = g_module_open (NULL, 0);
+       if (g_module_symbol (self, "nm_util_get_private", &func))
+               g_error ("libnm-util symbols detected; Mixing libnm with libnm-util/libnm-glib is not supported");
+       g_module_close (self);
+}
+
 static gboolean initialized = FALSE;
 
 /**
index 9c96601..a511353 100644 (file)
@@ -26,6 +26,7 @@
 #include <netinet/ether.h>
 #include <linux/if_infiniband.h>
 #include <uuid/uuid.h>
+#include <gmodule.h>
 
 #include "nm-utils.h"
 #include "nm-utils-private.h"
@@ -202,6 +203,18 @@ get_encodings_for_lang (const char *lang,
 
 /* init, deinit for libnm_util */
 
+static void __attribute__((constructor))
+_check_symbols (void)
+{
+       GModule *self;
+       gpointer func;
+
+       self = g_module_open (NULL, 0);
+       if (g_module_symbol (self, "nm_device_state_get_type", &func))
+               g_error ("libnm symbols detected; Mixing libnm with libnm-util/libnm-glib is not supported");
+       g_module_close (self);
+}
+
 static gboolean initialized = FALSE;
 
 /**
index 2b3366f..3acc4fc 100644 (file)
@@ -9,6 +9,7 @@ AM_CPPFLAGS = \
        -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \
        $(GLIB_CFLAGS) \
        $(DBUS_CFLAGS) \
+       -DBUILD_DIR=\"$(abs_builddir)\" \
        -DTEST_CERT_DIR=\"$(top_srcdir)/libnm-util/tests/certs/\"
 
 noinst_PROGRAMS = \
@@ -17,7 +18,8 @@ noinst_PROGRAMS = \
        test-secrets \
        test-general \
        test-setting-8021x \
-       test-setting-dcb
+       test-setting-dcb \
+       test-libnm-linking
 
 test_settings_defaults_SOURCES = \
        test-settings-defaults.c
@@ -51,6 +53,8 @@ test_general_LDADD = \
        $(GLIB_LIBS) \
        $(DBUS_LIBS)
 
+test_general_DEPENDENCIES = test-libnm-linking
+
 test_setting_8021x_SOURCES = \
        test-setting-8021x.c
 
@@ -67,6 +71,15 @@ test_setting_dcb_LDADD = \
        $(GLIB_LIBS) \
        $(DBUS_LIBS)
 
+test_libnm_linking_SOURCES = \
+       test-libnm-linking.c
+
+test_libnm_linking_LDADD = \
+       $(top_builddir)/libnm/libnm.la \
+       $(top_builddir)/libnm-util/libnm-util.la \
+       $(GLIB_LIBS) \
+       $(DBUS_LIBS)
+
 check-local: test-crypto test-setting-8021x
 # Private key and CA certificate in the same file (PEM)
        $(abs_builddir)/test-setting-8021x $(srcdir)/certs/test_key_and_cert.pem "test"
index 877c38a..b3d358d 100644 (file)
@@ -24,6 +24,7 @@
 #include <string.h>
 #include <netinet/ether.h>
 #include <linux/if_infiniband.h>
+#include <sys/wait.h>
 
 #include <nm-utils.h>
 
@@ -2445,6 +2446,25 @@ test_connection_normalize_virtual_iface_name (void)
        g_object_unref (con);
 }
 
+static void
+test_libnm_linking (void)
+{
+       char *argv[] = { "./test-libnm-linking", NULL };
+       char *out, *err;
+       int status;
+       GError *error = NULL;
+
+       g_spawn_sync (BUILD_DIR, argv, NULL, G_SPAWN_DEFAULT, NULL, NULL,
+                     &out, &err, &status, &error);
+       g_assert_no_error (error);
+
+       g_assert (WIFSIGNALED (status));
+
+       g_assert (strstr (err, "Mixing libnm") != NULL);
+       g_free (out);
+       g_free (err);
+}
+
 NMTST_DEFINE ();
 
 int main (int argc, char **argv)
@@ -2520,6 +2540,8 @@ int main (int argc, char **argv)
        test_setting_wireless_security_changed_signal ();
        test_setting_802_1x_changed_signal ();
 
+       test_libnm_linking ();
+
        base = g_path_get_basename (argv[0]);
        fprintf (stdout, "%s: SUCCESS\n", base);
        g_free (base);
diff --git a/libnm-util/tests/test-libnm-linking.c b/libnm-util/tests/test-libnm-linking.c
new file mode 100644 (file)
index 0000000..dd81d1c
--- /dev/null
@@ -0,0 +1,44 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2014 Red Hat, Inc.
+ *
+ */
+
+#include <glib.h>
+#include <nm-utils.h>
+
+extern GType nm_state_get_type (void);
+
+int
+main (int argc, char **argv)
+{
+       /* If we reach main(), then the test has failed. */
+       g_printerr ("libnm/libnm-util constructor failed to detect symbol mixing\n");
+
+       /* This is just to ensure that both libnm.so and libnm-util.so get pulled
+        * in; libnm-util doesn't have "nm_state_get_type" and libnm doesn't have
+        * "nm_utils_slist_free". (We intentionally choose different symbols than the
+        * ones that the libraries check for.)
+        */
+       nm_state_get_type ();
+       G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
+       nm_utils_slist_free (NULL, g_free);
+       G_GNUC_END_IGNORE_DEPRECATIONS;
+
+       g_assert_not_reached ();
+}