Rebase mingw-glib2 to 2.87.5

Resolves: RHEL-159874 - Rebase mingw-glib2 to 2.87.5
Resolves: RHEL-159187 - CVE-2025-14087

Drop 0001-Use-CreateFile-on-Win32-to-make-sure-g_unlink-always.patch see https://bugzilla.redhat.com/show_bug.cgi?id=2431179

Signed-off-by: Konstantin Kostiuk <kkostiuk@redhat.com>
This commit is contained in:
Konstantin Kostiuk 2026-03-25 12:04:21 +02:00
parent 99f1a41e46
commit b8cadbcb53
5 changed files with 8 additions and 1579 deletions

View File

@ -1,758 +0,0 @@
From 0754df10a2ce7dcfbbcb498071cb81e8642182a5 Mon Sep 17 00:00:00 2001
From: Kostiantyn Kostiuk <kkostiuk@redhat.com>
Date: Wed, 25 Feb 2026 14:38:06 +0200
Subject: [PATCH] Revert "gstdio: Add support for the `e` flag (O_CLOEXEC) to
g_fopen()"
This reverts commit f9a7ac11f59927642a7df6beabec129fe463cb23.
---
gio/gdbus-tool.c | 3 +-
gio/gdbusaddress.c | 8 +-
gio/gdbusprivate.c | 2 +-
gio/glib-compile-resources.c | 4 +-
gio/gunixmounts.c | 5 +-
gio/tests/g-file-info.c | 6 +-
gio/tests/live-g-file.c | 3 +-
girepository/compiler/compiler.c | 2 +-
girepository/gdump.c | 5 +-
girepository/girwriter.c | 2 +-
glib/deprecated/gcompletion.c | 3 +-
glib/gcharset.c | 3 +-
glib/gfileutils.c | 4 +-
glib/glib-mirroring-tab/gen-mirroring-tab.c | 3 +-
glib/grand.c | 87 ++++++++++-----------
glib/gstdio.c | 23 +-----
glib/tests/fileutils.c | 6 +-
glib/tests/unicode.c | 5 +-
18 files changed, 75 insertions(+), 99 deletions(-)
diff --git a/gio/gdbus-tool.c b/gio/gdbus-tool.c
index 56597d3f2..5e6c172dc 100644
--- a/gio/gdbus-tool.c
+++ b/gio/gdbus-tool.c
@@ -34,7 +34,6 @@
#endif
#include <gi18n.h>
-#include <glib/gstdio.h>
#ifdef G_OS_WIN32
#include "glib/glib-private.h"
@@ -72,7 +71,7 @@ completion_debug (const gchar *format, ...)
s = g_strdup_vprintf (format, var_args);
if (f == NULL)
{
- f = g_fopen ("/tmp/gdbus-completion-debug.txt", "a+e");
+ f = fopen ("/tmp/gdbus-completion-debug.txt", "a+");
}
fprintf (f, "%s\n", s);
g_free (s);
diff --git a/gio/gdbusaddress.c b/gio/gdbusaddress.c
index 4db3fc3c1..1b62247fa 100644
--- a/gio/gdbusaddress.c
+++ b/gio/gdbusaddress.c
@@ -53,6 +53,12 @@
#include <windows.h>
#endif
+#ifdef G_OS_WIN32
+#define FO_CLOEXEC ""
+#else
+#define FO_CLOEXEC "e"
+#endif
+
#include "glibintl.h"
/**
@@ -714,7 +720,7 @@ g_dbus_address_connect (const gchar *address_entry,
int errsv;
/* be careful to read only 16 bytes - we also check that the file is only 16 bytes long */
- f = g_fopen (nonce_file, "rbe");
+ f = fopen (nonce_file, "rb" FO_CLOEXEC);
errsv = errno;
if (f == NULL)
{
diff --git a/gio/gdbusprivate.c b/gio/gdbusprivate.c
index c68e3f620..28083e4ed 100644
--- a/gio/gdbusprivate.c
+++ b/gio/gdbusprivate.c
@@ -2195,7 +2195,7 @@ unpublish_session_bus (void)
static void
wait_console_window (void)
{
- FILE *console = g_fopen ("CONOUT$", "we");
+ FILE *console = fopen ("CONOUT$", "w");
SetConsoleTitleW (L"gdbus-daemon output. Type any character to close this window.");
fprintf (console, _("(Type any character to close this window)\n"));
diff --git a/gio/glib-compile-resources.c b/gio/glib-compile-resources.c
index ecf53b934..2329c627a 100644
--- a/gio/glib-compile-resources.c
+++ b/gio/glib-compile-resources.c
@@ -1132,7 +1132,7 @@ main (int argc, char **argv)
{
FILE *file;
- file = g_fopen (target, "we");
+ file = fopen (target, "w");
if (file == NULL)
{
g_printerr ("can't write to file %s", target);
@@ -1181,7 +1181,7 @@ main (int argc, char **argv)
}
g_unlink (binary_target);
- file = g_fopen (target, "we");
+ file = fopen (target, "w");
if (file == NULL)
{
g_printerr ("can't write to file %s", target);
diff --git a/gio/gunixmounts.c b/gio/gunixmounts.c
index 45a938933..0f327ec18 100644
--- a/gio/gunixmounts.c
+++ b/gio/gunixmounts.c
@@ -79,7 +79,6 @@ extern char* hasmntopt(const struct mntent* mnt, const char* opt);
#include "gfilemonitor.h"
#include "glibintl.h"
#include "glocalfile.h"
-#include "gstdio.h"
#include "gthemedicon.h"
#include "gcontextspecificgroup.h"
@@ -203,7 +202,7 @@ static GSource *proc_mounts_watch_source = NULL;
#endif
#ifndef HAVE_SETMNTENT
-#define setmntent(f,m) g_fopen (f, m)
+#define setmntent(f,m) fopen(f,m)
#endif
#ifndef HAVE_ENDMNTENT
#define endmntent(f) fclose(f)
@@ -3967,7 +3966,7 @@ _resolve_dev_root (void)
/* see if device with similar major:minor as /dev/root is mention
* in /etc/mtab (it usually is)
*/
- f = g_fopen ("/etc/mtab", "re");
+ f = fopen ("/etc/mtab", "re");
if (f != NULL)
{
struct mntent *entp;
diff --git a/gio/tests/g-file-info.c b/gio/tests/g-file-info.c
index 51e6aa534..9d97d5ac4 100644
--- a/gio/tests/g-file-info.c
+++ b/gio/tests/g-file-info.c
@@ -792,7 +792,7 @@ test_internal_enhanced_stdio (void)
g_remove (ps);
- f = g_fopen (ps, "wbe");
+ f = g_fopen (ps, "wb");
g_assert_nonnull (f);
h = (HANDLE) _get_osfhandle (fileno (f));
@@ -875,7 +875,7 @@ test_internal_enhanced_stdio (void)
g_assert_true (SystemTimeToFileTime (&st, &ft));
- f = g_fopen (p0, "we");
+ f = g_fopen (p0, "w");
g_assert_nonnull (f);
h = (HANDLE) _get_osfhandle (fileno (f));
@@ -888,7 +888,7 @@ test_internal_enhanced_stdio (void)
fclose (f);
- f = g_fopen (p1, "we");
+ f = g_fopen (p1, "w");
g_assert_nonnull (f);
fclose (f);
diff --git a/gio/tests/live-g-file.c b/gio/tests/live-g-file.c
index 5edc9b673..c96f9db94 100644
--- a/gio/tests/live-g-file.c
+++ b/gio/tests/live-g-file.c
@@ -23,7 +23,6 @@
*/
#include <glib/glib.h>
-#include <glib/gstdio.h>
#include <gio/gio.h>
#include <errno.h>
#include <stdlib.h>
@@ -306,7 +305,7 @@ test_create_structure (gconstpointer test_data)
basename = g_path_get_basename (item.filename);
path = g_build_filename (test_data, dir, ".hidden", NULL);
- f = g_fopen (path, "ae");
+ f = fopen (path, "a");
fprintf (f, "%s\n", basename);
fclose (f);
diff --git a/girepository/compiler/compiler.c b/girepository/compiler/compiler.c
index f9d588d52..0c8315399 100644
--- a/girepository/compiler/compiler.c
+++ b/girepository/compiler/compiler.c
@@ -86,7 +86,7 @@ write_out_typelib (gchar *prefix,
file_obj = g_file_new_for_path (filename);
tmp_filename = g_strdup_printf ("%s.tmp", filename);
tmp_file_obj = g_file_new_for_path (tmp_filename);
- file = file_owned = g_fopen (tmp_filename, "wbe");
+ file = g_fopen (tmp_filename, "wb");
if (file == NULL)
{
diff --git a/girepository/gdump.c b/girepository/gdump.c
index 8569b9d8f..e4adffee9 100644
--- a/girepository/gdump.c
+++ b/girepository/gdump.c
@@ -33,7 +33,6 @@
#include <glib.h>
#include <glib-object.h>
-#include <glib/gstdio.h>
#include <gmodule.h>
#include <stdlib.h>
@@ -657,7 +656,7 @@ gi_repository_dump (const char *input_filename,
return FALSE;
}
- input = g_fopen (input_filename, "rbe");
+ input = fopen (input_filename, "rb");
if (input == NULL)
{
int saved_errno = errno;
@@ -669,7 +668,7 @@ gi_repository_dump (const char *input_filename,
return FALSE;
}
- output = g_fopen (output_filename, "wbe");
+ output = fopen (output_filename, "wb");
if (output == NULL)
{
int saved_errno = errno;
diff --git a/girepository/girwriter.c b/girepository/girwriter.c
index 9c36db0f7..b2bd6395d 100644
--- a/girepository/girwriter.c
+++ b/girepository/girwriter.c
@@ -1368,7 +1368,7 @@ gi_ir_writer_write (GIRepository *repository,
full_filename = g_strdup_printf ("%s-%s", ns, filename);
else
full_filename = g_strdup (filename);
- ofile = g_fopen (filename, "we");
+ ofile = g_fopen (filename, "w");
if (ofile == NULL)
{
diff --git a/glib/deprecated/gcompletion.c b/glib/deprecated/gcompletion.c
index fa09a97fb..73192894f 100644
--- a/glib/deprecated/gcompletion.c
+++ b/glib/deprecated/gcompletion.c
@@ -39,7 +39,6 @@
#include <glib/gstrfuncs.h>
#include <glib/gmessages.h>
-#include <glib/gstdio.h>
#include <glib/gunicode.h>
#include <string.h>
@@ -468,7 +467,7 @@ main (int argc,
return 1;
}
- file = g_fopen (argv[1], "re");
+ file = fopen (argv[1], "r");
if (!file)
{
g_warning ("Cannot open %s", argv[1]);
diff --git a/glib/gcharset.c b/glib/gcharset.c
index 13d6270a0..c384c4b53 100644
--- a/glib/gcharset.c
+++ b/glib/gcharset.c
@@ -28,7 +28,6 @@
#include "ghash.h"
#include "glib-private.h"
#include "gmessages.h"
-#include "gstdio.h"
#include "gstrfuncs.h"
#include "gthread.h"
#include "gthreadprivate.h"
@@ -448,7 +447,7 @@ read_aliases (const gchar *file,
FILE *fp;
char buf[256];
- fp = g_fopen (file, "re");
+ fp = fopen (file, "re");
if (!fp)
return;
while (fgets (buf, 256, fp))
diff --git a/glib/gfileutils.c b/glib/gfileutils.c
index 8b70ddd7d..62fc3255c 100644
--- a/glib/gfileutils.c
+++ b/glib/gfileutils.c
@@ -938,7 +938,7 @@ get_contents_posix (const gchar *filename,
FILE *f;
gboolean retval;
- f = fdopen (fd, "re");
+ f = fdopen (fd, "r");
if (f == NULL)
{
@@ -969,7 +969,7 @@ get_contents_win32 (const gchar *filename,
FILE *f;
gboolean retval;
- f = g_fopen (filename, "rbe");
+ f = g_fopen (filename, "rb");
if (f == NULL)
{
diff --git a/glib/glib-mirroring-tab/gen-mirroring-tab.c b/glib/glib-mirroring-tab/gen-mirroring-tab.c
index 54935b4af..19efbecf3 100644
--- a/glib/glib-mirroring-tab/gen-mirroring-tab.c
+++ b/glib/glib-mirroring-tab/gen-mirroring-tab.c
@@ -30,7 +30,6 @@
*/
#include <glib.h>
-#include <glib/gstdio.h>
#include <stdlib.h>
#include <stdio.h>
@@ -157,7 +156,7 @@ read_data (
FILE *f;
fprintf (stderr, "Reading '%s'\n", data_file_name);
- if (!(f = g_fopen (data_file_name, "rte")))
+ if (!(f = fopen (data_file_name, "rt")))
die2 ("error: cannot open '%s' for reading", data_file_name);
if (!strcmp (data_file_type, "BidiMirroring.txt"))
diff --git a/glib/grand.c b/glib/grand.c
index 0a1d82eb1..32ece34a4 100644
--- a/glib/grand.c
+++ b/glib/grand.c
@@ -49,7 +49,6 @@
#include "genviron.h"
#include "gmain.h"
#include "gmem.h"
-#include "gstdio.h"
#include "gtestutils.h"
#include "gthread.h"
#include "gtimer.h"
@@ -73,14 +72,14 @@
G_LOCK_DEFINE_STATIC (global_random);
-/* Period parameters */
+/* Period parameters */
#define N 624
#define M 397
#define MATRIX_A 0x9908b0df /* constant vector a */
#define UPPER_MASK 0x80000000 /* most significant w-r bits */
#define LOWER_MASK 0x7fffffff /* least significant r bits */
-/* Tempering parameters */
+/* Tempering parameters */
#define TEMPERING_MASK_B 0x9d2c5680
#define TEMPERING_MASK_C 0xefc60000
#define TEMPERING_SHIFT_U(y) (y >> 11)
@@ -97,7 +96,7 @@ get_random_version (void)
if (g_once_init_enter (&initialized))
{
const gchar *version_string = g_getenv ("G_RANDOM_VERSION");
- if (!version_string || version_string[0] == '\000' ||
+ if (!version_string || version_string[0] == '\000' ||
strcmp (version_string, "2.2") == 0)
random_version = 22;
else if (strcmp (version_string, "2.0") == 0)
@@ -110,22 +109,22 @@ get_random_version (void)
}
g_once_init_leave (&initialized, TRUE);
}
-
+
return random_version;
}
struct _GRand
{
guint32 mt[N]; /* the array for the state vector */
- guint mti;
+ guint mti;
};
/**
* g_rand_new_with_seed: (constructor)
* @seed: a value to initialize the random number generator
- *
+ *
* Creates a new random number generator initialized with @seed.
- *
+ *
* Returns: (transfer full): the new #GRand
**/
GRand*
@@ -141,9 +140,9 @@ g_rand_new_with_seed (guint32 seed)
* @seed: an array of seeds to initialize the random number generator
* @seed_length: an array of seeds to initialize the random number
* generator
- *
+ *
* Creates a new random number generator initialized with @seed.
- *
+ *
* Returns: (transfer full): the new #GRand
*
* Since: 2.4
@@ -159,16 +158,16 @@ g_rand_new_with_seed_array (const guint32 *seed,
/**
* g_rand_new: (constructor)
- *
+ *
* Creates a new random number generator initialized with a seed taken
* either from `/dev/urandom` (if existing) or from the current time
* (as a fallback).
*
* On Windows, the seed is taken from rand_s().
- *
+ *
* Returns: (transfer full): the new #GRand
*/
-GRand*
+GRand*
g_rand_new (void)
{
guint32 seed[4];
@@ -195,7 +194,7 @@ g_rand_new (void)
dev_urandom_exists = FALSE;
close (dev_urandom);
- }
+ }
else
dev_urandom_exists = FALSE;
}
@@ -292,24 +291,24 @@ g_rand_set_seed (GRand *rand,
/* the generator Line 25 of Table 1 in */
/* [KNUTH 1981, The Art of Computer Programming */
/* Vol. 2 (2nd Ed.), pp102] */
-
+
if (seed == 0) /* This would make the PRNG produce only zeros */
seed = 0x6b842128; /* Just set it to another number */
-
+
rand->mt[0]= seed;
for (rand->mti=1; rand->mti<N; rand->mti++)
rand->mt[rand->mti] = (69069 * rand->mt[rand->mti-1]);
-
+
break;
case 22:
/* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
/* In the previous version (see above), MSBs of the */
/* seed affect only MSBs of the array mt[]. */
-
+
rand->mt[0]= seed;
for (rand->mti=1; rand->mti<N; rand->mti++)
- rand->mt[rand->mti] = 1812433253UL *
- (rand->mt[rand->mti-1] ^ (rand->mt[rand->mti-1] >> 30)) + rand->mti;
+ rand->mt[rand->mti] = 1812433253UL *
+ (rand->mt[rand->mti-1] ^ (rand->mt[rand->mti-1] >> 30)) + rand->mti;
break;
default:
g_assert_not_reached ();
@@ -373,7 +372,7 @@ g_rand_set_seed_array (GRand *rand,
}
}
- rand->mt[0] = 0x80000000UL; /* MSB is 1; assuring non-zero initial array */
+ rand->mt[0] = 0x80000000UL; /* MSB is 1; assuring non-zero initial array */
}
/**
@@ -405,7 +404,7 @@ g_rand_int (GRand *rand)
if (rand->mti >= N) { /* generate N words at one time */
int kk;
-
+
for (kk = 0; kk < N - M; kk++) {
y = (rand->mt[kk]&UPPER_MASK)|(rand->mt[kk+1]&LOWER_MASK);
rand->mt[kk] = rand->mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1];
@@ -416,17 +415,17 @@ g_rand_int (GRand *rand)
}
y = (rand->mt[N-1]&UPPER_MASK)|(rand->mt[0]&LOWER_MASK);
rand->mt[N-1] = rand->mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1];
-
+
rand->mti = 0;
}
-
+
y = rand->mt[rand->mti++];
y ^= TEMPERING_SHIFT_U(y);
y ^= TEMPERING_SHIFT_S(y) & TEMPERING_MASK_B;
y ^= TEMPERING_SHIFT_T(y) & TEMPERING_MASK_C;
y ^= TEMPERING_SHIFT_L(y);
-
- return y;
+
+ return y;
}
/* transform [0..2^32] -> [0..1] */
@@ -443,7 +442,7 @@ g_rand_int (GRand *rand)
*
* Returns: a random number
*/
-gint32
+gint32
g_rand_int_range (GRand *rand,
gint32 begin,
gint32 end)
@@ -465,13 +464,13 @@ g_rand_int_range (GRand *rand,
*
* We are using (trans + trans * trans), because g_rand_int only
* covers [0..2^32-1] and thus g_rand_int * trans only covers
- * [0..1-2^-32], but the biggest double < 1 is 1-2^-52.
+ * [0..1-2^-32], but the biggest double < 1 is 1-2^-52.
*/
-
- gdouble double_rand = g_rand_int (rand) *
+
+ gdouble double_rand = g_rand_int (rand) *
(G_RAND_DOUBLE_TRANSFORM +
G_RAND_DOUBLE_TRANSFORM * G_RAND_DOUBLE_TRANSFORM);
-
+
random = (gint32) (double_rand * dist);
}
else
@@ -486,7 +485,7 @@ g_rand_int_range (GRand *rand,
case 22:
if (dist == 0)
random = 0;
- else
+ else
{
/* maxvalue is set to the predecessor of the greatest
* multiple of dist less or equal 2^32.
@@ -501,18 +500,18 @@ g_rand_int_range (GRand *rand,
}
else
maxvalue = dist - 1;
-
+
do
random = g_rand_int (rand);
while (random > maxvalue);
-
+
random %= dist;
}
break;
default:
g_assert_not_reached ();
- }
-
+ }
+
return begin + random;
}
@@ -525,9 +524,9 @@ g_rand_int_range (GRand *rand,
*
* Returns: a random number
*/
-gdouble
+gdouble
g_rand_double (GRand *rand)
-{
+{
/* We set all 52 bits after the point for this, not only the first
32. That's why we need two calls to g_rand_int */
gdouble retval = g_rand_int (rand) * G_RAND_DOUBLE_TRANSFORM;
@@ -535,7 +534,7 @@ g_rand_double (GRand *rand)
/* The following might happen due to very bad rounding luck, but
* actually this should be more than rare, we just try again then */
- if (retval >= 1.0)
+ if (retval >= 1.0)
return g_rand_double (rand);
return retval;
@@ -552,7 +551,7 @@ g_rand_double (GRand *rand)
*
* Returns: a random number
*/
-gdouble
+gdouble
g_rand_double_range (GRand *rand,
gdouble begin,
gdouble end)
@@ -612,7 +611,7 @@ g_random_int (void)
*
* Returns: a random number
*/
-gint32
+gint32
g_random_int_range (gint32 begin,
gint32 end)
{
@@ -630,7 +629,7 @@ g_random_int_range (gint32 begin,
*
* Returns: a random number
*/
-gdouble
+gdouble
g_random_double (void)
{
double result;
@@ -650,7 +649,7 @@ g_random_double (void)
*
* Returns: a random number
*/
-gdouble
+gdouble
g_random_double_range (gdouble begin,
gdouble end)
{
@@ -664,7 +663,7 @@ g_random_double_range (gdouble begin,
/**
* g_random_set_seed:
* @seed: a value to reinitialize the global random number generator
- *
+ *
* Sets the seed for the global random number generator, which is used
* by the g_random_* functions, to @seed.
*/
diff --git a/glib/gstdio.c b/glib/gstdio.c
index f5c9448ed..9a27324e0 100644
--- a/glib/gstdio.c
+++ b/glib/gstdio.c
@@ -145,15 +145,11 @@ w32_error_to_errno (DWORD error_code)
* "wb+". The 'b' needs to be appended to "w+", i.e. "w+b". Note
* that otherwise these 2 modes are supposed to be aliases, hence
* swappable at will. TODO: Is this still true?
- *
- * It also doesnt accept `e`, which Unix uses for O_CLOEXEC. This function
- * rewrites that to `N` — see
- * https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/fopen-wfopen?view=msvc-170
*/
static void
_g_win32_fix_mode (wchar_t *mode)
{
- wchar_t *ptr, *e_ptr, *comma_ptr;
+ wchar_t *ptr;
wchar_t temp;
ptr = wcschr (mode, L'+');
@@ -163,13 +159,6 @@ _g_win32_fix_mode (wchar_t *mode)
mode[1] = *ptr;
*ptr = temp;
}
-
- /* Rewrite `e` (O_CLOEXEC) to `N`, if it occurs before any extended attributes
- * (https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/fopen-wfopen?view=msvc-170#unicode-support) */
- e_ptr = wcschr (mode, L'e');
- comma_ptr = wcschr (mode, L',');
- if (e_ptr != NULL && (comma_ptr == NULL || e_ptr < comma_ptr))
- *e_ptr = L'N';
}
/* From
@@ -1573,13 +1562,6 @@ g_rmdir (const gchar *filename)
* used by GLib are different. Convenience functions like g_file_set_contents_full()
* avoid this problem.
*
- * Since GLib 2.86, the `e` option is supported in @mode on all platforms. On
- * Unix platforms it will set `O_CLOEXEC` on the opened file descriptor. On
- * Windows platforms it will be converted to the
- * [`N` modifier](https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/fopen-wfopen?view=msvc-170).
- * It is recommended to set `e` unconditionally, unless you know the returned
- * file should be shared between this process and a new fork.
- *
* Returns: A `FILE*` if the file was successfully opened, or %NULL if
* an error occurred
*
@@ -1636,9 +1618,6 @@ g_fopen (const gchar *filename,
*
* See your C library manual for more details about freopen().
*
- * Since GLib 2.86, the `e` option is supported in @mode on all platforms. See
- * the documentation for [func@GLib.fopen] for more details.
- *
* Returns: A FILE* if the file was successfully opened, or %NULL if
* an error occurred.
*
diff --git a/glib/tests/fileutils.c b/glib/tests/fileutils.c
index b0f99949b..b27ea54c8 100644
--- a/glib/tests/fileutils.c
+++ b/glib/tests/fileutils.c
@@ -705,7 +705,7 @@ test_mkdir_with_parents_1 (const gchar *base)
if (g_file_test (p1, G_FILE_TEST_EXISTS))
g_error ("failed, did g_rmdir(%s), but %s is still there", p1, p1);
- f = g_fopen (p1, "we");
+ f = g_fopen (p1, "w");
if (f == NULL)
g_error ("failed, couldn't create file %s", p1);
fclose (f);
@@ -1446,7 +1446,7 @@ test_get_contents (void)
char *filename = g_build_filename (g_get_tmp_dir (), "file-test-get-contents", NULL);
gsize bytes_written;
- f = g_fopen (filename, "we");
+ f = g_fopen (filename, "w");
bytes_written = fwrite (text, 1, strlen (text), f);
g_assert_cmpint (bytes_written, ==, strlen (text));
fclose (f);
@@ -2042,7 +2042,7 @@ test_read_link (void)
g_free (newpath);
g_free (badpath);
- file = g_fopen (filename, "we");
+ file = fopen (filename, "w");
g_assert_nonnull (file);
fclose (file);
diff --git a/glib/tests/unicode.c b/glib/tests/unicode.c
index 4717a43dc..44d4ae904 100644
--- a/glib/tests/unicode.c
+++ b/glib/tests/unicode.c
@@ -33,7 +33,6 @@
#include <stdio.h>
#include "glib.h"
-#include "glib/gstdio.h"
#include "glib/gunidecomp.h"
@@ -638,7 +637,7 @@ test_casemap_and_casefold (void)
save_and_clear_env ("LANG", &old_lang);
filename = g_test_build_filename (G_TEST_DIST, "casemap.txt", NULL);
- infile = g_fopen (filename, "re");
+ infile = fopen (filename, "r");
g_assert (infile != NULL);
while (fgets (buffer, sizeof (buffer), infile))
@@ -702,7 +701,7 @@ test_casemap_and_casefold (void)
g_free (filename);
filename = g_test_build_filename (G_TEST_DIST, "casefold.txt", NULL);
- infile = g_fopen (filename, "re");
+ infile = fopen (filename, "r");
g_assert (infile != NULL);
while (fgets (buffer, sizeof (buffer), infile))
--
2.52.0

View File

@ -1,553 +0,0 @@
diff -rupN --no-dereference glib-2.79.1/gio/tests/org.gtk.test.gschema.override.orig glib-2.79.1-new/gio/tests/org.gtk.test.gschema.override.orig
--- glib-2.79.1/gio/tests/org.gtk.test.gschema.override.orig 2024-01-22 15:30:24.000000000 +0100
+++ glib-2.79.1-new/gio/tests/org.gtk.test.gschema.override.orig 1970-01-01 01:00:00.000000000 +0100
@@ -1,2 +0,0 @@
-[org.gtk.test.per-desktop:GNOME-Classic]
-desktop = "GNOME Classic"
diff -rupN --no-dereference glib-2.79.1/gio/tests/org.gtk.test.gschema.xml.orig glib-2.79.1-new/gio/tests/org.gtk.test.gschema.xml.orig
--- glib-2.79.1/gio/tests/org.gtk.test.gschema.xml.orig 2024-01-22 15:30:24.000000000 +0100
+++ glib-2.79.1-new/gio/tests/org.gtk.test.gschema.xml.orig 1970-01-01 01:00:00.000000000 +0100
@@ -1,225 +0,0 @@
-<schemalist>
-
- <schema id="org.gtk.test" path="/tests/" gettext-domain="test">
- <key name="greeting" type="s">
- <default l10n="messages">"Hello, earthlings"</default>
- <summary>A greeting</summary>
- <description>
- Greeting of the invading martians
- </description>
- </key>
- <key name="farewell" type="s">
- <default l10n="messages">"So long"</default>
- </key>
-
- <child name='basic-types' schema='org.gtk.test.basic-types'/>
- <child name='complex-types' schema='org.gtk.test.complex-types'/>
- <child name='localized' schema='org.gtk.test.localized'/>
- </schema>
-
- <schema id="org.gtk.test.no-path">
- <key name="test-boolean" type="b">
- <default>true</default>
- </key>
- </schema>
-
- <schema id="org.gtk.test.basic-types" path="/tests/basic-types/">
- <key name="test-boolean" type="b">
- <default>true</default>
- </key>
- <key name="test-byte" type="y">
- <default>25</default>
- </key>
- <key name="test-int16" type="n">
- <default>-1234</default>
- </key>
- <key name="test-uint16" type="q">
- <default>1234</default>
- </key>
- <key name="test-int32" type="i">
- <default>-123456</default>
- </key>
- <key name="test-uint32" type="u">
- <default>123456</default>
- </key>
- <key name="test-int64" type="x">
- <default>-123456789</default>
- </key>
- <key name="test-uint64" type="t">
- <default>123456789</default>
- </key>
- <key name="test-double" type="d">
- <default>123.456</default>
- </key>
- <key name="test-string" type="s">
- <default>"a string, it seems"</default>
- </key>
- <key name="test-objectpath" type="o">
- <default>"/a/object/path"</default>
- </key>
- </schema>
-
- <schema id="org.gtk.test.complex-types" path="/tests/complex-types/">
- <key name="test-tuple" type="(s(ii))">
- <default>("one",(2,3))</default>
- </key>
- <key name="test-array" type="ai">
- <default>[0,1,2,3,4,5]</default>
- </key>
- <key name="test-dict" type="a{sau}">
- <default>
- {
- "AC": [0,0, 0,0,0,0,0,0],
- "IV": [0,0, 0,0,0,0,0,0]
- }
- </default>
- </key>
- </schema>
-
- <schema id="org.gtk.test.localized" path="/tests/localized/" gettext-domain="test">
- <key name="error-message" type="s">
- <default l10n="messages">"Unnamed"</default>
- </key>
- <key name="backspace" type="s">
- <default l10n="messages" context="keyboard label">"BackSpace"</default>
- </key>
- <key name="midnight" type="s">
- <default l10n="time">"12:00 AM"</default>
- </key>
- </schema>
-
- <schema id="org.gtk.test.binding" path="/tests/binding/">
- <key name="bool" type="b">
- <default>false</default>
- </key>
- <key name="anti-bool" type="b">
- <default>false</default>
- </key>
- <key name="byte" type="y">
- <default>0</default>
- </key>
- <key name="int16" type="n">
- <default>0</default>
- </key>
- <key name="uint16" type="q">
- <default>0</default>
- </key>
- <key name="int" type="i">
- <default>0</default>
- </key>
- <key name="uint" type="u">
- <default>0</default>
- </key>
- <key name="int64" type="x">
- <default>0</default>
- </key>
- <key name="uint64" type="t">
- <default>0</default>
- </key>
- <key name="double" type="d">
- <default>0</default>
- </key>
- <key name="string" type="s">
- <default>""</default>
- </key>
- <key name="chararray" type="ay">
- <default>[48, 49]</default>
- </key>
- <key name="strv" type="as">
- <default>[]</default>
- </key>
- <key name="enum" enum="org.gtk.test.TestEnum">
- <default>'foo'</default>
- </key>
- <key name="flags" flags="org.gtk.test.TestFlags">
- <default>['mourning', 'laughing']</default>
- </key>
- <key name="range" type='u'>
- <default>33</default>
- <range min="2" max="44"/>
- </key>
- </schema>
-
- <schema id='org.gtk.test.enums' path='/tests/enums/'>
- <key name='test' enum='org.gtk.test.TestEnum'>
- <default>'bar'</default>
- <aliases>
- <alias value='qux' target='quux'/>
- </aliases>
- </key>
- <key name='f-test' flags='org.gtk.test.TestFlags'>
- <default>[]</default>
- <aliases>
- <alias value='speaking' target='talking'/>
- </aliases>
- </key>
- </schema>
-
- <schema id='org.gtk.test.enums.direct' path='/tests/enums/'>
- <key name='f-test' type='as'>
- <default>[]</default>
- </key>
- <key name='test' type='s'>
- <default>'bar'</default>
- </key>
- </schema>
-
- <schema id='org.gtk.test.range' path='/tests/range/'>
- <key name='val' type='i'>
- <default>33</default>
- <range min='2' max='44'/>
- </key>
- </schema>
-
- <schema id='org.gtk.test.range.direct' path='/tests/range/'>
- <key name='val' type='i'>
- <default>33</default>
- </key>
- </schema>
-
- <schema id='org.gtk.test.mapped' path='/tests/mapped/'>
- <key name='val' type='i'>
- <default>0</default>
- </key>
- </schema>
-
- <schema id="org.gtk.test.descriptions" path="/a/">
- <key name='a' type='i'>
- <summary>
- a paragraph.
-
- with some whitespace.
-
- because not everyone has a great editor.
-
-
-
-
- lots of space is as one.
- </summary>
- <default>0</default>
- </key>
- </schema>
-
- <schema id='org.gtk.test.extends.base'>
- <key name='int32' type='i'>
- <default>0</default>
- </key>
- <key name='string' type='s'>
- <default>''</default>
- </key>
- </schema>
- <schema id='org.gtk.test.extends.extended' extends='org.gtk.test.extends.base'>
- <override name="int32">42</override>
- <key name='another-int32' type='i'>
- <default>0</default>
- </key>
- </schema>
-
- <schema id="org.gtk.test.per-desktop" path="/tests/per-desktop/">
- <key name="desktop" type="s">
- <default>"GNOME"</default>
- </key>
- </schema>
-
-</schemalist>
diff -rupN --no-dereference glib-2.79.1/glib/gstdio.c glib-2.79.1-new/glib/gstdio.c
--- glib-2.79.1/glib/gstdio.c 2024-01-22 15:30:24.000000000 +0100
+++ glib-2.79.1-new/glib/gstdio.c 2024-01-26 23:24:18.267015824 +0100
@@ -1052,6 +1052,11 @@ g_open (const gchar *filename,
int mode)
{
#ifdef G_OS_WIN32
+ HANDLE hFile;
+ DWORD dwDesiredAccess = 0;
+ DWORD dwFlagsAndAttributes = 0;
+ DWORD dwDisposition = OPEN_EXISTING;
+ DWORD dwSharedAccess = FILE_SHARE_READ | FILE_SHARE_DELETE;
wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
int retval;
int save_errno;
@@ -1062,12 +1067,114 @@ g_open (const gchar *filename,
return -1;
}
- retval = _wopen (wfilename, flags, mode);
- save_errno = errno;
+ /* Set up the access modes and other attributes */
+ if ((flags & _O_CREAT) && (mode & _S_IREAD))
+ {
+ if (! (mode & _S_IWRITE))
+ dwFlagsAndAttributes = FILE_ATTRIBUTE_READONLY; /* Sets file to 'read only' after the file gets closed */
+ }
+ if ( !(flags & _O_ACCMODE))
+ {
+ /* Equates to _O_RDONLY */
+ if (flags & _O_TRUNC)
+ {
+ errno = EINVAL;
+ g_free (wfilename);
+ return -1;
+ }
+
+ dwDesiredAccess |= GENERIC_READ;
+ dwSharedAccess |= FILE_SHARE_WRITE;
+ }
+ if (flags & _O_WRONLY)
+ {
+ if (flags & _O_RDWR)
+ {
+ errno = EINVAL;
+ g_free (wfilename);
+ return -1;
+ }
+
+ dwDesiredAccess |= GENERIC_WRITE;
+ }
+ if (flags & _O_RDWR)
+ {
+ dwDesiredAccess |= GENERIC_READ;
+ dwDesiredAccess |= GENERIC_WRITE;
+ }
+ if (flags & _O_TRUNC)
+ {
+ if (flags & _O_CREAT)
+ dwDisposition = CREATE_ALWAYS;
+ else
+ dwDisposition = TRUNCATE_EXISTING;
+ }
+ if ((flags & _O_CREAT) && !(flags & _O_TRUNC))
+ {
+ if (flags & _O_EXCL)
+ dwDisposition = CREATE_NEW;
+ else
+ dwDisposition = OPEN_ALWAYS;
+ }
+ if (flags & _O_CREAT)
+ {
+ /* Handle the other flags that can be attached to _O_CREAT */
+ if ((flags & _O_TEMPORARY) || (flags & _O_SHORT_LIVED))
+ dwFlagsAndAttributes |= FILE_ATTRIBUTE_TEMPORARY;
+
+ if (flags & _O_TEMPORARY)
+ dwFlagsAndAttributes |= FILE_FLAG_DELETE_ON_CLOSE;
+ }
+ if ((flags & _O_SEQUENTIAL) || (flags & _O_APPEND))
+ {
+ dwFlagsAndAttributes |= FILE_FLAG_SEQUENTIAL_SCAN;
+ }
+ else if (flags & _O_RANDOM)
+ {
+ dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS;
+ }
+
+ if (0 == dwFlagsAndAttributes)
+ dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
+ hFile = CreateFileW(wfilename, dwDesiredAccess, dwSharedAccess, NULL, dwDisposition, dwFlagsAndAttributes, NULL);
+
+ if (INVALID_HANDLE_VALUE == hFile)
+ {
+ retval = (-1);
+
+ switch (GetLastError ())
+ {
+#define CASE(a,b) case ERROR_##a: errno = b; break
+ CASE (FILE_NOT_FOUND, ENOENT);
+ CASE (PATH_NOT_FOUND, ENOENT);
+ CASE (ACCESS_DENIED, EACCES);
+ CASE (NOT_SAME_DEVICE, EXDEV);
+ CASE (LOCK_VIOLATION, EACCES);
+ CASE (SHARING_VIOLATION, EACCES);
+ CASE (FILE_EXISTS, EEXIST);
+ CASE (ALREADY_EXISTS, EEXIST);
+#undef CASE
+ default: errno = EIO;
+ }
+ }
+ else
+ retval = _open_osfhandle((long)hFile, flags);
- g_free (wfilename);
+ if ((-1) != retval)
+ {
+ /* We have a valid file handle. Set its translation mode to text or binary, as appropriate */
+ if ((!(flags & _O_TEXT)) && (_fmode == _O_BINARY))
+ _setmode(retval, _O_BINARY);
+ else if ((flags & _O_TEXT) || (_fmode == _O_TEXT))
+ _setmode(retval, _O_TEXT);
+ else
+ _setmode(retval, _O_BINARY);
+ }
+ save_errno = errno;
+ g_free (wfilename);
errno = save_errno;
+
return retval;
#else
int fd;
@@ -1115,6 +1222,8 @@ g_creat (const gchar *filename,
int mode)
{
#ifdef G_OS_WIN32
+ HANDLE hFile;
+ DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
int retval;
int save_errno;
@@ -1125,12 +1234,41 @@ g_creat (const gchar *filename,
return -1;
}
- retval = _wcreat (wfilename, mode);
- save_errno = errno;
+ if (mode & _S_IREAD)
+ {
+ if (! (mode & _S_IWRITE))
+ dwFlagsAndAttributes = FILE_ATTRIBUTE_READONLY; /* Sets file to 'read only' after the file gets closed */
+ }
+
+ hFile = CreateFileW(wfilename, (GENERIC_READ | GENERIC_WRITE), (FILE_SHARE_READ | FILE_SHARE_DELETE),
+ NULL, CREATE_ALWAYS, dwFlagsAndAttributes, NULL);
+
+ if (INVALID_HANDLE_VALUE == hFile)
+ {
+ retval = (-1);
+
+ switch (GetLastError ())
+ {
+#define CASE(a,b) case ERROR_##a: errno = b; break
+ CASE (FILE_NOT_FOUND, ENOENT);
+ CASE (PATH_NOT_FOUND, ENOENT);
+ CASE (ACCESS_DENIED, EACCES);
+ CASE (NOT_SAME_DEVICE, EXDEV);
+ CASE (LOCK_VIOLATION, EACCES);
+ CASE (SHARING_VIOLATION, EACCES);
+ CASE (FILE_EXISTS, EEXIST);
+ CASE (ALREADY_EXISTS, EEXIST);
+#undef CASE
+ default: errno = EIO;
+ }
+ }
+ else
+ retval = _open_osfhandle((long)hFile, _O_RDWR);
+ save_errno = errno;
g_free (wfilename);
-
errno = save_errno;
+
return retval;
#else
return creat (filename, mode);
@@ -1572,34 +1710,102 @@ g_fopen (const gchar *filename,
const gchar *mode)
{
#ifdef G_OS_WIN32
- wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
- wchar_t *wmode;
- FILE *retval;
- int save_errno;
-
- if (wfilename == NULL)
- {
- errno = EINVAL;
- return NULL;
- }
-
- wmode = g_utf8_to_utf16 (mode, -1, NULL, NULL, NULL);
-
- if (wmode == NULL)
- {
- g_free (wfilename);
- errno = EINVAL;
- return NULL;
- }
-
- _g_win32_fix_mode (wmode);
- retval = _wfopen (wfilename, wmode);
- save_errno = errno;
-
- g_free (wfilename);
- g_free (wmode);
-
- errno = save_errno;
+ int hFile;
+ int flags = 0;
+ gchar priv_mode[4];
+ FILE *retval = NULL;
+
+ if ((NULL == filename) || (NULL == mode))
+ {
+ errno = EINVAL;
+ goto out;
+ }
+ if ((strlen(mode) < 1) || (strlen(mode) > 3))
+ {
+ errno - EINVAL;
+ goto out;
+ }
+
+ strncpy(priv_mode, mode, 3);
+ priv_mode[3] = '\0';
+
+ /* Set up any flags to pass to 'g_open()' */
+ if (3 == strlen(priv_mode))
+ {
+ if (('c' == priv_mode[2]) || ('n' == priv_mode[2]))
+ priv_mode[2] = '\0';
+ else
+ {
+ if (0 == strcmp(priv_mode, "a+b"))
+ flags = _O_RDWR | _O_CREAT | _O_APPEND | _O_BINARY;
+ else if (0 == strcmp(priv_mode, "a+t"))
+ flags = _O_RDWR | _O_CREAT | _O_APPEND | _O_TEXT;
+ else if (0 == strcmp(priv_mode, "r+b"))
+ flags = _O_RDWR | _O_BINARY;
+ else if (0 == strcmp(priv_mode, "r+t"))
+ flags = _O_RDWR | _O_TEXT;
+ else if (0 == strcmp(priv_mode, "w+b"))
+ flags = _O_RDWR | _O_CREAT |_O_TRUNC | _O_BINARY;
+ else if (0 == strcmp(priv_mode, "w+t"))
+ flags = _O_RDWR | _O_CREAT |_O_TRUNC | _O_TEXT;
+ else
+ {
+ errno = EINVAL;
+ goto out;
+ }
+ }
+ }
+ if (2 == strlen(priv_mode))
+ {
+ if (('c' == priv_mode[1]) || ('n' == priv_mode[1]))
+ priv_mode[1] = '\0';
+ else
+ {
+ if (0 == strcmp(priv_mode, "a+"))
+ flags = _O_RDWR | _O_CREAT | _O_APPEND;
+ else if (0 == strcmp(priv_mode, "ab"))
+ flags = _O_WRONLY | _O_CREAT | _O_APPEND | _O_BINARY;
+ else if (0 == strcmp(priv_mode, "at"))
+ flags = _O_WRONLY | _O_CREAT | _O_APPEND | _O_TEXT;
+ else if (0 == strcmp(priv_mode, "rb"))
+ flags = _O_RDONLY | _O_BINARY;
+ else if (0 == strcmp(priv_mode, "rt"))
+ flags = _O_RDONLY | _O_TEXT;
+ else if (0 == strcmp(priv_mode, "wb"))
+ flags = _O_WRONLY | _O_CREAT | _O_TRUNC | _O_BINARY;
+ else if (0 == strcmp(priv_mode, "wt"))
+ flags = _O_WRONLY | _O_CREAT | _O_TRUNC | _O_TEXT;
+ else
+ {
+ errno = EINVAL;
+ goto out;
+ }
+ }
+ }
+ if (1 == strlen(priv_mode))
+ {
+ if (0 == strcmp(priv_mode, "a"))
+ flags = _O_WRONLY | _O_CREAT | _O_APPEND;
+ else if (0 == strcmp(priv_mode, "r"))
+ flags = _O_RDONLY;
+ else if (0 == strcmp(priv_mode, "w"))
+ flags = _O_WRONLY | _O_CREAT | _O_TRUNC;
+ else if ( !((0 == strcmp(priv_mode, "c")) || (0 == strcmp(priv_mode, "n"))))
+ {
+ errno = EINVAL;
+ goto out;
+ }
+ }
+
+ hFile = g_open (filename, flags, (_S_IREAD | _S_IWRITE));
+
+ if (INVALID_HANDLE_VALUE == (HANDLE)hFile)
+ /* 'errno' will have already been set by 'g_open()' */
+ retval = NULL;
+ else
+ retval = _fdopen(hFile, mode);
+
+out:
return retval;
#else
return fopen (filename, mode);

View File

@ -1,253 +0,0 @@
From f28340ee62c655487972ad3c632d231ee098fb7f Mon Sep 17 00:00:00 2001
From: Philip Withnall <pwithnall@gnome.org>
Date: Thu, 13 Nov 2025 18:27:22 +0000
Subject: [PATCH 1/2] gconvert: Error out if g_escape_uri_string() would
overflow
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>
Fixes: #3827
---
glib/gconvert.c | 36 +++++++++++++++++++++++++-----------
1 file changed, 25 insertions(+), 11 deletions(-)
diff --git a/glib/gconvert.c b/glib/gconvert.c
index b066dd5a84..a02d2ea732 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,
+ _("The URI is too long"));
+ 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
@@ -1753,7 +1767,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 7bd3fc372040cdf8eada7f65c32c30da52a7461d Mon Sep 17 00:00:00 2001
From: Philip Withnall <pwithnall@gnome.org>
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 <pwithnall@gnome.org>
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() doesnt 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() doesnt 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

View File

@ -1,8 +1,8 @@
%{?mingw_package_header}
Name: mingw-glib2
Version: 2.87.0
Release: 2%{?dist}
Version: 2.87.5
Release: 1%{?dist}
Summary: MinGW Windows GLib2 library
License: LGPL-2.0-or-later
@ -41,14 +41,6 @@ BuildRequires: gettext
BuildRequires: glib2-devel >= 2.45.3
BuildRequires: python3-devel
# https://bugzilla.gnome.org/show_bug.cgi?id=674214
Patch1: 0001-Use-CreateFile-on-Win32-to-make-sure-g_unlink-always.patch
# https://issues.redhat.com/browse/RHEL-130993
# https://gitlab.gnome.org/GNOME/glib/-/issues/3827
# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/4914
Patch2: CVE-2025-13601-gconvert-Error-out-if-g_escape_uri_string-would-overflow.patch
# Prefer the use of GCC constructors over DllMain
# This prevents having to depend on DllMain in static libraries
# http://lists.fedoraproject.org/pipermail/mingw/2013-March/006429.html
@ -56,10 +48,6 @@ Patch2: CVE-2025-13601-gconvert-Error-out-if-g_escape_uri_string-would-o
# https://bugzilla.gnome.org/show_bug.cgi?id=698118
#Patch5: glib-prefer-constructors-over-DllMain.patch
# https://gitlab.gnome.org/GNOME/glib/-/issues/3898
# https://issues.redhat.com/browse/RHEL-151748
Patch3: 0001-Revert-gstdio-Add-support-for-the-e-flag-O_CLOEXEC-t.patch
%description
MinGW Windows Glib2 library.
@ -306,6 +294,11 @@ find %{buildroot} -name "*.la" -delete
%changelog
* Wed Mar 25 2026 Konstantin Kostiuk <kkostiuk@redhat.com> - 2.87.5-1
- RHEL-159874 - Rebase mingw-glib2 to 2.87.5
- RHEL-159187 - CVE-2025-14087 mingw-glib2: GLib: Buffer underflow in GVariant parser leads to heap corruption
- Drop 0001-Use-CreateFile-on-Win32-to-make-sure-g_unlink-always.patch see https://bugzilla.redhat.com/show_bug.cgi?id=2431179
* Wed Feb 25 2026 Konstantin Kostiuk <kkostiuk@redhat.com> - 2.87.0-2
- RHEL-151748 - Glib2 cause qga command 'guest-ssh-get-authorized-keys' failed

View File

@ -1 +1 @@
SHA512 (glib-2.87.0.tar.xz) = 07b58dc0bc395c6a53c9bc5d21674307ce9f0a836c82c04db5d5c3163685333f86ff237fc1cfde60daa10796d0de4c5ba90aa4bca056f4d670c73d97d0868b73
SHA512 (glib-2.87.5.tar.xz) = 5a4a48b7d2102b0e3be8326c88c9a2e014655f46623500705a1e925da10ee4091f0ce06dee5f800a5a0427481c1f13ffe0c078cd1a13c1ce432bbe66e526c8b2