commit:     d6ce0537470aac408e9dd90f244970113ddc1045
Author:     Lukas Schmelting <lschmelting <AT> posteo <DOT> com>
AuthorDate: Mon Dec  8 20:38:48 2025 +0000
Commit:     Sam James <sam <AT> gentoo <DOT> org>
CommitDate: Tue Dec 16 10:12:29 2025 +0000
URL:        https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=d6ce0537

dev-libs/glib: 2.84.4 security revbump

Contains fixes for:
- CVE-2025-13601
- CVE-2025-14087

See-also: https://gitlab.gnome.org/GNOME/glib/-/releases/2.86.3
Bug: https://bugs.gentoo.org/967237
Signed-off-by: Lukas Schmelting <lschmelting <AT> posteo.com>
Part-of: https://github.com/gentoo/gentoo/pull/44962
Signed-off-by: Sam James <sam <AT> gentoo.org>

 dev-libs/glib/files/glib-2.86-MR-4912.patch        | 186 ++++++++
 .../files/glib-2.86-MR-4915-CVE-2025-13601.patch   | 261 +++++++++++
 .../files/glib-2.86-MR-4934-CVE-2025-14087.patch   | 459 ++++++++++++++++++++
 dev-libs/glib/files/glib-2.86-MR-4936.patch        |  69 +++
 dev-libs/glib/glib-2.84.4-r1.ebuild                | 481 +++++++++++++++++++++
 5 files changed, 1456 insertions(+)

