glib2/backport-xdgmime-Handle-buggy-type-definitions-with-circular-inheritance.patch
hanhuihui 25a439df3d fix memory leak,xdg error,gdbus arg0 error
(cherry picked from commit afcd3d6adb1390bf06d72a58765f4b3df78a45f1)
2024-10-25 15:29:12 +08:00

266 lines
8.0 KiB
Diff

From d9c50cac5d160798498e42d5b190ad89920a9a6a Mon Sep 17 00:00:00 2001
From: Alex Henrie <alexhenrie24@gmail.com>
Date: Sun, 19 Nov 2023 15:54:27 -0700
Subject: [PATCH 1/2] 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
---
gio/xdgmime/xdgmime.c | 43 +++++++++++++++++++++++++++-------
gio/xdgmime/xdgmime.h | 3 ++-
gio/xdgmime/xdgmimecache.c | 47 ++++++++++++++++++++++++++++----------
gio/xdgmime/xdgmimecache.h | 3 ++-
4 files changed, 74 insertions(+), 22 deletions(-)
diff --git a/gio/xdgmime/xdgmime.c b/gio/xdgmime/xdgmime.c
index c3c11625e8..31f352ceee 100644
--- a/gio/xdgmime/xdgmime.c
+++ b/gio/xdgmime/xdgmime.c
@@ -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);
@@ -864,15 +867,39 @@ _xdg_mime_mime_type_subclass (const char *mime,
if (strcmp (ubase, "application/octet-stream") == 0 &&
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;
+ }
+
+ next_parent:
}
- return 0;
+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 **
diff --git a/gio/xdgmime/xdgmime.h b/gio/xdgmime/xdgmime.h
index c5909967f2..bbae1be790 100644
--- a/gio/xdgmime/xdgmime.h
+++ b/gio/xdgmime/xdgmime.h
@@ -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);
diff --git a/gio/xdgmime/xdgmimecache.c b/gio/xdgmime/xdgmimecache.c
index 234e4b4677..6b1985082f 100644
--- a/gio/xdgmime/xdgmimecache.c
+++ b/gio/xdgmime/xdgmimecache.c
@@ -751,8 +751,8 @@ 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))
- return mime_types[n];
+ if (mime_types[n] && _xdg_mime_cache_mime_type_subclass (mime_types[n], mime_type, NULL))
+ return mime_types[n];
}
if (n == 0)
{
@@ -901,13 +901,14 @@ 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);
@@ -932,7 +933,13 @@ _xdg_mime_cache_mime_type_subclass (const char *mime,
if (strcmp (ubase, "application/octet-stream") == 0 &&
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 *
diff --git a/gio/xdgmime/xdgmimecache.h b/gio/xdgmime/xdgmimecache.h
index df25b2a576..0ac0b054fe 100644
--- a/gio/xdgmime/xdgmimecache.h
+++ b/gio/xdgmime/xdgmimecache.h
@@ -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);
--
GitLab
From 77902e1b1c8ff906a560270656a51a28787b9492 Mon Sep 17 00:00:00 2001
From: Alex Henrie <alexhenrie24@gmail.com>
Date: Tue, 21 Nov 2023 11:04:50 -0700
Subject: [PATCH 2/2] xdgmime: Add continue statements after goto labels
in_xdg_mime_(cache_)mime_type_subclass
To fix the Android build.
---
gio/xdgmime/xdgmime.c | 1 +
gio/xdgmime/xdgmimecache.c | 3 ++-
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/gio/xdgmime/xdgmime.c b/gio/xdgmime/xdgmime.c
index 31f352ceee..dce938a6f5 100644
--- a/gio/xdgmime/xdgmime.c
+++ b/gio/xdgmime/xdgmime.c
@@ -894,6 +894,7 @@ _xdg_mime_mime_type_subclass (const char *mime,
}
next_parent:
+ continue;
}
done:
diff --git a/gio/xdgmime/xdgmimecache.c b/gio/xdgmime/xdgmimecache.c
index 6b1985082f..9ea10f901d 100644
--- a/gio/xdgmime/xdgmimecache.c
+++ b/gio/xdgmime/xdgmimecache.c
@@ -989,7 +989,8 @@ _xdg_mime_cache_mime_type_subclass (const char *mime,
goto done;
}
- next_parent:
+ next_parent:
+ continue;
}
break;
--
GitLab