diff --git a/debian/changelog b/debian/changelog
index 982cbafac0..cb0d81fc96 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,24 @@
+glib2.0 (2.84.4-3~deb13u2) UNRELEASED; urgency=medium
+
+  * d/patches: Add patches from 2.86.3 upstream to avoid integer overflows
+    - d/p/gconvert-Error-out-if-g_escape_uri_string-would-overflow.patch,
+      d/p/fuzzing-Add-fuzz-tests-for-g_filename_-to-from-_uri.patch:
+      Fix an integer overflow when interpolating hundreds of megabytes of
+      unescaped text into a URI, and add test coverage
+      (CVE-2025-13601, glib#3827 upstream, Closes: #1121488)
+    - d/p/gvariant-parser-Fix-potential-integer-overflow-parsing-by.patch:
+      Fix an integer overflow when parsing very large strings in GVariant
+      text format (CVE-2025-14087, glib#3834 upstream, Closes: #1122347)
+    - d/p/gvariant-parser-Use-size_t-to-count-numbers-of-child-elem.patch,
+      d/p/gvariant-parser-Convert-error-handling-code-to-use-size_t.patch:
+      Fix other potential integer overflows parsing very large container
+      types in GVariant text format, related to CVE-2025-14087
+    - d/p/gfileattribute-Fix-integer-overflow-calculating-escaping-.patch:
+      Fix an integer overflow when escaping invalid characters in very
+      large file attributes (glib#3845 upstream, Closes: #1122346)
+
+ -- Simon McVittie <smcv@debian.org>  Wed, 10 Dec 2025 12:13:08 +0000
+
 glib2.0 (2.84.4-3~deb13u1) trixie; urgency=medium
 
   * Go back to debian/trixie branch for a stable update
diff --git a/debian/patches/fuzzing-Add-fuzz-tests-for-g_filename_-to-from-_uri.patch b/debian/patches/fuzzing-Add-fuzz-tests-for-g_filename_-to-from-_uri.patch
new file mode 100644
index 0000000000..7cb6e04ac9
--- /dev/null
+++ b/debian/patches/fuzzing-Add-fuzz-tests-for-g_filename_-to-from-_uri.patch
@@ -0,0 +1,122 @@
+From: Philip Withnall <pwithnall@gnome.org>
+Date: Thu, 13 Nov 2025 18:31:43 +0000
+Subject: 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 <pwithnall@gnome.org>
+Origin: upstream, 2.86.3, commit:7e5489cb921d0531ee4ebc9938da30a02084b2fa
+Bug: https://gitlab.gnome.org/GNOME/glib/-/issues/3827
+Bug-Debian: https://bugs.debian.org/1121488
+---
+ ...get_locale_variants.c => fuzz_filename_from_uri.c} | 19 +++++++------------
+ ...z_get_locale_variants.c => fuzz_filename_to_uri.c} | 19 +++++++------------
+ fuzzing/meson.build                                   |  2 ++
+ 3 files changed, 16 insertions(+), 24 deletions(-)
+ copy fuzzing/{fuzz_get_locale_variants.c => fuzz_filename_from_uri.c} (70%)
+ copy fuzzing/{fuzz_get_locale_variants.c => fuzz_filename_to_uri.c} (70%)
+
+diff --git a/fuzzing/fuzz_get_locale_variants.c b/fuzzing/fuzz_filename_from_uri.c
+similarity index 70%
+copy from fuzzing/fuzz_get_locale_variants.c
+copy to fuzzing/fuzz_filename_from_uri.c
+index 248dbbf..9b7a715 100644
+--- a/fuzzing/fuzz_get_locale_variants.c
++++ b/fuzzing/fuzz_filename_from_uri.c
+@@ -15,9 +15,6 @@
+  *
+  * 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/>.
+- *
+- * Authors:
+- *  - Philip Withnall <pwithnall@gnome.org>
+  */
+ 
+ #include "fuzz.h"
+@@ -26,20 +23,18 @@ int
+ LLVMFuzzerTestOneInput (const unsigned char *data, size_t size)
+ {
+   unsigned char *nul_terminated_data = NULL;
+-  char **v;
++  char *filename = NULL;
++  GError *local_error = NULL;
+ 
+   fuzz_set_logging_func ();
+ 
+-  /* ignore @size (g_get_locale_variants() doesn’t support it); ensure @data is nul-terminated */
++  /* 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);
+-
+-  v = g_get_locale_variants ((char *) nul_terminated_data);
+-  g_assert_nonnull (v);
+-  /* g_get_locale_variants() guarantees that the input is always in the output: */
+-  g_assert_true (g_strv_contains ((const char * const *) v, (char *) nul_terminated_data));
+-  g_strfreev (v);
+-
++  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_get_locale_variants.c b/fuzzing/fuzz_filename_to_uri.c
+similarity index 70%
+copy from fuzzing/fuzz_get_locale_variants.c
+copy to fuzzing/fuzz_filename_to_uri.c
+index 248dbbf..acb3192 100644
+--- a/fuzzing/fuzz_get_locale_variants.c
++++ b/fuzzing/fuzz_filename_to_uri.c
+@@ -15,9 +15,6 @@
+  *
+  * 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/>.
+- *
+- * Authors:
+- *  - Philip Withnall <pwithnall@gnome.org>
+  */
+ 
+ #include "fuzz.h"
+@@ -26,20 +23,18 @@ int
+ LLVMFuzzerTestOneInput (const unsigned char *data, size_t size)
+ {
+   unsigned char *nul_terminated_data = NULL;
+-  char **v;
++  char *uri = NULL;
++  GError *local_error = NULL;
+ 
+   fuzz_set_logging_func ();
+ 
+-  /* ignore @size (g_get_locale_variants() doesn’t support it); ensure @data is nul-terminated */
++  /* 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);
+-
+-  v = g_get_locale_variants ((char *) nul_terminated_data);
+-  g_assert_nonnull (v);
+-  /* g_get_locale_variants() guarantees that the input is always in the output: */
+-  g_assert_true (g_strv_contains ((const char * const *) v, (char *) nul_terminated_data));
+-  g_strfreev (v);
+-
++  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 d3107a1..accff0a 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',
diff --git a/debian/patches/gconvert-Error-out-if-g_escape_uri_string-would-overflow.patch b/debian/patches/gconvert-Error-out-if-g_escape_uri_string-would-overflow.patch
new file mode 100644
index 0000000000..73cdcdfd72
--- /dev/null
+++ b/debian/patches/gconvert-Error-out-if-g_escape_uri_string-would-overflow.patch
@@ -0,0 +1,131 @@
+From: Philip Withnall <pwithnall@gnome.org>
+Date: Thu, 13 Nov 2025 18:27:22 +0000
+Subject: 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 <pwithnall@gnome.org>
+
+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.
+
+Origin: upstream, 2.86.3, commit:9bcd65ba5fa1b92ff0fb8380faea335ccef56253
+Bug: https://gitlab.gnome.org/GNOME/glib/-/issues/3827
+Bug-CVE: CVE-2025-13601
+Bug-Debian: https://bugs.debian.org/1121488
+---
+ glib/gconvert.c | 36 +++++++++++++++++++++++++-----------
+ 1 file changed, 25 insertions(+), 11 deletions(-)
+
+diff --git a/glib/gconvert.c b/glib/gconvert.c
+index c6a2441..7a23d7d 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;
+ }
diff --git a/debian/patches/gfileattribute-Fix-integer-overflow-calculating-escaping-.patch b/debian/patches/gfileattribute-Fix-integer-overflow-calculating-escaping-.patch
new file mode 100644
index 0000000000..d90bf1c6df
--- /dev/null
+++ b/debian/patches/gfileattribute-Fix-integer-overflow-calculating-escaping-.patch
@@ -0,0 +1,67 @@
+From: Philip Withnall <pwithnall@gnome.org>
+Date: Thu, 4 Dec 2025 16:37:19 +0000
+Subject: 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 <pwithnall@gnome.org>
+
+Origin: upstream, 2.86.3, commit:4f0399c0aaf3ffc86b5625424580294bc7460404
+Bug: https://gitlab.gnome.org/GNOME/glib/-/issues/3845
+Bug-Debian: https://bugs.debian.org/1122346
+---
+ gio/gfileattribute.c | 11 +++++++++--
+ 1 file changed, 9 insertions(+), 2 deletions(-)
+
+diff --git a/gio/gfileattribute.c b/gio/gfileattribute.c
+index c6fde60..d3083e5 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++)
diff --git a/debian/patches/gfileutils-Preserve-mode-during-atomic-updates.patch b/debian/patches/gfileutils-Preserve-mode-during-atomic-updates.patch
index 5d0771924c..ba158cfd97 100644
--- a/debian/patches/gfileutils-Preserve-mode-during-atomic-updates.patch
+++ b/debian/patches/gfileutils-Preserve-mode-during-atomic-updates.patch
@@ -23,7 +23,7 @@ Comment: This was actually reverted from the glib-2-84 branch but
  2 files changed, 33 insertions(+), 6 deletions(-)
 
 diff --git a/glib/gfileutils.c b/glib/gfileutils.c
-index bc4bcf1..1768358 100644
+index 9930030..62928fd 100644
 --- a/glib/gfileutils.c
 +++ b/glib/gfileutils.c
 @@ -1318,8 +1318,8 @@ g_file_set_contents (const gchar  *filename,
diff --git a/debian/patches/gvariant-parser-Convert-error-handling-code-to-use-size_t.patch b/debian/patches/gvariant-parser-Convert-error-handling-code-to-use-size_t.patch
new file mode 100644
index 0000000000..2701039ffb
--- /dev/null
+++ b/debian/patches/gvariant-parser-Convert-error-handling-code-to-use-size_t.patch
@@ -0,0 +1,148 @@
+From: Philip Withnall <pwithnall@gnome.org>
+Date: Tue, 25 Nov 2025 19:25:58 +0000
+Subject: 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 <pwithnall@gnome.org>
+Origin: upstream, 2.86.3, commit:dd333a40aa95819720a01caf6de564cd8a4a6310
+Bug: https://gitlab.gnome.org/GNOME/glib/-/issues/3834
+Bug-Debian: https://bugs.debian.org/1122347
+---
+ 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 519baa3..1b1ddd6 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))
diff --git a/debian/patches/gvariant-parser-Fix-potential-integer-overflow-parsing-by.patch b/debian/patches/gvariant-parser-Fix-potential-integer-overflow-parsing-by.patch
new file mode 100644
index 0000000000..c34b4ed5a3
--- /dev/null
+++ b/debian/patches/gvariant-parser-Fix-potential-integer-overflow-parsing-by.patch
@@ -0,0 +1,67 @@
+From: Philip Withnall <pwithnall@gnome.org>
+Date: Tue, 25 Nov 2025 19:02:56 +0000
+Subject: 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 <pwithnall@gnome.org>
+Origin: upstream, 2.86.3, commit:3e72fe0fbb32c18a66486c4da8bc851f656af287
+Bug: https://gitlab.gnome.org/GNOME/glib/-/issues/3834
+Bug-CVE: CVE-2025-14087
+Bug-Debian: https://bugs.debian.org/1122347
+---
+ 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 2f1d3db..2d6e985 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);
diff --git a/debian/patches/gvariant-parser-Use-size_t-to-count-numbers-of-child-elem.patch b/debian/patches/gvariant-parser-Use-size_t-to-count-numbers-of-child-elem.patch
new file mode 100644
index 0000000000..cab75cc353
--- /dev/null
+++ b/debian/patches/gvariant-parser-Use-size_t-to-count-numbers-of-child-elem.patch
@@ -0,0 +1,237 @@
+From: Philip Withnall <pwithnall@gnome.org>
+Date: Tue, 25 Nov 2025 19:19:16 +0000
+Subject: 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 <pwithnall@gnome.org>
+Origin: upstream, 2.86.3, commit:6fe481cec709ec65b5846113848723bc25a8782a
+Bug: https://gitlab.gnome.org/GNOME/glib/-/issues/3834
+Bug-Debian: https://bugs.debian.org/1122347
+---
+ 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 2d6e985..519baa3 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;
diff --git a/debian/patches/series b/debian/patches/series
index b289a11790..1efc465162 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -15,3 +15,9 @@ workarounds/tests-Skip-debugcontroller-test.patch
 workarounds/testfilemonitor-Skip-if-we-are-avoiding-flaky-tests.patch
 debian/girepository-Describe-the-Debian-specific-cross-prefixed-.patch
 gfileutils-Preserve-mode-during-atomic-updates.patch
+gconvert-Error-out-if-g_escape_uri_string-would-overflow.patch
+fuzzing-Add-fuzz-tests-for-g_filename_-to-from-_uri.patch
+gvariant-parser-Fix-potential-integer-overflow-parsing-by.patch
+gvariant-parser-Use-size_t-to-count-numbers-of-child-elem.patch
+gvariant-parser-Convert-error-handling-code-to-use-size_t.patch
+gfileattribute-Fix-integer-overflow-calculating-escaping-.patch