diff --git a/dev-libs/glib/files/glib-2.86-MR-4912.patch 
b/dev-libs/glib/files/glib-2.86-MR-4912.patch
new file mode 100644
index 000000000000..4fdbb3a31195
--- /dev/null
+++ b/dev-libs/glib/files/glib-2.86-MR-4912.patch
@@ -0,0 +1,186 @@
+From d3a16bc03c58a4f7c3222462110509e39c209ebf Mon Sep 17 00:00:00 2001
+From: Jehan <[email protected]>
+Date: Fri, 7 Nov 2025 12:09:43 +0100
+Subject: [PATCH] Issue #3819: G_FILE_MONITOR_WATCH_HARD_LINK does not monitor
+ files on Windows.
+
+Current code was clearly considering the case of having only a filename
+as a directory monitoring, instead of a hard-link monitoring. As I
+assume that hard links don't exist on Windows, this case should simply
+revert back to the basic file monitoring code path.
+---
+ gio/win32/gwin32fsmonitorutils.c | 121 ++++++++++++++++---------------
+ 1 file changed, 63 insertions(+), 58 deletions(-)
+
+diff --git a/gio/win32/gwin32fsmonitorutils.c 
b/gio/win32/gwin32fsmonitorutils.c
+index d06dc458a0..cc2a60b116 100644
+--- a/gio/win32/gwin32fsmonitorutils.c
++++ b/gio/win32/gwin32fsmonitorutils.c
+@@ -245,9 +245,9 @@ g_win32_fs_monitor_init (GWin32FSMonitorPrivate *monitor,
+                          const gchar *filename,
+                          gboolean isfile)
+ {
+-  wchar_t *wdirname_with_long_prefix = NULL;
++  gchar   *dirname_with_long_prefix;
++  wchar_t *wdirname_with_long_prefix;
+   const gchar LONGPFX[] = "\\\\?\\";
+-  gchar *fullpath_with_long_prefix, *dirname_with_long_prefix;
+   DWORD notify_filter = isfile ?
+                         (FILE_NOTIFY_CHANGE_FILE_NAME |
+                          FILE_NOTIFY_CHANGE_ATTRIBUTES |
+@@ -260,83 +260,88 @@ g_win32_fs_monitor_init (GWin32FSMonitorPrivate *monitor,
+   gboolean success_attribs;
+   WIN32_FILE_ATTRIBUTE_DATA attrib_data = {0, };
+ 
++  g_return_if_fail ((filename && isfile) || (dirname && ! isfile));
+ 
+   if (dirname != NULL)
+     {
+       dirname_with_long_prefix = g_strconcat (LONGPFX, dirname, NULL);
+-      wdirname_with_long_prefix = g_utf8_to_utf16 (dirname_with_long_prefix, 
-1, NULL, NULL, NULL);
+-
+-      if (isfile)
+-        {
+-          gchar *fullpath;
+-          wchar_t wlongname[MAX_PATH_LONG];
+-          wchar_t wshortname[MAX_PATH_LONG];
+-          wchar_t *wfullpath, *wbasename_long, *wbasename_short;
++    }
++  else
++    {
++      gchar *tmp_dirname = g_path_get_dirname (filename);
++      dirname_with_long_prefix = g_strconcat (LONGPFX, tmp_dirname, NULL);
++      g_free (tmp_dirname);
++    }
++  wdirname_with_long_prefix = g_utf8_to_utf16 (dirname_with_long_prefix, -1, 
NULL, NULL, NULL);
+ 
+-          fullpath = g_build_filename (dirname, filename, NULL);
+-          fullpath_with_long_prefix = g_strconcat (LONGPFX, fullpath, NULL);
++  if (isfile)
++    {
++      gchar *fullpath;
++      gchar *fullpath_with_long_prefix;
++      wchar_t wlongname[MAX_PATH_LONG];
++      wchar_t wshortname[MAX_PATH_LONG];
++      wchar_t *wfullpath, *wbasename_long, *wbasename_short;
++
++      if (dirname)
++        fullpath = g_build_filename (dirname, filename, NULL);
++      else
++        fullpath = g_strdup (filename);
+ 
+-          wfullpath = g_utf8_to_utf16 (fullpath, -1, NULL, NULL, NULL);
++      fullpath_with_long_prefix = g_strconcat (LONGPFX, fullpath, NULL);
+ 
+-          monitor->wfullpath_with_long_prefix =
+-            g_utf8_to_utf16 (fullpath_with_long_prefix, -1, NULL, NULL, NULL);
++      wfullpath = g_utf8_to_utf16 (fullpath, -1, NULL, NULL, NULL);
+ 
+-          /* ReadDirectoryChangesW() can return the normal filename or the
+-           * "8.3" format filename, so we need to keep track of both these 
names
+-           * so that we can check against them later when it returns
+-           */
+-          if (GetLongPathNameW (monitor->wfullpath_with_long_prefix, 
wlongname, MAX_PATH_LONG) == 0)
+-            {
+-              wbasename_long = wcsrchr (monitor->wfullpath_with_long_prefix, 
L'\\');
+-              monitor->wfilename_long = wbasename_long != NULL ?
+-                                        wcsdup (wbasename_long + 1) :
+-                                        wcsdup (wfullpath);
+-            }
+-          else
+-            {
+-              wbasename_long = wcsrchr (wlongname, L'\\');
+-              monitor->wfilename_long = wbasename_long != NULL ?
+-                                        wcsdup (wbasename_long + 1) :
+-                                        wcsdup (wlongname);
++      monitor->wfullpath_with_long_prefix =
++        g_utf8_to_utf16 (fullpath_with_long_prefix, -1, NULL, NULL, NULL);
+ 
+-            }
++      /* ReadDirectoryChangesW() can return the normal filename or the
++       * "8.3" format filename, so we need to keep track of both these names
++       * so that we can check against them later when it returns
++       */
++      if (GetLongPathNameW (monitor->wfullpath_with_long_prefix, wlongname, 
MAX_PATH_LONG) == 0)
++        {
++          wbasename_long = wcsrchr (monitor->wfullpath_with_long_prefix, 
L'\\');
++          monitor->wfilename_long = wbasename_long != NULL ?
++            wcsdup (wbasename_long + 1) :
++            wcsdup (wfullpath);
++        }
++      else
++        {
++          wbasename_long = wcsrchr (wlongname, L'\\');
++          monitor->wfilename_long = wbasename_long != NULL ?
++            wcsdup (wbasename_long + 1) :
++            wcsdup (wlongname);
+ 
+-          if (GetShortPathNameW (monitor->wfullpath_with_long_prefix, 
wshortname, MAX_PATH_LONG) == 0)
+-            {
+-              wbasename_short = wcsrchr (monitor->wfullpath_with_long_prefix, 
L'\\');
+-              monitor->wfilename_short = wbasename_short != NULL ?
+-                                         wcsdup (wbasename_short + 1) :
+-                                         wcsdup (wfullpath);
+-            }
+-          else
+-            {
+-              wbasename_short = wcsrchr (wshortname, L'\\');
+-              monitor->wfilename_short = wbasename_short != NULL ?
+-                                         wcsdup (wbasename_short + 1) :
+-                                         wcsdup (wshortname);
+-            }
++        }
+ 
+-          g_free (wfullpath);
+-          g_free (fullpath);
++      if (GetShortPathNameW (monitor->wfullpath_with_long_prefix, wshortname, 
MAX_PATH_LONG) == 0)
++        {
++          wbasename_short = wcsrchr (monitor->wfullpath_with_long_prefix, 
L'\\');
++          monitor->wfilename_short = wbasename_short != NULL ?
++            wcsdup (wbasename_short + 1) :
++            wcsdup (wfullpath);
+         }
+       else
+         {
+-          monitor->wfilename_short = NULL;
+-          monitor->wfilename_long = NULL;
+-          monitor->wfullpath_with_long_prefix = g_utf8_to_utf16 
(dirname_with_long_prefix, -1, NULL, NULL, NULL);
++          wbasename_short = wcsrchr (wshortname, L'\\');
++          monitor->wfilename_short = wbasename_short != NULL ?
++            wcsdup (wbasename_short + 1) :
++            wcsdup (wshortname);
+         }
+ 
+-      monitor->isfile = isfile;
++      g_free (wfullpath);
++      g_free (fullpath);
++      g_free (fullpath_with_long_prefix);
+     }
+   else
+     {
+-      dirname_with_long_prefix = g_strconcat (LONGPFX, filename, NULL);
+-      monitor->wfullpath_with_long_prefix = g_utf8_to_utf16 
(dirname_with_long_prefix, -1, NULL, NULL, NULL);
+-      monitor->wfilename_long = NULL;
+       monitor->wfilename_short = NULL;
+-      monitor->isfile = FALSE;
++      monitor->wfilename_long = NULL;
++      monitor->wfullpath_with_long_prefix = g_utf8_to_utf16 
(dirname_with_long_prefix, -1, NULL, NULL, NULL);
+     }
+ 
++  monitor->isfile = isfile;
++
+   success_attribs = GetFileAttributesExW (monitor->wfullpath_with_long_prefix,
+                                           GetFileExInfoStandard,
+                                           &attrib_data);
+@@ -345,7 +350,7 @@ g_win32_fs_monitor_init (GWin32FSMonitorPrivate *monitor,
+   else
+     monitor->file_attribs = INVALID_FILE_ATTRIBUTES;
+   monitor->pfni_prev = NULL;
+-  monitor->hDirectory = CreateFileW (wdirname_with_long_prefix != NULL ? 
wdirname_with_long_prefix : monitor->wfullpath_with_long_prefix,
++  monitor->hDirectory = CreateFileW (wdirname_with_long_prefix,
+                                      FILE_LIST_DIRECTORY,
+                                      FILE_SHARE_DELETE | FILE_SHARE_READ | 
FILE_SHARE_WRITE,
+                                      NULL,
+-- 
+GitLab
+

diff --git a/dev-libs/glib/files/glib-2.86-MR-4915-CVE-2025-13601.patch 
b/dev-libs/glib/files/glib-2.86-MR-4915-CVE-2025-13601.patch
new file mode 100644
index 000000000000..acba3fd7bd2d
--- /dev/null
+++ b/dev-libs/glib/files/glib-2.86-MR-4915-CVE-2025-13601.patch
@@ -0,0 +1,261 @@
+From 9bcd65ba5fa1b92ff0fb8380faea335ccef56253 Mon Sep 17 00:00:00 2001
+From: Philip Withnall <[email protected]>
+Date: Thu, 13 Nov 2025 18:27:22 +0000
+Subject: [PATCH 1/2] gconvert: Error out if g_escape_uri_string() would
+ overflow
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+If the string to escape contains a very large number of unacceptable
+characters (which would need escaping), the calculation of the length of
+the escaped string could overflow, leading to a potential write off the
+end of the newly allocated string.
+
+In addition to that, the number of unacceptable characters was counted
+in a signed integer, which would overflow to become negative, making it
+easier for an attacker to craft an input string which would cause an
+out-of-bounds write.
+
+Fix that by validating the allocation length, and using an unsigned
+integer to count the number of unacceptable characters.
+
+Spotted by treeplus. Thanks to the Sovereign Tech Resilience programme
+from the Sovereign Tech Agency. ID: #YWH-PGM9867-134
+
+Signed-off-by: Philip Withnall <[email protected]>
+
+Fixes: #3827
+
+Backport 2.86: Changed the translatable error message to re-use an
+existing translatable string, to avoid adding new translatable strings
+to a stable branch. The re-used string doesn’t perfectly match the
+error, but it’s good enough given that no users will ever see it.
+---
+ glib/gconvert.c | 36 +++++++++++++++++++++++++-----------
+ 1 file changed, 25 insertions(+), 11 deletions(-)
+
+diff --git a/glib/gconvert.c b/glib/gconvert.c
+index 7ad8ca018f..367e9b4661 100644
+--- a/glib/gconvert.c
++++ b/glib/gconvert.c
+@@ -1336,8 +1336,9 @@ static const gchar hex[] = "0123456789ABCDEF";
+ /* Note: This escape function works on file: URIs, but if you want to
+  * escape something else, please read RFC-2396 */
+ static gchar *
+-g_escape_uri_string (const gchar *string, 
+-                   UnsafeCharacterSet mask)
++g_escape_uri_string (const gchar         *string,
++                     UnsafeCharacterSet   mask,
++                     GError             **error)
+ {
+ #define ACCEPTABLE(a) ((a)>=32 && (a)<128 && (acceptable[(a)-32] & use_mask))
+ 
+@@ -1345,7 +1346,7 @@ g_escape_uri_string (const gchar *string,
+   gchar *q;
+   gchar *result;
+   int c;
+-  gint unacceptable;
++  size_t unacceptable;
+   UnsafeCharacterSet use_mask;
+   
+   g_return_val_if_fail (mask == UNSAFE_ALL
+@@ -1362,7 +1363,14 @@ g_escape_uri_string (const gchar *string,
+       if (!ACCEPTABLE (c)) 
+       unacceptable++;
+     }
+-  
++
++  if (unacceptable >= (G_MAXSIZE - (p - string)) / 2)
++    {
++      g_set_error_literal (error, G_CONVERT_ERROR, G_CONVERT_ERROR_BAD_URI,
++                           _("Invalid hostname"));
++      return NULL;
++    }
++
+   result = g_malloc (p - string + unacceptable * 2 + 1);
+   
+   use_mask = mask;
+@@ -1387,12 +1395,13 @@ g_escape_uri_string (const gchar *string,
+ 
+ 
+ static gchar *
+-g_escape_file_uri (const gchar *hostname,
+-                 const gchar *pathname)
++g_escape_file_uri (const gchar  *hostname,
++                   const gchar  *pathname,
++                   GError      **error)
+ {
+   char *escaped_hostname = NULL;
+-  char *escaped_path;
+-  char *res;
++  char *escaped_path = NULL;
++  char *res = NULL;
+ 
+ #ifdef G_OS_WIN32
+   char *p, *backslash;
+@@ -1413,10 +1422,14 @@ g_escape_file_uri (const gchar *hostname,
+ 
+   if (hostname && *hostname != '\0')
+     {
+-      escaped_hostname = g_escape_uri_string (hostname, UNSAFE_HOST);
++      escaped_hostname = g_escape_uri_string (hostname, UNSAFE_HOST, error);
++      if (escaped_hostname == NULL)
++        goto out;
+     }
+ 
+-  escaped_path = g_escape_uri_string (pathname, UNSAFE_PATH);
++  escaped_path = g_escape_uri_string (pathname, UNSAFE_PATH, error);
++  if (escaped_path == NULL)
++    goto out;
+ 
+   res = g_strconcat ("file://",
+                    (escaped_hostname) ? escaped_hostname : "",
+@@ -1424,6 +1437,7 @@ g_escape_file_uri (const gchar *hostname,
+                    escaped_path,
+                    NULL);
+ 
++out:
+ #ifdef G_OS_WIN32
+   g_free ((char *) pathname);
+ #endif
+@@ -1757,7 +1771,7 @@ g_filename_to_uri (const gchar *filename,
+     hostname = NULL;
+ #endif
+ 
+-  escaped_uri = g_escape_file_uri (hostname, filename);
++  escaped_uri = g_escape_file_uri (hostname, filename, error);
+ 
+   return escaped_uri;
+ }
+-- 
+GitLab
+
+
+From 7e5489cb921d0531ee4ebc9938da30a02084b2fa Mon Sep 17 00:00:00 2001
+From: Philip Withnall <[email protected]>
+Date: Thu, 13 Nov 2025 18:31:43 +0000
+Subject: [PATCH 2/2] fuzzing: Add fuzz tests for g_filename_{to,from}_uri()
+
+These functions could be called on untrusted input data, and since they
+do URI escaping/unescaping, they have non-trivial string handling code.
+
+Signed-off-by: Philip Withnall <[email protected]>
+
+See: #3827
+---
+ fuzzing/fuzz_filename_from_uri.c | 40 ++++++++++++++++++++++++++++++++
+ fuzzing/fuzz_filename_to_uri.c   | 40 ++++++++++++++++++++++++++++++++
+ fuzzing/meson.build              |  2 ++
+ 3 files changed, 82 insertions(+)
+ create mode 100644 fuzzing/fuzz_filename_from_uri.c
+ create mode 100644 fuzzing/fuzz_filename_to_uri.c
+
+diff --git a/fuzzing/fuzz_filename_from_uri.c 
b/fuzzing/fuzz_filename_from_uri.c
+new file mode 100644
+index 0000000000..9b7a715f07
+--- /dev/null
++++ b/fuzzing/fuzz_filename_from_uri.c
+@@ -0,0 +1,40 @@
++/*
++ * Copyright 2025 GNOME Foundation, Inc.
++ *
++ * SPDX-License-Identifier: LGPL-2.1-or-later
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Lesser General Public
++ * License as published by the Free Software Foundation; either
++ * version 2.1 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with this library; if not, see 
<http://www.gnu.org/licenses/>.
++ */
++
++#include "fuzz.h"
++
++int
++LLVMFuzzerTestOneInput (const unsigned char *data, size_t size)
++{
++  unsigned char *nul_terminated_data = NULL;
++  char *filename = NULL;
++  GError *local_error = NULL;
++
++  fuzz_set_logging_func ();
++
++  /* ignore @size (g_filename_from_uri() doesn’t support it); ensure @data is 
nul-terminated */
++  nul_terminated_data = (unsigned char *) g_strndup ((const char *) data, 
size);
++  filename = g_filename_from_uri ((const char *) nul_terminated_data, NULL, 
&local_error);
++  g_free (nul_terminated_data);
++
++  g_free (filename);
++  g_clear_error (&local_error);
++
++  return 0;
++}
+diff --git a/fuzzing/fuzz_filename_to_uri.c b/fuzzing/fuzz_filename_to_uri.c
+new file mode 100644
+index 0000000000..acb3192035
+--- /dev/null
++++ b/fuzzing/fuzz_filename_to_uri.c
+@@ -0,0 +1,40 @@
++/*
++ * Copyright 2025 GNOME Foundation, Inc.
++ *
++ * SPDX-License-Identifier: LGPL-2.1-or-later
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Lesser General Public
++ * License as published by the Free Software Foundation; either
++ * version 2.1 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with this library; if not, see 
<http://www.gnu.org/licenses/>.
++ */
++
++#include "fuzz.h"
++
++int
++LLVMFuzzerTestOneInput (const unsigned char *data, size_t size)
++{
++  unsigned char *nul_terminated_data = NULL;
++  char *uri = NULL;
++  GError *local_error = NULL;
++
++  fuzz_set_logging_func ();
++
++  /* ignore @size (g_filename_to_uri() doesn’t support it); ensure @data is 
nul-terminated */
++  nul_terminated_data = (unsigned char *) g_strndup ((const char *) data, 
size);
++  uri = g_filename_to_uri ((const char *) nul_terminated_data, NULL, 
&local_error);
++  g_free (nul_terminated_data);
++
++  g_free (uri);
++  g_clear_error (&local_error);
++
++  return 0;
++}
+diff --git a/fuzzing/meson.build b/fuzzing/meson.build
+index addbe90717..05f936eeb2 100644
+--- a/fuzzing/meson.build
++++ b/fuzzing/meson.build
+@@ -25,6 +25,8 @@ fuzz_targets = [
+   'fuzz_date_parse',
+   'fuzz_date_time_new_from_iso8601',
+   'fuzz_dbus_message',
++  'fuzz_filename_from_uri',
++  'fuzz_filename_to_uri',
+   'fuzz_get_locale_variants',
+   'fuzz_inet_address_mask_new_from_string',
+   'fuzz_inet_address_new_from_string',
+-- 
+GitLab
+

diff --git a/dev-libs/glib/files/glib-2.86-MR-4934-CVE-2025-14087.patch 
b/dev-libs/glib/files/glib-2.86-MR-4934-CVE-2025-14087.patch
new file mode 100644
index 000000000000..018c4fbffcd8
--- /dev/null
+++ b/dev-libs/glib/files/glib-2.86-MR-4934-CVE-2025-14087.patch
@@ -0,0 +1,459 @@
+From 3e72fe0fbb32c18a66486c4da8bc851f656af287 Mon Sep 17 00:00:00 2001
+From: Philip Withnall <[email protected]>
+Date: Tue, 25 Nov 2025 19:02:56 +0000
+Subject: [PATCH 1/3] gvariant-parser: Fix potential integer overflow parsing
+ (byte)strings
+
+The termination condition for parsing string and bytestring literals in
+GVariant text format input was subject to an integer overflow for input
+string (or bytestring) literals longer than `INT_MAX`.
+
+Fix that by counting as a `size_t` rather than as an `int`. The counter
+can never correctly be negative.
+
+Spotted by treeplus. Thanks to the Sovereign Tech Resilience programme
+from the Sovereign Tech Agency. ID: #YWH-PGM9867-145
+
+Signed-off-by: Philip Withnall <[email protected]>
+Fixes: #3834
+---
+ glib/gvariant-parser.c | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/glib/gvariant-parser.c b/glib/gvariant-parser.c
+index 2f1d3db9f6..2d6e9856f8 100644
+--- a/glib/gvariant-parser.c
++++ b/glib/gvariant-parser.c
+@@ -609,7 +609,7 @@ ast_resolve (AST     *ast,
+ {
+   GVariant *value;
+   gchar *pattern;
+-  gint i, j = 0;
++  size_t i, j = 0;
+ 
+   pattern = ast_get_pattern (ast, error);
+ 
+@@ -1637,9 +1637,9 @@ string_free (AST *ast)
+  */
+ static gboolean
+ unicode_unescape (const gchar  *src,
+-                  gint         *src_ofs,
++                  size_t       *src_ofs,
+                   gchar        *dest,
+-                  gint         *dest_ofs,
++                  size_t       *dest_ofs,
+                   gsize         length,
+                   SourceRef    *ref,
+                   GError      **error)
+@@ -1700,7 +1700,7 @@ string_parse (TokenStream  *stream,
+   gsize length;
+   gchar quote;
+   gchar *str;
+-  gint i, j;
++  size_t i, j;
+ 
+   token_stream_start_ref (stream, &ref);
+   token = token_stream_get (stream);
+@@ -1833,7 +1833,7 @@ bytestring_parse (TokenStream  *stream,
+   gsize length;
+   gchar quote;
+   gchar *str;
+-  gint i, j;
++  size_t i, j;
+ 
+   token_stream_start_ref (stream, &ref);
+   token = token_stream_get (stream);
+-- 
+GitLab
+
+
+From 6fe481cec709ec65b5846113848723bc25a8782a Mon Sep 17 00:00:00 2001
+From: Philip Withnall <[email protected]>
+Date: Tue, 25 Nov 2025 19:19:16 +0000
+Subject: [PATCH 2/3] gvariant-parser: Use size_t to count numbers of child
+ elements
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Rather than using `gint`, which could overflow for arrays (or dicts, or
+tuples) longer than `INT_MAX`. There may be other limits which prevent
+parsed containers becoming that long, but we might as well make the type
+system reflect the programmer’s intention as best it can anyway.
+
+For arrays and tuples this is straightforward. For dictionaries, it’s
+slightly complicated by the fact that the code used
+`dict->n_children == -1` to indicate that the `Dictionary` struct in
+question actually represented a single freestanding dict entry. In
+GVariant text format, that would be `{1, "one"}`.
+
+The implementation previously didn’t define the semantics of
+`dict->n_children < -1`.
+
+Now, instead, change `Dictionary.n_children` to `size_t`, and define a
+magic value `DICTIONARY_N_CHILDREN_FREESTANDING_ENTRY` to indicate that
+the `Dictionary` represents a single freestanding dict entry.
+
+This magic value is `SIZE_MAX`, and given that a dictionary entry takes
+more than one byte to represent in GVariant text format, that means it’s
+not possible to have that many entries in a parsed dictionary, so this
+magic value won’t be hit by a normal dictionary. An assertion checks
+this anyway.
+
+Spotted while working on #3834.
+
+Signed-off-by: Philip Withnall <[email protected]>
+---
+ glib/gvariant-parser.c | 58 ++++++++++++++++++++++++------------------
+ 1 file changed, 33 insertions(+), 25 deletions(-)
+
+diff --git a/glib/gvariant-parser.c b/glib/gvariant-parser.c
+index 2d6e9856f8..519baa3f36 100644
+--- a/glib/gvariant-parser.c
++++ b/glib/gvariant-parser.c
+@@ -662,9 +662,9 @@ static AST *parse (TokenStream  *stream,
+                    GError      **error);
+ 
+ static void
+-ast_array_append (AST  ***array,
+-                  gint   *n_items,
+-                  AST    *ast)
++ast_array_append (AST    ***array,
++                  size_t   *n_items,
++                  AST      *ast)
+ {
+   if ((*n_items & (*n_items - 1)) == 0)
+     *array = g_renew (AST *, *array, *n_items ? 2 ** n_items : 1);
+@@ -673,10 +673,10 @@ ast_array_append (AST  ***array,
+ }
+ 
+ static void
+-ast_array_free (AST  **array,
+-                gint   n_items)
++ast_array_free (AST    **array,
++                size_t   n_items)
+ {
+-  gint i;
++  size_t i;
+ 
+   for (i = 0; i < n_items; i++)
+     ast_free (array[i]);
+@@ -685,11 +685,11 @@ ast_array_free (AST  **array,
+ 
+ static gchar *
+ ast_array_get_pattern (AST    **array,
+-                       gint     n_items,
++                       size_t   n_items,
+                        GError **error)
+ {
+   gchar *pattern;
+-  gint i;
++  size_t i;
+ 
+   /* Find the pattern which applies to all children in the array, by 
l-folding a
+    * coalesce operation.
+@@ -721,7 +721,7 @@ ast_array_get_pattern (AST    **array,
+          * pair of values.
+          */
+         {
+-          int j = 0;
++          size_t j = 0;
+ 
+           while (TRUE)
+             {
+@@ -969,7 +969,7 @@ typedef struct
+   AST ast;
+ 
+   AST **children;
+-  gint n_children;
++  size_t n_children;
+ } Array;
+ 
+ static gchar *
+@@ -1002,7 +1002,7 @@ array_get_value (AST                 *ast,
+   Array *array = (Array *) ast;
+   const GVariantType *childtype;
+   GVariantBuilder builder;
+-  gint i;
++  size_t i;
+ 
+   if (!g_variant_type_is_array (type))
+     return ast_type_error (ast, type, error);
+@@ -1088,7 +1088,7 @@ typedef struct
+   AST ast;
+ 
+   AST **children;
+-  gint n_children;
++  size_t n_children;
+ } Tuple;
+ 
+ static gchar *
+@@ -1098,7 +1098,7 @@ tuple_get_pattern (AST     *ast,
+   Tuple *tuple = (Tuple *) ast;
+   gchar *result = NULL;
+   gchar **parts;
+-  gint i;
++  size_t i;
+ 
+   parts = g_new (gchar *, tuple->n_children + 4);
+   parts[tuple->n_children + 1] = (gchar *) ")";
+@@ -1128,7 +1128,7 @@ tuple_get_value (AST                 *ast,
+   Tuple *tuple = (Tuple *) ast;
+   const GVariantType *childtype;
+   GVariantBuilder builder;
+-  gint i;
++  size_t i;
+ 
+   if (!g_variant_type_is_tuple (type))
+     return ast_type_error (ast, type, error);
+@@ -1320,9 +1320,16 @@ typedef struct
+ 
+   AST **keys;
+   AST **values;
+-  gint n_children;
++
++  /* Iff this is DICTIONARY_N_CHILDREN_FREESTANDING_ENTRY then this struct
++   * represents a single freestanding dict entry (`{1, "one"}`) rather than a
++   * full dict. In the freestanding case, @keys and @values have exactly one
++   * member each. */
++  size_t n_children;
+ } Dictionary;
+ 
++#define DICTIONARY_N_CHILDREN_FREESTANDING_ENTRY ((size_t) -1)
++
+ static gchar *
+ dictionary_get_pattern (AST     *ast,
+                         GError **error)
+@@ -1337,7 +1344,7 @@ dictionary_get_pattern (AST     *ast,
+     return g_strdup ("Ma{**}");
+ 
+   key_pattern = ast_array_get_pattern (dict->keys,
+-                                       abs (dict->n_children),
++                                       (dict->n_children == 
DICTIONARY_N_CHILDREN_FREESTANDING_ENTRY) ? 1 : dict->n_children,
+                                        error);
+ 
+   if (key_pattern == NULL)
+@@ -1368,7 +1375,7 @@ dictionary_get_pattern (AST     *ast,
+     return NULL;
+ 
+   result = g_strdup_printf ("M%s{%c%s}",
+-                            dict->n_children > 0 ? "a" : "",
++                            (dict->n_children > 0 && dict->n_children != 
DICTIONARY_N_CHILDREN_FREESTANDING_ENTRY) ? "a" : "",
+                             key_char, value_pattern);
+   g_free (value_pattern);
+ 
+@@ -1382,7 +1389,7 @@ dictionary_get_value (AST                 *ast,
+ {
+   Dictionary *dict = (Dictionary *) ast;
+ 
+-  if (dict->n_children == -1)
++  if (dict->n_children == DICTIONARY_N_CHILDREN_FREESTANDING_ENTRY)
+     {
+       const GVariantType *subtype;
+       GVariantBuilder builder;
+@@ -1415,7 +1422,7 @@ dictionary_get_value (AST                 *ast,
+     {
+       const GVariantType *entry, *key, *val;
+       GVariantBuilder builder;
+-      gint i;
++      size_t i;
+ 
+       if (!g_variant_type_is_subtype_of (type, G_VARIANT_TYPE_DICTIONARY))
+         return ast_type_error (ast, type, error);
+@@ -1456,12 +1463,12 @@ static void
+ dictionary_free (AST *ast)
+ {
+   Dictionary *dict = (Dictionary *) ast;
+-  gint n_children;
++  size_t n_children;
+ 
+-  if (dict->n_children > -1)
+-    n_children = dict->n_children;
+-  else
++  if (dict->n_children == DICTIONARY_N_CHILDREN_FREESTANDING_ENTRY)
+     n_children = 1;
++  else
++    n_children = dict->n_children;
+ 
+   ast_array_free (dict->keys, n_children);
+   ast_array_free (dict->values, n_children);
+@@ -1479,7 +1486,7 @@ dictionary_parse (TokenStream  *stream,
+     maybe_wrapper, dictionary_get_value,
+     dictionary_free
+   };
+-  gint n_keys, n_values;
++  size_t n_keys, n_values;
+   gboolean only_one;
+   Dictionary *dict;
+   AST *first;
+@@ -1522,7 +1529,7 @@ dictionary_parse (TokenStream  *stream,
+         goto error;
+ 
+       g_assert (n_keys == 1 && n_values == 1);
+-      dict->n_children = -1;
++      dict->n_children = DICTIONARY_N_CHILDREN_FREESTANDING_ENTRY;
+ 
+       return (AST *) dict;
+     }
+@@ -1555,6 +1562,7 @@ dictionary_parse (TokenStream  *stream,
+     }
+ 
+   g_assert (n_keys == n_values);
++  g_assert (n_keys != DICTIONARY_N_CHILDREN_FREESTANDING_ENTRY);
+   dict->n_children = n_keys;
+ 
+   return (AST *) dict;
+-- 
+GitLab
+
+
+From dd333a40aa95819720a01caf6de564cd8a4a6310 Mon Sep 17 00:00:00 2001
+From: Philip Withnall <[email protected]>
+Date: Tue, 25 Nov 2025 19:25:58 +0000
+Subject: [PATCH 3/3] gvariant-parser: Convert error handling code to use
+ size_t
+
+The error handling code allows for printing out the range of input bytes
+related to a parsing error. This was previously done using `gint`, but
+the input could be longer than `INT_MAX`, so it should really be done
+using `size_t`.
+
+Spotted while working on #3834.
+
+Signed-off-by: Philip Withnall <[email protected]>
+---
+ glib/gvariant-parser.c | 36 +++++++++++++++++++++++-------------
+ 1 file changed, 23 insertions(+), 13 deletions(-)
+
+diff --git a/glib/gvariant-parser.c b/glib/gvariant-parser.c
+index 519baa3f36..1b1ddd654b 100644
+--- a/glib/gvariant-parser.c
++++ b/glib/gvariant-parser.c
+@@ -91,7 +91,9 @@ g_variant_parser_get_error_quark (void)
+ 
+ typedef struct
+ {
+-  gint start, end;
++  /* Offsets from the start of the input, in bytes. Can be equal when 
referring
++   * to a point rather than a range. The invariant `end >= start` always 
holds. */
++  size_t start, end;
+ } SourceRef;
+ 
+ G_GNUC_PRINTF(5, 0)
+@@ -106,14 +108,16 @@ parser_set_error_va (GError      **error,
+   GString *msg = g_string_new (NULL);
+ 
+   if (location->start == location->end)
+-    g_string_append_printf (msg, "%d", location->start);
++    g_string_append_printf (msg, "%" G_GSIZE_FORMAT, location->start);
+   else
+-    g_string_append_printf (msg, "%d-%d", location->start, location->end);
++    g_string_append_printf (msg, "%" G_GSIZE_FORMAT "-%" G_GSIZE_FORMAT,
++                            location->start, location->end);
+ 
+   if (other != NULL)
+     {
+       g_assert (other->start != other->end);
+-      g_string_append_printf (msg, ",%d-%d", other->start, other->end);
++      g_string_append_printf (msg, ",%" G_GSIZE_FORMAT "-%" G_GSIZE_FORMAT,
++                              other->start, other->end);
+     }
+   g_string_append_c (msg, ':');
+ 
+@@ -140,11 +144,15 @@ parser_set_error (GError      **error,
+ 
+ typedef struct
+ {
++  /* We should always have the following ordering constraint:
++   *   start <= this <= stream <= end
++   * Additionally, unless in an error or EOF state, `this < stream`.
++   */
+   const gchar *start;
+   const gchar *stream;
+   const gchar *end;
+ 
+-  const gchar *this;
++  const gchar *this;  /* (nullable) */
+ } TokenStream;
+ 
+ 
+@@ -175,7 +183,7 @@ token_stream_set_error (TokenStream  *stream,
+ static gboolean
+ token_stream_prepare (TokenStream *stream)
+ {
+-  gint brackets = 0;
++  gssize brackets = 0;
+   const gchar *end;
+ 
+   if (stream->this != NULL)
+@@ -407,7 +415,7 @@ static void
+ pattern_copy (gchar       **out,
+               const gchar **in)
+ {
+-  gint brackets = 0;
++  gssize brackets = 0;
+ 
+   while (**in == 'a' || **in == 'm' || **in == 'M')
+     *(*out)++ = *(*in)++;
+@@ -2765,7 +2773,7 @@ g_variant_builder_add_parsed (GVariantBuilder *builder,
+ static gboolean
+ parse_num (const gchar *num,
+            const gchar *limit,
+-           guint       *result)
++           size_t      *result)
+ {
+   gchar *endptr;
+   gint64 bignum;
+@@ -2775,10 +2783,12 @@ parse_num (const gchar *num,
+   if (endptr != limit)
+     return FALSE;
+ 
++  /* The upper bound here is more restrictive than it technically needs to be,
++   * but should be enough for any practical situation: */
+   if (bignum < 0 || bignum > G_MAXINT)
+     return FALSE;
+ 
+-  *result = (guint) bignum;
++  *result = (size_t) bignum;
+ 
+   return TRUE;
+ }
+@@ -2789,7 +2799,7 @@ add_last_line (GString     *err,
+ {
+   const gchar *last_nl;
+   gchar *chomped;
+-  gint i;
++  size_t i;
+ 
+   /* This is an error at the end of input.  If we have a file
+    * with newlines, that's probably the empty string after the
+@@ -2934,7 +2944,7 @@ g_variant_parse_error_print_context (GError      *error,
+ 
+   if (dash == NULL || colon < dash)
+     {
+-      guint point;
++      size_t point;
+ 
+       /* we have a single point */
+       if (!parse_num (error->message, colon, &point))
+@@ -2952,7 +2962,7 @@ g_variant_parse_error_print_context (GError      *error,
+       /* We have one or two ranges... */
+       if (comma && comma < colon)
+         {
+-          guint start1, end1, start2, end2;
++          size_t start1, end1, start2, end2;
+           const gchar *dash2;
+ 
+           /* Two ranges */
+@@ -2968,7 +2978,7 @@ g_variant_parse_error_print_context (GError      *error,
+         }
+       else
+         {
+-          guint start, end;
++          size_t start, end;
+ 
+           /* One range */
+           if (!parse_num (error->message, dash, &start) || !parse_num (dash + 
1, colon, &end))
+-- 
+GitLab
+

diff --git a/dev-libs/glib/files/glib-2.86-MR-4936.patch 
b/dev-libs/glib/files/glib-2.86-MR-4936.patch
new file mode 100644
index 000000000000..ce1d9b1328f4
--- /dev/null
+++ b/dev-libs/glib/files/glib-2.86-MR-4936.patch
@@ -0,0 +1,69 @@
+From 4f0399c0aaf3ffc86b5625424580294bc7460404 Mon Sep 17 00:00:00 2001
+From: Philip Withnall <[email protected]>
+Date: Thu, 4 Dec 2025 16:37:19 +0000
+Subject: [PATCH] gfileattribute: Fix integer overflow calculating escaping for
+ byte strings
+
+The number of invalid characters in the byte string (characters which
+would have to be percent-encoded) was only stored in an `int`, which
+gave the possibility of a long string largely full of invalid
+characters overflowing this and allowing an attacker-controlled buffer
+size to be allocated.
+
+This could be triggered by an attacker controlled file attribute (of
+type `G_FILE_ATTRIBUTE_TYPE_BYTE_STRING`), such as
+`G_FILE_ATTRIBUTE_THUMBNAIL_PATH` or `G_FILE_ATTRIBUTE_STANDARD_NAME`,
+being read by user code.
+
+Spotted by Codean Labs.
+
+Signed-off-by: Philip Withnall <[email protected]>
+
+Fixes: #3845
+---
+ gio/gfileattribute.c | 11 +++++++++--
+ 1 file changed, 9 insertions(+), 2 deletions(-)
+
+diff --git a/gio/gfileattribute.c b/gio/gfileattribute.c
+index c6fde60fa9..d3083e5bd8 100644
+--- a/gio/gfileattribute.c
++++ b/gio/gfileattribute.c
+@@ -22,6 +22,7 @@
+ 
+ #include "config.h"
+ 
++#include <stdint.h>
+ #include <string.h>
+ 
+ #include "gfileattribute.h"
+@@ -166,11 +167,12 @@ valid_char (char c)
+   return c >= 32 && c <= 126 && c != '\\';
+ }
+ 
++/* Returns NULL on error */
+ static char *
+ escape_byte_string (const char *str)
+ {
+   size_t i, len;
+-  int num_invalid;
++  size_t num_invalid;
+   char *escaped_val, *p;
+   unsigned char c;
+   const char hex_digits[] = "0123456789abcdef";
+@@ -188,7 +190,12 @@ escape_byte_string (const char *str)
+     return g_strdup (str);
+   else
+     {
+-      escaped_val = g_malloc (len + num_invalid*3 + 1);
++      /* Check for overflow. We want to check the inequality:
++       * !(len + num_invalid * 3 + 1 > SIZE_MAX) */
++      if (num_invalid >= (SIZE_MAX - len) / 3)
++        return NULL;
++
++      escaped_val = g_malloc (len + num_invalid * 3 + 1);
+ 
+       p = escaped_val;
+       for (i = 0; i < len; i++)
+-- 
+GitLab
+

diff --git a/dev-libs/glib/glib-2.84.4-r1.ebuild 
b/dev-libs/glib/glib-2.84.4-r1.ebuild
new file mode 100644
index 000000000000..1c75be26b295
--- /dev/null
+++ b/dev-libs/glib/glib-2.84.4-r1.ebuild
@@ -0,0 +1,481 @@
+# Copyright 1999-2025 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+EAPI=8
+PYTHON_REQ_USE="xml(+)"
+PYTHON_COMPAT=( python3_{11..14} )
+
+inherit dot-a eapi9-ver gnome.org gnome2-utils linux-info meson-multilib 
multilib python-any-r1 toolchain-funcs xdg
+
+DESCRIPTION="The GLib library of C routines"
+HOMEPAGE="https://www.gtk.org/";
+
+INTROSPECTION_PN="gobject-introspection"
+INTROSPECTION_PV="1.82.0"
+INTROSPECTION_P="${INTROSPECTION_PN}-${INTROSPECTION_PV}"
+SRC_URI="
+       ${SRC_URI}
+       introspection? ( 
mirror://gnome/sources/gobject-introspection/${INTROSPECTION_PV%.*}/gobject-introspection-${INTROSPECTION_PV}.tar.${GNOME_TARBALL_SUFFIX}
 )
+"
+INTROSPECTION_SOURCE_DIR="${WORKDIR}/${INTROSPECTION_P}"
+INTROSPECTION_BUILD_DIR="${WORKDIR}/${INTROSPECTION_P}-build"
+
+LICENSE="LGPL-2.1+"
+SLOT="2"
+KEYWORDS="~alpha ~amd64 ~arm ~arm64 ~hppa ~loong ~m68k ~mips ~ppc ~ppc64 
~riscv ~s390 ~sparc ~x86 ~amd64-linux ~x86-linux ~arm64-macos ~ppc-macos 
~x64-macos ~x64-solaris"
+IUSE="dbus debug +elf doc +introspection +mime selinux static-libs sysprof 
systemtap test utils xattr"
+RESTRICT="!test? ( test )"
+
+# * elfutils (via libelf) does not build on Windows. gresources are not 
embedded
+# within ELF binaries on that platform anyway and inspecting ELF binaries from
+# other platforms is not that useful so exclude the dependency in this case.
+# * Technically static-libs is needed on zlib, util-linux and perhaps more, but
+# these are used by GIO, which glib[static-libs] consumers don't really seem
+# to need at all, thus not imposing the deps for now and once some consumers
+# are actually found to static link libgio-2.0.a, we can revisit and either add
+# them or just put the (build) deps in that rare consumer instead of recursive
+# RDEPEND here (due to lack of recursive DEPEND).
+RDEPEND="
+       !<dev-libs/gobject-introspection-1.80.1
+       !<dev-util/gdbus-codegen-${PV}
+       >=virtual/libiconv-0-r1[${MULTILIB_USEDEP}]
+       >=dev-libs/libpcre2-10.32:0=[${MULTILIB_USEDEP},unicode(+),static-libs?]
+       >=dev-libs/libffi-3.0.13-r1:=[${MULTILIB_USEDEP}]
+       >=virtual/zlib-1.2.8-r1:=[${MULTILIB_USEDEP}]
+       >=virtual/libintl-0-r2[${MULTILIB_USEDEP}]
+       introspection? (
+               >=dev-libs/gobject-introspection-common-${INTROSPECTION_PV}
+       )
+       kernel_linux? ( >=sys-apps/util-linux-2.23[${MULTILIB_USEDEP}] )
+       selinux? ( >=sys-libs/libselinux-2.2.2-r5[${MULTILIB_USEDEP}] )
+       xattr? ( !elibc_glibc? ( >=sys-apps/attr-2.4.47-r1[${MULTILIB_USEDEP}] 
) )
+       elf? ( virtual/libelf:0= )
+       sysprof? ( >=dev-util/sysprof-capture-3.40.1:4[${MULTILIB_USEDEP}] )
+"
+DEPEND="${RDEPEND}"
+# libxml2 used for optional tests that get automatically skipped
+BDEPEND="
+       app-text/docbook-xsl-stylesheets
+       >=dev-build/meson-1.4.0
+       dev-libs/libxslt
+       >=sys-devel/gettext-0.19.8
+       doc? ( >=dev-util/gi-docgen-2023.1 )
+       dev-python/docutils
+       systemtap? ( >=dev-debug/systemtap-1.3 )
+       ${PYTHON_DEPS}
+       test? ( >=sys-apps/dbus-1.2.14 )
+       virtual/pkgconfig
+
+       introspection? (
+               $(python_gen_any_dep '
+                       dev-python/setuptools[${PYTHON_USEDEP}]
+               ')
+               virtual/pkgconfig
+               sys-devel/bison
+               app-alternatives/lex
+               ${PYTHON_DEPS}
+       )
+"
+# TODO: >=dev-util/gdbus-codegen-${PV} test dep once we modify 
gio/tests/meson.build to use external gdbus-codegen
+
+PDEPEND="
+       dbus? ( gnome-base/dconf )
+       mime? ( x11-misc/shared-mime-info )
+"
+# shared-mime-info needed for gio/xdgmime, bug #409481
+# dconf is needed to be able to save settings, bug #498436
+
+MULTILIB_CHOST_TOOLS=(
+       /usr/bin/gio-querymodules$(get_exeext)
+)
+
+PATCHES=(
+       "${FILESDIR}"/${PN}-2.64.1-mark-gdbus-server-auth-test-flaky.patch
+       "${FILESDIR}"/${PN}-2.84.4-libpcre2-10.47.patch
+       "${FILESDIR}"/${PN}-2.86-MR-4912.patch
+       "${FILESDIR}"/${PN}-2.86-MR-4915-CVE-2025-13601.patch
+       "${FILESDIR}"/${PN}-2.86-MR-4934-CVE-2025-14087.patch
+       "${FILESDIR}"/${PN}-2.86-MR-4936.patch
+)
+
+python_check_deps() {
+       if use introspection ; then
+               python_has_version "dev-python/setuptools[${PYTHON_USEDEP}]"
+       fi
+}
+
+pkg_setup() {
+       if use kernel_linux ; then
+               CONFIG_CHECK="~INOTIFY_USER"
+               if use test ; then
+                       CONFIG_CHECK="~IPV6"
+                       WARNING_IPV6="Your kernel needs IPV6 support for 
running some tests, skipping them."
+               fi
+               linux-info_pkg_setup
+       fi
+       python-any-r1_pkg_setup
+}
+
+src_prepare() {
+       if use test; then
+               # TODO: Review the test exclusions, especially now with meson
+               # gdesktopappinfo requires existing terminal (gnome-terminal or 
any
+               # other), falling back to xterm if one doesn't exist
+               #if ! has_version x11-terms/xterm && ! has_version 
x11-terms/gnome-terminal ; then
+               #       ewarn "Some tests will be skipped due to missing 
terminal program"
+               # These tests seem to sometimes fail even with a terminal; skip 
for now and reevulate with meson
+               # Also try https://gitlab.gnome.org/GNOME/glib/issues/1601 once 
ready
+               # for backport (or in a bump) and file new issue if still fails
+               sed -i -e "/appinfo\/launch/d" gio/tests/appinfo.c || die
+               # desktop-app-info/launch* might fail similarly
+               sed -i -e "/desktop-app-info\/launch-as-manager/d" 
gio/tests/desktop-app-info.c || die
+               #fi
+
+               # https://bugzilla.gnome.org/show_bug.cgi?id=722604
+               sed -i -e "/timer\/stop/d" glib/tests/timer.c || die
+               sed -i -e "/timer\/basic/d" glib/tests/timer.c || die
+
+               ewarn "Tests for search-utils have been skipped"
+               sed -i -e "/search-utils/d" glib/tests/meson.build || die
+
+               # Running gdb inside a test within sandbox is brittle
+               sed -i -e '/self.__gdb = 
shutil.which("gdb")/s:"gdb":"gdb-idonotexist":' glib/tests/assert-msg-test.py 
|| die
+
+               # Play nice with network-sandbox, but this approach would 
defeat the purpose of the test
+               #sed -i -e "s/localhost/127.0.0.1/g" 
gio/tests/gsocketclient-slow.c || die
+       else
+               # Don't build tests, also prevents extra deps, bug #512022
+               sed -i -e '/subdir.*tests/d' {.,gio,glib}/meson.build || die
+       fi
+
+       # Don't build fuzzing binaries - not used
+       sed -i -e '/subdir.*fuzzing/d' meson.build || die
+
+       # gdbus-codegen is a separate package
+       sed -i -e '/install_dir/d' gio/gdbus-2.0/codegen/meson.build || die
+       sed -i -e '/install : true/d' gio/gdbus-2.0/codegen/meson.build || die
+
+       # Same kind of meson-0.50 issue with some installed-tests files; will 
likely be fixed upstream soon
+       sed -i -e '/install_dir/d' gio/tests/meson.build || die
+
+       cat > "${T}/glib-test-ld-wrapper" <<-EOF
+               #!/usr/bin/env sh
+               exec \${LD:-ld} "\$@"
+       EOF
+       chmod a+x "${T}/glib-test-ld-wrapper" || die
+       sed -i -e "s|'ld'|'${T}/glib-test-ld-wrapper'|g" gio/tests/meson.build 
|| die
+
+       # make default sane for us
+       if use prefix ; then
+               sed -i -e "s:/usr/local:${EPREFIX}/usr:" gio/xdgmime/xdgmime.c 
|| die
+               # bug #308609, without path, bug #314057
+               export PERL=perl
+       fi
+
+       if [[ ${CHOST} == *-solaris* ]] ; then
+               # fix standards conflicts
+               sed -i \
+                       -e 
's/\<\(_XOPEN_SOURCE_EXTENDED\)\>/_POSIX_PTHREAD_SEMANTICS/' \
+                       -e '/\<_XOPEN_SOURCE\>/s/\<2\>/600/' \
+                       meson.build || die
+               sed -i -e '/#define\s\+_POSIX_SOURCE/d' \
+                       glib/giounix.c || die
+       fi
+
+       # disable native macOS integrations
+       sed -i -e '/glib_conf.set(.HAVE_\(CARBON\|COCOA\).,/s/true/false/' \
+               meson.build || die
+       sed -i \
+               -e '/AvailabilityMacros.h/d' \
+               gio/giomodule.c || die
+
+       # Link the glib source to the introspection subproject directory so it 
can be built there first
+       if use introspection ; then
+               ln -s "${S}" "${INTROSPECTION_SOURCE_DIR}/subprojects/glib"
+       fi
+
+       default
+       gnome2_environment_reset
+       # TODO: python_name sedding for correct python shebang? Might be 
relevant mainly for glib-utils only
+}
+
+src_configure() {
+       lto-guarantee-fat
+       meson-multilib_src_configure
+}
+
+multilib_src_configure() {
+       # TODO: figure a way to pass appropriate values for all cross properties
+       # that glib uses (search for get_cross_property)
+       #if tc-is-cross-compiler ; then
+               # https://bugzilla.gnome.org/show_bug.cgi?id=756473
+               # TODO-meson: This should be in meson cross file as 
'growing_stack'
+               # property; and more, look at get_cross_property
+               #case ${CHOST} in
+               #hppa*|metag*) export glib_cv_stack_grows=yes ;;
+               #*)            export glib_cv_stack_grows=no ;;
+               #esac
+       #fi
+
+       _need_bootstrap_gi() {
+               if ! multilib_native_use introspection ; then
+                       return 1
+               fi
+
+               if ! has_version ">=dev-libs/${INTROSPECTION_P}" ; then
+                       return 0
+               fi
+
+               # Is the installed gobject-introspection usable?
+               if ! g-ir-scanner --version &> /dev/null ; then
+                       return 0
+               fi
+
+               # Do we somehow have a dev-libs/gobject-introspection installed
+               # with an unsatisfied dependency? (bug #951487)
+               if ! $(tc-getPKG_CONFIG) --cflags gobject-introspection-1.0 &> 
/dev/null ; then
+                       return 0
+               fi
+
+               # Make sure has_version didn't lie to us while at it as well,
+               # given bug #951487.
+               if ! $(tc-getPKG_CONFIG) --atleast-version=${INTROSPECTION_PV} 
gobject-introspection-1.0 &> /dev/null ; then
+                       return 0
+               fi
+
+               return 1
+       }
+
+       # Build internal copy of gobject-introspection to avoid circular 
dependency (built for native abi only)
+       if _need_bootstrap_gi ; then
+               einfo "Bootstrapping gobject-introspection..."
+               INTROSPECTION_BIN_DIR="${T}/bootstrap-gi-prefix/usr/bin"
+               
INTROSPECTION_LIB_DIR="${T}/bootstrap-gi-prefix/usr/$(get_libdir)"
+
+               local emesonargs=(
+                       --prefix="${T}/bootstrap-gi-prefix/usr"
+                       -Dpython="${EPYTHON}"
+                       -Dbuild_introspection_data=true
+                       # Build an internal copy of glib for the internal copy 
of gobject-introspection
+                       --force-fallback-for=glib
+                       # Make the paths in pkgconfig files relative as we used 
to not
+                       # do a proper install here and it seems less risky to 
keep it
+                       # this way.
+                       -Dpkgconfig.relocatable=true
+
+                       # We want as minimal a build as possible here to speed 
things up
+                       # and reduce the risk of failures.
+                       -Dglib:selinux=disabled
+                       -Dglib:xattr=false
+                       -Dglib:libmount=disabled
+                       -Dglib:man-pages=disabled
+                       -Dglib:dtrace=disabled
+                       -Dglib:systemtap=disabled
+                       -Dglib:sysprof=disabled
+                       -Dglib:documentation=false
+                       -Dglib:tests=false
+                       -Dglib:installed_tests=false
+                       -Dglib:nls=disabled
+                       -Dglib:oss_fuzz=disabled
+                       -Dglib:libelf=disabled
+                       -Dglib:multiarch=false
+               )
+
+               ORIG_SOURCE_DIR=${EMESON_SOURCE}
+               EMESON_SOURCE=${INTROSPECTION_SOURCE_DIR}
+
+               # g-ir-scanner has some relocatable logic but it searches
+               # for 'lib', not 'lib64', so it can't find itself and eventually
+               # falls back to the system installation. See bug #946221.
+               sed -i -e "/^pylibdir =/s:'lib:'$(get_libdir):" 
"${EMESON_SOURCE}"/tools/g-ir-tool-template.in || die
+
+               ORIG_BUILD_DIR=${BUILD_DIR}
+               BUILD_DIR=${INTROSPECTION_BUILD_DIR}
+
+               pushd ${INTROSPECTION_SOURCE_DIR} || die
+
+               meson_src_configure
+               meson_src_compile
+               # We already provide a prefix in ${T} above. Blank DESTDIR
+               # as it may be set in the environment by Portage (though not
+               # guaranteed in src_configure).
+               meson_src_install --destdir ""
+
+               popd || die
+
+               EMESON_SOURCE=${ORIG_SOURCE_DIR}
+               BUILD_DIR=${ORIG_BUILD_DIR}
+
+               # Add gobject-introspection binaries and pkgconfig files to path
+               export PATH="${INTROSPECTION_BIN_DIR}:${PATH}"
+
+               # Override primary pkgconfig search paths to prioritize our 
internal copy
+               local -x 
PKG_CONFIG_LIBDIR="${INTROSPECTION_LIB_DIR}/pkgconfig:${INTROSPECTION_BUILD_DIR}/meson-private:$($(tc-getPKG_CONFIG)
 --variable pc_system_libdirs pkg-config)"
+
+               # Set the normal primary pkgconfig search paths as secondary
+               # (We also need to prepend our just-built one for later use of
+               # g-ir-scanner to use the new one and to help workaround bugs 
like
+               # bug #946221.)
+               local -x 
PKG_CONFIG_PATH="${PKG_CONFIG_LIBDIR}:$($(tc-getPKG_CONFIG) --variable pc_path 
pkg-config)"
+
+               # Add the paths to the built glib libraries to the library path 
so that gobject-introspection can load them
+               local gliblib
+               for gliblib in glib gobject gthread gmodule gio girepository; do
+                       export 
LD_LIBRARY_PATH="${BUILD_DIR}/${gliblib}:${LD_LIBRARY_PATH}"
+               done
+
+               # Add the path to introspection libraries so that glib can call 
gir utilities
+               export 
LD_LIBRARY_PATH="${INTROSPECTION_LIB_DIR}:${LD_LIBRARY_PATH}"
+
+               # Add the paths to the gobject-introspection python modules to 
python path so they can be imported
+               export 
PYTHONPATH="${INTROSPECTION_LIB_DIR}/gobject-introspection:${PYTHONPATH}"
+       fi
+
+       # TODO: Can this be cleaned up now we have -Dglib_debug? (bug #946485)
+       use debug && EMESON_BUILD_TYPE=debug
+
+       local emesonargs=(
+               -Ddefault_library=$(usex static-libs both shared)
+               -Druntime_dir="${EPREFIX}"/run
+               $(meson_feature debug glib_debug)
+               $(meson_feature selinux)
+               $(meson_use xattr)
+               -Dlibmount=enabled # only used if host_system == 'linux'
+               -Dman-pages=enabled
+               $(meson_feature systemtap dtrace)
+               $(meson_feature systemtap)
+               $(meson_feature sysprof)
+               $(meson_use doc documentation)
+               $(meson_use test tests)
+               -Dinstalled_tests=false
+               -Dnls=enabled
+               -Doss_fuzz=disabled
+               $(meson_native_use_feature elf libelf)
+               -Dmultiarch=false
+               $(meson_native_use_feature introspection)
+       )
+
+       # Workaround for bug #938302
+       if use systemtap && has_version 
"dev-debug/systemtap[-dtrace-symlink(+)]" ; then
+               local native_file="${T}"/meson.${CHOST}.ini.local
+               cat >> ${native_file} <<-EOF || die
+               [binaries]
+               dtrace='stap-dtrace'
+               EOF
+               emesonargs+=( --native-file "${native_file}" )
+       fi
+
+       meson_src_configure
+}
+
+multilib_src_test() {
+       export XDG_CONFIG_DIRS=/etc/xdg
+       export XDG_DATA_DIRS=/usr/local/share:/usr/share
+       # TODO: Use ${ABI} here to be unique for multilib?
+       export G_DBUS_COOKIE_SHA1_KEYRING_DIR="${T}/temp"
+       export LC_TIME=C # bug #411967
+       export TZ=UTC
+       unset GSETTINGS_BACKEND # bug #596380
+       python_setup
+
+       # https://bugs.gentoo.org/839807
+       local -x SANDBOX_PREDICT=${SANDBOX_PREDICT}
+       addpredict /usr/b
+
+       # Related test is a bit nitpicking
+       mkdir -p "$G_DBUS_COOKIE_SHA1_KEYRING_DIR" || die
+       chmod 0700 "$G_DBUS_COOKIE_SHA1_KEYRING_DIR" || die
+
+       meson_src_test --timeout-multiplier 20 --no-suite flaky
+}
+
+multilib_src_install() {
+       meson_src_install
+       keepdir /usr/$(get_libdir)/gio/modules
+}
+
+multilib_src_install_all() {
+       strip-lto-bytecode
+
+       # These are installed by dev-util/glib-utils
+       # TODO: With patching we might be able to get rid of the python-any deps
+       # and removals, and test depend on glib-utils instead; revisit now with
+       # meson
+       rm "${ED}/usr/bin/glib-genmarshal" || die
+       rm "${ED}/usr/share/man/man1/glib-genmarshal.1" || die
+       rm "${ED}/usr/bin/glib-mkenums" || die
+       rm "${ED}/usr/share/man/man1/glib-mkenums.1" || die
+       rm "${ED}/usr/bin/gtester-report" || die
+       rm "${ED}/usr/share/man/man1/gtester-report.1" || die
+       # gdbus-codegen manpage installed by dev-util/gdbus-codegen
+       rm "${ED}/usr/share/man/man1/gdbus-codegen.1" || die
+}
+
+pkg_preinst() {
+       xdg_pkg_preinst
+
+       # Make gschemas.compiled belong to glib alone
+       local cache="/usr/share/glib-2.0/schemas/gschemas.compiled"
+
+       if [[ -e ${EROOT}${cache} ]]; then
+               cp "${EROOT}"${cache} "${ED}"/${cache} || die
+       else
+               touch "${ED}"${cache} || die
+       fi
+
+       multilib_pkg_preinst() {
+               # Make giomodule.cache belong to glib alone
+               local cache="/usr/$(get_libdir)/gio/modules/giomodule.cache"
+
+               if [[ -e ${EROOT}${cache} ]]; then
+                       cp "${EROOT}"${cache} "${ED}"${cache} || die
+               else
+                       touch "${ED}"${cache} || die
+               fi
+       }
+
+       # Don't run the cache ownership when cross-compiling, as it would end 
up with an empty cache
+       # file due to inability to create it and GIO might not look at any of 
the modules there
+       if ! tc-is-cross-compiler ; then
+               multilib_foreach_abi multilib_pkg_preinst
+       fi
+}
+
+pkg_postinst() {
+       xdg_pkg_postinst
+       # glib installs no schemas itself, but we force update for fresh 
install in case
+       # something has dropped in a schemas file without direct glib dep; and 
for upgrades
+       # in case the compiled schema format could have changed
+       gnome2_schemas_update
+
+       multilib_pkg_postinst() {
+               gnome2_giomodule_cache_update \
+                       || die "Update GIO modules cache failed (for ${ABI})"
+       }
+       if ! tc-is-cross-compiler ; then
+               multilib_foreach_abi multilib_pkg_postinst
+       else
+               ewarn "Updating of GIO modules cache skipped due to 
cross-compilation."
+               ewarn "You might want to run gio-querymodules manually on the 
target for"
+               ewarn "your final image for performance reasons and re-run it 
when packages"
+               ewarn "installing GIO modules get upgraded or added to the 
image."
+       fi
+
+       if ver_replacing "-lt" "2.63.6"; then
+               ewarn "glib no longer installs the gio-launch-desktop binary. 
You may need"
+               ewarn "to restart your session for \"Open With\" dialogs to 
work."
+       fi
+}
+
+pkg_postrm() {
+       xdg_pkg_postrm
+       gnome2_schemas_update
+
+       if [[ -z ${REPLACED_BY_VERSION} ]]; then
+               multilib_pkg_postrm() {
+                       rm -f 
"${EROOT}"/usr/$(get_libdir)/gio/modules/giomodule.cache || die
+               }
+               multilib_foreach_abi multilib_pkg_postrm
+               rm -f "${EROOT}"/usr/share/glib-2.0/schemas/gschemas.compiled 
|| die
+       fi
+}

Reply via email to