recent-manager: Add a limit to the list's size

This fixes a DOS where any app can cause all running gtk apps
to use arbitrary amounts of memory.

Originally reported against mate-panel, where running a big slideshow
in eye-of-mate caused increasing RAM usage in mate-panel.

v2: Hardcode the value
Signed-off-by: Lauri Kasanen <curaga@operamail.com>

https://bugzilla.gnome.org/show_bug.cgi?id=773587
This commit is contained in:
Lauri Kasanen 2016-10-27 16:51:29 +03:00 committed by Matthias Clasen
parent 3c27774a5d
commit 0d364173f6

View File

@ -113,6 +113,9 @@
/* return all items by default */
#define DEFAULT_LIMIT -1
/* limit the size of the list */
#define MAX_LIST_SIZE 1000
/* keep in sync with xdgmime */
#define GTK_RECENT_DEFAULT_MIME "application/octet-stream"
@ -211,6 +214,9 @@ static void gtk_recent_manager_set_filename (GtkRecentManager *manag
const gchar *filename);
static void gtk_recent_manager_clamp_to_age (GtkRecentManager *manager,
gint age);
static void gtk_recent_manager_clamp_to_size (GtkRecentManager *manager,
const gint size);
static void gtk_recent_manager_enabled_changed (GtkRecentManager *manager);
@ -462,6 +468,7 @@ gtk_recent_manager_real_changed (GtkRecentManager *manager)
{
GtkSettings *settings;
gint age;
gint max_size = MAX_LIST_SIZE;
gboolean enabled;
settings = gtk_settings_get_default ();
@ -476,14 +483,19 @@ gtk_recent_manager_real_changed (GtkRecentManager *manager)
enabled = TRUE;
}
if (age == 0 || !enabled)
if (age == 0 || max_size == 0 || !enabled)
{
g_bookmark_file_free (priv->recent_items);
priv->recent_items = g_bookmark_file_new ();
priv->size = 0;
}
else if (age > 0)
gtk_recent_manager_clamp_to_age (manager, age);
else
{
if (age > 0)
gtk_recent_manager_clamp_to_age (manager, age);
if (max_size > 0)
gtk_recent_manager_clamp_to_size (manager, max_size);
}
}
if (priv->filename != NULL)
@ -1455,6 +1467,31 @@ gtk_recent_manager_clamp_to_age (GtkRecentManager *manager,
g_strfreev (uris);
}
static void
gtk_recent_manager_clamp_to_size (GtkRecentManager *manager,
const gint size)
{
GtkRecentManagerPrivate *priv = manager->priv;
gchar **uris;
gsize n_uris, i;
if (G_UNLIKELY (!priv->recent_items) || G_UNLIKELY (size < 0))
return;
uris = g_bookmark_file_get_uris (priv->recent_items, &n_uris);
if (n_uris < size)
return;
for (i = 0; i < n_uris - size; i++)
{
const gchar *uri = uris[i];
g_bookmark_file_remove_item (priv->recent_items, uri, NULL);
}
g_strfreev (uris);
}
/*****************
* GtkRecentInfo *
*****************/