mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-12-25 15:06:14 +01:00
xdgmime: Handle buggy type definitions with circular inheritance
This fixes a stack overflow reported by a user who had both the
definition of text/javascript from shared-mime-info 2.3 and the
definition of text/javascript from shared-mime-info 2.4 installed at the
same time. In 2.3, text/javascript is a subtype of
application/ecmascript, but in 2.4 application/ecmascript is a subtype
of text/javascript. Having both at the same time resulted in circular
inheritance.
The new logic keeps a list of all parents that have already been
checked, which is more comprehensive than the old workaround that was
implemented in commit 38869ece2
("xdgmime: Prevent infinite loops from
badly-formed MIME registrations").
https://bugs.archlinux.org/task/80279
This commit is contained in:
parent
09b728b2da
commit
d9c50cac5d
@ -835,13 +835,16 @@ xdg_mime_is_super_type (const char *mime)
|
||||
|
||||
int
|
||||
_xdg_mime_mime_type_subclass (const char *mime,
|
||||
const char *base)
|
||||
const char *base,
|
||||
const char **seen)
|
||||
{
|
||||
const char *umime, *ubase;
|
||||
const char *umime, *ubase, *parent;
|
||||
const char **parents;
|
||||
|
||||
int first_seen = 0, i, ret = 0;
|
||||
|
||||
if (_caches)
|
||||
return _xdg_mime_cache_mime_type_subclass (mime, base);
|
||||
return _xdg_mime_cache_mime_type_subclass (mime, base, NULL);
|
||||
|
||||
umime = _xdg_mime_unalias_mime_type (mime);
|
||||
ubase = _xdg_mime_unalias_mime_type (base);
|
||||
@ -865,14 +868,38 @@ _xdg_mime_mime_type_subclass (const char *mime,
|
||||
strncmp (umime, "inode/", 6) != 0)
|
||||
return 1;
|
||||
|
||||
if (!seen)
|
||||
{
|
||||
seen = calloc (1, sizeof (char *));
|
||||
first_seen = 1;
|
||||
}
|
||||
|
||||
parents = _xdg_mime_parent_list_lookup (parent_list, umime);
|
||||
for (; parents && *parents; parents++)
|
||||
{
|
||||
if (_xdg_mime_mime_type_subclass (*parents, ubase))
|
||||
return 1;
|
||||
parent = *parents;
|
||||
|
||||
/* Detect and avoid buggy circular relationships */
|
||||
for (i = 0; seen[i] != NULL; i++)
|
||||
if (parent == seen[i])
|
||||
goto next_parent;
|
||||
seen = realloc (seen, (i + 2) * sizeof (char *));
|
||||
seen[i] = parent;
|
||||
seen[i + 1] = NULL;
|
||||
|
||||
if (_xdg_mime_mime_type_subclass (parent, ubase, seen))
|
||||
{
|
||||
ret = 1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
return 0;
|
||||
next_parent:
|
||||
}
|
||||
|
||||
done:
|
||||
if (first_seen)
|
||||
free (seen);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
@ -881,7 +908,7 @@ xdg_mime_mime_type_subclass (const char *mime,
|
||||
{
|
||||
xdg_mime_init ();
|
||||
|
||||
return _xdg_mime_mime_type_subclass (mime, base);
|
||||
return _xdg_mime_mime_type_subclass (mime, base, NULL);
|
||||
}
|
||||
|
||||
char **
|
||||
|
@ -125,7 +125,8 @@ void xdg_mime_set_dirs (const char * const *dirs);
|
||||
int _xdg_mime_mime_type_equal (const char *mime_a,
|
||||
const char *mime_b);
|
||||
int _xdg_mime_mime_type_subclass (const char *mime,
|
||||
const char *base);
|
||||
const char *base,
|
||||
const char **seen);
|
||||
const char *_xdg_mime_unalias_mime_type (const char *mime);
|
||||
|
||||
|
||||
|
@ -751,7 +751,7 @@ cache_get_mime_type_for_data (const void *data,
|
||||
/* Pick glob-result R where mime_type inherits from R */
|
||||
for (n = 0; n < n_mime_types; n++)
|
||||
{
|
||||
if (mime_types[n] && _xdg_mime_cache_mime_type_subclass(mime_types[n], mime_type))
|
||||
if (mime_types[n] && _xdg_mime_cache_mime_type_subclass (mime_types[n], mime_type, NULL))
|
||||
return mime_types[n];
|
||||
}
|
||||
if (n == 0)
|
||||
@ -901,12 +901,13 @@ is_super_type (const char *mime)
|
||||
|
||||
int
|
||||
_xdg_mime_cache_mime_type_subclass (const char *mime,
|
||||
const char *base)
|
||||
const char *base,
|
||||
const char **seen)
|
||||
{
|
||||
const char *umime, *ubase;
|
||||
const char *umime, *ubase, *parent;
|
||||
|
||||
xdg_uint32_t j;
|
||||
int i, min, max, med, cmp;
|
||||
int i, k, min, max, med, cmp, first_seen = 0, ret = 0;
|
||||
|
||||
umime = _xdg_mime_cache_unalias_mime_type (mime);
|
||||
ubase = _xdg_mime_cache_unalias_mime_type (base);
|
||||
@ -933,6 +934,12 @@ _xdg_mime_cache_mime_type_subclass (const char *mime,
|
||||
strncmp (umime, "inode/", 6) != 0)
|
||||
return 1;
|
||||
|
||||
if (!seen)
|
||||
{
|
||||
seen = calloc (1, sizeof (char *));
|
||||
first_seen = 1;
|
||||
}
|
||||
|
||||
for (i = 0; _caches[i]; i++)
|
||||
{
|
||||
XdgMimeCache *cache = _caches[i];
|
||||
@ -966,10 +973,23 @@ _xdg_mime_cache_mime_type_subclass (const char *mime,
|
||||
for (j = 0; j < n_parents; j++)
|
||||
{
|
||||
parent_offset = GET_UINT32 (cache->buffer, offset + 4 + 4 * j);
|
||||
if (strcmp (cache->buffer + parent_offset, mime) != 0 &&
|
||||
strcmp (cache->buffer + parent_offset, umime) != 0 &&
|
||||
_xdg_mime_cache_mime_type_subclass (cache->buffer + parent_offset, ubase))
|
||||
return 1;
|
||||
parent = cache->buffer + parent_offset;
|
||||
|
||||
/* Detect and avoid buggy circular relationships */
|
||||
for (k = 0; seen[k] != NULL; k++)
|
||||
if (parent == seen[k])
|
||||
goto next_parent;
|
||||
seen = realloc (seen, (k + 2) * sizeof (char *));
|
||||
seen[k] = parent;
|
||||
seen[k + 1] = NULL;
|
||||
|
||||
if (_xdg_mime_cache_mime_type_subclass (parent, ubase, seen))
|
||||
{
|
||||
ret = 1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
next_parent:
|
||||
}
|
||||
|
||||
break;
|
||||
@ -977,7 +997,10 @@ _xdg_mime_cache_mime_type_subclass (const char *mime,
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
done:
|
||||
if (first_seen)
|
||||
free (seen);
|
||||
return ret;
|
||||
}
|
||||
|
||||
const char *
|
||||
|
@ -70,7 +70,8 @@ int _xdg_mime_cache_mime_type_equal (const char *mime_a,
|
||||
int _xdg_mime_cache_media_type_equal (const char *mime_a,
|
||||
const char *mime_b);
|
||||
int _xdg_mime_cache_mime_type_subclass (const char *mime_a,
|
||||
const char *mime_b);
|
||||
const char *mime_b,
|
||||
const char **seen);
|
||||
char **_xdg_mime_cache_list_mime_parents (const char *mime);
|
||||
const char *_xdg_mime_cache_unalias_mime_type (const char *mime);
|
||||
int _xdg_mime_cache_get_max_buffer_extents (void);
|
||||
|
Loading…
Reference in New Issue
Block a user