From dade5055fb4d859d69d6f3ec07eff3d0ce27b208 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 28 Apr 2020 18:10:55 +0200 Subject: [PATCH] keyfile: add nm_keyfile_plugin_kf_get_integer_list_uint() to parse a list of integers We had three callers of nm_keyfile_plugin_kf_get_integer_list(). Two only wanted to read values in range of guint8. One, wanted to read unsigned integers (for which nm_keyfile_plugin_kf_get_integer_list() was not suitable). Instead, implement a integer list reader ourself. One change is that g_key_file_get_integer_list() would accept list elements with a number followed by a white space and garbage ([1]). We don't do that, so there is a change in behavior here. That seems preferable, we don't want to accept garbage. The error reason text from the reader now also changes, and obviously we no longer fail for integer values larger than G_MAXINT. [1] https://gitlab.gnome.org/GNOME/glib/-/blob/c9bf247eb90805cc7a0020db20b8808ed42fe61c/glib/gkeyfile.c#L4445 --- shared/nm-keyfile/nm-keyfile-utils.c | 48 +++++++++++++++++++++++++++- shared/nm-keyfile/nm-keyfile-utils.h | 10 +++--- shared/nm-keyfile/nm-keyfile.c | 33 ++++++++----------- 3 files changed, 65 insertions(+), 26 deletions(-) diff --git a/shared/nm-keyfile/nm-keyfile-utils.c b/shared/nm-keyfile/nm-keyfile-utils.c index 8ba7613b69..c28af81541 100644 --- a/shared/nm-keyfile/nm-keyfile-utils.c +++ b/shared/nm-keyfile/nm-keyfile-utils.c @@ -133,9 +133,55 @@ fcn_name (GKeyFile *kf, \ return list; \ } -DEFINE_KF_LIST_WRAPPER_GET (nm_keyfile_plugin_kf_get_integer_list, int *, g_key_file_get_integer_list); DEFINE_KF_LIST_WRAPPER_GET (nm_keyfile_plugin_kf_get_string_list, char **, g_key_file_get_string_list); +guint * +nm_keyfile_plugin_kf_get_integer_list_uint (GKeyFile *key_file, + const char *group_name, + const char *key, + gsize *out_length, + GError **error) +{ + GError *key_file_error = NULL; + gs_strfreev char **values = NULL; + gs_free guint *int_values = NULL; + gsize i, num_ints; + + g_return_val_if_fail (key_file != NULL, NULL); + g_return_val_if_fail (group_name != NULL, NULL); + g_return_val_if_fail (key != NULL, NULL); + + NM_SET_OUT (out_length, 0); + + values = nm_keyfile_plugin_kf_get_string_list (key_file, group_name, key, &num_ints, &key_file_error); + + if (key_file_error) + g_propagate_error (error, key_file_error); + if (!values) + return NULL; + + int_values = g_new (guint, num_ints); + + for (i = 0; i < num_ints; i++) { + gint64 v; + + G_STATIC_ASSERT_EXPR (sizeof (v) > sizeof (guint)); + v = _nm_utils_ascii_str_to_int64 (values[i], 10, 0, G_MAXUINT, -1); + if (v == -1) { + g_set_error (error, + G_KEY_FILE_ERROR, + G_KEY_FILE_ERROR_INVALID_VALUE, + _("Value cannot be interpreted as a list of numbers.")); + return NULL; + } + + int_values[i] = v; + } + + NM_SET_OUT (out_length, num_ints); + return g_steal_pointer (&int_values); +} + void nm_keyfile_plugin_kf_set_string_list (GKeyFile *kf, const char *group, diff --git a/shared/nm-keyfile/nm-keyfile-utils.h b/shared/nm-keyfile/nm-keyfile-utils.h index ab9f44dc7f..9b35e17ed6 100644 --- a/shared/nm-keyfile/nm-keyfile-utils.h +++ b/shared/nm-keyfile/nm-keyfile-utils.h @@ -19,11 +19,11 @@ const char *nm_keyfile_plugin_get_setting_name_for_alias (const char *alias); /*****************************************************************************/ -int *nm_keyfile_plugin_kf_get_integer_list (GKeyFile *kf, const char *group, const char *key, gsize *out_length, GError **error); -char **nm_keyfile_plugin_kf_get_string_list (GKeyFile *kf, const char *group, const char *key, gsize *out_length, GError **error); -char *nm_keyfile_plugin_kf_get_string (GKeyFile *kf, const char *group, const char *key, GError **error); -gboolean nm_keyfile_plugin_kf_get_boolean (GKeyFile *kf, const char *group, const char *key, GError **error); -char *nm_keyfile_plugin_kf_get_value (GKeyFile *kf, const char *group, const char *key, GError **error); +guint *nm_keyfile_plugin_kf_get_integer_list_uint (GKeyFile *kf, const char *group, const char *key, gsize *out_length, GError **error); +char **nm_keyfile_plugin_kf_get_string_list (GKeyFile *kf, const char *group, const char *key, gsize *out_length, GError **error); +char *nm_keyfile_plugin_kf_get_string (GKeyFile *kf, const char *group, const char *key, GError **error); +gboolean nm_keyfile_plugin_kf_get_boolean (GKeyFile *kf, const char *group, const char *key, GError **error); +char *nm_keyfile_plugin_kf_get_value (GKeyFile *kf, const char *group, const char *key, GError **error); void nm_keyfile_plugin_kf_set_integer_list_uint8 (GKeyFile *kf, const char *group, const char *key, const guint8 *list, gsize length); void nm_keyfile_plugin_kf_set_integer_list_uint (GKeyFile *kf, const char *group, const char *key, const guint *list, gsize length); diff --git a/shared/nm-keyfile/nm-keyfile.c b/shared/nm-keyfile/nm-keyfile.c index 474377bfcf..c98fbdf2bb 100644 --- a/shared/nm-keyfile/nm-keyfile.c +++ b/shared/nm-keyfile/nm-keyfile.c @@ -164,23 +164,16 @@ read_array_of_uint (GKeyFile *file, const char *key) { gs_unref_array GArray *array = NULL; - gsize length; - gsize i; - gs_free int *tmp = NULL; gs_free_error GError *error = NULL; + gs_free guint *tmp = NULL; + gsize length; - tmp = nm_keyfile_plugin_kf_get_integer_list (file, nm_setting_get_name (setting), key, &length, &error); + tmp = nm_keyfile_plugin_kf_get_integer_list_uint (file, nm_setting_get_name (setting), key, &length, &error); if (error) return; array = g_array_sized_new (FALSE, FALSE, sizeof (guint), length); - - for (i = 0; i < length; i++) { - if (tmp[i] < 0) - return; - g_array_append_val (array, tmp[i]); - } - + g_array_append_vals (array, tmp, length); g_object_set (setting, key, array, NULL); } @@ -941,7 +934,7 @@ mac_address_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *key char addr_str[NM_UTILS_HWADDR_LEN_MAX * 3]; guint8 addr_bin[NM_UTILS_HWADDR_LEN_MAX]; gs_free char *tmp_string = NULL; - gs_free int *int_list = NULL; + gs_free guint *int_list = NULL; const char *mac_str; gsize int_list_len; gsize i; @@ -962,12 +955,12 @@ mac_address_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *key goto good_addr_bin; /* Old format; list of ints */ - int_list = nm_keyfile_plugin_kf_get_integer_list (info->keyfile, setting_name, key, &int_list_len, NULL); + int_list = nm_keyfile_plugin_kf_get_integer_list_uint (info->keyfile, setting_name, key, &int_list_len, NULL); if (int_list_len == addr_len) { for (i = 0; i < addr_len; i++) { - const int val = int_list[i]; + const guint val = int_list[i]; - if (val < 0 || val > 255) + if (val > 255) break; addr_bin[i] = (guint8) val; } @@ -3095,24 +3088,24 @@ read_one_setting_value (KeyfileReaderInfo *info, nm_g_object_set_property_int64 (G_OBJECT (setting), key, i64, &err); } } else if (type == G_TYPE_BYTES) { - gs_free int *tmp = NULL; + gs_free guint *tmp = NULL; GByteArray *array; GBytes *bytes; gsize length; int i; gboolean already_warned = FALSE; - tmp = nm_keyfile_plugin_kf_get_integer_list (keyfile, setting_info->setting_name, key, &length, NULL); + tmp = nm_keyfile_plugin_kf_get_integer_list_uint (keyfile, setting_info->setting_name, key, &length, NULL); array = g_byte_array_sized_new (length); for (i = 0; i < length; i++) { - const int val = tmp[i]; + const guint val = tmp[i]; unsigned char v = (unsigned char) (val & 0xFF); - if (val < 0 || val > 255) { + if (val > 255u) { if ( !already_warned && !handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN, - _("ignoring invalid byte element '%d' (not between 0 and 255 inclusive)"), + _("ignoring invalid byte element '%u' (not between 0 and 255 inclusive)"), val)) { g_byte_array_unref (array); return;