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] c9bf247eb9/glib/gkeyfile.c (L4445)
This commit is contained in:
Thomas Haller 2020-04-28 18:10:55 +02:00
parent bbdb47adaf
commit dade5055fb
No known key found for this signature in database
GPG key ID: 29C2366E4DFC5728
3 changed files with 65 additions and 26 deletions

View file

@ -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,

View file

@ -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);

View file

@ -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;