gcontenttype: Make filename valid utf-8 string before processing

The `g_content_type_guess_for_tree` function segfaults currently when
processing filenames that are not valid unicode strings. Let's use the
`g_filename_to_utf8` and `g_utf8_make_valid` functions before other
processing to prevent that.

Let's also add a test for it to avoid this in future.

Fixes: https://gitlab.gnome.org/GNOME/glib/-/issues/3168
This commit is contained in:
Ondrej Holy 2023-11-13 12:14:01 +00:00 committed by Philip Withnall
parent b50a8a69d9
commit 30e102518a
2 changed files with 60 additions and 2 deletions

View File

@ -1274,7 +1274,7 @@ component_match (Enumerator *e,
gint depth,
const gchar *name)
{
gchar *case_folded, *key;
gchar *case_folded, *key, *utf8_name;
gboolean found;
if (strcmp (name, e->components[depth]) == 0)
@ -1283,11 +1283,16 @@ component_match (Enumerator *e,
if (!e->ignore_case)
return FALSE;
case_folded = g_utf8_casefold (name, -1);
utf8_name = g_filename_to_utf8 (name, -1, NULL, NULL, NULL);
if (utf8_name == NULL)
utf8_name = g_utf8_make_valid (name, -1);
case_folded = g_utf8_casefold (utf8_name, -1);
key = g_utf8_collate_key (case_folded, -1);
found = strcmp (key, e->case_components[depth]) == 0;
g_free (utf8_name);
g_free (case_folded);
g_free (key);

View File

@ -360,6 +360,57 @@ test_tree (void)
}
}
static void
test_tree_invalid_encoding (void)
{
gchar *path;
gchar *name;
GFile *tmpdir;
GFile *file;
gchar **types;
GError *error = NULL;
g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/3168");
#if defined(__APPLE__) || defined(G_OS_WIN32)
g_test_skip ("The OSX & Windows backends do not implement g_content_type_guess_for_tree()");
return;
#endif
path = g_dir_make_tmp ("gio-test-tree-invalid-encoding-XXXXXX", &error);
g_assert_no_error (error);
tmpdir = g_file_new_for_path (path);
g_free (path);
name = g_strdup_printf ("\260");
file = g_file_get_child (tmpdir, name);
g_free (name);
g_file_replace_contents (file, "", 0, NULL, FALSE, 0, NULL, NULL, &error);
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT))
{
g_test_skip ("Unable to create testing file with non-ASCII characters.");
g_object_unref (tmpdir);
g_object_unref (file);
g_clear_error (&error);
return;
}
g_assert_no_error (error);
types = g_content_type_guess_for_tree (tmpdir);
g_strfreev (types);
g_file_delete (file, NULL, &error);
g_assert_no_error (error);
g_object_unref (file);
g_file_delete (tmpdir, NULL, &error);
g_assert_no_error (error);
g_object_unref (tmpdir);
}
static void
test_type_is_a_special_case (void)
{
@ -442,6 +493,8 @@ main (int argc, char *argv[])
g_test_add_func ("/contenttype/icon", test_icon);
g_test_add_func ("/contenttype/symbolic-icon", test_symbolic_icon);
g_test_add_func ("/contenttype/tree", test_tree);
g_test_add_func ("/contenttype/tree_invalid_encoding",
test_tree_invalid_encoding);
g_test_add_func ("/contenttype/test_type_is_a_special_case",
test_type_is_a_special_case);