NetworkManager/0008-utf8safe-fixes-rh1443114.patch

1804 lines
56 KiB
Diff
Raw Normal View History

From 7f3d60df818fb2b1dd99b12f893a50fd2402968f Mon Sep 17 00:00:00 2001
From: Thomas Haller <thaller@redhat.com>
Date: Wed, 17 May 2017 16:45:46 +0200
Subject: [PATCH 01/13] libnm: fix unterminated NUL string when parsing UDev
properties
This can result in trailing garbage (which fails UTF-8 validation
checks) or even worse, in read-out-of-bounds.
Fixes: 6808bf8195d427975638610781f8c5384228218d
https://bugzilla.redhat.com/show_bug.cgi?id=1443114
https://bugzilla.redhat.com/show_bug.cgi?id=1451160
https://bugzilla.redhat.com/show_bug.cgi?id=1451286
(cherry picked from commit 9594ee6e6921c3e37615a572de7e986274a68500)
(cherry picked from commit 5eb11aa8ec4e402b3e5795723519cdaab1cfb828)
---
shared/nm-utils/nm-udev-utils.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/shared/nm-utils/nm-udev-utils.c b/shared/nm-utils/nm-udev-utils.c
index bf0ad5b..1f1811c 100644
--- a/shared/nm-utils/nm-udev-utils.c
+++ b/shared/nm-utils/nm-udev-utils.c
@@ -89,6 +89,7 @@ nm_udev_utils_property_decode (const char *uproperty, char **to_free)
return uproperty;
}
+ *n++ = '\0';
return (*to_free = unescaped);
}
--
2.9.4
From be2a87e07f7a75e568d68afed1532b24edbee414 Mon Sep 17 00:00:00 2001
From: Thomas Haller <thaller@redhat.com>
Date: Wed, 17 May 2017 17:04:13 +0200
Subject: [PATCH 02/13] libnm: don't cunescape \x00 encoding in
nm_udev_utils_property_decode()
UDev never creates such invalid escape sequences. Anyway,
we cannot accept a NUL character at this point. Just take
the ill escape verbatim -- it should never happen anyway.
(cherry picked from commit c15eae92c0c5fc12017dd84a66ee0bbb9638b270)
(cherry picked from commit 822282754d1653ac24f6e5a9bf616fc74f957050)
---
shared/nm-utils/nm-udev-utils.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/shared/nm-utils/nm-udev-utils.c b/shared/nm-utils/nm-udev-utils.c
index 1f1811c..79d4426 100644
--- a/shared/nm-utils/nm-udev-utils.c
+++ b/shared/nm-utils/nm-udev-utils.c
@@ -67,8 +67,9 @@ nm_udev_utils_property_decode (const char *uproperty, char **to_free)
if ( p[0] == '\\'
&& p[1] == 'x'
&& (a = g_ascii_xdigit_value (p[2])) >= 0
- && (b = g_ascii_xdigit_value (p[3])) >= 0) {
- if (!unescaped) {
+ && (b = g_ascii_xdigit_value (p[3])) >= 0
+ && (a || b)) {
+ if (!n) {
gssize l = p - uproperty;
unescaped = g_malloc (l + strlen (p) + 1 - 3);
@@ -84,7 +85,7 @@ nm_udev_utils_property_decode (const char *uproperty, char **to_free)
}
}
- if (!unescaped) {
+ if (!n) {
*to_free = NULL;
return uproperty;
}
--
2.9.4
From e1679a6a48ba7367528927f3e7f0021be71e37d6 Mon Sep 17 00:00:00 2001
From: Thomas Haller <thaller@redhat.com>
Date: Wed, 17 May 2017 15:18:20 +0200
Subject: [PATCH 03/13] device: fix setting device's UDI property
Fixes: e8139f56c26ae3bcc5e14abdb29970ae07e93299
(cherry picked from commit 5eac18b58d2be9b5b611f4b4e356b2ac59e46bce)
(cherry picked from commit 4ae14d3677609ef3c702c1a7a706b6bc38030958)
---
src/devices/nm-device.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index b14dc49..62cb5dd 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -2460,7 +2460,7 @@ device_link_changed (NMDevice *self)
info = *pllink;
udi = nm_platform_link_get_udi (nm_device_get_platform (self), info.ifindex);
- if (udi && g_strcmp0 (udi, priv->udi)) {
+ if (udi && !nm_streq0 (udi, priv->udi)) {
/* Update UDI to what udev gives us */
g_free (priv->udi);
priv->udi = g_strdup (udi);
@@ -2841,7 +2841,7 @@ update_device_from_platform_link (NMDevice *self, const NMPlatformLink *plink)
g_return_if_fail (plink != NULL);
udi = nm_platform_link_get_udi (nm_device_get_platform (self), plink->ifindex);
- if (udi && !g_strcmp0 (udi, priv->udi)) {
+ if (udi && !nm_streq0 (udi, priv->udi)) {
g_free (priv->udi);
priv->udi = g_strdup (udi);
_notify (self, PROP_UDI);
--
2.9.4
From 84b1c78c2474d9e579955fa0ebdfc6a8c0761548 Mon Sep 17 00:00:00 2001
From: Thomas Haller <thaller@redhat.com>
Date: Wed, 17 May 2017 15:01:10 +0200
Subject: [PATCH 04/13] device: make UDI property construct-only
(cherry picked from commit e216d5eac0768b5936f3415cde7808982c74f0ac)
(cherry picked from commit c3b180198fe10d1fe84fea8b9944834be4f4ad56)
---
src/devices/nm-device.c | 9 +++------
1 file changed, 3 insertions(+), 6 deletions(-)
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index 62cb5dd..ed9bc49 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -13894,14 +13894,11 @@ set_property (GObject *object, guint prop_id,
switch (prop_id) {
case PROP_UDI:
- if (g_value_get_string (value)) {
- g_free (priv->udi);
- priv->udi = g_value_dup_string (value);
- }
+ /* construct-only */
+ priv->udi = g_value_dup_string (value);
break;
case PROP_IFACE:
/* construct-only */
- g_return_if_fail (!priv->iface);
priv->iface = g_value_dup_string (value);
break;
case PROP_DRIVER:
@@ -14212,7 +14209,7 @@ nm_device_class_init (NMDeviceClass *klass)
obj_properties[PROP_UDI] =
g_param_spec_string (NM_DEVICE_UDI, "", "",
NULL,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT |
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
obj_properties[PROP_IFACE] =
g_param_spec_string (NM_DEVICE_IFACE, "", "",
--
2.9.4
From c63800b21cb46b7fbdc318205ed6af93aac9aeac Mon Sep 17 00:00:00 2001
From: Thomas Haller <thaller@redhat.com>
Date: Tue, 16 May 2017 18:50:21 +0200
Subject: [PATCH 05/13] shared: add nm_utils_str_utf8safe_*() API to sanitize
UTF-8 strings
Use C-style backslash escaping to sanitize non-UTF-8 strings.
The functions are compatible with glib's g_strcompress() and
g_strescape().
The difference is only that g_strescape() escapes all non-printable,
non ASCII character as well, while nm_utils_str_utf8safe_escape()
-- depending on the flags -- preserves valid UTF-8 sequence except
backslash.
The flags allow to optionally escape ASCII control characters and
all non-ASCII (valid UTF-8) characters. But the option to preserve
valid UTF-8 (non-ASCII) characters verbatim, is what distinguishes
from g_strescape().
(cherry picked from commit df6d27b33a86e2ecdc5a8e1deff275d19b2cbde1)
(cherry picked from commit 52105f27df974715a8481fb240f98f73a6a8be08)
---
libnm-core/tests/test-general.c | 95 ++++++++++++++++++++++++++
shared/nm-utils/nm-shared-utils.c | 138 ++++++++++++++++++++++++++++++++++++++
shared/nm-utils/nm-shared-utils.h | 16 +++++
3 files changed, 249 insertions(+)
diff --git a/libnm-core/tests/test-general.c b/libnm-core/tests/test-general.c
index 7ecd681..fbcfa7d 100644
--- a/libnm-core/tests/test-general.c
+++ b/libnm-core/tests/test-general.c
@@ -5248,6 +5248,100 @@ static void test_nm_utils_enum (void)
/*****************************************************************************/
+static void
+do_test_utils_str_utf8safe (const char *str, const char *expected, NMUtilsStrUtf8SafeFlags flags)
+{
+ const char *str_safe, *s;
+ gs_free char *str2 = NULL;
+ gs_free char *str3 = NULL;
+
+ str_safe = nm_utils_str_utf8safe_escape (str, flags, &str2);
+
+ str3 = nm_utils_str_utf8safe_escape_cp (str, flags);
+ g_assert_cmpstr (str3, ==, str_safe);
+ g_assert ((!str && !str3) || (str != str3));
+ g_clear_pointer (&str3, g_free);
+
+ if (expected == NULL) {
+ g_assert (str_safe == str);
+ g_assert (!str2);
+ if (str) {
+ g_assert (!strchr (str, '\\'));
+ g_assert (g_utf8_validate (str, -1, NULL));
+ }
+
+ g_assert (str == nm_utils_str_utf8safe_unescape (str_safe, &str3));
+ g_assert (!str3);
+
+ str3 = nm_utils_str_utf8safe_unescape_cp (str_safe);
+ if (str) {
+ g_assert (str3 != str);
+ g_assert_cmpstr (str3, ==, str);
+ } else
+ g_assert (!str3);
+ g_clear_pointer (&str3, g_free);
+ return;
+ }
+
+ g_assert (str);
+ g_assert (str_safe != str);
+ g_assert (str_safe == str2);
+ g_assert ( strchr (str, '\\')
+ || !g_utf8_validate (str, -1, NULL)
+ || ( NM_FLAGS_HAS (flags, NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_NON_ASCII)
+ && NM_STRCHAR_ANY (str, ch, (guchar) ch >= 127))
+ || ( NM_FLAGS_HAS (flags, NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL)
+ && NM_STRCHAR_ANY (str, ch, (guchar) ch < ' ')));
+ g_assert (g_utf8_validate (str_safe, -1, NULL));
+
+ str3 = g_strcompress (str_safe);
+ g_assert_cmpstr (str, ==, str3);
+ g_clear_pointer (&str3, g_free);
+
+ str3 = nm_utils_str_utf8safe_unescape_cp (str_safe);
+ g_assert (str3 != str);
+ g_assert_cmpstr (str3, ==, str);
+ g_clear_pointer (&str3, g_free);
+
+ s = nm_utils_str_utf8safe_unescape (str_safe, &str3);
+ g_assert (str3 != str);
+ g_assert (s == str3);
+ g_assert_cmpstr (str3, ==, str);
+ g_clear_pointer (&str3, g_free);
+
+ g_assert_cmpstr (str_safe, ==, expected);
+}
+
+static void
+test_utils_str_utf8safe (void)
+{
+ do_test_utils_str_utf8safe (NULL, NULL, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
+ do_test_utils_str_utf8safe ("", NULL, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
+ do_test_utils_str_utf8safe ("\314", "\\314", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
+ do_test_utils_str_utf8safe ("\314\315x\315\315x", "\\314\\315x\\315\\315x", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
+ do_test_utils_str_utf8safe ("\314\315xx", "\\314\\315xx", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
+ do_test_utils_str_utf8safe ("\314xx", "\\314xx", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
+ do_test_utils_str_utf8safe ("\xa0", "\\240", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
+ do_test_utils_str_utf8safe ("\xe2\x91\xa0", NULL, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
+ do_test_utils_str_utf8safe ("\xe2\xe2\x91\xa0", "\\342\xe2\x91\xa0", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
+ do_test_utils_str_utf8safe ("\xe2\xe2\x91\xa0\xa0", "\\342\xe2\x91\xa0\\240", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
+ do_test_utils_str_utf8safe ("a", NULL, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
+ do_test_utils_str_utf8safe ("ab", NULL, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
+ do_test_utils_str_utf8safe ("ab\314", "ab\\314", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
+ do_test_utils_str_utf8safe ("ab\314adsf", "ab\\314adsf", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
+ do_test_utils_str_utf8safe ("abadsf", NULL, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
+ do_test_utils_str_utf8safe ("abäb", NULL, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
+ do_test_utils_str_utf8safe ("x\xa0", "x\\240", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
+ do_test_utils_str_utf8safe ("Ä\304ab\\äb", "Ä\\304ab\\\\äb", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
+ do_test_utils_str_utf8safe ("Äab\\äb", "Äab\\\\äb", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
+ do_test_utils_str_utf8safe ("ÄÄab\\äb", "ÄÄab\\\\äb", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
+ do_test_utils_str_utf8safe ("㈞abä㈞b", NULL, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
+ do_test_utils_str_utf8safe ("abäb", "ab\\303\\244b", NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_NON_ASCII);
+ do_test_utils_str_utf8safe ("ab\ab", "ab\\007b", NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL);
+}
+
+/*****************************************************************************/
+
static int
_test_nm_in_set_get (int *call_counter, gboolean allow_called, int value)
{
@@ -5605,6 +5699,7 @@ int main (int argc, char **argv)
nmtst_init (&argc, &argv, TRUE);
/* The tests */
+ g_test_add_func ("/core/general/test_utils_str_utf8safe", test_utils_str_utf8safe);
g_test_add_func ("/core/general/test_nm_in_set", test_nm_in_set);
g_test_add_func ("/core/general/test_nm_in_strset", test_nm_in_strset);
g_test_add_func ("/core/general/test_setting_vpn_items", test_setting_vpn_items);
diff --git a/shared/nm-utils/nm-shared-utils.c b/shared/nm-utils/nm-shared-utils.c
index 413526d..e7f31cb 100644
--- a/shared/nm-utils/nm-shared-utils.c
+++ b/shared/nm-utils/nm-shared-utils.c
@@ -364,3 +364,141 @@ nm_g_object_set_property (GObject *object,
}
/*****************************************************************************/
+
+static void
+_str_append_escape (GString *s, char ch)
+{
+ g_string_append_c (s, '\\');
+ g_string_append_c (s, '0' + ((((guchar) ch) >> 6) & 07));
+ g_string_append_c (s, '0' + ((((guchar) ch) >> 3) & 07));
+ g_string_append_c (s, '0' + ( ((guchar) ch) & 07));
+}
+
+/**
+ * nm_utils_str_utf8safe_escape:
+ * @str: NUL terminated input string, possibly in utf-8 encoding
+ * @flags: #NMUtilsStrUtf8SafeFlags flags
+ * @to_free: (out): return the pointer location of the string
+ * if a copying was necessary.
+ *
+ * Returns the possible non-UTF-8 NUL terminated string @str
+ * and uses backslash escaping (C escaping, like g_strescape())
+ * to sanitize non UTF-8 characters. The result is valid
+ * UTF-8.
+ *
+ * The operation can be reverted with g_strcompress() or
+ * nm_utils_str_utf8safe_unescape().
+ *
+ * Depending on @flags, valid UTF-8 characters are not escaped at all
+ * (except the escape character '\\'). This is the difference to g_strescape(),
+ * which escapes all non-ASCII characters. This allows to pass on
+ * valid UTF-8 characters as-is and can be directly shown to the user
+ * as UTF-8 -- with exception of the backslash escape character,
+ * invalid UTF-8 sequences, and other (depending on @flags).
+ *
+ * Returns: the escaped input string, as valid UTF-8. If no escaping
+ * is necessary, it returns the input @str. Otherwise, an allocated
+ * string @to_free is returned which must be freed by the caller
+ * with g_free. The escaping can be reverted by g_strcompress().
+ **/
+const char *
+nm_utils_str_utf8safe_escape (const char *str, NMUtilsStrUtf8SafeFlags flags, char **to_free)
+{
+ const char *p = NULL;
+ GString *s;
+
+ g_return_val_if_fail (to_free, NULL);
+
+ *to_free = NULL;
+ if (!str || !str[0])
+ return str;
+
+ if ( g_utf8_validate (str, -1, &p)
+ && !NM_STRCHAR_ANY (str, ch,
+ ( ch == '\\' \
+ || ( NM_FLAGS_HAS (flags, NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL) \
+ && ch < ' ') \
+ || ( NM_FLAGS_HAS (flags, NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_NON_ASCII) \
+ && ((guchar) ch) >= 127))))
+ return str;
+
+ s = g_string_sized_new ((p - str) + strlen (p) + 5);
+
+ do {
+ for (; str < p; str++) {
+ char ch = str[0];
+
+ if (ch == '\\')
+ g_string_append (s, "\\\\");
+ else if ( ( NM_FLAGS_HAS (flags, NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL) \
+ && ch < ' ') \
+ || ( NM_FLAGS_HAS (flags, NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_NON_ASCII) \
+ && ((guchar) ch) >= 127))
+ _str_append_escape (s, ch);
+ else
+ g_string_append_c (s, ch);
+ }
+
+ if (p[0] == '\0')
+ break;
+ _str_append_escape (s, p[0]);
+
+ str = &p[1];
+ g_utf8_validate (str, -1, &p);
+ } while (TRUE);
+
+ *to_free = g_string_free (s, FALSE);
+ return *to_free;
+}
+
+const char *
+nm_utils_str_utf8safe_unescape (const char *str, char **to_free)
+{
+ g_return_val_if_fail (to_free, NULL);
+
+ if (!str || !strchr (str, '\\')) {
+ *to_free = NULL;
+ return str;
+ }
+ return (*to_free = g_strcompress (str));
+}
+
+/**
+ * nm_utils_str_utf8safe_escape_cp:
+ * @str: NUL terminated input string, possibly in utf-8 encoding
+ * @flags: #NMUtilsStrUtf8SafeFlags flags
+ *
+ * Like nm_utils_str_utf8safe_escape(), except the returned value
+ * is always a copy of the input and must be freed by the caller.
+ *
+ * Returns: the escaped input string in UTF-8 encoding. The returned
+ * value should be freed with g_free().
+ * The escaping can be reverted by g_strcompress().
+ **/
+char *
+nm_utils_str_utf8safe_escape_cp (const char *str, NMUtilsStrUtf8SafeFlags flags)
+{
+ char *s;
+
+ nm_utils_str_utf8safe_escape (str, flags, &s);
+ return s ?: g_strdup (str);
+}
+
+char *
+nm_utils_str_utf8safe_unescape_cp (const char *str)
+{
+ return str ? g_strcompress (str) : NULL;
+}
+
+char *
+nm_utils_str_utf8safe_escape_take (char *str, NMUtilsStrUtf8SafeFlags flags)
+{
+ char *str_to_free;
+
+ nm_utils_str_utf8safe_escape (str, flags, &str_to_free);
+ if (str_to_free) {
+ g_free (str);
+ return str_to_free;
+ }
+ return str;
+}
diff --git a/shared/nm-utils/nm-shared-utils.h b/shared/nm-utils/nm-shared-utils.h
index f1f9f51..69f9533 100644
--- a/shared/nm-utils/nm-shared-utils.h
+++ b/shared/nm-utils/nm-shared-utils.h
@@ -86,4 +86,20 @@ gboolean nm_g_object_set_property (GObject *object,
/*****************************************************************************/
+typedef enum {
+ NM_UTILS_STR_UTF8_SAFE_FLAG_NONE = 0,
+ NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL = 0x0001,
+ NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_NON_ASCII = 0x0002,
+} NMUtilsStrUtf8SafeFlags;
+
+const char *nm_utils_str_utf8safe_escape (const char *str, NMUtilsStrUtf8SafeFlags flags, char **to_free);
+const char *nm_utils_str_utf8safe_unescape (const char *str, char **to_free);
+
+char *nm_utils_str_utf8safe_escape_cp (const char *str, NMUtilsStrUtf8SafeFlags flags);
+char *nm_utils_str_utf8safe_unescape_cp (const char *str);
+
+char *nm_utils_str_utf8safe_escape_take (char *str, NMUtilsStrUtf8SafeFlags flags);
+
+/*****************************************************************************/
+
#endif /* __NM_SHARED_UTILS_H__ */
--
2.9.4
From e9eee9c65818e7dd85e79c1db6ad4c32b4c7fb52 Mon Sep 17 00:00:00 2001
From: Thomas Haller <thaller@redhat.com>
Date: Tue, 16 May 2017 14:11:07 +0200
Subject: [PATCH 06/13] device: sanitze UTF-8 values for D-Bus
ip link add name $'d\xccf\\c' type dummy
Use nm_utils_str_utf8safe_escape() to sanitize non UTF-8 sequences
before exposing them on D-Bus. The operation can be reverted client
side via nm_utils_str_utf8safe_unescape() or simply g_strcompress().
Note that this preserves all valid UTF-8 sequences as-is, with exception
of the backslash escape character and ASCII control characters. Thus, this
is a change in behavior for strings that contain such characters.
Note that nmcli is not changed to somehow unescape the string before
printing. As the string is not valid UTF-8 (or contains ASCII characters
that need escaping), they are not printable as-is, so unescaping before
printing makes little sense.
(cherry picked from commit 0870906540506d0157f305df32b6b1f65b10ee85)
(cherry picked from commit 3a96772918a391ec8186183b5c14c9b165322d3a)
---
.../org.freedesktop.NetworkManager.Device.xml | 15 +++++++++++
src/devices/nm-device.c | 31 ++++++++++++++++------
2 files changed, 38 insertions(+), 8 deletions(-)
diff --git a/introspection/org.freedesktop.NetworkManager.Device.xml b/introspection/org.freedesktop.NetworkManager.Device.xml
index ee42410..be0a612 100644
--- a/introspection/org.freedesktop.NetworkManager.Device.xml
+++ b/introspection/org.freedesktop.NetworkManager.Device.xml
@@ -21,6 +21,9 @@
each device in your application, use the object path. If you're looking
for a way to track a specific piece of hardware across reboot or hotplug,
use a MAC address or USB serial number.
+
+ Note that non-UTF-8 characters are backslash escaped. Use g_strcompress()
+ to obtain the true (non-UTF-8) string.
-->
<property name="Udi" type="s" access="read"/>
@@ -28,6 +31,9 @@
Interface:
The name of the device's control (and often data) interface.
+ Note that non UTF-8 characters are backslash escaped, so the
+ resulting name may be longer then 15 characters. Use g_strcompress()
+ to revert the escaping.
-->
<property name="Interface" type="s" access="read"/>
@@ -38,6 +44,9 @@
not refer to the actual data interface until the device has successfully
established a data connection, indicated by the device's State becoming
ACTIVATED.
+ Note that non UTF-8 characters are backslash escaped, so the
+ resulting name may be longer then 15 characters. Use g_strcompress()
+ to revert the escaping.
-->
<property name="IpInterface" type="s" access="read"/>
@@ -45,6 +54,8 @@
Driver:
The driver handling the device.
+ Non-UTF-8 sequences are backslash escaped. Use g_strcompress()
+ to revert.
-->
<property name="Driver" type="s" access="read"/>
@@ -52,6 +63,8 @@
DriverVersion:
The version of the driver handling the device.
+ Non-UTF-8 sequences are backslash escaped. Use g_strcompress()
+ to revert.
-->
<property name="DriverVersion" type="s" access="read"/>
@@ -59,6 +72,8 @@
FirmwareVersion:
The firmware version for the device.
+ Non-UTF-8 sequences are backslash escaped. Use g_strcompress()
+ to revert.
-->
<property name="FirmwareVersion" type="s" access="read"/>
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index ed9bc49..e61bde3 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -13993,28 +13993,43 @@ get_property (GObject *object, guint prop_id,
switch (prop_id) {
case PROP_UDI:
- g_value_set_string (value, priv->udi);
+ /* UDI is (depending on the device type) a path to sysfs and can contain
+ * non-UTF-8.
+ * ip link add name $'d\xccf\\c' type dummy */
+ g_value_take_string (value,
+ nm_utils_str_utf8safe_escape_cp (priv->udi,
+ NM_UTILS_STR_UTF8_SAFE_FLAG_NONE));
break;
case PROP_IFACE:
- g_value_set_string (value, priv->iface);
+ g_value_take_string (value,
+ nm_utils_str_utf8safe_escape_cp (priv->iface,
+ NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL));
break;
case PROP_IP_IFACE:
- if (ip_config_valid (priv->state))
- g_value_set_string (value, nm_device_get_ip_iface (self));
- else
+ if (ip_config_valid (priv->state)) {
+ g_value_take_string (value,
+ nm_utils_str_utf8safe_escape_cp (nm_device_get_ip_iface (self),
+ NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL));
+ } else
g_value_set_string (value, NULL);
break;
case PROP_IFINDEX:
g_value_set_int (value, priv->ifindex);
break;
case PROP_DRIVER:
- g_value_set_string (value, priv->driver);
+ g_value_take_string (value,
+ nm_utils_str_utf8safe_escape_cp (priv->driver,
+ NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL));
break;
case PROP_DRIVER_VERSION:
- g_value_set_string (value, priv->driver_version);
+ g_value_take_string (value,
+ nm_utils_str_utf8safe_escape_cp (priv->driver_version,
+ NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL));
break;
case PROP_FIRMWARE_VERSION:
- g_value_set_string (value, priv->firmware_version);
+ g_value_take_string (value,
+ nm_utils_str_utf8safe_escape_cp (priv->firmware_version,
+ NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL));
break;
case PROP_CAPABILITIES:
g_value_set_uint (value, (priv->capabilities & ~NM_DEVICE_CAP_INTERNAL_MASK));
--
2.9.4
From 0b8676b887f63a708e6444f6b3d19003a2f9b4c8 Mon Sep 17 00:00:00 2001
From: Thomas Haller <thaller@redhat.com>
Date: Wed, 17 May 2017 11:48:53 +0200
Subject: [PATCH 07/13] libnm: UTF-8 sanitize strings from UDev in NMDevice
(cherry picked from commit b9e9f7616556f693e2642ed433f3289f9c6da452)
(cherry picked from commit d7b184d99257a6e6e59b22709007675430ec308b)
---
libnm/nm-device.c | 273 ++++++++++++++++++++++++++++++------------------------
1 file changed, 152 insertions(+), 121 deletions(-)
diff --git a/libnm/nm-device.c b/libnm/nm-device.c
index 9cbdbd0..7e8feb1 100644
--- a/libnm/nm-device.c
+++ b/libnm/nm-device.c
@@ -81,7 +81,7 @@ typedef struct {
GPtrArray *available_connections;
struct udev *udev;
- char *product, *short_product;
+ char *product;
char *vendor, *short_vendor;
char *description, *bus_name;
@@ -320,7 +320,6 @@ finalize (GObject *object)
g_free (priv->driver_version);
g_free (priv->firmware_version);
g_free (priv->product);
- g_free (priv->short_product);
g_free (priv->vendor);
g_free (priv->short_vendor);
g_free (priv->description);
@@ -1357,6 +1356,17 @@ _get_udev_property (NMDevice *device,
return db_value;
}
+static char *
+_get_udev_property_utf8safe (NMDevice *device,
+ const char *enc_prop, /* ID_XXX_ENC */
+ const char *db_prop) /* ID_XXX_FROM_DATABASE */
+{
+ return nm_utils_str_utf8safe_escape_take (_get_udev_property (device,
+ enc_prop,
+ db_prop),
+ NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL);
+}
+
/**
* nm_device_get_product:
* @device: a #NMDevice
@@ -1365,6 +1375,9 @@ _get_udev_property (NMDevice *device,
*
* Returns: the product name of the device. This is the internal string used by the
* device, and must not be modified.
+ *
+ * The string is backslash escaped (C escaping) for invalid characters. The escaping
+ * can be reverted with g_strcompress(), however the result may not be valid UTF-8.
**/
const char *
nm_device_get_product (NMDevice *device)
@@ -1374,15 +1387,16 @@ nm_device_get_product (NMDevice *device)
g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
priv = NM_DEVICE_GET_PRIVATE (device);
- if (!priv->product)
- priv->product = _get_udev_property (device, "ID_MODEL_ENC", "ID_MODEL_FROM_DATABASE");
+ if (!priv->product) {
+ priv->product = _get_udev_property_utf8safe (device, "ID_MODEL_ENC", "ID_MODEL_FROM_DATABASE");
- /* Sometimes ID_PRODUCT_FROM_DATABASE is used? */
- if (!priv->product)
- priv->product = _get_udev_property (device, "ID_MODEL_ENC", "ID_PRODUCT_FROM_DATABASE");
+ /* Sometimes ID_PRODUCT_FROM_DATABASE is used? */
+ if (!priv->product)
+ priv->product = _get_udev_property_utf8safe (device, "ID_MODEL_ENC", "ID_PRODUCT_FROM_DATABASE");
- if (!priv->product)
- priv->product = g_strdup ("");
+ if (!priv->product)
+ priv->product = g_strdup ("");
+ }
return priv->product;
}
@@ -1395,6 +1409,9 @@ nm_device_get_product (NMDevice *device)
*
* Returns: the vendor name of the device. This is the internal string used by the
* device, and must not be modified.
+ *
+ * The string is backslash escaped (C escaping) for invalid characters. The escaping
+ * can be reverted with g_strcompress(), however the result may not be valid UTF-8.
**/
const char *
nm_device_get_vendor (NMDevice *device)
@@ -1406,7 +1423,7 @@ nm_device_get_vendor (NMDevice *device)
priv = NM_DEVICE_GET_PRIVATE (device);
if (!priv->vendor)
- priv->vendor = _get_udev_property (device, "ID_VENDOR_ENC", "ID_VENDOR_FROM_DATABASE");
+ priv->vendor = _get_udev_property_utf8safe (device, "ID_VENDOR_ENC", "ID_VENDOR_FROM_DATABASE");
if (!priv->vendor)
priv->vendor = g_strdup ("");
@@ -1414,128 +1431,146 @@ nm_device_get_vendor (NMDevice *device)
return priv->vendor;
}
-static const char * const ignored_words[] = {
- "Semiconductor",
- "Components",
- "Corporation",
- "Communications",
- "Company",
- "Corp.",
- "Corp",
- "Co.",
- "Inc.",
- "Inc",
- "Incorporated",
- "Ltd.",
- "Limited.",
- "Intel?",
- "chipset",
- "adapter",
- "[hex]",
- "NDIS",
- "Module",
- NULL
-};
-
-static const char * const ignored_phrases[] = {
- "Multiprotocol MAC/baseband processor",
- "Wireless LAN Controller",
- "Wireless LAN Adapter",
- "Wireless Adapter",
- "Network Connection",
- "Wireless Cardbus Adapter",
- "Wireless CardBus Adapter",
- "54 Mbps Wireless PC Card",
- "Wireless PC Card",
- "Wireless PC",
- "PC Card with XJACK(r) Antenna",
- "Wireless cardbus",
- "Wireless LAN PC Card",
- "Technology Group Ltd.",
- "Communication S.p.A.",
- "Business Mobile Networks BV",
- "Mobile Broadband Minicard Composite Device",
- "Mobile Communications AB",
- "(PC-Suite Mode)",
- NULL
-};
-
static char *
fixup_desc_string (const char *desc)
{
- char *p, *temp;
- char **words, **item;
- GString *str;
+ static const char *const IGNORED_PHRASES[] = {
+ "Multiprotocol MAC/baseband processor",
+ "Wireless LAN Controller",
+ "Wireless LAN Adapter",
+ "Wireless Adapter",
+ "Network Connection",
+ "Wireless Cardbus Adapter",
+ "Wireless CardBus Adapter",
+ "54 Mbps Wireless PC Card",
+ "Wireless PC Card",
+ "Wireless PC",
+ "PC Card with XJACK(r) Antenna",
+ "Wireless cardbus",
+ "Wireless LAN PC Card",
+ "Technology Group Ltd.",
+ "Communication S.p.A.",
+ "Business Mobile Networks BV",
+ "Mobile Broadband Minicard Composite Device",
+ "Mobile Communications AB",
+ "(PC-Suite Mode)",
+ };
+ static const char *const IGNORED_WORDS[] = {
+ "Semiconductor",
+ "Components",
+ "Corporation",
+ "Communications",
+ "Company",
+ "Corp.",
+ "Corp",
+ "Co.",
+ "Inc.",
+ "Inc",
+ "Incorporated",
+ "Ltd.",
+ "Limited.",
+ "Intel?",
+ "chipset",
+ "adapter",
+ "[hex]",
+ "NDIS",
+ "Module",
+ };
+ char *desc_full;
+ char *p, *q;
int i;
- if (!desc)
+ if (!desc || !desc[0])
return NULL;
- p = temp = g_strdup (desc);
- while (*p) {
- if (*p == '_' || *p == ',')
+ /* restore original non-UTF-8-safe text. */
+ desc_full = nm_utils_str_utf8safe_unescape_cp (desc);
+
+ /* replace all invalid UTF-8 bytes with space. */
+ p = desc_full;
+ while (!g_utf8_validate (p, -1, (const char **) &q)) {
+ /* the byte is invalid UTF-8. Replace it with space and proceed. */
+ *q = ' ';
+ p = q + 1;
+ }
+
+ /* replace '_', ',', and ASCII controll characters with space. */
+ for (p = desc_full; p[0]; p++) {
+ if ( NM_IN_SET (*p, '_', ',')
+ || *p < ' ')
*p = ' ';
- p++;
}
/* Attempt to shorten ID by ignoring certain phrases */
- for (i = 0; ignored_phrases[i]; i++) {
- p = strstr (temp, ignored_phrases[i]);
+ for (i = 0; i < G_N_ELEMENTS (IGNORED_PHRASES); i++) {
+ p = strstr (desc_full, IGNORED_PHRASES[i]);
if (p) {
- guint32 ignored_len = strlen (ignored_phrases[i]);
+ const char *eow = &p[strlen (IGNORED_PHRASES[i])];
- memmove (p, p + ignored_len, strlen (p + ignored_len) + 1); /* +1 for the \0 */
+ memmove (p, eow, strlen (eow) + 1); /* +1 for the \0 */
}
}
- /* Attempt to shorten ID by ignoring certain individual words */
- words = g_strsplit (temp, " ", 0);
- str = g_string_new_len (NULL, strlen (temp));
- g_free (temp);
-
- for (item = words; *item; item++) {
- gboolean ignore = FALSE;
-
- if (**item == '\0')
- continue;
-
- for (i = 0; ignored_words[i]; i++) {
- if (!strcmp (*item, ignored_words[i])) {
- ignore = TRUE;
- break;
- }
+ /* Attempt to shorten ID by ignoring certain individual words.
+ * - word-split the description at spaces
+ * - coalesce multiple spaces
+ * - skip over IGNORED_WORDS */
+ p = desc_full;
+ q = desc_full;
+ for (;;) {
+ char *eow;
+ gsize l;
+
+ /* skip leading spaces. */
+ while (p[0] == ' ')
+ p++;
+
+ if (!p[0])
+ break;
+
+ /* split leading word on first space */
+ eow = strchr (p, ' ');
+ if (eow)
+ *eow = '\0';
+
+ if (nm_utils_strv_find_first ((char **) IGNORED_WORDS,
+ G_N_ELEMENTS (IGNORED_WORDS),
+ p) < 0)
+ goto next;
+
+ l = strlen (p);
+ if (q != p) {
+ if (q != desc_full)
+ *q++ = ' ';
+ memmove (q, p, l);
}
+ q += l;
- if (!ignore) {
- if (str->len)
- g_string_append_c (str, ' ');
- g_string_append (str, *item);
- }
+next:
+ if (!eow)
+ break;
+ p = eow + 1;
}
- g_strfreev (words);
- temp = str->str;
- g_string_free (str, FALSE);
+ *q++ = '\0';
- return temp;
+ if (!desc_full[0]) {
+ g_free (desc_full);
+ return NULL;
+ }
+
+ nm_assert (g_utf8_validate (desc_full, -1, NULL));
+ return desc_full;
}
static void
-get_description (NMDevice *device)
+ensure_description (NMDevice *device)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device);
- const char *dev_product;
- const char *dev_vendor;
- char *pdown;
- char *vdown;
- GString *str;
GParamSpec *name_prop;
+ gs_free char *short_product = NULL;
- dev_product = nm_device_get_product (device);
- priv->short_product = fixup_desc_string (dev_product);
-
- dev_vendor = nm_device_get_vendor (device);
- priv->short_vendor = fixup_desc_string (dev_vendor);
+ priv->short_vendor = nm_str_realloc (fixup_desc_string (nm_device_get_vendor (device)));
/* Grab device's preferred name, if any */
name_prop = g_object_class_find_property (G_OBJECT_GET_CLASS (G_OBJECT (device)), "name");
@@ -1546,28 +1581,24 @@ get_description (NMDevice *device)
g_clear_pointer (&priv->description, g_free);
}
- if (!dev_product || !dev_vendor) {
- priv->description = g_strdup (nm_device_get_iface (device));
+ if ( !priv->short_vendor
+ || !(short_product = fixup_desc_string (nm_device_get_product (device)))) {
+ priv->description = g_strdup (nm_device_get_iface (device) ?: "");
return;
}
- str = g_string_new_len (NULL, strlen (priv->short_vendor) + strlen (priv->short_product) + 1);
-
/* Another quick hack; if all of the fixed up vendor string
* is found in product, ignore the vendor.
*/
- pdown = g_ascii_strdown (priv->short_product, -1);
- vdown = g_ascii_strdown (priv->short_vendor, -1);
- if (!strstr (pdown, vdown)) {
- g_string_append (str, priv->short_vendor);
- g_string_append_c (str, ' ');
+ {
+ gs_free char *pdown = g_ascii_strdown (short_product, -1);
+ gs_free char *vdown = g_ascii_strdown (priv->short_vendor, -1);
+
+ if (!strstr (pdown, vdown))
+ priv->description = g_strconcat (priv->short_vendor, " ", short_product, NULL);
+ else
+ priv->description = g_steal_pointer (&short_product);
}
- g_free (pdown);
- g_free (vdown);
-
- g_string_append (str, priv->short_product);
-
- priv->description = g_string_free (str, FALSE);
}
static const char *
@@ -1580,7 +1611,7 @@ get_short_vendor (NMDevice *device)
priv = NM_DEVICE_GET_PRIVATE (device);
if (!priv->description)
- get_description (device);
+ ensure_description (device);
return priv->short_vendor;
}
@@ -1604,7 +1635,7 @@ nm_device_get_description (NMDevice *device)
priv = NM_DEVICE_GET_PRIVATE (device);
if (!priv->description)
- get_description (device);
+ ensure_description (device);
return priv->description;
}
--
2.9.4
From aee0c50ffa840e67642749189bd323620fff8d93 Mon Sep 17 00:00:00 2001
From: Thomas Haller <thaller@redhat.com>
Date: Fri, 19 May 2017 10:18:59 +0200
Subject: [PATCH 08/13] libnm: fix device description in fixup_desc_string()
Fixes: b9e9f7616556f693e2642ed433f3289f9c6da452
(cherry picked from commit 12c881ad40c4829eb430bd0148fa5dbbdfd0ec01)
(cherry picked from commit c22075dc98fc79021e9a4847b57188f09b489ddd)
---
libnm/nm-device.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libnm/nm-device.c b/libnm/nm-device.c
index 7e8feb1..6c27190 100644
--- a/libnm/nm-device.c
+++ b/libnm/nm-device.c
@@ -1535,7 +1535,7 @@ fixup_desc_string (const char *desc)
if (nm_utils_strv_find_first ((char **) IGNORED_WORDS,
G_N_ELEMENTS (IGNORED_WORDS),
- p) < 0)
+ p) >= 0)
goto next;
l = strlen (p);
--
2.9.4
From 47527d343339cf0df13fa852ef73c5d0e4713890 Mon Sep 17 00:00:00 2001
From: Thomas Haller <thaller@redhat.com>
Date: Fri, 19 May 2017 11:01:23 +0200
Subject: [PATCH 09/13] libnm: ignore phrases in fixup device description only
when delimited by space
(cherry picked from commit 72104ea10a26d4b4ff245ed60c5ccd5c043c5fe0)
(cherry picked from commit aa60b77146641db5f5d670356d8244f46dd90f81)
---
libnm/nm-device.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/libnm/nm-device.c b/libnm/nm-device.c
index 6c27190..3a6052b 100644
--- a/libnm/nm-device.c
+++ b/libnm/nm-device.c
@@ -1507,7 +1507,11 @@ fixup_desc_string (const char *desc)
if (p) {
const char *eow = &p[strlen (IGNORED_PHRASES[i])];
- memmove (p, eow, strlen (eow) + 1); /* +1 for the \0 */
+ /* require that the phrase is delimited by space, or
+ * at the beginning or end of the description. */
+ if ( (p == desc_full || p[-1] == ' ')
+ && NM_IN_SET (eow[0], '\0', ' '))
+ memmove (p, eow, strlen (eow) + 1); /* +1 for the \0 */
}
}
--
2.9.4
From 6bc607bd944e83eb4e1c668bba5f750ac98ea451 Mon Sep 17 00:00:00 2001
From: Thomas Haller <thaller@redhat.com>
Date: Fri, 19 May 2017 10:19:25 +0200
Subject: [PATCH 10/13] libnm: add testable libnm/nm-libnm-utils.c file
Previously, internal parts of libnm were not testable.
Instead, add "libnm/nm-libnm-utils.c" and "libnm/libnm-utils.la"
to contain code that can be statically linked with a new
test "libnm/tests/test-general".
(cherry picked from commit 8df944c7e495d18bfecaf9d8316ef7783039c94b)
(cherry picked from commit 1ebac60d2219dd29634e5d375f487d5ffa624266)
---
Makefile.am | 45 ++++++++++++++++++++++++++++++++++++++-------
libnm/nm-libnm-utils.c | 27 +++++++++++++++++++++++++++
libnm/nm-libnm-utils.h | 26 ++++++++++++++++++++++++++
libnm/tests/test-general.c | 34 ++++++++++++++++++++++++++++++++++
4 files changed, 125 insertions(+), 7 deletions(-)
create mode 100644 libnm/nm-libnm-utils.c
create mode 100644 libnm/nm-libnm-utils.h
create mode 100644 libnm/tests/test-general.c
diff --git a/Makefile.am b/Makefile.am
index 709d79b..a6776e9 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -734,6 +734,7 @@ libnm_lib_h_pub_nointrospect = \
libnm_lib_h_pub_mkenums = \
libnm/nm-enum-types.h
libnm_lib_h_priv = \
+ libnm/nm-libnm-utils.h \
libnm/nm-dbus-helpers.h \
libnm/nm-device-private.h \
libnm/nm-dhcp4-config.h \
@@ -790,6 +791,14 @@ libnm_lib_c_real = \
libnm_lib_c_mkenums = \
libnm/nm-enum-types.c
+libnm_lib_cppflags = \
+ $(dflt_cppflags_libnm_core) \
+ -I$(srcdir)/libnm \
+ -I$(builddir)/libnm \
+ -DG_LOG_DOMAIN=\""libnm"\" \
+ -DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_LIB \
+ -DNMRUNDIR=\"$(nmrundir)\"
+
libnminclude_HEADERS += \
$(libnm_lib_h_pub_real) \
$(libnm_lib_h_pub_nointrospect)
@@ -799,6 +808,23 @@ nodist_libnminclude_HEADERS += \
###############################################################################
+lib_LTLIBRARIES += libnm/libnm-utils.la
+
+libnm_libnm_utils_la_CPPFLAGS = \
+ $(libnm_lib_cppflags)
+
+libnm_libnm_utils_la_SOURCES = \
+ libnm/nm-libnm-utils.c
+
+libnm_libnm_utils_la_LIBADD = \
+ libnm-core/libnm-core.la \
+ introspection/libnmdbus.la \
+ $(GLIB_LIBS)
+
+$(libnm_libnm_utils_la_OBJECTS) : $(libnm_lib_h_pub_mkenums)
+
+###############################################################################
+
lib_LTLIBRARIES += libnm/libnm.la
GLIB_GENERATED += \
@@ -817,13 +843,8 @@ $(libnm_libnm_la_OBJECTS): $(libnm_lib_h_pub_mkenum
$(libnm_tests_libnm_vpn_plugin_utils_test_la_OBJECTS): $(libnm_core_lib_h_pub_mkenums)
libnm_libnm_la_CPPFLAGS = \
- $(dflt_cppflags_libnm_core) \
- -I$(srcdir)/libnm \
- -I$(builddir)/libnm \
- $(LIBUDEV_CFLAGS) \
- -DG_LOG_DOMAIN=\""libnm"\" \
- -DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_LIB \
- -DNMRUNDIR=\"$(nmrundir)\"
+ $(libnm_lib_cppflags) \
+ $(LIBUDEV_CFLAGS)
libnm_libnm_la_SOURCES = \
$(libnm_lib_h_pub_real) \
@@ -841,6 +862,7 @@ EXTRA_libnm_libnm_la_DEPENDENCIES = \
libnm_libnm_la_LIBADD = \
libnm-core/libnm-core.la \
introspection/libnmdbus.la \
+ libnm/libnm-utils.la \
$(DL_LIBS) \
$(GLIB_LIBS) \
$(UUID_LIBS) \
@@ -947,6 +969,7 @@ EXTRA_DIST += \
###############################################################################
libnm_tests_programs = \
+ libnm/tests/test-general \
libnm/tests/test-nm-client \
libnm/tests/test-remote-settings-client \
libnm/tests/test-secret-agent
@@ -964,10 +987,14 @@ libnm_tests_ldadd = \
libnm/libnm.la \
$(GLIB_LIBS)
+libnm_tests_test_general_CPPFLAGS = $(libnm_tests_cppflags)
libnm_tests_test_nm_client_CPPFLAGS = $(libnm_tests_cppflags)
libnm_tests_test_remote_settings_client_CPPFLAGS = $(libnm_tests_cppflags)
libnm_tests_test_secret_agent_CPPFLAGS = $(libnm_tests_cppflags)
+libnm_tests_test_general_SOURCES = \
+ libnm/tests/test-general.c
+
libnm_tests_test_nm_client_SOURCES = \
shared/nm-test-utils-impl.c \
shared/nm-test-libnm-utils.h \
@@ -983,10 +1010,14 @@ libnm_tests_test_secret_agent_SOURCES = \
shared/nm-test-libnm-utils.h \
libnm/tests/test-secret-agent.c
+libnm_tests_test_general_LDADD = \
+ libnm/libnm-utils.la \
+ $(libnm_tests_ldadd)
libnm_tests_test_nm_client_LDADD = $(libnm_tests_ldadd)
libnm_tests_test_remote_settings_client_LDADD = $(libnm_tests_ldadd)
libnm_tests_test_secret_agent_LDADD = $(libnm_tests_ldadd)
+$(libnm_tests_test_general_OBJECTS): $(libnm_core_lib_h_pub_mkenums)
$(libnm_tests_test_nm_client_OBJECTS): $(libnm_core_lib_h_pub_mkenums)
$(libnm_tests_test_remote_settings_client_OBJECTS): $(libnm_core_lib_h_pub_mkenums)
$(libnm_tests_test_secret_agent_OBJECTS): $(libnm_core_lib_h_pub_mkenums)
diff --git a/libnm/nm-libnm-utils.c b/libnm/nm-libnm-utils.c
new file mode 100644
index 0000000..8cea276
--- /dev/null
+++ b/libnm/nm-libnm-utils.c
@@ -0,0 +1,27 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2007 - 2008 Novell, Inc.
+ * Copyright 2007 - 2017 Red Hat, Inc.
+ */
+
+#include "nm-default.h"
+
+#include "nm-libnm-utils.h"
+
+/*****************************************************************************/
+
diff --git a/libnm/nm-libnm-utils.h b/libnm/nm-libnm-utils.h
new file mode 100644
index 0000000..356b2f9
--- /dev/null
+++ b/libnm/nm-libnm-utils.h
@@ -0,0 +1,26 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2017 Red Hat, Inc.
+ */
+
+#ifndef __NM_LIBNM_UTILS_H__
+#define __NM_LIBNM_UTILS_H__
+
+
+
+#endif /* __NM_LIBNM_UTILS_H__ */
diff --git a/libnm/tests/test-general.c b/libnm/tests/test-general.c
new file mode 100644
index 0000000..2653cb9
--- /dev/null
+++ b/libnm/tests/test-general.c
@@ -0,0 +1,34 @@
+/* -*- 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 SC 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 2017 Red Hat, Inc.
+ */
+
+#include "nm-default.h"
+
+#include "nm-utils/nm-test-utils.h"
+
+/*****************************************************************************/
+
+NMTST_DEFINE ();
+
+int main (int argc, char **argv)
+{
+ nmtst_init (&argc, &argv, TRUE);
+
+ return g_test_run ();
+}
--
2.9.4
From 3ac56f2ad81a4104f0bc3b95ebcc648fe8445c1d Mon Sep 17 00:00:00 2001
From: Thomas Haller <thaller@redhat.com>
Date: Fri, 19 May 2017 10:32:13 +0200
Subject: [PATCH 11/13] libnm: move fixup_desc_string() to nm-libnm-utils.c
(cherry picked from commit e255ad2a03c84f806f9606b420fa12757bbd883f)
(cherry picked from commit ea0fd21428bd3b287a6537d9238a53f174c8854c)
---
libnm/nm-device.c | 141 +--------------------------------------------
libnm/nm-libnm-utils.c | 135 +++++++++++++++++++++++++++++++++++++++++++
libnm/nm-libnm-utils.h | 2 +-
libnm/tests/test-general.c | 35 +++++++++++
4 files changed, 174 insertions(+), 139 deletions(-)
diff --git a/libnm/nm-device.c b/libnm/nm-device.c
index 3a6052b..969d08a 100644
--- a/libnm/nm-device.c
+++ b/libnm/nm-device.c
@@ -26,6 +26,7 @@
#include <string.h>
#include <libudev.h>
+#include "nm-libnm-utils.h"
#include "nm-dbus-interface.h"
#include "nm-active-connection.h"
#include "nm-device-bt.h"
@@ -1431,142 +1432,6 @@ nm_device_get_vendor (NMDevice *device)
return priv->vendor;
}
-static char *
-fixup_desc_string (const char *desc)
-{
- static const char *const IGNORED_PHRASES[] = {
- "Multiprotocol MAC/baseband processor",
- "Wireless LAN Controller",
- "Wireless LAN Adapter",
- "Wireless Adapter",
- "Network Connection",
- "Wireless Cardbus Adapter",
- "Wireless CardBus Adapter",
- "54 Mbps Wireless PC Card",
- "Wireless PC Card",
- "Wireless PC",
- "PC Card with XJACK(r) Antenna",
- "Wireless cardbus",
- "Wireless LAN PC Card",
- "Technology Group Ltd.",
- "Communication S.p.A.",
- "Business Mobile Networks BV",
- "Mobile Broadband Minicard Composite Device",
- "Mobile Communications AB",
- "(PC-Suite Mode)",
- };
- static const char *const IGNORED_WORDS[] = {
- "Semiconductor",
- "Components",
- "Corporation",
- "Communications",
- "Company",
- "Corp.",
- "Corp",
- "Co.",
- "Inc.",
- "Inc",
- "Incorporated",
- "Ltd.",
- "Limited.",
- "Intel?",
- "chipset",
- "adapter",
- "[hex]",
- "NDIS",
- "Module",
- };
- char *desc_full;
- char *p, *q;
- int i;
-
- if (!desc || !desc[0])
- return NULL;
-
- /* restore original non-UTF-8-safe text. */
- desc_full = nm_utils_str_utf8safe_unescape_cp (desc);
-
- /* replace all invalid UTF-8 bytes with space. */
- p = desc_full;
- while (!g_utf8_validate (p, -1, (const char **) &q)) {
- /* the byte is invalid UTF-8. Replace it with space and proceed. */
- *q = ' ';
- p = q + 1;
- }
-
- /* replace '_', ',', and ASCII controll characters with space. */
- for (p = desc_full; p[0]; p++) {
- if ( NM_IN_SET (*p, '_', ',')
- || *p < ' ')
- *p = ' ';
- }
-
- /* Attempt to shorten ID by ignoring certain phrases */
- for (i = 0; i < G_N_ELEMENTS (IGNORED_PHRASES); i++) {
- p = strstr (desc_full, IGNORED_PHRASES[i]);
- if (p) {
- const char *eow = &p[strlen (IGNORED_PHRASES[i])];
-
- /* require that the phrase is delimited by space, or
- * at the beginning or end of the description. */
- if ( (p == desc_full || p[-1] == ' ')
- && NM_IN_SET (eow[0], '\0', ' '))
- memmove (p, eow, strlen (eow) + 1); /* +1 for the \0 */
- }
- }
-
- /* Attempt to shorten ID by ignoring certain individual words.
- * - word-split the description at spaces
- * - coalesce multiple spaces
- * - skip over IGNORED_WORDS */
- p = desc_full;
- q = desc_full;
- for (;;) {
- char *eow;
- gsize l;
-
- /* skip leading spaces. */
- while (p[0] == ' ')
- p++;
-
- if (!p[0])
- break;
-
- /* split leading word on first space */
- eow = strchr (p, ' ');
- if (eow)
- *eow = '\0';
-
- if (nm_utils_strv_find_first ((char **) IGNORED_WORDS,
- G_N_ELEMENTS (IGNORED_WORDS),
- p) >= 0)
- goto next;
-
- l = strlen (p);
- if (q != p) {
- if (q != desc_full)
- *q++ = ' ';
- memmove (q, p, l);
- }
- q += l;
-
-next:
- if (!eow)
- break;
- p = eow + 1;
- }
-
- *q++ = '\0';
-
- if (!desc_full[0]) {
- g_free (desc_full);
- return NULL;
- }
-
- nm_assert (g_utf8_validate (desc_full, -1, NULL));
- return desc_full;
-}
-
static void
ensure_description (NMDevice *device)
{
@@ -1574,7 +1439,7 @@ ensure_description (NMDevice *device)
GParamSpec *name_prop;
gs_free char *short_product = NULL;
- priv->short_vendor = nm_str_realloc (fixup_desc_string (nm_device_get_vendor (device)));
+ priv->short_vendor = nm_str_realloc (nm_utils_fixup_desc_string (nm_device_get_vendor (device)));
/* Grab device's preferred name, if any */
name_prop = g_object_class_find_property (G_OBJECT_GET_CLASS (G_OBJECT (device)), "name");
@@ -1586,7 +1451,7 @@ ensure_description (NMDevice *device)
}
if ( !priv->short_vendor
- || !(short_product = fixup_desc_string (nm_device_get_product (device)))) {
+ || !(short_product = nm_utils_fixup_desc_string (nm_device_get_product (device)))) {
priv->description = g_strdup (nm_device_get_iface (device) ?: "");
return;
}
diff --git a/libnm/nm-libnm-utils.c b/libnm/nm-libnm-utils.c
index 8cea276..fbbfe2c 100644
--- a/libnm/nm-libnm-utils.c
+++ b/libnm/nm-libnm-utils.c
@@ -25,3 +25,138 @@
/*****************************************************************************/
+char *
+nm_utils_fixup_desc_string (const char *desc)
+{
+ static const char *const IGNORED_PHRASES[] = {
+ "Multiprotocol MAC/baseband processor",
+ "Wireless LAN Controller",
+ "Wireless LAN Adapter",
+ "Wireless Adapter",
+ "Network Connection",
+ "Wireless Cardbus Adapter",
+ "Wireless CardBus Adapter",
+ "54 Mbps Wireless PC Card",
+ "Wireless PC Card",
+ "Wireless PC",
+ "PC Card with XJACK(r) Antenna",
+ "Wireless cardbus",
+ "Wireless LAN PC Card",
+ "Technology Group Ltd.",
+ "Communication S.p.A.",
+ "Business Mobile Networks BV",
+ "Mobile Broadband Minicard Composite Device",
+ "Mobile Communications AB",
+ "(PC-Suite Mode)",
+ };
+ static const char *const IGNORED_WORDS[] = {
+ "Semiconductor",
+ "Components",
+ "Corporation",
+ "Communications",
+ "Company",
+ "Corp.",
+ "Corp",
+ "Co.",
+ "Inc.",
+ "Inc",
+ "Incorporated",
+ "Ltd.",
+ "Limited.",
+ "Intel?",
+ "chipset",
+ "adapter",
+ "[hex]",
+ "NDIS",
+ "Module",
+ };
+ char *desc_full;
+ char *p, *q;
+ int i;
+
+ if (!desc || !desc[0])
+ return NULL;
+
+ /* restore original non-UTF-8-safe text. */
+ desc_full = nm_utils_str_utf8safe_unescape_cp (desc);
+
+ /* replace all invalid UTF-8 bytes with space. */
+ p = desc_full;
+ while (!g_utf8_validate (p, -1, (const char **) &q)) {
+ /* the byte is invalid UTF-8. Replace it with space and proceed. */
+ *q = ' ';
+ p = q + 1;
+ }
+
+ /* replace '_', ',', and ASCII controll characters with space. */
+ for (p = desc_full; p[0]; p++) {
+ if ( NM_IN_SET (*p, '_', ',')
+ || *p < ' ')
+ *p = ' ';
+ }
+
+ /* Attempt to shorten ID by ignoring certain phrases */
+ for (i = 0; i < G_N_ELEMENTS (IGNORED_PHRASES); i++) {
+ p = strstr (desc_full, IGNORED_PHRASES[i]);
+ if (p) {
+ const char *eow = &p[strlen (IGNORED_PHRASES[i])];
+
+ /* require that the phrase is delimited by space, or
+ * at the beginning or end of the description. */
+ if ( (p == desc_full || p[-1] == ' ')
+ && NM_IN_SET (eow[0], '\0', ' '))
+ memmove (p, eow, strlen (eow) + 1); /* +1 for the \0 */
+ }
+ }
+
+ /* Attempt to shorten ID by ignoring certain individual words.
+ * - word-split the description at spaces
+ * - coalesce multiple spaces
+ * - skip over IGNORED_WORDS */
+ p = desc_full;
+ q = desc_full;
+ for (;;) {
+ char *eow;
+ gsize l;
+
+ /* skip leading spaces. */
+ while (p[0] == ' ')
+ p++;
+
+ if (!p[0])
+ break;
+
+ /* split leading word on first space */
+ eow = strchr (p, ' ');
+ if (eow)
+ *eow = '\0';
+
+ if (nm_utils_strv_find_first ((char **) IGNORED_WORDS,
+ G_N_ELEMENTS (IGNORED_WORDS),
+ p) >= 0)
+ goto next;
+
+ l = strlen (p);
+ if (q != p) {
+ if (q != desc_full)
+ *q++ = ' ';
+ memmove (q, p, l);
+ }
+ q += l;
+
+next:
+ if (!eow)
+ break;
+ p = eow + 1;
+ }
+
+ *q++ = '\0';
+
+ if (!desc_full[0]) {
+ g_free (desc_full);
+ return NULL;
+ }
+
+ nm_assert (g_utf8_validate (desc_full, -1, NULL));
+ return desc_full;
+}
diff --git a/libnm/nm-libnm-utils.h b/libnm/nm-libnm-utils.h
index 356b2f9..4a5a361 100644
--- a/libnm/nm-libnm-utils.h
+++ b/libnm/nm-libnm-utils.h
@@ -21,6 +21,6 @@
#ifndef __NM_LIBNM_UTILS_H__
#define __NM_LIBNM_UTILS_H__
-
+char *nm_utils_fixup_desc_string (const char *desc);
#endif /* __NM_LIBNM_UTILS_H__ */
diff --git a/libnm/tests/test-general.c b/libnm/tests/test-general.c
index 2653cb9..7e0b7bb 100644
--- a/libnm/tests/test-general.c
+++ b/libnm/tests/test-general.c
@@ -20,15 +20,50 @@
#include "nm-default.h"
+#include "nm-libnm-utils.h"
+
#include "nm-utils/nm-test-utils.h"
/*****************************************************************************/
+static void
+do_test_fixup_desc_string (const char *desc, const char *expected)
+{
+ gs_free char *result = NULL;
+
+ result = nm_utils_fixup_desc_string (desc);
+ g_assert_cmpstr (result, ==, expected);
+}
+
+#define do_test_fixup_desc_string_same(desc) (do_test_fixup_desc_string (""desc"", ""desc""))
+
+static void
+test_fixup_desc_string (void)
+{
+ do_test_fixup_desc_string (NULL, NULL);
+ do_test_fixup_desc_string ("", NULL);
+ do_test_fixup_desc_string_same ("a");
+ do_test_fixup_desc_string_same ("a b");
+ do_test_fixup_desc_string ("a b ", "a b");
+ do_test_fixup_desc_string (" a bbc ", "a bbc");
+ do_test_fixup_desc_string (" a \xcc bbc ", "a bbc");
+ do_test_fixup_desc_string (" a\xcc bbc ", "a bbc");
+ do_test_fixup_desc_string (" a\xcc""bbc Wireless PC", "a bbc");
+ do_test_fixup_desc_string (" a\xcc""bbc Wireless PC ", "a bbc");
+ do_test_fixup_desc_string (" a\xcc""bbcWireless PC ", "a bbcWireless PC");
+ do_test_fixup_desc_string (" a\xcc""bbc Wireless PCx", "a bbc Wireless PCx");
+ do_test_fixup_desc_string (" a\xcc""bbc Inc Wireless PC ", "a bbc");
+}
+
+/*****************************************************************************/
+
NMTST_DEFINE ();
int main (int argc, char **argv)
{
nmtst_init (&argc, &argv, TRUE);
+ g_test_add_func ("/libnm/general/fixup_desc_string", test_fixup_desc_string);
+
return g_test_run ();
}
--
2.9.4
From 1e5a95c89c35fadbefd6db21c20fcc4a7750063a Mon Sep 17 00:00:00 2001
From: Thomas Haller <thaller@redhat.com>
Date: Fri, 19 May 2017 14:13:37 +0200
Subject: [PATCH 12/13] build: don't install intermediate library
libnm/libnm-utils.la
Fixes: 8df944c7e495d18bfecaf9d8316ef7783039c94b
(cherry picked from commit 733160c862452721821c508465429ffbbda203ae)
(cherry picked from commit 23b5bdd8435bfaf729488e1d3d8821cce948e92e)
---
Makefile.am | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Makefile.am b/Makefile.am
index a6776e9..7ba3603 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -808,7 +808,7 @@ nodist_libnminclude_HEADERS += \
###############################################################################
-lib_LTLIBRARIES += libnm/libnm-utils.la
+noinst_LTLIBRARIES += libnm/libnm-utils.la
libnm_libnm_utils_la_CPPFLAGS = \
$(libnm_lib_cppflags)
--
2.9.4
From 32ec4059fd17a30003571c6d97c9859e84de92ed Mon Sep 17 00:00:00 2001
From: Thomas Haller <thaller@redhat.com>
Date: Fri, 19 May 2017 14:24:14 +0200
Subject: [PATCH 13/13] build: don't link static libraries multiple times
libnm-core.a should only be linked once in libnm.so. Previously,
it was linked twice, once as part of libnm-utils.a and once
directly in libnm.so.
Fixes: 8df944c7e495d18bfecaf9d8316ef7783039c94b
(cherry picked from commit 5a67130e1548bd9314fbd007e131ef378d8b51c7)
(cherry picked from commit da2a02138dc7f0c5aff41019a0517854f379a44c)
---
Makefile.am | 2 --
1 file changed, 2 deletions(-)
diff --git a/Makefile.am b/Makefile.am
index 7ba3603..909847e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -860,8 +860,6 @@ EXTRA_libnm_libnm_la_DEPENDENCIES = \
libnm/libnm.ver
libnm_libnm_la_LIBADD = \
- libnm-core/libnm-core.la \
- introspection/libnmdbus.la \
libnm/libnm-utils.la \
$(DL_LIBS) \
$(GLIB_LIBS) \
--
2.9.4