uri: fix g_uri_unescape_string() regression

The illegal character set used to be applied only to the decoded
characters.

Fixes: https://gitlab.gnome.org/GNOME/glib/-/issues/2160

Fixes: d83d68d64c ("guri: new URI parsing and generating functions")
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
This commit is contained in:
Marc-André Lureau 2020-07-14 12:10:51 +04:00
parent 1135ca25fd
commit 4433a46e06
2 changed files with 20 additions and 19 deletions

View File

@ -237,6 +237,7 @@ g_uri_char_is_unreserved (gchar ch)
static gssize static gssize
uri_decoder (gchar **out, uri_decoder (gchar **out,
const gchar *illegal_chars,
const gchar *start, const gchar *start,
gsize length, gsize length,
gboolean just_normalize, gboolean just_normalize,
@ -280,6 +281,13 @@ uri_decoder (gchar **out,
} }
c = HEXCHAR (s); c = HEXCHAR (s);
if (illegal_chars && strchr (illegal_chars, c))
{
g_set_error_literal (error, G_URI_ERROR, parse_error,
_("Illegal character in URI"));
g_free (decoded);
return -1;
}
if (just_normalize && !g_uri_char_is_unreserved (c)) if (just_normalize && !g_uri_char_is_unreserved (c))
{ {
/* Leave the % sequence there. */ /* Leave the % sequence there. */
@ -318,6 +326,7 @@ uri_decoder (gchar **out,
static gboolean static gboolean
uri_decode (gchar **out, uri_decode (gchar **out,
const gchar *illegal_chars,
const gchar *start, const gchar *start,
gsize length, gsize length,
gboolean www_form, gboolean www_form,
@ -325,7 +334,7 @@ uri_decode (gchar **out,
GUriError parse_error, GUriError parse_error,
GError **error) GError **error)
{ {
return uri_decoder (out, start, length, FALSE, www_form, flags, return uri_decoder (out, illegal_chars, start, length, FALSE, www_form, flags,
parse_error, error) != -1; parse_error, error) != -1;
} }
@ -337,7 +346,7 @@ uri_normalize (gchar **out,
GUriError parse_error, GUriError parse_error,
GError **error) GError **error)
{ {
return uri_decoder (out, start, length, TRUE, FALSE, flags, return uri_decoder (out, NULL, start, length, TRUE, FALSE, flags,
parse_error, error) != -1; parse_error, error) != -1;
} }
@ -457,7 +466,7 @@ parse_host (const gchar *start,
} }
flags &= ~G_URI_FLAGS_ENCODED; flags &= ~G_URI_FLAGS_ENCODED;
if (!uri_decode (&decoded, start, length, FALSE, flags, if (!uri_decode (&decoded, NULL, start, length, FALSE, flags,
G_URI_ERROR_BAD_HOST, error)) G_URI_ERROR_BAD_HOST, error))
return FALSE; return FALSE;
@ -778,7 +787,7 @@ g_uri_split_internal (const gchar *uri_string,
end = p + strcspn (p, "#"); end = p + strcspn (p, "#");
if (*end == '#') if (*end == '#')
{ {
if (!uri_decode (fragment, end + 1, strlen (end + 1), FALSE, flags, if (!uri_decode (fragment, NULL, end + 1, strlen (end + 1), FALSE, flags,
G_URI_ERROR_BAD_FRAGMENT, error)) G_URI_ERROR_BAD_FRAGMENT, error))
goto fail; goto fail;
} }
@ -1842,7 +1851,7 @@ g_uri_parse_params (const gchar *params,
_("Missing '=' and parameter value")); _("Missing '=' and parameter value"));
return NULL; return NULL;
} }
if (!uri_decode (&decoded_attr, attr, attr_end - attr, if (!uri_decode (&decoded_attr, NULL, attr, attr_end - attr,
www_form, G_URI_FLAGS_NONE, G_URI_ERROR_MISC, error)) www_form, G_URI_FLAGS_NONE, G_URI_ERROR_MISC, error))
{ {
g_hash_table_destroy (hash); g_hash_table_destroy (hash);
@ -1850,7 +1859,7 @@ g_uri_parse_params (const gchar *params,
} }
value = attr_end + 1; value = attr_end + 1;
if (!uri_decode (&decoded_value, value, value_end - value, if (!uri_decode (&decoded_value, NULL, value, value_end - value,
www_form, G_URI_FLAGS_NONE, G_URI_ERROR_MISC, error)) www_form, G_URI_FLAGS_NONE, G_URI_ERROR_MISC, error))
{ {
g_free (decoded_attr); g_free (decoded_attr);
@ -2119,7 +2128,7 @@ g_uri_unescape_segment (const gchar *escaped_string,
const gchar *escaped_string_end, const gchar *escaped_string_end,
const gchar *illegal_characters) const gchar *illegal_characters)
{ {
gchar *unescaped, *p; gchar *unescaped;
gsize length; gsize length;
if (!escaped_string) if (!escaped_string)
@ -2131,24 +2140,13 @@ g_uri_unescape_segment (const gchar *escaped_string,
length = strlen (escaped_string); length = strlen (escaped_string);
if (!uri_decode (&unescaped, if (!uri_decode (&unescaped,
illegal_characters,
escaped_string, length, escaped_string, length,
FALSE, FALSE,
G_URI_FLAGS_PARSE_STRICT, G_URI_FLAGS_PARSE_STRICT,
0, NULL)) 0, NULL))
return NULL; return NULL;
if (illegal_characters)
{
for (p = unescaped; *p; p++)
{
if (strchr (illegal_characters, *p))
{
g_free (unescaped);
return NULL;
}
}
}
return unescaped; return unescaped;
} }
@ -2245,6 +2243,7 @@ g_uri_unescape_bytes (const gchar *escaped_string,
length = strlen (escaped_string); length = strlen (escaped_string);
unescaped_length = uri_decoder (&buf, unescaped_length = uri_decoder (&buf,
NULL,
escaped_string, length, escaped_string, length,
FALSE, FALSE,
FALSE, FALSE,

View File

@ -343,6 +343,8 @@ test_uri_unescape_string (void)
{ "%2Babc %4F", NULL, "+abc O" }, { "%2Babc %4F", NULL, "+abc O" },
{ "%2Babc %4F", "+", NULL }, { "%2Babc %4F", "+", NULL },
{ "%00abc %4F", "+/", NULL }, { "%00abc %4F", "+/", NULL },
{ "/cursors/none.png", "/", "/cursors/none.png" },
{ "/cursors%2fbad-subdir/none.png", "/", NULL },
{ "%0", NULL, NULL }, { "%0", NULL, NULL },
{ "%ra", NULL, NULL }, { "%ra", NULL, NULL },
{ "%2r", NULL, NULL }, { "%2r", NULL, NULL },