summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2019-05-01 10:27:32 +0200
committerThomas Haller <thaller@redhat.com>2019-05-07 20:58:17 +0200
commitcc9f07167607124bcb0df735034858aadfdb8541 (patch)
treebdadd96081a36aca04ca0c4eb62be6b2e1935073
parentfac95d0062d9bbe256b8e479ba7cb452cbac340e (diff)
downloadNetworkManager-cc9f07167607124bcb0df735034858aadfdb8541.tar.gz
libnm: cleanup _nm_utils_parse_tc_handle()
- g_ascii_strtoll() accepts leading spaces, but it leaves the end pointer at the first space after the digit. That means, we accepted "1: 0" but not "1 :0". We should either consistently accept spaces around the digits/colon or reject it. - g_ascii_strtoll() accepts "\v" as a space (just like `man 3 isspace` comments that "\v" is a space in C and POSIX locale. For some reasons (unknown to me) g_ascii_isspace() does not treat "\v" as space. And neither does NM_ASCII_SPACES and nm_str_skip_leading_spaces(). We should be consistent about what we consider spaces and what not. It's already odd to accept '\n' as spaces here, but well, lets do it for the sake of consistency (so that it matches with our understanding of ASCII spaces, albeit not POSIX's). - don't use bogus error domains in "g_set_error (error, 1, 0, ..." That is a bug and we have NM_UTILS_ERROR exactly for error instances with unspecified domain and code. - as before, accept a trailing ":" with omitted minor number. - reject all unexpected characters. strtoll() accepts '+' / '-' and a "0x" prefix of the numbers (and leading POSIX spaces). Be strict here and only accepts NM_ASCII_SPACES, ':', and hexdigits. In particular, don't accept the "0x" prefix. This parsing would be significantly simpler to implement, if we could just strdup() the string, split the string at the colon delimiter and use _nm_utils_ascii_str_to_int64() which gets leading/trailing spaces right. But let's save the "overhead" of an additional alloc.
-rw-r--r--libnm-core/nm-utils.c43
-rw-r--r--libnm-core/tests/test-setting.c18
2 files changed, 41 insertions, 20 deletions
diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c
index e5fd8d181c..d25aa45245 100644
--- a/libnm-core/nm-utils.c
+++ b/libnm-core/nm-utils.c
@@ -2279,21 +2279,42 @@ _nm_utils_string_append_tc_parent (GString *string, const char *prefix, guint32
guint32
_nm_utils_parse_tc_handle (const char *str, GError **error)
{
- gint64 maj, min;
- char *sep;
+ gint64 maj;
+ gint64 min = 0;
+ const char *sep;
- maj = g_ascii_strtoll (str, &sep, 0x10);
- if (*sep == ':')
- min = g_ascii_strtoll (&sep[1], &sep, 0x10);
- else
- min = 0;
+ nm_assert (str);
+
+ maj = g_ascii_strtoll (str, (char **) &sep, 0x10);
+ if (sep == str)
+ goto fail;
+
+ sep = nm_str_skip_leading_spaces (sep);
- if (*sep != '\0' || maj <= 0 || maj > 0xffff || min < 0 || min > 0xffff) {
- g_set_error (error, 1, 0, _("'%s' is not a valid handle."), str);
- return TC_H_UNSPEC;
+ if (sep[0] == ':') {
+ const char *str2 = &sep[1];
+
+ min = g_ascii_strtoll (str2, (char **) &sep, 0x10);
+ sep = nm_str_skip_leading_spaces (sep);
+ if (sep[0] != '\0')
+ goto fail;
+ } else if (sep[0] != '\0')
+ goto fail;
+
+ if ( maj <= 0
+ || maj > 0xffff
+ || min < 0
+ || min > 0xffff
+ || !NM_STRCHAR_ALL (str, ch, ( g_ascii_isxdigit (ch)
+ || ch == ':'
+ || g_ascii_isspace (ch)))) {
+ goto fail;
}
- return TC_H_MAKE (maj << 16, min);
+ return TC_H_MAKE (((guint32) maj) << 16, (guint32) min);
+fail:
+ nm_utils_error_set (error, NM_UTILS_ERROR_UNKNOWN, _("'%s' is not a valid handle."), str);
+ return TC_H_UNSPEC;
}
#define TC_ATTR_SPEC_PTR(name, type, no_value, consumes_rest, str_type) \
diff --git a/libnm-core/tests/test-setting.c b/libnm-core/tests/test-setting.c
index 8bb6f04dee..5b2c323df4 100644
--- a/libnm-core/tests/test-setting.c
+++ b/libnm-core/tests/test-setting.c
@@ -3117,27 +3117,27 @@ test_parse_tc_handle (void)
_parse_tc_handle_inval (" ");
_parse_tc_handle_inval (" \n");
_parse_tc_handle_valid ("1", 1, 0);
- _parse_tc_handle_inval(" 1 ");
+ _parse_tc_handle_valid(" 1 ", 1, 0);
_parse_tc_handle_valid ("1:", 1, 0);
- _parse_tc_handle_inval ("1: ");
+ _parse_tc_handle_valid ("1: ", 1, 0);
_parse_tc_handle_valid ("1:0", 1, 0);
- _parse_tc_handle_inval ("1 :0");
- _parse_tc_handle_inval ("1 \t\n\f\r:0");
+ _parse_tc_handle_valid ("1 :0", 1, 0);
+ _parse_tc_handle_valid ("1 \t\n\f\r:0", 1, 0);
_parse_tc_handle_inval ("1 \t\n\f\r\v:0");
- _parse_tc_handle_inval (" 1 : 0 ");
- _parse_tc_handle_valid (" \t\v\n1: 0", 1, 0);
+ _parse_tc_handle_valid (" 1 : 0 ", 1, 0);
+ _parse_tc_handle_inval (" \t\v\n1: 0");
_parse_tc_handle_valid ("1:2", 1, 2);
_parse_tc_handle_valid ("01:02", 1, 2);
- _parse_tc_handle_valid ("0x01:0x02", 1, 2);
+ _parse_tc_handle_inval ("0x01:0x02");
_parse_tc_handle_valid (" 01: 02", 1, 2);
_parse_tc_handle_valid ("019: 020", 0x19, 0x20);
_parse_tc_handle_valid ("FFFF: 020", 0xFFFF, 0x20);
_parse_tc_handle_valid ("FfFF: ffff", 0xFFFF, 0xFFFF);
_parse_tc_handle_valid ("FFFF", 0xFFFF, 0);
- _parse_tc_handle_valid ("0xFFFF", 0xFFFF, 0);
+ _parse_tc_handle_inval ("0xFFFF");
_parse_tc_handle_inval ("10000");
_parse_tc_handle_valid ("\t\n\f\r FFFF", 0xFFFF, 0);
- _parse_tc_handle_valid ("\t\n\f\r \vFFFF", 0xFFFF, 0);
+ _parse_tc_handle_inval ("\t\n\f\r \vFFFF");
}
/*****************************************************************************/