diff --git a/src/libnm-core-impl/tests/test-general.c b/src/libnm-core-impl/tests/test-general.c index 4bbb3df451..30b1ca5da8 100644 --- a/src/libnm-core-impl/tests/test-general.c +++ b/src/libnm-core-impl/tests/test-general.c @@ -7,6 +7,7 @@ #include "libnm-core-impl/nm-default-libnm-core.h" +#include #include #include #include @@ -87,21 +88,65 @@ G_STATIC_ASSERT(NM_UTILS_HWADDR_LEN_MAX == _NM_UTILS_HWADDR_LEN_MAX); static void test_nm_ascii_spaces(void) { - int i; - const char *const S = NM_ASCII_SPACES; + int i; - for (i = 0; S[i]; i++) - g_assert(!strchr(&S[i + 1], S[i])); + { + const char *const S = NM_ASCII_SPACES; - for (i = 0; S[i] != '\0'; i++) - g_assert(g_ascii_isspace(S[i])); + for (i = 0; S[i]; i++) + g_assert(!strchr(&S[i + 1], S[i])); - g_assert(!g_ascii_isspace((char) 0)); - for (i = 1; i < 0x100; i++) { - if (g_ascii_isspace((char) i)) - g_assert(strchr(S, (char) i)); - else - g_assert(!strchr(S, (char) i)); + for (i = 0; S[i] != '\0'; i++) + g_assert(g_ascii_isspace(S[i])); + + g_assert(!g_ascii_isspace((char) 0)); + for (i = 1; i < 0x100; i++) { + g_assert((!!g_ascii_isspace((char) i)) == (!!strchr(S, (char) i))); + } + } + + { + const char *const S = NM_ASCII_WHITESPACES; + + for (i = 0; S[i]; i++) + g_assert(!strchr(&S[i + 1], S[i])); + + for (i = 0; S[i] != '\0'; i++) + g_assert(nm_ascii_is_whitespace(S[i])); + + g_assert(!nm_ascii_is_whitespace((char) 0)); + for (i = 1; i < 0x100; i++) { + g_assert(nm_ascii_is_whitespace((char) i) == (!!strchr(S, (char) i))); + } + } + + { + const char *const S = NM_ASCII_SPACES_CTYPE; + + for (i = 0; S[i]; i++) + g_assert(!strchr(&S[i + 1], S[i])); + + if (nm_streq0(g_getenv("LANG"), "C")) { + g_assert(!isspace((char) 0)); + for (i = 1; i < 0x100; i++) { + g_assert((!!isspace((char) i)) == (!!strchr(S, (char) i))); + } + } + } + + { + const char *const S = NM_ASCII_SPACES_KERNEL; + + for (i = 0; S[i]; i++) + g_assert(!strchr(&S[i + 1], S[i])); + + for (i = 0; S[i] != '\0'; i++) + g_assert(nm_ascii_is_space_kernel(S[i])); + + g_assert(!nm_ascii_is_space_kernel((char) 0)); + for (i = 1; i < 0x100; i++) { + g_assert(nm_ascii_is_space_kernel((char) i) == (!!strchr(S, (char) i))); + } } } diff --git a/src/libnm-glib-aux/nm-macros-internal.h b/src/libnm-glib-aux/nm-macros-internal.h index b74d732407..9972dc4452 100644 --- a/src/libnm-glib-aux/nm-macros-internal.h +++ b/src/libnm-glib-aux/nm-macros-internal.h @@ -1086,11 +1086,20 @@ nm_g_variant_equal(GVariant *a, GVariant *b) /* mirrors g_ascii_isspace() and what we consider spaces in general. */ #define NM_ASCII_SPACES " \n\t\r\f" -/* Like NM_ASCII_SPACES, but without "\f" (0x0c, Formfeed Page Break). - * This is what for example systemd calls WHITESPACE and what it uses to tokenize - * the kernel command line. */ +/* Like NM_ASCII_SPACES, but without "\f" (0x0c, Formfeed Page Break). This is + * what for example systemd calls WHITESPACE and what it uses to tokenize the + * kernel command line. */ #define NM_ASCII_WHITESPACES " \n\t\r" +/* mirrors 's isspace() with C locale. It's like NM_ASCII_SPACES but + * additionally also considers '\v' (vertical tab). */ +#define NM_ASCII_SPACES_CTYPE NM_ASCII_SPACES "\v" + +/* mirrors kernel's isspace() from "include/linux/ctype.h", which treats as + * space the common ASCII spaces, including '\v' (vertical tab), but also + * '\240' (non-breaking space, NBSP in Latin-1). */ +#define NM_ASCII_SPACES_KERNEL NM_ASCII_SPACES_CTYPE "\240" + static inline gboolean nm_ascii_is_whitespace(char ch) { @@ -1100,6 +1109,13 @@ nm_ascii_is_whitespace(char ch) return NM_IN_SET(ch, ' ', '\n', '\t', '\r'); } +static inline gboolean +nm_ascii_is_space_kernel(char ch) +{ + /* Checks whether @ch is in NM_ASCII_SPACES_KERNEL. */ + return NM_IN_SET(ch, ' ', '\n', '\t', '\r', '\f', '\v', '\240'); +} + #define NM_ASCII_NEWLINE "\n\r" static inline gboolean diff --git a/src/libnm-glib-aux/nm-shared-utils.c b/src/libnm-glib-aux/nm-shared-utils.c index a51ff765d7..34a3af2053 100644 --- a/src/libnm-glib-aux/nm-shared-utils.c +++ b/src/libnm-glib-aux/nm-shared-utils.c @@ -5352,7 +5352,7 @@ nm_utils_ifname_valid_kernel(const char *name, GError **error) if (ch == '\0') return TRUE; - if (NM_IN_SET(ch, '/', ':') || g_ascii_isspace(ch)) { + if (NM_IN_SET(ch, '/', ':') || nm_ascii_is_space_kernel(ch)) { g_set_error_literal(error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,