mirror of
https://gitlab.freedesktop.org/xorg/lib/libxcursor.git
synced 2025-12-20 09:20:12 +01:00
Handle more theme loop situations
This is a follow up for commit f64a8cc1a6
resulting from https://bugs.freedesktop.org/show_bug.cgi?id=3603
The current loop detection only works for direct self references but not
for transitive ones. Limiting the inheritance depth fixes this issue as
suggested by Keith Packard.
I avoided the introduction of a recursion function. Instead I modified
XcursorScanTheme to work iterative.
The current recursion code adds the "Inherits=..." line to heap and has
an iteration variable to go through all themes listed in that line per
recursion. This is covered with the newly introduced XcursorInherit
struct with its fields "line" and "theme". Since "theme" points into
"line", only "line" has to be freed eventually.
If a fixed inheritage limit of 32 is reached, the code stops processing
and returns NULL. It also returns NULL if it detects the initial theme
in one of the inheritages to break the loop early on.
Last but not least I removed the printf statement. The only situation in
which libXcursor writes to stdout is when it is explicitly requested.
Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
This commit is contained in:
parent
403bb32d5f
commit
b47ca9858e
1 changed files with 73 additions and 36 deletions
|
|
@ -32,6 +32,11 @@
|
||||||
#define XCURSORPATH "~/.local/share/icons:~/.icons:/usr/share/icons:/usr/share/pixmaps:"ICONDIR
|
#define XCURSORPATH "~/.local/share/icons:~/.icons:/usr/share/icons:/usr/share/pixmaps:"ICONDIR
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
typedef struct XcursorInherit {
|
||||||
|
char *line;
|
||||||
|
const char *theme;
|
||||||
|
} XcursorInherit;
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
XcursorLibraryPath (void)
|
XcursorLibraryPath (void)
|
||||||
{
|
{
|
||||||
|
|
@ -206,6 +211,7 @@ _XcursorThemeInherits (const char *full)
|
||||||
}
|
}
|
||||||
|
|
||||||
#define XCURSOR_SCAN_CORE ((FILE *) 1)
|
#define XCURSOR_SCAN_CORE ((FILE *) 1)
|
||||||
|
#define MAX_INHERITS_DEPTH 32
|
||||||
|
|
||||||
static FILE *
|
static FILE *
|
||||||
XcursorScanTheme (const char *theme, const char *name)
|
XcursorScanTheme (const char *theme, const char *name)
|
||||||
|
|
@ -214,8 +220,8 @@ XcursorScanTheme (const char *theme, const char *name)
|
||||||
char *full;
|
char *full;
|
||||||
char *dir;
|
char *dir;
|
||||||
const char *path;
|
const char *path;
|
||||||
char *inherits = NULL;
|
XcursorInherit inherits[MAX_INHERITS_DEPTH + 1];
|
||||||
const char *i;
|
int d;
|
||||||
|
|
||||||
if (!theme || !name)
|
if (!theme || !name)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
@ -228,6 +234,14 @@ XcursorScanTheme (const char *theme, const char *name)
|
||||||
*/
|
*/
|
||||||
if (!strcmp (theme, XCURSOR_CORE_THEME) && XcursorLibraryShape (name) >= 0)
|
if (!strcmp (theme, XCURSOR_CORE_THEME) && XcursorLibraryShape (name) >= 0)
|
||||||
return XCURSOR_SCAN_CORE;
|
return XCURSOR_SCAN_CORE;
|
||||||
|
|
||||||
|
memset (inherits, 0, sizeof (inherits));
|
||||||
|
|
||||||
|
d = 0;
|
||||||
|
inherits[d].theme = theme;
|
||||||
|
|
||||||
|
while (f == NULL && d >= 0 && inherits[d].theme != NULL)
|
||||||
|
{
|
||||||
/*
|
/*
|
||||||
* Scan this theme
|
* Scan this theme
|
||||||
*/
|
*/
|
||||||
|
|
@ -235,7 +249,7 @@ XcursorScanTheme (const char *theme, const char *name)
|
||||||
path && f == NULL;
|
path && f == NULL;
|
||||||
path = _XcursorNextPath (path))
|
path = _XcursorNextPath (path))
|
||||||
{
|
{
|
||||||
dir = _XcursorBuildThemeDir (path, theme);
|
dir = _XcursorBuildThemeDir (path, inherits[d].theme);
|
||||||
if (dir)
|
if (dir)
|
||||||
{
|
{
|
||||||
full = _XcursorBuildFullname (dir, "cursors", name);
|
full = _XcursorBuildFullname (dir, "cursors", name);
|
||||||
|
|
@ -244,30 +258,53 @@ XcursorScanTheme (const char *theme, const char *name)
|
||||||
f = fopen (full, "r");
|
f = fopen (full, "r");
|
||||||
free (full);
|
free (full);
|
||||||
}
|
}
|
||||||
if (!f && !inherits)
|
if (!f && inherits[d + 1].line == NULL)
|
||||||
{
|
{
|
||||||
|
if (d + 1 >= MAX_INHERITS_DEPTH)
|
||||||
|
{
|
||||||
|
free (dir);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
full = _XcursorBuildFullname (dir, "", "index.theme");
|
full = _XcursorBuildFullname (dir, "", "index.theme");
|
||||||
if (full)
|
if (full)
|
||||||
{
|
{
|
||||||
inherits = _XcursorThemeInherits (full);
|
inherits[d + 1].line = _XcursorThemeInherits (full);
|
||||||
|
inherits[d + 1].theme = inherits[d + 1].line;
|
||||||
free (full);
|
free (full);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free (dir);
|
free (dir);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
* Recurse to scan inherited themes
|
if (inherits[d + 1].line == NULL)
|
||||||
*/
|
|
||||||
for (i = inherits; i && f == NULL; i = _XcursorNextPath (i))
|
|
||||||
{
|
{
|
||||||
if (strcmp(i, theme) != 0)
|
if (d == 0)
|
||||||
f = XcursorScanTheme (i, name);
|
inherits[d].theme = NULL;
|
||||||
else
|
else
|
||||||
printf("Not calling XcursorScanTheme because of circular dependency: %s. %s", i, name);
|
{
|
||||||
|
inherits[d].theme = _XcursorNextPath (inherits[d].theme);
|
||||||
|
if (inherits[d].theme == NULL)
|
||||||
|
{
|
||||||
|
free (inherits[d].line);
|
||||||
|
inherits[d--].line = NULL;
|
||||||
}
|
}
|
||||||
if (inherits != NULL)
|
}
|
||||||
free (inherits);
|
}
|
||||||
|
else
|
||||||
|
d++;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Detect and break self reference loop early on.
|
||||||
|
*/
|
||||||
|
if (inherits[d].theme != NULL && strcmp (inherits[d].theme, theme) == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
for (d = 1; d <= MAX_INHERITS_DEPTH; d++)
|
||||||
|
free (inherits[d].line);
|
||||||
|
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue