libnm: handle illegal characters in nm_utils_ssid_to_utf8() (rh #1243078)
authorDavid Shea <dshea@redhat.com>
Tue, 14 Jul 2015 19:25:52 +0000 (15:25 -0400)
committerJiří Klimeš <jklimes@redhat.com>
Thu, 16 Jul 2015 12:22:03 +0000 (14:22 +0200)
g_convert_with_fallback() will fail if the SSID contains characters that
are not legal in the source encoding, which, if $LANG is not set, will
be ASCII. If this happens, replace all non-ASCII and non-printable
characters with '?'. It is possible that nm_utils_ssid_to_utf8() will
now return an empty string (e.g., the source string is actually
big-endian UTF-16 and g_strcanon() stops on the first byte), but it will
not return NULL.

https://bugzilla.redhat.com/show_bug.cgi?id=1243078

libnm-core/nm-utils.c
libnm-util/nm-utils.c

index 3e1cf80..89a960e 100644 (file)
@@ -317,6 +317,21 @@ nm_utils_ssid_to_utf8 (const guint8 *ssid, gsize len)
                                                     "UTF-8", e1, "?", NULL, NULL, NULL);
        }
 
+       if (!converted) {
+               /* If there is still no converted string, the SSID probably
+                * contains characters not valid in the current locale. Convert
+                * the string to ASCII instead.
+                */
+
+               /* Use the printable range of 0x20-0x7E */
+               gchar *valid_chars = " !\"#$%&'()*+,-./0123456789:;<=>?@"
+                                    "ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`"
+                                    "abcdefghijklmnopqrstuvwxyz{|}~";
+
+               converted = g_strndup ((const gchar *)ssid, len);
+               g_strcanon (converted, valid_chars, '?');
+       }
+
        return converted;
 }
 
index d0c2ca3..143063e 100644 (file)
@@ -332,6 +332,21 @@ nm_utils_ssid_to_utf8 (const GByteArray *ssid)
                                                     "UTF-8", e1, "?", NULL, NULL, NULL);
        }
 
+       if (!converted) {
+               /* If there is still no converted string, the SSID probably
+                * contains characters not valid in the current locale. Convert
+                * the string to ASCII instead.
+                */
+
+               /* Use the printable range of 0x20-0x7E */
+               gchar *valid_chars = " !\"#$%&'()*+,-./0123456789:;<=>?@"
+                                    "ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`"
+                                    "abcdefghijklmnopqrstuvwxyz{|}~";
+
+               converted = g_strndup ((const gchar *)ssid->data, ssid->len);
+               g_strcanon (converted, valid_chars, '?');
+       }
+
        return converted;
 }