shared: support stripping whitespace from nm_utils_buf_utf8safe_unescape()

When parsing user input if is often convenient to allow stripping whitespace.
Especially with escaped strings, the user could still escape the whitespace,
if the space should be taken literally.

Add support for that to nm_utils_buf_utf8safe_unescape().

Note that this is not the same as calling g_strstrip() before/after
unescape. That is, because nm_utils_buf_utf8safe_unescape() correctly
preserves escaped whitespace. If you call g_strstrip() before/after
the unescape, you don't know whether the whitespace is escaped.
This commit is contained in:
Thomas Haller
2020-05-04 09:52:16 +02:00
parent 5fe447d4a6
commit 0f22f77b1c
7 changed files with 50 additions and 21 deletions

View File

@@ -2186,7 +2186,7 @@ nm_ip_routing_rule_get_xifname_bin (const NMIPRoutingRule *self,
if (!xifname)
return FALSE;
bin = nm_utils_buf_utf8safe_unescape (xifname, &len, &bin_to_free);
bin = nm_utils_buf_utf8safe_unescape (xifname, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE, &len, &bin_to_free);
strncpy (out_xifname, bin, 16 /* IFNAMSIZ */);
out_xifname[15] = '\0';

View File

@@ -4673,7 +4673,7 @@ nm_utils_is_valid_iface_name_utf8safe (const char *utf8safe_name)
g_return_val_if_fail (utf8safe_name, FALSE);
bin = nm_utils_buf_utf8safe_unescape (utf8safe_name, &len, &bin_to_free);
bin = nm_utils_buf_utf8safe_unescape (utf8safe_name, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE, &len, &bin_to_free);
if (bin_to_free) {
/* some unescaping happened... */

View File

@@ -7815,7 +7815,7 @@ _do_test_utils_str_utf8safe_unescape (const char *str, const char *expected, gsi
gs_free gpointer buf_free_1 = NULL;
gs_free char *str_free_1 = NULL;
s = nm_utils_buf_utf8safe_unescape (str, &l, &buf_free_1);
s = nm_utils_buf_utf8safe_unescape (str, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE, &l, &buf_free_1);
g_assert_cmpint (expected_len, ==, l);
g_assert_cmpstr (s, ==, expected);
@@ -7839,7 +7839,7 @@ _do_test_utils_str_utf8safe_unescape (const char *str, const char *expected, gsi
if ( expected
&& l == strlen (expected)) {
/* there are no embeeded NULs. Check that nm_utils_str_utf8safe_unescape() yields the same result. */
s = nm_utils_str_utf8safe_unescape (str, &str_free_1);
s = nm_utils_str_utf8safe_unescape (str, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE, &str_free_1);
g_assert_cmpstr (s, ==, expected);
if (strchr (str, '\\')) {
g_assert (str_free_1 != str);
@@ -7908,10 +7908,10 @@ _do_test_utils_str_utf8safe (const char *str, gsize str_len, const char *expecte
g_assert (g_utf8_validate (str, -1, NULL));
}
g_assert (str == nm_utils_str_utf8safe_unescape (str_safe, &str_free_4));
g_assert (str == nm_utils_str_utf8safe_unescape (str_safe, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE, &str_free_4));
g_assert (!str_free_4);
str_free_5 = nm_utils_str_utf8safe_unescape_cp (str_safe);
str_free_5 = nm_utils_str_utf8safe_unescape_cp (str_safe, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
if (str) {
g_assert (str_free_5 != str);
g_assert_cmpstr (str_free_5, ==, str);
@@ -7935,11 +7935,11 @@ _do_test_utils_str_utf8safe (const char *str, gsize str_len, const char *expecte
str_free_6 = g_strcompress (str_safe);
g_assert_cmpstr (str, ==, str_free_6);
str_free_7 = nm_utils_str_utf8safe_unescape_cp (str_safe);
str_free_7 = nm_utils_str_utf8safe_unescape_cp (str_safe, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
g_assert (str_free_7 != str);
g_assert_cmpstr (str_free_7, ==, str);
s = nm_utils_str_utf8safe_unescape (str_safe, &str_free_8);
s = nm_utils_str_utf8safe_unescape (str_safe, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE, &str_free_8);
g_assert (str_free_8 != str);
g_assert (s == str_free_8);
g_assert_cmpstr (str_free_8, ==, str);

View File

@@ -139,7 +139,7 @@ _fixup_string (const char *desc,
return NULL;
/* restore original non-UTF-8-safe text. */
desc_full = nm_utils_str_utf8safe_unescape_cp (desc);
desc_full = nm_utils_str_utf8safe_unescape_cp (desc, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
/* replace all invalid UTF-8 bytes with space. */
p = desc_full;

View File

@@ -2456,11 +2456,12 @@ _str_buf_append_c_escape_octal (NMStrBuf *strbuf,
}
gconstpointer
nm_utils_buf_utf8safe_unescape (const char *str, gsize *out_len, gpointer *to_free)
nm_utils_buf_utf8safe_unescape (const char *str, NMUtilsStrUtf8SafeFlags flags, gsize *out_len, gpointer *to_free)
{
gboolean strip_spaces = NM_FLAGS_HAS (flags, NM_UTILS_STR_UTF8_SAFE_UNESCAPE_STRIP_SPACES);
NMStrBuf strbuf;
gsize len;
const char *s;
gsize len;
g_return_val_if_fail (to_free, NULL);
g_return_val_if_fail (out_len, NULL);
@@ -2471,10 +2472,23 @@ nm_utils_buf_utf8safe_unescape (const char *str, gsize *out_len, gpointer *to_fr
return NULL;
}
if (strip_spaces)
str = nm_str_skip_leading_spaces (str);
len = strlen (str);
s = memchr (str, '\\', len);
if (!s) {
if ( strip_spaces
&& len > 0
&& g_ascii_isspace (str[len - 1])) {
len--;
while ( len > 0
&& g_ascii_isspace (str[len - 1]))
len--;
*out_len = len;
return (*to_free = g_strndup (str, len));
}
*out_len = len;
*to_free = NULL;
return str;
@@ -2494,7 +2508,7 @@ nm_utils_buf_utf8safe_unescape (const char *str, gsize *out_len, gpointer *to_fr
ch = (++str)[0];
if (ch == '\0') {
// error. Trailing '\\'
/* error. Trailing '\\' */
break;
}
@@ -2533,7 +2547,14 @@ nm_utils_buf_utf8safe_unescape (const char *str, gsize *out_len, gpointer *to_fr
s = strchr (str, '\\');
if (!s) {
nm_str_buf_append (&strbuf, str);
gsize l = strlen (str);
if (strip_spaces) {
while ( l > 0
&& g_ascii_isspace (str[l - 1]))
l--;
}
nm_str_buf_append_len (&strbuf, str, l);
break;
}
@@ -2678,14 +2699,14 @@ nm_utils_buf_utf8safe_escape_bytes (GBytes *bytes, NMUtilsStrUtf8SafeFlags flags
/*****************************************************************************/
const char *
nm_utils_str_utf8safe_unescape (const char *str, char **to_free)
nm_utils_str_utf8safe_unescape (const char *str, NMUtilsStrUtf8SafeFlags flags, char **to_free)
{
const char *res;
gsize len;
g_return_val_if_fail (to_free, NULL);
res = nm_utils_buf_utf8safe_unescape (str, &len, (gpointer *) to_free);
res = nm_utils_buf_utf8safe_unescape (str, flags, &len, (gpointer *) to_free);
nm_assert ( (!res && len == 0)
|| (strlen (res) <= len));
@@ -2748,11 +2769,11 @@ nm_utils_str_utf8safe_escape_cp (const char *str, NMUtilsStrUtf8SafeFlags flags)
}
char *
nm_utils_str_utf8safe_unescape_cp (const char *str)
nm_utils_str_utf8safe_unescape_cp (const char *str, NMUtilsStrUtf8SafeFlags flags)
{
char *s;
str = nm_utils_str_utf8safe_unescape (str, &s);
str = nm_utils_str_utf8safe_unescape (str, flags, &s);
return s ?: g_strdup (str);
}

View File

@@ -1197,17 +1197,25 @@ typedef enum {
* reallocation happens. Thus, unescape always avoids leaking
* secrets already. */
NM_UTILS_STR_UTF8_SAFE_FLAG_SECRET = 0x0004,
/* This flag only has an effect during unescaping. It means
* that non-escaped whitespaces (g_ascii_isspace()) will be
* stripped from the front and end of the string. Note that
* this flag is only useful for gracefully accepting user input
* with spaces. With this flag, escape and unescape may no longer
* yield the original input. */
NM_UTILS_STR_UTF8_SAFE_UNESCAPE_STRIP_SPACES = 0x0008,
} NMUtilsStrUtf8SafeFlags;
const char *nm_utils_buf_utf8safe_escape (gconstpointer buf, gssize buflen, NMUtilsStrUtf8SafeFlags flags, char **to_free);
const char *nm_utils_buf_utf8safe_escape_bytes (GBytes *bytes, NMUtilsStrUtf8SafeFlags flags, char **to_free);
gconstpointer nm_utils_buf_utf8safe_unescape (const char *str, gsize *out_len, gpointer *to_free);
gconstpointer nm_utils_buf_utf8safe_unescape (const char *str, NMUtilsStrUtf8SafeFlags flags, gsize *out_len, gpointer *to_free);
const char *nm_utils_str_utf8safe_escape (const char *str, NMUtilsStrUtf8SafeFlags flags, char **to_free);
const char *nm_utils_str_utf8safe_unescape (const char *str, char **to_free);
const char *nm_utils_str_utf8safe_unescape (const char *str, NMUtilsStrUtf8SafeFlags flags, char **to_free);
char *nm_utils_str_utf8safe_escape_cp (const char *str, NMUtilsStrUtf8SafeFlags flags);
char *nm_utils_str_utf8safe_unescape_cp (const char *str);
char *nm_utils_str_utf8safe_unescape_cp (const char *str, NMUtilsStrUtf8SafeFlags flags);
char *nm_utils_str_utf8safe_escape_take (char *str, NMUtilsStrUtf8SafeFlags flags);

View File

@@ -344,7 +344,7 @@ no_auto_default_from_file (const char *no_auto_default_file)
if (list) {
for (i = 0; list[i]; i++)
list[i] = nm_utils_str_utf8safe_unescape_cp (list[i]);
list[i] = nm_utils_str_utf8safe_unescape_cp (list[i], NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
}
/* The returned buffer here is not at all compact. That means, it has additional