diffstat for glib2.0-2.74.6 glib2.0-2.74.6

 debian/changelog                                                             |   40 ++
 debian/libglib2.0-0.postrm.in                                                |   89 +++++-
 debian/patches/gfileutils-fix-computation-of-temporary-file-name.patch       |   42 +++
 debian/patches/glib-gfileutils.c-use-64-bits-for-value-in-get_tmp_file.patch |   40 ++
 debian/patches/gstring-Make-len_unsigned-unsigned.patch                      |   25 +
 debian/patches/gstring-carefully-handle-gssize-parameters.patch              |  119 ++++++++
 debian/patches/series                                                        |    4 
 debian/tests/1065022-futureproofing                                          |  137 ++++++++++
 debian/tests/control                                                         |    4 
 glib/gfileutils.c                                                            |    8 
 glib/gstring.c                                                               |   36 +-
 11 files changed, 515 insertions(+), 29 deletions(-)

diff -Nru glib2.0-2.74.6/debian/changelog glib2.0-2.74.6/debian/changelog
--- glib2.0-2.74.6/debian/changelog	2025-04-12 14:52:16.000000000 +0100
+++ glib2.0-2.74.6/debian/changelog	2025-08-18 09:27:51.000000000 +0100
@@ -1,3 +1,43 @@
+glib2.0 (2.74.6-2+deb12u7) bookworm; urgency=medium
+
+  * d/p/gstring-carefully-handle-gssize-parameters.patch,
+    d/p/gstring-Make-len_unsigned-unsigned.patch:
+    Add patches from upstream to fix a buffer underflow in GString.
+    This could cause a memory overwrite if a program handles extremely large
+    text strings of an attacker-controlled length. The required string length
+    would be close to 2 GiB on 32-bit and the bug is not believed to be
+    practically feasible to exploit on 64-bit. (CVE-2025-4373)
+    (Closes: #1104930)
+  * d/p/glib-gfileutils.c-use-64-bits-for-value-in-get_tmp_file.patch,
+    d/p/gfileutils-fix-computation-of-temporary-file-name.patch:
+    Add patches from upstream to fix a buffer underflow in get_tmp_file().
+    This is used in g_mkstemp(), g_mkdtemp() and similar functions, and
+    could cause a crash or possibly arbitrary file overwrites (believed to
+    be unlikely to be exploitable in practice) if a long-running program
+    creates more than 2 billion temporary files. (CVE-2025-7039)
+    (Closes: #1110640)
+  * d/libglib2.0-0.postrm.in:
+    Rewrite postrm for safer upgrade behaviour, based on the version
+    in unstable and proposed for inclusion in trixie:
+    - Only remove giomodule.cache during purge, not during remove.
+      This matches the behaviour of gschemas.compiled and avoids a window
+      between old-postrm and new-postinst during which giomodule.cache is
+      missing, breaking applications that need GIO modules.
+    - Don't remove gschemas.compiled or giomodule.cache during purge
+      if there is evidence that they might still be needed
+      (Closes: #1065022, #1110696):
+      + don't remove them if ${libdir}/glib-2.0 still exists, for example
+        provided by libglib2.0-0t64 after upgrading to trixie;
+      + don't remove gschemas.compiled if at least one GSettings schema
+        still exists;
+      + don't remove giomodule.cache if at least one GIO module still exists
+    - Refactoring to support the above
+  * d/tests/1065022-futureproofing:
+    Add a test for #1065022, modified from the version in unstable and
+    proposed for inclusion in trixie
+
+ -- Simon McVittie <smcv@debian.org>  Mon, 18 Aug 2025 09:27:51 +0100
+
 glib2.0 (2.74.6-2+deb12u6) bookworm; urgency=medium
 
   * Non-maintainer upload.
diff -Nru glib2.0-2.74.6/debian/libglib2.0-0.postrm.in glib2.0-2.74.6/debian/libglib2.0-0.postrm.in
--- glib2.0-2.74.6/debian/libglib2.0-0.postrm.in	2024-11-14 09:42:34.000000000 +0000
+++ glib2.0-2.74.6/debian/libglib2.0-0.postrm.in	2025-08-18 09:27:51.000000000 +0100
@@ -1,21 +1,86 @@
 #! /bin/sh
+# Debian Policy §10.4 says /bin/sh has a superset of POSIX functionality
+# shellcheck disable=SC3043
+
 set -e
 
 #DEBHELPER#
 
-case "$1" in
-    (remove|purge)
-        if [ -d /usr/lib/#MULTIARCH#/gio/modules ]; then
-            # Purge the cache
-            rm -f /usr/lib/#MULTIARCH#/gio/modules/giomodule.cache
-            rmdir -p --ignore-fail-on-non-empty /usr/lib/#MULTIARCH#/gio/modules
+clean_up_giomodule_cache ()
+{
+    local multiarch="#MULTIARCH#"
+    local modules="/usr/lib/${multiarch}/gio/modules"
+    local iter
+
+    if ! [ -d "$modules" ]; then
+        return 0
+    fi
+
+    # Don't remove giomodule.cache if libglib2.0-0 is replaced
+    # by some other ABI variant of essentially the same library
+    # (for example libglib2.0-0t64 in trixie), to avoid causing
+    # <https://bugs.debian.org/1065022>.
+    #
+    # This implementation is based on the assumption that any GLib
+    # version that still uses ${libdir}/gio/modules/giomodule.cache
+    # will also continue to ship ${libdir}/glib-2.0.
+    if [ -d "/usr/lib/${multiarch}/glib-2.0" ]; then
+        return 0
+    fi
+
+    # As an additional safety-catch, don't remove giomodule.cache if
+    # there is at least one module that should have been listed in it.
+    for iter in "$modules"/*.so; do
+        if [ -e "$iter" ]; then
+            echo "$0: not removing $modules/giomodule.cache because $iter still exists" >&2
+            return 0
         fi
+    done
+
+    rm -f "$modules/giomodule.cache"
+    rmdir -p --ignore-fail-on-non-empty "$modules"
+}
+
+clean_up_gsettings_schemas ()
+{
+    local schemas="/usr/share/glib-2.0/schemas"
+    local iter
+
+    if ! [ -d "$schemas" ]; then
+        return 0
+    fi
+
+    # Similarly, instead of using $DPKG_MAINTSCRIPT_PACKAGE_REFCOUNT, only
+    # remove gschemas.compiled if GLib has completely gone away - not just
+    # libglib2.0-0, but any future ABI variant like libglib2.0-0t64.
+    #
+    # This implementation is based on the assumption that any GLib
+    # version that still uses ${datadir}/glib-2.0/schemas
+    # will also continue to ship ${libdir}/glib-2.0.
+    for iter in /usr/lib/*/glib-2.0; do
+        if [ -e "$iter" ]; then
+            return 0
+        fi
+    done
+
+    # As an additional safety-catch, don't remove gschemas.compiled if
+    # there is at least one schema that should have been listed in it.
+    for iter in "$schemas"/*.xml; do
+        if [ -e "$iter" ]; then
+            echo "$0: not removing $schemas/gschemas.compiled because $iter still exists" >&2
+            return 0
+        fi
+    done
+
+    rm -f "$schemas/gschemas.compiled"
+    rmdir -p --ignore-fail-on-non-empty "$schemas"
+}
+
+case "$1" in
+    (purge)
+        clean_up_giomodule_cache
+        clean_up_gsettings_schemas
         ;;
 esac
 
-if [ "$1" = purge ] && [ -d /usr/share/glib-2.0/schemas ] && [ "$DPKG_MAINTSCRIPT_PACKAGE_REFCOUNT" = 1 ]; then
-    # This is the last multiarch variant to be removed, so drop the
-    # architecture-independent compiled schemas
-    rm -f /usr/share/glib-2.0/schemas/gschemas.compiled
-    rmdir -p --ignore-fail-on-non-empty /usr/share/glib-2.0/schemas
-fi
+# vim:set sw=4 sts=4 et:
diff -Nru glib2.0-2.74.6/debian/patches/gfileutils-fix-computation-of-temporary-file-name.patch glib2.0-2.74.6/debian/patches/gfileutils-fix-computation-of-temporary-file-name.patch
--- glib2.0-2.74.6/debian/patches/gfileutils-fix-computation-of-temporary-file-name.patch	1970-01-01 01:00:00.000000000 +0100
+++ glib2.0-2.74.6/debian/patches/gfileutils-fix-computation-of-temporary-file-name.patch	2025-08-18 09:27:51.000000000 +0100
@@ -0,0 +1,42 @@
+From: Michael Catanzaro <mcatanzaro@redhat.com>
+Date: Tue, 1 Jul 2025 10:58:07 -0500
+Subject: gfileutils: fix computation of temporary file name
+
+We need to ensure that the value we use to index into the letters array
+is always positive.
+
+Origin: upstream, 2.84.4, commit:8f4da99bf2f112b8e4329d8c44b6ab5dea467cb1
+Origin: upstream, 2.85.2, commit:61e963284889ddb4544e6f1d5261c16120f6fcc3
+Bug: https://gitlab.gnome.org/GNOME/glib/-/issues/3716
+Bug-CVE: CVE-2025-7039
+Bug-Debian: https://bugs.debian.org/1110640
+---
+ glib/gfileutils.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/glib/gfileutils.c b/glib/gfileutils.c
+index 22c04e1..28b424a 100644
+--- a/glib/gfileutils.c
++++ b/glib/gfileutils.c
+@@ -1483,9 +1483,9 @@ get_tmp_file (gchar            *tmpl,
+   static const char letters[] =
+     "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+   static const int NLETTERS = sizeof (letters) - 1;
+-  gint64 value;
+-  gint64 now_us;
+-  static int counter = 0;
++  guint64 value;
++  guint64 now_us;
++  static guint counter = 0;
+ 
+   g_return_val_if_fail (tmpl != NULL, -1);
+ 
+@@ -1504,7 +1504,7 @@ get_tmp_file (gchar            *tmpl,
+ 
+   for (count = 0; count < 100; value += 7777, ++count)
+     {
+-      gint64 v = value;
++      guint64 v = value;
+ 
+       /* Fill in the random bits.  */
+       XXXXXX[0] = letters[v % NLETTERS];
diff -Nru glib2.0-2.74.6/debian/patches/glib-gfileutils.c-use-64-bits-for-value-in-get_tmp_file.patch glib2.0-2.74.6/debian/patches/glib-gfileutils.c-use-64-bits-for-value-in-get_tmp_file.patch
--- glib2.0-2.74.6/debian/patches/glib-gfileutils.c-use-64-bits-for-value-in-get_tmp_file.patch	1970-01-01 01:00:00.000000000 +0100
+++ glib2.0-2.74.6/debian/patches/glib-gfileutils.c-use-64-bits-for-value-in-get_tmp_file.patch	2025-08-18 09:27:51.000000000 +0100
@@ -0,0 +1,40 @@
+From: Alexander Kanavin <alex@linutronix.de>
+Date: Tue, 22 Aug 2023 19:57:48 +0200
+Subject: glib/gfileutils.c: use 64 bits for value in get_tmp_file()
+
+On 32 bit systems 'long' value will overflow in 2038 and become negative.
+As it is used to index into letters array, and % operation preserves signs,
+data corruption will then occur.
+
+[This change makes the patch for CVE-2025-7039 apply cleanly -smcv]
+
+Signed-off-by: Alexander Kanavin <alex@linutronix.de>
+Origin: upstream, 2.77.3, commit:285db475ecaa4d2cc39ce326b4c63aacb87ca6ad
+Origin: upstream, 2.76.5, commit:b4d60ba1367f15843577d4363b32fb16847b9582
+Bug-CVE: CVE-2025-7039
+---
+ glib/gfileutils.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/glib/gfileutils.c b/glib/gfileutils.c
+index 722575e..22c04e1 100644
+--- a/glib/gfileutils.c
++++ b/glib/gfileutils.c
+@@ -1483,7 +1483,7 @@ get_tmp_file (gchar            *tmpl,
+   static const char letters[] =
+     "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+   static const int NLETTERS = sizeof (letters) - 1;
+-  glong value;
++  gint64 value;
+   gint64 now_us;
+   static int counter = 0;
+ 
+@@ -1504,7 +1504,7 @@ get_tmp_file (gchar            *tmpl,
+ 
+   for (count = 0; count < 100; value += 7777, ++count)
+     {
+-      glong v = value;
++      gint64 v = value;
+ 
+       /* Fill in the random bits.  */
+       XXXXXX[0] = letters[v % NLETTERS];
diff -Nru glib2.0-2.74.6/debian/patches/gstring-carefully-handle-gssize-parameters.patch glib2.0-2.74.6/debian/patches/gstring-carefully-handle-gssize-parameters.patch
--- glib2.0-2.74.6/debian/patches/gstring-carefully-handle-gssize-parameters.patch	1970-01-01 01:00:00.000000000 +0100
+++ glib2.0-2.74.6/debian/patches/gstring-carefully-handle-gssize-parameters.patch	2025-08-18 09:27:51.000000000 +0100
@@ -0,0 +1,119 @@
+From: Michael Catanzaro <mcatanzaro@redhat.com>
+Date: Mon, 28 Apr 2025 16:03:08 +0000
+Subject: gstring: carefully handle gssize parameters
+
+Wherever we use gssize to allow passing -1, we need to ensure we don't
+overflow the value by assigning a gsize to it without checking if the
+size exceeds the maximum gssize. The safest way to do this is to just
+use normal gsize everywhere instead and use gssize only for the
+parameter.
+
+Our computers don't have enough RAM to write tests for this. I tried
+forcing string->len to high values for test purposes, but this isn't
+valid and will just cause out of bounds reads/writes due to
+string->allocated_len being unexpectedly small, so I don't think we can
+test this easily.
+
+(cherry picked from commit cc647f9e46d55509a93498af19659baf9c80f2e3)
+
+Co-authored-by: Michael Catanzaro <mcatanzaro@redhat.com>
+Bug: https://gitlab.gnome.org/GNOME/glib/-/issues/3677
+Bug-CVE: CVE-2025-4373
+Bug-Debian: https://bugs.debian.org/1104930
+Origin: upstream, 2.84.2, commit:a47dc889463d73dd47ad428ac217e3d84f28e242
+---
+ glib/gstring.c | 36 +++++++++++++++++++++++-------------
+ 1 file changed, 23 insertions(+), 13 deletions(-)
+
+diff --git a/glib/gstring.c b/glib/gstring.c
+index 6abb70b..1a79759 100644
+--- a/glib/gstring.c
++++ b/glib/gstring.c
+@@ -426,8 +426,9 @@ g_string_insert_len (GString     *string,
+     return string;
+ 
+   if (len < 0)
+-    len = strlen (val);
+-  len_unsigned = len;
++    len_unsigned = strlen (val);
++  else
++    len_unsigned = len;
+ 
+   if (pos < 0)
+     pos_unsigned = string->len;
+@@ -725,10 +726,12 @@ g_string_insert_c (GString *string,
+   g_string_maybe_expand (string, 1);
+ 
+   if (pos < 0)
+-    pos = string->len;
++    pos_unsigned = string->len;
+   else
+-    g_return_val_if_fail ((gsize) pos <= string->len, string);
+-  pos_unsigned = pos;
++    {
++      pos_unsigned = pos;
++      g_return_val_if_fail (pos_unsigned <= string->len, string);
++    }
+ 
+   /* If not just an append, move the old stuff */
+   if (pos_unsigned < string->len)
+@@ -761,6 +764,7 @@ g_string_insert_unichar (GString  *string,
+                          gssize    pos,
+                          gunichar  wc)
+ {
++  gsize pos_unsigned;
+   gint charlen, first, i;
+   gchar *dest;
+ 
+@@ -802,15 +806,18 @@ g_string_insert_unichar (GString  *string,
+   g_string_maybe_expand (string, charlen);
+ 
+   if (pos < 0)
+-    pos = string->len;
++    pos_unsigned = string->len;
+   else
+-    g_return_val_if_fail ((gsize) pos <= string->len, string);
++    {
++      pos_unsigned = pos;
++      g_return_val_if_fail (pos_unsigned <= string->len, string);
++    }
+ 
+   /* If not just an append, move the old stuff */
+-  if ((gsize) pos < string->len)
+-    memmove (string->str + pos + charlen, string->str + pos, string->len - pos);
++  if (pos_unsigned < string->len)
++    memmove (string->str + pos_unsigned + charlen, string->str + pos_unsigned, string->len - pos_unsigned);
+ 
+-  dest = string->str + pos;
++  dest = string->str + pos_unsigned;
+   /* Code copied from g_unichar_to_utf() */
+   for (i = charlen - 1; i > 0; --i)
+     {
+@@ -868,6 +875,7 @@ g_string_overwrite_len (GString     *string,
+                         const gchar *val,
+                         gssize       len)
+ {
++  gssize len_unsigned;
+   gsize end;
+ 
+   g_return_val_if_fail (string != NULL, NULL);
+@@ -879,14 +887,16 @@ g_string_overwrite_len (GString     *string,
+   g_return_val_if_fail (pos <= string->len, string);
+ 
+   if (len < 0)
+-    len = strlen (val);
++    len_unsigned = strlen (val);
++  else
++    len_unsigned = len;
+ 
+-  end = pos + len;
++  end = pos + len_unsigned;
+ 
+   if (end > string->len)
+     g_string_maybe_expand (string, end - string->len);
+ 
+-  memcpy (string->str + pos, val, len);
++  memcpy (string->str + pos, val, len_unsigned);
+ 
+   if (end > string->len)
+     {
diff -Nru glib2.0-2.74.6/debian/patches/gstring-Make-len_unsigned-unsigned.patch glib2.0-2.74.6/debian/patches/gstring-Make-len_unsigned-unsigned.patch
--- glib2.0-2.74.6/debian/patches/gstring-Make-len_unsigned-unsigned.patch	1970-01-01 01:00:00.000000000 +0100
+++ glib2.0-2.74.6/debian/patches/gstring-Make-len_unsigned-unsigned.patch	2025-08-18 09:27:51.000000000 +0100
@@ -0,0 +1,25 @@
+From: Peter Bloomfield <peterbloomfield@bellsouth.net>
+Date: Fri, 11 Apr 2025 05:52:33 +0000
+Subject: gstring: Make len_unsigned unsigned
+
+Bug: https://gitlab.gnome.org/GNOME/glib/-/issues/3677
+Bug-CVE: CVE-2025-4373
+Bug-Debian: https://bugs.debian.org/1104930
+Origin: upstream, 2.84.2, commit:f32f4aea514e39086a2627e9483d841c9eeb9bc3
+---
+ glib/gstring.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/glib/gstring.c b/glib/gstring.c
+index 1a79759..4cba302 100644
+--- a/glib/gstring.c
++++ b/glib/gstring.c
+@@ -875,7 +875,7 @@ g_string_overwrite_len (GString     *string,
+                         const gchar *val,
+                         gssize       len)
+ {
+-  gssize len_unsigned;
++  gsize len_unsigned;
+   gsize end;
+ 
+   g_return_val_if_fail (string != NULL, NULL);
diff -Nru glib2.0-2.74.6/debian/patches/series glib2.0-2.74.6/debian/patches/series
--- glib2.0-2.74.6/debian/patches/series	2025-04-12 14:52:16.000000000 +0100
+++ glib2.0-2.74.6/debian/patches/series	2025-08-18 09:27:51.000000000 +0100
@@ -49,3 +49,7 @@
 0003-gdatetime-Track-timezone-length-as-an-unsigned-size_.patch
 0004-gdatetime-Factor-out-some-string-pointer-arithmetic.patch
 0005-gdatetime-Factor-out-an-undersized-variable.patch
+gstring-carefully-handle-gssize-parameters.patch
+gstring-Make-len_unsigned-unsigned.patch
+glib-gfileutils.c-use-64-bits-for-value-in-get_tmp_file.patch
+gfileutils-fix-computation-of-temporary-file-name.patch
diff -Nru glib2.0-2.74.6/debian/tests/1065022-futureproofing glib2.0-2.74.6/debian/tests/1065022-futureproofing
--- glib2.0-2.74.6/debian/tests/1065022-futureproofing	1970-01-01 01:00:00.000000000 +0100
+++ glib2.0-2.74.6/debian/tests/1065022-futureproofing	2025-08-18 09:27:51.000000000 +0100
@@ -0,0 +1,137 @@
+#!/bin/sh
+# Copyright 2024 Simon McVittie
+# SPDX-License-Identifier: LGPL-2.1-or-later
+
+# Ensure that if the content of libglib2.0-0 is taken over by some
+# other package like libglib2.0-0t64 (in this test it is named
+# libglib2.0-0xyz), then that other package will not trigger
+# #1065022.
+
+set -eux
+
+export DEBIAN_FRONTEND=noninteractive
+n=0
+failed=0
+binary_package="libglib2.0-0"
+future_binary_package="libglib2.0-0xyz"
+srcdir="$(pwd)"
+tmpdir="$(mktemp -d)"
+cd "$tmpdir"
+
+# Machine-readable TAP on fd 3, human-readable diagnostics on fds 1 and 2
+exec 3>&1 >&2
+
+assert () {
+    n=$(( n + 1 ))
+
+    if "$@"; then
+        echo "ok $n - $*" >&3
+    else
+        echo "not ok $n - $* exit status $?" >&3
+        failed=1
+    fi
+}
+
+assert_not () {
+    n=$(( n + 1 ))
+
+    if ! "$@"; then
+        echo "ok $n - unsuccessful as expected: $*" >&3
+    else
+        echo "not ok $n - should not have succeeded: $*" >&3
+        failed=1
+    fi
+}
+
+# Add a deb822-formatted apt source at this location if you are testing a
+# locally-built glib2.0 before upload
+if [ -e "$srcdir/debian/tests/manual/local-1065022.sources" ]; then
+    install -m644 -t /etc/apt/sources.list.d/ -D \
+        "$srcdir/debian/tests/manual/local-1065022.sources"
+fi
+
+# For more convenient manual testing
+if ! dpkg-query -W dpkg-repack; then
+    apt-get -y update
+    apt-get -y install "$binary_package"
+    apt-get -y install dconf-gsettings-backend dpkg-repack gsettings-desktop-schemas
+fi
+
+# This assumes that libglib2.0-0 has at least one Breaks but no Provides
+# or Replaces, and will need to be adjusted if that assumption is broken in
+# the future for whatever reason.
+dpkg-query -s "$binary_package"
+# The $ substitution is to be expanded by dpkg-query:
+# shellcheck disable=SC2016
+binary_version="$(dpkg-query -W -f '${Version}' "$binary_package")"
+dpkg-repack --generate "$binary_package"
+assert grep -q '^Breaks:' dpkg-repack.*/DEBIAN/control
+assert_not grep -q '^Provides:' dpkg-repack.*/DEBIAN/control
+assert_not grep -q '^Replaces:' dpkg-repack.*/DEBIAN/control
+# The $ substitutions in the Perl expressions are to be expanded by Perl,
+# not by the shell, so:
+# shellcheck disable=SC2016
+env \
+    binary_package="$binary_package" \
+    binary_version="$binary_version" \
+    future_binary_package="$future_binary_package" \
+    perl -p -i \
+        -e 's/^Package:.*$/Package: $ENV{future_binary_package}/;' \
+        -e 's/^(Breaks:.*)$/$1, $ENV{binary_package}/;' \
+        dpkg-repack.*/DEBIAN/control
+echo "Replaces: ${binary_package}" | tee -a dpkg-repack.*/DEBIAN/control
+echo "Provides: ${binary_package} (= ${binary_version})" | tee -a dpkg-repack.*/DEBIAN/control
+dpkg-deb --build dpkg-repack.* "$future_binary_package.deb"
+dpkg-deb --info "$future_binary_package.deb"
+dpkg-deb --contents "$future_binary_package.deb"
+apt-get -y install ./"$future_binary_package.deb" dconf-gsettings-backend gsettings-desktop-schemas
+
+assert test -e /usr/share/glib-2.0/schemas/org.gnome.desktop.interface.gschema.xml
+assert test -s /usr/share/glib-2.0/schemas/gschemas.compiled
+
+for f in /usr/lib/*/gio/modules/libdconfsettings.so; do
+    assert test -e "$f"
+    assert test -s "$f"
+done
+
+for f in /usr/lib/*/gio/modules/giomodule.cache; do
+    assert test -e "$f"
+    assert test -s "$f"
+done
+
+# Purging the "old" (pre-transition) binary package does not destroy the
+# GIO modules and GSettings schema summaries
+apt-get -y purge "$binary_package"
+
+assert test -e /usr/share/glib-2.0/schemas/org.gnome.desktop.interface.gschema.xml
+assert test -s /usr/share/glib-2.0/schemas/gschemas.compiled
+
+for f in /usr/lib/*/gio/modules/libdconfsettings.so; do
+    assert test -e "$f"
+    assert test -s "$f"
+done
+
+for f in /usr/lib/*/gio/modules/giomodule.cache; do
+    assert test -e "$f"
+    assert test -s "$f"
+done
+
+# Purging the "new" (post-transition) binary package still *does* destroy the
+# GIO modules and GSettings schema summaries
+apt-get -y purge "$future_binary_package"
+
+assert_not test -e /usr/share/glib-2.0/schemas/org.gnome.desktop.interface.gschema.xml
+assert_not test -e /usr/share/glib-2.0/schemas/gschemas.compiled
+
+for f in /usr/lib/*/gio/modules/libdconfsettings.so; do
+    assert_not test -e "$f"
+done
+
+for f in /usr/lib/*/gio/modules/giomodule.cache; do
+    assert_not test -e "$f"
+done
+
+echo "1..$n" >&3
+exit "$failed"
+
+# vim:set sw=4 sts=4 et:
diff -Nru glib2.0-2.74.6/debian/tests/control glib2.0-2.74.6/debian/tests/control
--- glib2.0-2.74.6/debian/tests/control	2024-11-14 09:42:34.000000000 +0000
+++ glib2.0-2.74.6/debian/tests/control	2025-08-18 09:27:51.000000000 +0100
@@ -9,3 +9,7 @@
 Tests: closure-refcount debugcontroller gdbus-server-auth gdbus-threading gmenumodel mainloop memory-monitor-dbus socket testfilemonitor threadtests timeout timer
 Depends: dbus-daemon (>= 1.8), dbus-x11, gnome-desktop-testing, libglib2.0-tests, locales | locales-all, xauth, xvfb
 Restrictions: allow-stderr flaky
+
+Tests: 1065022-futureproofing
+Depends: dconf-gsettings-backend, dpkg-repack, gsettings-desktop-schemas, libglib2.0-0
+Restrictions: allow-stderr breaks-testbed flaky needs-root
diff -Nru glib2.0-2.74.6/glib/gfileutils.c glib2.0-2.74.6/glib/gfileutils.c
--- glib2.0-2.74.6/glib/gfileutils.c	2023-02-23 13:54:27.000000000 +0000
+++ glib2.0-2.74.6/glib/gfileutils.c	2025-08-18 10:52:22.000000000 +0100
@@ -1483,9 +1483,9 @@
   static const char letters[] =
     "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
   static const int NLETTERS = sizeof (letters) - 1;
-  glong value;
-  gint64 now_us;
-  static int counter = 0;
+  guint64 value;
+  guint64 now_us;
+  static guint counter = 0;
 
   g_return_val_if_fail (tmpl != NULL, -1);
 
@@ -1504,7 +1504,7 @@
 
   for (count = 0; count < 100; value += 7777, ++count)
     {
-      glong v = value;
+      guint64 v = value;
 
       /* Fill in the random bits.  */
       XXXXXX[0] = letters[v % NLETTERS];
diff -Nru glib2.0-2.74.6/glib/gstring.c glib2.0-2.74.6/glib/gstring.c
--- glib2.0-2.74.6/glib/gstring.c	2023-02-23 13:54:27.000000000 +0000
+++ glib2.0-2.74.6/glib/gstring.c	2025-08-18 10:52:22.000000000 +0100
@@ -426,8 +426,9 @@
     return string;
 
   if (len < 0)
-    len = strlen (val);
-  len_unsigned = len;
+    len_unsigned = strlen (val);
+  else
+    len_unsigned = len;
 
   if (pos < 0)
     pos_unsigned = string->len;
@@ -725,10 +726,12 @@
   g_string_maybe_expand (string, 1);
 
   if (pos < 0)
-    pos = string->len;
+    pos_unsigned = string->len;
   else
-    g_return_val_if_fail ((gsize) pos <= string->len, string);
-  pos_unsigned = pos;
+    {
+      pos_unsigned = pos;
+      g_return_val_if_fail (pos_unsigned <= string->len, string);
+    }
 
   /* If not just an append, move the old stuff */
   if (pos_unsigned < string->len)
@@ -761,6 +764,7 @@
                          gssize    pos,
                          gunichar  wc)
 {
+  gsize pos_unsigned;
   gint charlen, first, i;
   gchar *dest;
 
@@ -802,15 +806,18 @@
   g_string_maybe_expand (string, charlen);
 
   if (pos < 0)
-    pos = string->len;
+    pos_unsigned = string->len;
   else
-    g_return_val_if_fail ((gsize) pos <= string->len, string);
+    {
+      pos_unsigned = pos;
+      g_return_val_if_fail (pos_unsigned <= string->len, string);
+    }
 
   /* If not just an append, move the old stuff */
-  if ((gsize) pos < string->len)
-    memmove (string->str + pos + charlen, string->str + pos, string->len - pos);
+  if (pos_unsigned < string->len)
+    memmove (string->str + pos_unsigned + charlen, string->str + pos_unsigned, string->len - pos_unsigned);
 
-  dest = string->str + pos;
+  dest = string->str + pos_unsigned;
   /* Code copied from g_unichar_to_utf() */
   for (i = charlen - 1; i > 0; --i)
     {
@@ -868,6 +875,7 @@
                         const gchar *val,
                         gssize       len)
 {
+  gsize len_unsigned;
   gsize end;
 
   g_return_val_if_fail (string != NULL, NULL);
@@ -879,14 +887,16 @@
   g_return_val_if_fail (pos <= string->len, string);
 
   if (len < 0)
-    len = strlen (val);
+    len_unsigned = strlen (val);
+  else
+    len_unsigned = len;
 
-  end = pos + len;
+  end = pos + len_unsigned;
 
   if (end > string->len)
     g_string_maybe_expand (string, end - string->len);
 
-  memcpy (string->str + pos, val, len);
+  memcpy (string->str + pos, val, len_unsigned);
 
   if (end > string->len)
     {
