mirror of
https://gitlab.freedesktop.org/wayland/wayland.git
synced 2025-10-29 05:40:16 -04:00
xcursor: catch theme inheritance loops
As of currently, when an xcursor theme depends on itself or another theme that will eventually depend on it, `xcursor_load_theme` will recurse infinitely while processing the inherits. This change introduces a stack-allocated linked list of visited nodes by name, and skips any already visited nodes in the inherit list. Side effects: * Since the linked list is stack-allocated, there is a potential for an overflow if there is a very long list of dependencies. If this turns out to be a legitimate concern, the linked list is trivial to convert to being heap-allocated. * There is an existing linked list (technically doubly linked list) implementation in the wayland codebase. As of currently, the xcursor codebase does not refer to it. Consequently, this change writes a minimal single linked list implementation to utilize directly. This changeset fixes #317. Signed-off-by: Chloé Vulquin <toast@bunkerlabs.net>
This commit is contained in:
parent
b258d5f361
commit
16aee2ec38
1 changed files with 77 additions and 35 deletions
112
cursor/xcursor.c
112
cursor/xcursor.c
|
|
@ -726,6 +726,78 @@ load_all_cursors_from_dir(const char *path, int size,
|
||||||
closedir(dir);
|
closedir(dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct xcursor_nodelist {
|
||||||
|
size_t nodelen;
|
||||||
|
const char *node;
|
||||||
|
struct xcursor_nodelist *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool
|
||||||
|
nodelist_contains(struct xcursor_nodelist *nodelist, const char *s, size_t ss)
|
||||||
|
{
|
||||||
|
struct xcursor_nodelist *vi;
|
||||||
|
|
||||||
|
for (vi = nodelist; vi && vi->node; vi = vi->next) {
|
||||||
|
if (vi->nodelen == ss && !strncmp(s, vi->node, vi->nodelen))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
xcursor_load_theme_protected(const char *theme, int size,
|
||||||
|
void (*load_callback)(struct xcursor_images *, void *),
|
||||||
|
void *user_data,
|
||||||
|
struct xcursor_nodelist *visited_nodes)
|
||||||
|
{
|
||||||
|
char *full, *dir;
|
||||||
|
char *inherits = NULL;
|
||||||
|
const char *path, *i;
|
||||||
|
char *xcursor_path;
|
||||||
|
size_t si;
|
||||||
|
struct xcursor_nodelist current_node;
|
||||||
|
|
||||||
|
if (!theme)
|
||||||
|
theme = "default";
|
||||||
|
|
||||||
|
current_node.next = visited_nodes;
|
||||||
|
current_node.node = theme;
|
||||||
|
current_node.nodelen = strlen(theme);
|
||||||
|
visited_nodes = ¤t_node;
|
||||||
|
|
||||||
|
xcursor_path = xcursor_library_path();
|
||||||
|
for (path = xcursor_path;
|
||||||
|
path;
|
||||||
|
path = xcursor_next_path(path)) {
|
||||||
|
dir = xcursor_build_theme_dir(path, theme);
|
||||||
|
if (!dir)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
full = xcursor_build_fullname(dir, "cursors", "");
|
||||||
|
load_all_cursors_from_dir(full, size, load_callback,
|
||||||
|
user_data);
|
||||||
|
free(full);
|
||||||
|
|
||||||
|
if (!inherits) {
|
||||||
|
full = xcursor_build_fullname(dir, "", "index.theme");
|
||||||
|
inherits = xcursor_theme_inherits(full);
|
||||||
|
free(full);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = inherits; i; i = xcursor_next_path(i)) {
|
||||||
|
si = strlen(i);
|
||||||
|
if (nodelist_contains(visited_nodes, i, si))
|
||||||
|
continue;
|
||||||
|
xcursor_load_theme_protected(i, size, load_callback, user_data, visited_nodes);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(inherits);
|
||||||
|
free(xcursor_path);
|
||||||
|
}
|
||||||
|
|
||||||
/** Load all the cursor of a theme
|
/** Load all the cursor of a theme
|
||||||
*
|
*
|
||||||
* This function loads all the cursor images of a given theme and its
|
* This function loads all the cursor images of a given theme and its
|
||||||
|
|
@ -750,39 +822,9 @@ xcursor_load_theme(const char *theme, int size,
|
||||||
void (*load_callback)(struct xcursor_images *, void *),
|
void (*load_callback)(struct xcursor_images *, void *),
|
||||||
void *user_data)
|
void *user_data)
|
||||||
{
|
{
|
||||||
char *full, *dir;
|
xcursor_load_theme_protected(theme,
|
||||||
char *inherits = NULL;
|
size,
|
||||||
const char *path, *i;
|
load_callback,
|
||||||
char *xcursor_path;
|
user_data,
|
||||||
|
NULL);
|
||||||
if (!theme)
|
|
||||||
theme = "default";
|
|
||||||
|
|
||||||
xcursor_path = xcursor_library_path();
|
|
||||||
for (path = xcursor_path;
|
|
||||||
path;
|
|
||||||
path = xcursor_next_path(path)) {
|
|
||||||
dir = xcursor_build_theme_dir(path, theme);
|
|
||||||
if (!dir)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
full = xcursor_build_fullname(dir, "cursors", "");
|
|
||||||
load_all_cursors_from_dir(full, size, load_callback,
|
|
||||||
user_data);
|
|
||||||
free(full);
|
|
||||||
|
|
||||||
if (!inherits) {
|
|
||||||
full = xcursor_build_fullname(dir, "", "index.theme");
|
|
||||||
inherits = xcursor_theme_inherits(full);
|
|
||||||
free(full);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = inherits; i; i = xcursor_next_path(i))
|
|
||||||
xcursor_load_theme(i, size, load_callback, user_data);
|
|
||||||
|
|
||||||
free(inherits);
|
|
||||||
free(xcursor_path);
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue