From 22fe3b0224b5070c7387883f68aa0a164661d978 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Wed, 8 Jul 2020 17:47:30 +0400 Subject: [PATCH] uri: fix regression in g_uri_unescape_segment/string MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous implementation of g_uri_unescape_segment() allowed non-utf8 decoded characters. uri_decoder() allows it too with FLAGS_ENCODED (I think it's abusing a bit the user-facing flags for some internal decoding behaviour) However, it didn't allow \0 in the decoded string. Let's have an extra check for that, outside of uri_decoder(). Fixes: d83d68d64c40021be432416f9912ff9e59a337ce Reported-by: Matthias Clasen Signed-off-by: Marc-André Lureau --- glib/guri.c | 23 +++++++++++++++++------ glib/tests/uri.c | 1 + 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/glib/guri.c b/glib/guri.c index 62d0fa718..6179ea01d 100644 --- a/glib/guri.c +++ b/glib/guri.c @@ -2116,6 +2116,9 @@ g_uri_get_flags (GUri *uri) * want to avoid for instance having a slash being expanded in an * escaped path element, which might confuse pathname handling. * + * Note: `NUL` byte is not accepted in the output, in contrast to + * g_uri_unescape_bytes(). + * * Returns: an unescaped version of @escaped_string or %NULL on error. * The returned string should be freed when no longer needed. As a * special case if %NULL is given for @escaped_string, this function @@ -2130,6 +2133,7 @@ g_uri_unescape_segment (const gchar *escaped_string, { gchar *unescaped; gsize length; + gssize decoded_len; if (!escaped_string) return NULL; @@ -2139,14 +2143,21 @@ g_uri_unescape_segment (const gchar *escaped_string, else length = strlen (escaped_string); - if (!uri_decode (&unescaped, - illegal_characters, - escaped_string, length, - FALSE, - G_URI_FLAGS_PARSE_STRICT, - 0, NULL)) + decoded_len = uri_decoder (&unescaped, + illegal_characters, + escaped_string, length, + FALSE, FALSE, + G_URI_FLAGS_PARSE_STRICT|G_URI_FLAGS_ENCODED, + 0, NULL); + if (decoded_len < 0) return NULL; + if (memchr (unescaped, '\0', decoded_len)) + { + g_free (unescaped); + return NULL; + } + return unescaped; } diff --git a/glib/tests/uri.c b/glib/tests/uri.c index 191fa4274..01ca68c26 100644 --- a/glib/tests/uri.c +++ b/glib/tests/uri.c @@ -348,6 +348,7 @@ test_uri_unescape_string (void) { "%0", NULL, NULL }, { "%ra", NULL, NULL }, { "%2r", NULL, NULL }, + { "Timm B\344der", NULL, "Timm B\344der" }, { NULL, NULL, NULL }, /* actually a valid test, not a delimiter */ }; gsize i;