From 142e72b5b5f7bfb53dd04c4e450028a26fe859ca Mon Sep 17 00:00:00 2001 From: Jan Vaclav Date: Mon, 15 Jul 2024 13:01:02 +0200 Subject: [PATCH 1/2] glib-aux: add nm_utils_buf_utf8safe_escape_strv() This function allows us to escape whole strv arrays, only copying them when necessary, indicated by the "to_free" output parameter. --- src/libnm-glib-aux/nm-shared-utils.c | 54 ++++++++++++++++++++++++++++ src/libnm-glib-aux/nm-shared-utils.h | 6 ++++ 2 files changed, 60 insertions(+) diff --git a/src/libnm-glib-aux/nm-shared-utils.c b/src/libnm-glib-aux/nm-shared-utils.c index 421e4d1bef..c344a681e8 100644 --- a/src/libnm-glib-aux/nm-shared-utils.c +++ b/src/libnm-glib-aux/nm-shared-utils.c @@ -3014,6 +3014,60 @@ nm_utils_buf_utf8safe_escape_cp(gconstpointer buf, gssize buflen, NMUtilsStrUtf8 return s ?: g_strdup(s_const); } +/** + * nm_utils_buf_utf8safe_escape_strv: + * @strv: an array of strings of length @strv_len + * @strv_len: the length of @strv, or -1 for a NULL terminated strv array. + * @flags: #NMUtilsStrUtf8SafeFlags flags + * @to_free: (out): return the pointer location of the newly created + * strv if copying was necessary. + * + * Ensures all strings in a strv are valid UTF-8, copying them unless they + * need to be escaped, and escaping them using nm_utils_buf_utf8safe_escape(). + * + * Returns: a strv with all its strings escaped, as valid UTF-8. All the strings + * contained within are escaped using nm_utils_buf_utf8safe_escape(). + * If no escaping was necessary it returns the input @strv. + * Otherwise, an allocated strv @to_free is returned which must be freed + * by the caller with g_strfreev(). + **/ +const char *const * +nm_utils_buf_utf8safe_escape_strv(const char *const *strv, + gssize strv_len, + NMUtilsStrUtf8SafeFlags flags, + char ***out_to_free) +{ + char **new_strv = NULL; + guint len; + + g_return_val_if_fail(strv, NULL); + g_return_val_if_fail(out_to_free, NULL); + + *out_to_free = NULL; + len = strv_len < 0 ? g_strv_length((char **) strv) : strv_len; + + for (guint i = 0; i < len; ++i) { + char *to_free_str = NULL; + + nm_utils_buf_utf8safe_escape(strv[i], -1, flags, &to_free_str); + + if (to_free_str) { + if (!new_strv) { + new_strv = nm_strv_dup(strv, len, TRUE); + } + + g_free(new_strv[i]); + new_strv[i] = to_free_str; + } + } + + if (new_strv) { + return (const char *const *) (*out_to_free = new_strv); + } + + return strv; +} + /*****************************************************************************/ const char * diff --git a/src/libnm-glib-aux/nm-shared-utils.h b/src/libnm-glib-aux/nm-shared-utils.h index ca9feb6080..1dbd502322 100644 --- a/src/libnm-glib-aux/nm-shared-utils.h +++ b/src/libnm-glib-aux/nm-shared-utils.h @@ -1297,6 +1297,12 @@ const char *nm_utils_buf_utf8safe_escape(gconstpointer buf, char **to_free); char * nm_utils_buf_utf8safe_escape_cp(gconstpointer buf, gssize buflen, NMUtilsStrUtf8SafeFlags flags); + +const char *const *nm_utils_buf_utf8safe_escape_strv(const char *const *strv, + gssize strv_len, + NMUtilsStrUtf8SafeFlags flags, + char ***out_to_free); + const char * nm_utils_buf_utf8safe_escape_bytes(GBytes *bytes, NMUtilsStrUtf8SafeFlags flags, char **to_free); gconstpointer nm_utils_buf_utf8safe_unescape(const char *str, From 522a7d6bafcff03c53c3b86766c229195c38f38c Mon Sep 17 00:00:00 2001 From: Jan Vaclav Date: Mon, 15 Jul 2024 14:05:12 +0200 Subject: [PATCH 2/2] nm-ip-config: escape searches when exposing to dbus Previously, when a connection was configured with search domains that contained non-ASCII characters, GLib would try to parse the search name as UTF-8, and an assertion would fail (which meant that if NM was running with fatal assertions, it would crash). Expose the search domains only as an escaped string to avoid this. --- src/core/nm-ip-config.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/core/nm-ip-config.c b/src/core/nm-ip-config.c index c4dc04da2a..663e839e4c 100644 --- a/src/core/nm-ip-config.c +++ b/src/core/nm-ip-config.c @@ -162,6 +162,7 @@ get_property_ip(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec NMIPConfig *self = NM_IP_CONFIG(object); NMIPConfigPrivate *priv = NM_IP_CONFIG_GET_PRIVATE(self); const int addr_family = nm_ip_config_get_addr_family(self); + char **to_free = NULL; char sbuf_addr[NM_INET_ADDRSTRLEN]; const char *const *strv; guint len; @@ -193,7 +194,20 @@ get_property_ip(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec break; case PROP_IP_SEARCHES: strv = nm_l3_config_data_get_searches(priv->l3cd, addr_family, &len); + if (strv) { + strv = nm_utils_buf_utf8safe_escape_strv( + strv, + -1, + NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL + | NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_NON_ASCII, + &to_free); + } + _value_set_variant_as(value, strv, len); + + if (to_free) { + g_strfreev(to_free); + } break; case PROP_IP_DNS_PRIORITY: v_i = nm_l3_config_data_get_dns_priority_or_default(priv->l3cd, addr_family);