mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-28 13:12:10 +01:00
gdesktopappinfo: Fail early if trying to launch an invalid executable
GDesktopAppInfo never failed in the most simple of the cases: when a desktop file or a command line app info was pointing to an invalid executable (for the context). The reason for this is that we're launching all the programs using gio-launch-desktop which will always exist in a sane GLib installation, and thus our call to execvp won't ever fail on failure. This was partially mitigated by not allowing to create a desktop app icon using a non-existent executable (even if not fully correctly) but still did not work in case a custom PATH was provided in the launch context. To avoid this, use g_find_program_for_path() to find early if a program that we're about to launch is available, and if it's not the case return the same error that g_spawn_async_with_fds() would throw in such cases. While this is slowing a bit our preparation phase, would avoid to leave to the exec function the job to find where our program is. Add tests simulating this behavior.
This commit is contained in:
parent
da8aa0b66d
commit
511d1cad02
@ -2919,6 +2919,46 @@ g_desktop_app_info_launch_uris_with_spawn (GDesktopAppInfo *info,
|
||||
emit_launch_started (launch_context, info, sn_id);
|
||||
}
|
||||
|
||||
g_assert (argc > 0);
|
||||
|
||||
if (!g_path_is_absolute (argv[0]) ||
|
||||
!g_file_test (argv[0], G_FILE_TEST_IS_EXECUTABLE) ||
|
||||
g_file_test (argv[0], G_FILE_TEST_IS_DIR))
|
||||
{
|
||||
char *program = g_steal_pointer (&argv[0]);
|
||||
char *program_path = NULL;
|
||||
|
||||
if (!g_path_is_absolute (program))
|
||||
{
|
||||
const char *env_path = g_environ_getenv (envp, "PATH");
|
||||
|
||||
program_path = g_find_program_for_path (program,
|
||||
env_path,
|
||||
info->path);
|
||||
}
|
||||
|
||||
if (program_path)
|
||||
{
|
||||
argv[0] = g_steal_pointer (&program_path);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (sn_id)
|
||||
g_app_launch_context_launch_failed (launch_context, sn_id);
|
||||
|
||||
g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_NOENT,
|
||||
_("Program ‘%s’ not found in $PATH"),
|
||||
program);
|
||||
|
||||
g_free (program);
|
||||
g_clear_pointer (&sn_id, g_free);
|
||||
g_clear_list (&launched_uris, NULL);
|
||||
goto out;
|
||||
}
|
||||
|
||||
g_free (program);
|
||||
}
|
||||
|
||||
if (g_once_init_enter (&gio_launch_desktop_path))
|
||||
{
|
||||
const gchar *tmp = NULL;
|
||||
|
@ -1697,6 +1697,102 @@ test_app_path_wrong (void)
|
||||
g_clear_object (&appinfo);
|
||||
}
|
||||
|
||||
static void
|
||||
test_launch_startup_notify_fail (void)
|
||||
{
|
||||
GAppInfo *app_info;
|
||||
GAppLaunchContext *context;
|
||||
GError *error = NULL;
|
||||
gboolean launch_started;
|
||||
gboolean launch_failed;
|
||||
gboolean launched;
|
||||
GList *uris;
|
||||
|
||||
app_info = g_app_info_create_from_commandline ("this-must-not-exist‼",
|
||||
"failing app",
|
||||
G_APP_INFO_CREATE_NONE |
|
||||
G_APP_INFO_CREATE_SUPPORTS_STARTUP_NOTIFICATION,
|
||||
&error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
context = g_object_new (test_launch_context_get_type (), NULL);
|
||||
g_signal_connect (context, "launch-started",
|
||||
G_CALLBACK (on_launch_started),
|
||||
&launch_started);
|
||||
g_signal_connect (context, "launched",
|
||||
G_CALLBACK (on_launch_started),
|
||||
&launched);
|
||||
g_signal_connect (context, "launch-failed",
|
||||
G_CALLBACK (on_launch_failed),
|
||||
&launch_failed);
|
||||
|
||||
launch_started = FALSE;
|
||||
launch_failed = FALSE;
|
||||
launched = FALSE;
|
||||
uris = g_list_prepend (NULL, g_file_new_for_uri ("foo://bar"));
|
||||
uris = g_list_prepend (uris, g_file_new_for_uri ("bar://foo"));
|
||||
g_assert_false (g_app_info_launch (app_info, uris, context, &error));
|
||||
g_assert_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_NOENT);
|
||||
g_assert_true (launch_started);
|
||||
g_assert_true (launch_failed);
|
||||
g_assert_false (launched);
|
||||
|
||||
g_clear_error (&error);
|
||||
g_clear_object (&app_info);
|
||||
g_clear_object (&context);
|
||||
g_clear_list (&uris, g_object_unref);
|
||||
}
|
||||
|
||||
static void
|
||||
test_launch_fail (void)
|
||||
{
|
||||
GAppInfo *app_info;
|
||||
GError *error = NULL;
|
||||
|
||||
app_info = g_app_info_create_from_commandline ("this-must-not-exist‼",
|
||||
"failing app",
|
||||
G_APP_INFO_CREATE_NONE,
|
||||
&error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
g_assert_false (g_app_info_launch (app_info, NULL, NULL, &error));
|
||||
g_assert_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_NOENT);
|
||||
|
||||
g_clear_error (&error);
|
||||
g_clear_object (&app_info);
|
||||
}
|
||||
|
||||
static void
|
||||
test_launch_fail_absolute_path (void)
|
||||
{
|
||||
GAppInfo *app_info;
|
||||
GError *error = NULL;
|
||||
|
||||
app_info = g_app_info_create_from_commandline ("/nothing/of/this-must-exist‼",
|
||||
NULL,
|
||||
G_APP_INFO_CREATE_NONE,
|
||||
&error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
g_assert_false (g_app_info_launch (app_info, NULL, NULL, &error));
|
||||
g_assert_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_NOENT);
|
||||
|
||||
g_clear_error (&error);
|
||||
g_clear_object (&app_info);
|
||||
|
||||
app_info = g_app_info_create_from_commandline ("/",
|
||||
NULL,
|
||||
G_APP_INFO_CREATE_NONE,
|
||||
&error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
g_assert_false (g_app_info_launch (app_info, NULL, NULL, &error));
|
||||
g_assert_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_NOENT);
|
||||
|
||||
g_clear_error (&error);
|
||||
g_clear_object (&app_info);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char *argv[])
|
||||
@ -1736,6 +1832,9 @@ main (int argc,
|
||||
g_test_add_func ("/desktop-app-info/show-in", test_show_in);
|
||||
g_test_add_func ("/desktop-app-info/app-path", test_app_path);
|
||||
g_test_add_func ("/desktop-app-info/app-path/wrong", test_app_path_wrong);
|
||||
g_test_add_func ("/desktop-app-info/launch/fail", test_launch_fail);
|
||||
g_test_add_func ("/desktop-app-info/launch/fail-absolute-path", test_launch_fail_absolute_path);
|
||||
g_test_add_func ("/desktop-app-info/launch/fail-startup-notify", test_launch_startup_notify_fail);
|
||||
g_test_add_func ("/desktop-app-info/launch-as-manager", test_launch_as_manager);
|
||||
g_test_add_func ("/desktop-app-info/launch-as-manager/fail", test_launch_as_manager_fail);
|
||||
g_test_add_func ("/desktop-app-info/launch-default-uri-handler", test_default_uri_handler);
|
||||
|
Loading…
x
Reference in New Issue
Block a user