Commit 5b49df3b authored by Marc-André Lureau's avatar Marc-André Lureau

Merge branch 'uri-non-utf8' into 'master'

Fix non-utf8 URI pct-decoding / unescape regression

Closes #2165

See merge request !1569
parents c60d6599 22fe3b02
Pipeline #199110 passed with stages
in 18 minutes and 14 seconds
...@@ -4,15 +4,20 @@ static void ...@@ -4,15 +4,20 @@ static void
test_bytes (const guint8 *data, test_bytes (const guint8 *data,
gsize size) gsize size)
{ {
GError *error = NULL;
GBytes *unescaped_bytes = NULL; GBytes *unescaped_bytes = NULL;
gchar *escaped_string = NULL; gchar *escaped_string = NULL;
if (size > G_MAXSSIZE) if (size > G_MAXSSIZE)
return; return;
unescaped_bytes = g_uri_unescape_bytes ((const gchar *) data, (gssize) size, NULL); unescaped_bytes = g_uri_unescape_bytes ((const gchar *) data, (gssize) size, NULL, &error);
if (unescaped_bytes == NULL) if (unescaped_bytes == NULL)
return; {
g_assert_nonnull (error);
g_clear_error (&error);
return;
}
escaped_string = g_uri_escape_bytes (g_bytes_get_data (unescaped_bytes, NULL), escaped_string = g_uri_escape_bytes (g_bytes_get_data (unescaped_bytes, NULL),
g_bytes_get_size (unescaped_bytes), g_bytes_get_size (unescaped_bytes),
......
...@@ -2116,6 +2116,9 @@ g_uri_get_flags (GUri *uri) ...@@ -2116,6 +2116,9 @@ g_uri_get_flags (GUri *uri)
* want to avoid for instance having a slash being expanded in an * want to avoid for instance having a slash being expanded in an
* escaped path element, which might confuse pathname handling. * 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. * Returns: an unescaped version of @escaped_string or %NULL on error.
* The returned string should be freed when no longer needed. As a * The returned string should be freed when no longer needed. As a
* special case if %NULL is given for @escaped_string, this function * special case if %NULL is given for @escaped_string, this function
...@@ -2130,6 +2133,7 @@ g_uri_unescape_segment (const gchar *escaped_string, ...@@ -2130,6 +2133,7 @@ g_uri_unescape_segment (const gchar *escaped_string,
{ {
gchar *unescaped; gchar *unescaped;
gsize length; gsize length;
gssize decoded_len;
if (!escaped_string) if (!escaped_string)
return NULL; return NULL;
...@@ -2139,14 +2143,21 @@ g_uri_unescape_segment (const gchar *escaped_string, ...@@ -2139,14 +2143,21 @@ g_uri_unescape_segment (const gchar *escaped_string,
else else
length = strlen (escaped_string); length = strlen (escaped_string);
if (!uri_decode (&unescaped, decoded_len = uri_decoder (&unescaped,
illegal_characters, illegal_characters,
escaped_string, length, escaped_string, length,
FALSE, FALSE, FALSE,
G_URI_FLAGS_PARSE_STRICT, G_URI_FLAGS_PARSE_STRICT|G_URI_FLAGS_ENCODED,
0, NULL)) 0, NULL);
if (decoded_len < 0)
return NULL; return NULL;
if (memchr (unescaped, '\0', decoded_len))
{
g_free (unescaped);
return NULL;
}
return unescaped; return unescaped;
} }
...@@ -2220,6 +2231,7 @@ g_uri_escape_string (const gchar *unescaped, ...@@ -2220,6 +2231,7 @@ g_uri_escape_string (const gchar *unescaped,
* is NUL-terminated. * is NUL-terminated.
* @illegal_characters: (nullable): a string of illegal characters * @illegal_characters: (nullable): a string of illegal characters
* not to be allowed, or %NULL. * not to be allowed, or %NULL.
* @error: #GError for error reporting, or %NULL to ignore.
* *
* Unescapes a segment of an escaped string as binary data. * Unescapes a segment of an escaped string as binary data.
* *
...@@ -2232,21 +2244,23 @@ g_uri_escape_string (const gchar *unescaped, ...@@ -2232,21 +2244,23 @@ g_uri_escape_string (const gchar *unescaped,
* want to avoid for instance having a slash being expanded in an * want to avoid for instance having a slash being expanded in an
* escaped path element, which might confuse pathname handling. * escaped path element, which might confuse pathname handling.
* *
* Returns: (transfer full): an unescaped version of @escaped_string * Returns: (transfer full): an unescaped version of @escaped_string or %NULL on
* or %NULL on error. The returned #GBytes should be unreffed when no * error (if decoding failed, using %G_URI_ERROR_MISC error code). The returned
* longer needed. * #GBytes should be unreffed when no longer needed.
* *
* Since: 2.66 * Since: 2.66
**/ **/
GBytes * GBytes *
g_uri_unescape_bytes (const gchar *escaped_string, g_uri_unescape_bytes (const gchar *escaped_string,
gssize length, gssize length,
const char *illegal_characters) const char *illegal_characters,
GError **error)
{ {
gchar *buf; gchar *buf;
gssize unescaped_length; gssize unescaped_length;
g_return_val_if_fail (escaped_string != NULL, NULL); g_return_val_if_fail (escaped_string != NULL, NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
if (length == -1) if (length == -1)
length = strlen (escaped_string); length = strlen (escaped_string);
...@@ -2257,7 +2271,7 @@ g_uri_unescape_bytes (const gchar *escaped_string, ...@@ -2257,7 +2271,7 @@ g_uri_unescape_bytes (const gchar *escaped_string,
FALSE, FALSE,
FALSE, FALSE,
G_URI_FLAGS_PARSE_STRICT|G_URI_FLAGS_ENCODED, G_URI_FLAGS_PARSE_STRICT|G_URI_FLAGS_ENCODED,
0, NULL); G_URI_ERROR_MISC, error);
if (unescaped_length == -1) if (unescaped_length == -1)
return NULL; return NULL;
......
...@@ -358,7 +358,9 @@ char * g_uri_escape_string (const char *unescaped, ...@@ -358,7 +358,9 @@ char * g_uri_escape_string (const char *unescaped,
GLIB_AVAILABLE_IN_2_66 GLIB_AVAILABLE_IN_2_66
GBytes * g_uri_unescape_bytes (const char *escaped_string, GBytes * g_uri_unescape_bytes (const char *escaped_string,
gssize length, gssize length,
const char *illegal_characters); const char *illegal_characters,
GError **error);
GLIB_AVAILABLE_IN_2_66 GLIB_AVAILABLE_IN_2_66
char * g_uri_escape_bytes (const guchar *unescaped, char * g_uri_escape_bytes (const guchar *unescaped,
gsize length, gsize length,
......
...@@ -348,6 +348,7 @@ test_uri_unescape_string (void) ...@@ -348,6 +348,7 @@ test_uri_unescape_string (void)
{ "%0", NULL, NULL }, { "%0", NULL, NULL },
{ "%ra", NULL, NULL }, { "%ra", NULL, NULL },
{ "%2r", NULL, NULL }, { "%2r", NULL, NULL },
{ "Timm B\344der", NULL, "Timm B\344der" },
{ NULL, NULL, NULL }, /* actually a valid test, not a delimiter */ { NULL, NULL, NULL }, /* actually a valid test, not a delimiter */
}; };
gsize i; gsize i;
...@@ -367,6 +368,7 @@ test_uri_unescape_string (void) ...@@ -367,6 +368,7 @@ test_uri_unescape_string (void)
static void static void
test_uri_unescape_bytes (gconstpointer test_data) test_uri_unescape_bytes (gconstpointer test_data)
{ {
GError *error = NULL;
gboolean use_nul_terminated = GPOINTER_TO_INT (test_data); gboolean use_nul_terminated = GPOINTER_TO_INT (test_data);
const struct const struct
{ {
...@@ -410,14 +412,17 @@ test_uri_unescape_bytes (gconstpointer test_data) ...@@ -410,14 +412,17 @@ test_uri_unescape_bytes (gconstpointer test_data)
escaped = g_memdup (tests[i].escaped, escaped_len); escaped = g_memdup (tests[i].escaped, escaped_len);
} }
bytes = g_uri_unescape_bytes (escaped, escaped_len, tests[i].illegal); bytes = g_uri_unescape_bytes (escaped, escaped_len, tests[i].illegal, &error);
if (tests[i].expected_unescaped_len < 0) if (tests[i].expected_unescaped_len < 0)
{ {
g_assert_null (bytes); g_assert_null (bytes);
g_assert_error (error, G_URI_ERROR, G_URI_ERROR_MISC);
g_clear_error (&error);
} }
else else
{ {
g_assert_no_error (error);
g_assert_cmpmem (g_bytes_get_data (bytes, NULL), g_assert_cmpmem (g_bytes_get_data (bytes, NULL),
g_bytes_get_size (bytes), g_bytes_get_size (bytes),
tests[i].expected_unescaped, tests[i].expected_unescaped,
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment