diff --git a/fuzzing/fuzz_uri_escape.c b/fuzzing/fuzz_uri_escape.c index 3ee7f7089..ca14973f3 100644 --- a/fuzzing/fuzz_uri_escape.c +++ b/fuzzing/fuzz_uri_escape.c @@ -10,7 +10,7 @@ test_bytes (const guint8 *data, if (size > G_MAXSSIZE) return; - unescaped_bytes = g_uri_unescape_bytes ((const gchar *) data, (gssize) size); + unescaped_bytes = g_uri_unescape_bytes ((const gchar *) data, (gssize) size, NULL); if (unescaped_bytes == NULL) return; diff --git a/glib/guri.c b/glib/guri.c index e4fbc003d..7a4fc5b18 100644 --- a/glib/guri.c +++ b/glib/guri.c @@ -2218,12 +2218,20 @@ g_uri_escape_string (const gchar *unescaped, * @escaped_string: A URI-escaped string * @length: the length of @escaped_string to escape, or -1 if it * is NUL-terminated. + * @illegal_characters: (nullable): a string of illegal characters + * not to be allowed, or %NULL. * * Unescapes a segment of an escaped string as binary data. * * Note that in contrast to g_uri_unescape_string(), this does allow * `NUL` bytes to appear in the output. * + * If any of the characters in @illegal_characters or the NUL + * character appears as an escaped character in @escaped_string, then + * that is an error and %NULL will be returned. This is useful if you + * want to avoid for instance having a slash being expanded in an + * escaped path element, which might confuse pathname handling. + * * Returns: (transfer full): an unescaped version of @escaped_string * or %NULL on error. The returned #GBytes should be unreffed when no * longer needed. @@ -2232,7 +2240,8 @@ g_uri_escape_string (const gchar *unescaped, **/ GBytes * g_uri_unescape_bytes (const gchar *escaped_string, - gssize length) + gssize length, + const char *illegal_characters) { gchar *buf; gssize unescaped_length; @@ -2243,7 +2252,7 @@ g_uri_unescape_bytes (const gchar *escaped_string, length = strlen (escaped_string); unescaped_length = uri_decoder (&buf, - NULL, + illegal_characters, escaped_string, length, FALSE, FALSE, diff --git a/glib/guri.h b/glib/guri.h index 5db6691ba..3c061c9ba 100644 --- a/glib/guri.h +++ b/glib/guri.h @@ -357,7 +357,8 @@ char * g_uri_escape_string (const char *unescaped, GLIB_AVAILABLE_IN_2_66 GBytes * g_uri_unescape_bytes (const char *escaped_string, - gssize length); + gssize length, + const char *illegal_characters); GLIB_AVAILABLE_IN_2_66 char * g_uri_escape_bytes (const guchar *unescaped, gsize length, diff --git a/glib/tests/uri.c b/glib/tests/uri.c index 6927b8904..7d3082637 100644 --- a/glib/tests/uri.c +++ b/glib/tests/uri.c @@ -372,15 +372,18 @@ test_uri_unescape_bytes (gconstpointer test_data) { /* Inputs */ const gchar *escaped; /* (nullable) */ + const gchar *illegal; /* Outputs */ gssize expected_unescaped_len; /* -1 => error expected */ const guint8 *expected_unescaped; /* (nullable) */ } tests[] = { - { "%00%00", 2, (const guint8 *) "\x00\x00" }, - { "%%", -1, NULL }, - { "%", -1, NULL }, + { "%00%00", NULL, 2, (const guint8 *) "\x00\x00" }, + { "/cursors/none.png", "/", 17, "/cursors/none.png" }, + { "/cursors%2fbad-subdir/none.png", "/", -1, NULL }, + { "%%", NULL, -1, NULL }, + { "%", NULL, -1, NULL }, }; gsize i; @@ -407,7 +410,7 @@ test_uri_unescape_bytes (gconstpointer test_data) escaped = g_memdup (tests[i].escaped, escaped_len); } - bytes = g_uri_unescape_bytes (escaped, escaped_len); + bytes = g_uri_unescape_bytes (escaped, escaped_len, tests[i].illegal); if (tests[i].expected_unescaped_len < 0) {