From cb5ef4b3a0a62122da0cda616967de623f378bd7 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Fri, 17 Nov 2023 09:03:08 +0100 Subject: [PATCH 1/6] glib-aux: add NM_PTRARRAY_EMPTY_NEW()/nm_strv_empty_new() helpers --- src/libnm-glib-aux/nm-shared-utils.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/libnm-glib-aux/nm-shared-utils.h b/src/libnm-glib-aux/nm-shared-utils.h index 6c553cc085..8d2e542b5e 100644 --- a/src/libnm-glib-aux/nm-shared-utils.h +++ b/src/libnm-glib-aux/nm-shared-utils.h @@ -332,9 +332,10 @@ gboolean nm_utils_memeqzero(gconstpointer data, gsize length); extern const void *const _NM_PTRARRAY_EMPTY[1]; -#define NM_PTRARRAY_EMPTY(type) ((type const *) _NM_PTRARRAY_EMPTY) -#define NM_STRV_EMPTY() ((char **) _NM_PTRARRAY_EMPTY) -#define NM_STRV_EMPTY_CC() NM_PTRARRAY_EMPTY(const char *) +#define NM_PTRARRAY_EMPTY(type) ((type const *) _NM_PTRARRAY_EMPTY) +#define NM_STRV_EMPTY() ((char **) _NM_PTRARRAY_EMPTY) +#define NM_STRV_EMPTY_CC() NM_PTRARRAY_EMPTY(const char *) +#define NM_PTRARRAY_EMPTY_NEW(type) (g_new0(type, 1)) static inline void nm_strbuf_init(char *buf, gsize len, char **p_buf_ptr, gsize *p_buf_len) @@ -1850,6 +1851,8 @@ int nm_utils_hashtable_cmp(const GHashTable *a, GCompareDataFunc cmp_values, gpointer user_data); +#define nm_strv_empty_new() NM_PTRARRAY_EMPTY_NEW(char *) + char **nm_strv_make_deep_copied(const char **strv); char **nm_strv_make_deep_copied_n(const char **strv, gsize len); From 503a76f6049b2405dc7773e03789bd6aa17d8b44 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Fri, 17 Nov 2023 09:05:04 +0100 Subject: [PATCH 2/6] all: use nm_strv_empty_new() helper --- src/contrib/nm-vpn-editor-plugin-call.h | 2 +- src/libnm-client-impl/nm-ip-config.c | 2 +- src/libnm-core-impl/nm-vpn-plugin-info.c | 2 +- src/libnm-glib-aux/nm-shared-utils.c | 2 +- src/libnm-glib-aux/nm-shared-utils.h | 6 +++--- src/libnm-glib-aux/nm-test-utils.h | 2 +- src/libnm-glib-aux/tests/test-shared-general.c | 2 +- src/nmcli/utils.c | 2 +- src/nmtui/nmt-address-list.c | 2 +- 9 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/contrib/nm-vpn-editor-plugin-call.h b/src/contrib/nm-vpn-editor-plugin-call.h index bf6036ee17..2f3eb0740c 100644 --- a/src/contrib/nm-vpn-editor-plugin-call.h +++ b/src/contrib/nm-vpn-editor-plugin-call.h @@ -103,7 +103,7 @@ nm_vpn_editor_plugin_get_service_add_details(NMVpnEditorPlugin *plugin, const ch if (vt.fcn_get_service_add_details) details = vt.fcn_get_service_add_details(plugin, service_name); if (!details) - return g_new0(char *, 1); + return nm_strv_empty_new(); return details; } diff --git a/src/libnm-client-impl/nm-ip-config.c b/src/libnm-client-impl/nm-ip-config.c index 9aa2e778ce..c054f2ccd6 100644 --- a/src/libnm-client-impl/nm-ip-config.c +++ b/src/libnm-client-impl/nm-ip-config.c @@ -190,7 +190,7 @@ next: if (arr && arr->len > 0) nameservers_new = nm_strv_dup((char **) arr->pdata, arr->len, FALSE); else - nameservers_new = g_new0(char *, 1); + nameservers_new = nm_strv_empty_new(); } nm_assert(nameservers_new); } diff --git a/src/libnm-core-impl/nm-vpn-plugin-info.c b/src/libnm-core-impl/nm-vpn-plugin-info.c index 588df91726..223d8ab33b 100644 --- a/src/libnm-core-impl/nm-vpn-plugin-info.c +++ b/src/libnm-core-impl/nm-vpn-plugin-info.c @@ -728,7 +728,7 @@ nm_vpn_plugin_info_list_get_service_types(GSList *list, if (l->len <= 0) { g_ptr_array_free(l, TRUE); - return g_new0(char *, 1); + return nm_strv_empty_new(); } /* sort the result and remove duplicates. */ diff --git a/src/libnm-glib-aux/nm-shared-utils.c b/src/libnm-glib-aux/nm-shared-utils.c index 99bb8d6e18..40bb59200d 100644 --- a/src/libnm-glib-aux/nm-shared-utils.c +++ b/src/libnm-glib-aux/nm-shared-utils.c @@ -1937,7 +1937,7 @@ nm_utils_strsplit_quoted(const char *str) } if (!arr) - return g_new0(char *, 1); + return nm_strv_empty_new(); /* We want to return an optimally sized strv array, with no excess * memory allocated. Hence, clone once more. */ diff --git a/src/libnm-glib-aux/nm-shared-utils.h b/src/libnm-glib-aux/nm-shared-utils.h index 8d2e542b5e..11c87bec8f 100644 --- a/src/libnm-glib-aux/nm-shared-utils.h +++ b/src/libnm-glib-aux/nm-shared-utils.h @@ -1860,7 +1860,7 @@ char **nm_strv_make_deep_copied_n(const char **strv, gsize len); static inline char ** nm_strv_make_deep_copied_nonnull(const char **strv) { - return nm_strv_make_deep_copied(strv) ?: g_new0(char *, 1); + return nm_strv_make_deep_copied(strv) ?: nm_strv_empty_new(); } char **_nm_strv_dup(const char *const *strv, gssize len, gboolean deep_copied); @@ -3110,7 +3110,7 @@ nm_strvarray_get_strv_full_dup(const GArray *arr, { if (!arr) { NM_SET_OUT(length, 0); - return not_null ? g_new0(char *, 1) : NULL; + return not_null ? nm_strv_empty_new() : NULL; } nm_assert(sizeof(char *) == g_array_get_element_size((GArray *) arr)); @@ -3119,7 +3119,7 @@ nm_strvarray_get_strv_full_dup(const GArray *arr, if (arr->len == 0) { if (preserve_empty || not_null) - return g_new0(char *, 1); + return nm_strv_empty_new(); return NULL; } diff --git a/src/libnm-glib-aux/nm-test-utils.h b/src/libnm-glib-aux/nm-test-utils.h index 627151fa21..ca93d649ea 100644 --- a/src/libnm-glib-aux/nm-test-utils.h +++ b/src/libnm-glib-aux/nm-test-utils.h @@ -1228,7 +1228,7 @@ nmtst_rand_perm_strv(const char *const *strv) /* this returns a (scrambled) SHALLOW copy of the strv array! */ n = NM_PTRARRAY_LEN(strv); - res = (const char **) (nm_strv_dup(strv, n, FALSE) ?: g_new0(char *, 1)); + res = (const char **) (nm_strv_dup(strv, n, FALSE) ?: nm_strv_empty_new()); nmtst_rand_perm(NULL, res, res, sizeof(char *), n); return res; } diff --git a/src/libnm-glib-aux/tests/test-shared-general.c b/src/libnm-glib-aux/tests/test-shared-general.c index 55f8cbb1d1..e65c0efc1d 100644 --- a/src/libnm-glib-aux/tests/test-shared-general.c +++ b/src/libnm-glib-aux/tests/test-shared-general.c @@ -450,7 +450,7 @@ _strv_cmp_fuzz_input(const char *const *in, if (l < 0) ss = g_strdupv((char **) in); else if (l == 0) { - ss = nmtst_get_rand_bool() ? NULL : g_new0(char *, 1); + ss = nmtst_get_rand_bool() ? NULL : nm_strv_empty_new(); } else { ss = nm_memdup(in, sizeof(const char *) * l); for (i = 0; i < (gsize) l; i++) diff --git a/src/nmcli/utils.c b/src/nmcli/utils.c index 615d1f8656..c65a5486bc 100644 --- a/src/nmcli/utils.c +++ b/src/nmcli/utils.c @@ -497,7 +497,7 @@ nmc_string_to_arg_array(const char *line, arr0 = nm_strsplit_set(line ?: "", delim ?: " \t"); if (!arr0) - arr = g_new0(char *, 1); + arr = nm_strv_empty_new(); else arr = g_strdupv((char **) arr0); diff --git a/src/nmtui/nmt-address-list.c b/src/nmtui/nmt-address-list.c index dba8e790c5..ff4bf1a475 100644 --- a/src/nmtui/nmt-address-list.c +++ b/src/nmtui/nmt-address-list.c @@ -194,7 +194,7 @@ nmt_address_list_set_property(GObject *object, g_strfreev(priv->strings); priv->strings = g_value_dup_boxed(value); if (!priv->strings) - priv->strings = g_new0(char *, 1); + priv->strings = nm_strv_empty_new(); nmt_widget_list_set_length(NMT_WIDGET_LIST(object), g_strv_length(priv->strings)); break; default: From 541979d09838cabc9038feef898fef2213449dd9 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Fri, 17 Nov 2023 09:10:52 +0100 Subject: [PATCH 3/6] glib-aux: add nm_strv_dup_full() helper to preserve empty strv --- src/libnm-glib-aux/nm-shared-utils.c | 19 ++++++++++++++----- src/libnm-glib-aux/nm-shared-utils.h | 11 ++++++++--- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/src/libnm-glib-aux/nm-shared-utils.c b/src/libnm-glib-aux/nm-shared-utils.c index 40bb59200d..7db45e1b90 100644 --- a/src/libnm-glib-aux/nm-shared-utils.c +++ b/src/libnm-glib-aux/nm-shared-utils.c @@ -3580,6 +3580,9 @@ nm_strv_make_deep_copied_n(const char **strv, gsize len) * the returned array must be freed with g_strfreev(). Otherwise, the * strings themself are not copied. You must take care of who owns the * strings yourself. + * @preserved_empty: affects how to handle if the strv array is empty (length 0). + * If TRUE, results in a non-NULL, empty, allocated strv array. If FALSE, + * returns NULL instead of an empty strv array. * * Like g_strdupv(), with two differences: * @@ -3598,7 +3601,10 @@ nm_strv_make_deep_copied_n(const char **strv, gsize len) * cloned or not. */ char ** -_nm_strv_dup(const char *const *strv, gssize len, gboolean deep_copied) +_nm_strv_dup_full(const char *const *strv, + gssize len, + gboolean deep_copied, + gboolean preserve_empty) { gsize i, l; char **v; @@ -3607,13 +3613,16 @@ _nm_strv_dup(const char *const *strv, gssize len, gboolean deep_copied) l = NM_PTRARRAY_LEN(strv); else l = len; - if (l == 0) { - /* this function never returns an empty strv array. If you - * need that, handle it yourself. */ + + if (l == 0 && !preserve_empty) { + /* An empty strv array is not returned (as requested by + * !preserved_empty). Instead, return NULL. */ return NULL; } - v = g_new(char *, l + 1); + nm_assert(l < G_MAXSIZE); + + v = g_new(char *, l + 1u); for (i = 0; i < l; i++) { if (G_UNLIKELY(!strv[i])) { /* NULL strings are not allowed. Clear the remainder of the array diff --git a/src/libnm-glib-aux/nm-shared-utils.h b/src/libnm-glib-aux/nm-shared-utils.h index 11c87bec8f..74d7b1b921 100644 --- a/src/libnm-glib-aux/nm-shared-utils.h +++ b/src/libnm-glib-aux/nm-shared-utils.h @@ -1863,10 +1863,15 @@ nm_strv_make_deep_copied_nonnull(const char **strv) return nm_strv_make_deep_copied(strv) ?: nm_strv_empty_new(); } -char **_nm_strv_dup(const char *const *strv, gssize len, gboolean deep_copied); +char **_nm_strv_dup_full(const char *const *strv, + gssize len, + gboolean deep_copied, + gboolean preserve_empty); -#define nm_strv_dup(strv, len, deep_copied) \ - _nm_strv_dup(NM_CAST_STRV_CC(strv), (len), (deep_copied)) +#define nm_strv_dup_full(strv, len, deep_copied, preserve_empty) \ + _nm_strv_dup_full(NM_CAST_STRV_CC(strv), (len), (deep_copied), (preserve_empty)) + +#define nm_strv_dup(strv, len, deep_copied) nm_strv_dup_full((strv), (len), (deep_copied), FALSE) const char **_nm_strv_dup_packed(const char *const *strv, gssize len); From 7c16eb36abecb56bda60fa321209f7fd5f5f3743 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Fri, 17 Nov 2023 09:25:48 +0100 Subject: [PATCH 4/6] glib-aux: add nm_strv_ptrarray_to_strv() helper This will replace _nm_utils_ptrarray_to_strv(). One difference is, that this will fail an assertion if there are any NULL string in the GPtrArray. --- src/libnm-glib-aux/nm-shared-utils.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/libnm-glib-aux/nm-shared-utils.h b/src/libnm-glib-aux/nm-shared-utils.h index 74d7b1b921..a99ae61229 100644 --- a/src/libnm-glib-aux/nm-shared-utils.h +++ b/src/libnm-glib-aux/nm-shared-utils.h @@ -2536,6 +2536,21 @@ nm_strv_ptrarray_get_unsafe(GPtrArray *arr, guint *out_len) return (const char *const *) arr->pdata; } +static inline char ** +nm_strv_ptrarray_to_strv_full(const GPtrArray *a, gboolean not_null) +{ + if (!a) + return not_null ? nm_strv_empty_new() : NULL; + return nm_strv_dup_full((const char *const *) a->pdata, a->len, TRUE, TRUE); +} + +static inline char ** +nm_strv_ptrarray_to_strv(const GPtrArray *a) +{ + /* Returns never NULL ("not_null"!) */ + return nm_strv_ptrarray_to_strv_full(a, TRUE); +} + static inline GPtrArray * nm_strv_ptrarray_clone(const GPtrArray *src, gboolean null_if_empty) { From 0b95cd5b801be00f2d175aa356502d5883ab712a Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Fri, 17 Nov 2023 09:51:36 +0100 Subject: [PATCH 5/6] libnm: drop unused nm_strv_to_ptrarray() helper It also doesn't make much sense to have this. We may use a GPtrArray to construct and keep track of a (dynamic) strv list. Then we add the strings to the GPtrArray one by one. We almost never will want to create a GPtrArray based on a strv array. --- src/libnm-core-impl/nm-utils.c | 18 ------------------ src/libnm-core-intern/nm-core-internal.h | 1 - 2 files changed, 19 deletions(-) diff --git a/src/libnm-core-impl/nm-utils.c b/src/libnm-core-impl/nm-utils.c index 0dda3915ac..998a0b91ad 100644 --- a/src/libnm-core-impl/nm-utils.c +++ b/src/libnm-core-impl/nm-utils.c @@ -897,24 +897,6 @@ _nm_utils_slist_to_strv(const GSList *slist, gboolean deep_copy) return strv; } -GPtrArray * -nm_strv_to_ptrarray(char **strv) -{ - GPtrArray *ptrarray; - gsize i, l; - - l = NM_PTRARRAY_LEN(strv); - - ptrarray = g_ptr_array_new_full(l, g_free); - - if (strv) { - for (i = 0; strv[i]; i++) - g_ptr_array_add(ptrarray, g_strdup(strv[i])); - } - - return ptrarray; -} - char ** _nm_utils_ptrarray_to_strv(const GPtrArray *ptrarray) { diff --git a/src/libnm-core-intern/nm-core-internal.h b/src/libnm-core-intern/nm-core-internal.h index 673348c640..8bbb2c64fb 100644 --- a/src/libnm-core-intern/nm-core-internal.h +++ b/src/libnm-core-intern/nm-core-internal.h @@ -347,7 +347,6 @@ GPtrArray *_nm_utils_copy_object_array(const GPtrArray *array); GSList *nm_strv_to_gslist(char **strv, gboolean deep_copy); char **_nm_utils_slist_to_strv(const GSList *slist, gboolean deep_copy); -GPtrArray *nm_strv_to_ptrarray(char **strv); char **_nm_utils_ptrarray_to_strv(const GPtrArray *ptrarray); gboolean _nm_utils_check_file(const char *filename, From 420451540c685fde03f27e444eb4b55d90c1adf1 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Fri, 17 Nov 2023 09:12:37 +0100 Subject: [PATCH 6/6] libnm: replace _nm_utils_ptrarray_to_strv() with nm_strv_ptrarray_to_strv() The difference is that nm_strv_ptrarray_to_strv() fails an assertion, if there are any NULL strings inside the GPtrArray. --- src/libnm-core-impl/nm-setting-ip-config.c | 2 +- src/libnm-core-impl/nm-setting-team.c | 3 +-- src/libnm-core-impl/nm-utils.c | 18 ------------------ src/libnm-core-intern/nm-core-internal.h | 2 -- 4 files changed, 2 insertions(+), 23 deletions(-) diff --git a/src/libnm-core-impl/nm-setting-ip-config.c b/src/libnm-core-impl/nm-setting-ip-config.c index c55babaf20..ed6cdf90ef 100644 --- a/src/libnm-core-impl/nm-setting-ip-config.c +++ b/src/libnm-core-impl/nm-setting-ip-config.c @@ -6146,7 +6146,7 @@ get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) switch (prop_id) { case PROP_DNS: - g_value_take_boxed(value, _nm_utils_ptrarray_to_strv(priv->dns)); + g_value_take_boxed(value, nm_strv_ptrarray_to_strv(priv->dns)); break; case PROP_ADDRESSES: g_value_take_boxed(value, diff --git a/src/libnm-core-impl/nm-setting-team.c b/src/libnm-core-impl/nm-setting-team.c index 5cc63870fc..2195757fcf 100644 --- a/src/libnm-core-impl/nm-setting-team.c +++ b/src/libnm-core-impl/nm-setting-team.c @@ -1384,8 +1384,7 @@ get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) break; case NM_TEAM_ATTRIBUTE_MASTER_RUNNER_TX_HASH: v_ptrarr = priv->team_setting->d.master.runner_tx_hash; - g_value_take_boxed(value, - v_ptrarr ? _nm_utils_ptrarray_to_strv((GPtrArray *) v_ptrarr) : NULL); + g_value_take_boxed(value, nm_strv_ptrarray_to_strv_full(v_ptrarr, FALSE)); break; case NM_TEAM_ATTRIBUTE_LINK_WATCHERS: g_value_take_boxed(value, diff --git a/src/libnm-core-impl/nm-utils.c b/src/libnm-core-impl/nm-utils.c index 998a0b91ad..61b931868a 100644 --- a/src/libnm-core-impl/nm-utils.c +++ b/src/libnm-core-impl/nm-utils.c @@ -897,24 +897,6 @@ _nm_utils_slist_to_strv(const GSList *slist, gboolean deep_copy) return strv; } -char ** -_nm_utils_ptrarray_to_strv(const GPtrArray *ptrarray) -{ - char **strv; - guint i; - - if (!ptrarray) - return g_new0(char *, 1); - - strv = g_new(char *, ptrarray->len + 1); - - for (i = 0; i < ptrarray->len; i++) - strv[i] = g_strdup(ptrarray->pdata[i]); - strv[i] = NULL; - - return strv; -} - /*****************************************************************************/ static gboolean diff --git a/src/libnm-core-intern/nm-core-internal.h b/src/libnm-core-intern/nm-core-internal.h index 8bbb2c64fb..16f972a9ce 100644 --- a/src/libnm-core-intern/nm-core-internal.h +++ b/src/libnm-core-intern/nm-core-internal.h @@ -347,8 +347,6 @@ GPtrArray *_nm_utils_copy_object_array(const GPtrArray *array); GSList *nm_strv_to_gslist(char **strv, gboolean deep_copy); char **_nm_utils_slist_to_strv(const GSList *slist, gboolean deep_copy); -char **_nm_utils_ptrarray_to_strv(const GPtrArray *ptrarray); - gboolean _nm_utils_check_file(const char *filename, gint64 check_owner, NMUtilsCheckFilePredicate check_file,