Compare commits

...

No commits in common. "c8s" and "c9-beta" have entirely different histories.
c8s ... c9-beta

17 changed files with 745 additions and 1655 deletions

3
.gitignore vendored
View File

@ -1,2 +1 @@
SOURCES/glib-2.70.1.tar.xz SOURCES/glib-2.78.6.tar.xz
/glib-2.70.1.tar.xz

1
.mingw-glib2.metadata Normal file
View File

@ -0,0 +1 @@
99b8a81357314c6fa279003ce1b95b5d708ba7a8 SOURCES/glib-2.78.6.tar.xz

View File

@ -1,28 +1,242 @@
From 7f4f4354540440c0a8a37beaccbec8bc7fc15ec7 Mon Sep 17 00:00:00 2001 diff -rupN --no-dereference glib-2.78.0/gio/tests/org.gtk.test.gschema.override.orig glib-2.78.0-new/gio/tests/org.gtk.test.gschema.override.orig
From: Erik van Pienbroek <epienbro@fedoraproject.org> --- glib-2.78.0/gio/tests/org.gtk.test.gschema.override.orig 2023-09-08 15:42:18.000000000 +0200
Date: Mon, 27 Aug 2012 23:28:54 +0200 +++ glib-2.78.0-new/gio/tests/org.gtk.test.gschema.override.orig 1970-01-01 01:00:00.000000000 +0100
Subject: [PATCH] Use CreateFile on Win32 to make sure g_unlink always works @@ -1,2 +0,0 @@
-[org.gtk.test.per-desktop:GNOME-Classic]
The functions g_open(), g_creat() and g_fopen() defer to _wopen(), -desktop = "GNOME Classic"
_wcreat() and _wfopen() respectively. This is very similar to diff -rupN --no-dereference glib-2.78.0/gio/tests/org.gtk.test.gschema.xml.orig glib-2.78.0-new/gio/tests/org.gtk.test.gschema.xml.orig
the corresponding arrangement for Linux. However, those Windows --- glib-2.78.0/gio/tests/org.gtk.test.gschema.xml.orig 2023-09-08 15:42:18.000000000 +0200
functions do not support renaming a file whilst it's open. As a +++ glib-2.78.0-new/gio/tests/org.gtk.test.gschema.xml.orig 1970-01-01 01:00:00.000000000 +0100
result, g_rename() behaves differently on the Windows platform @@ -1,225 +0,0 @@
compared to its Linux behaviour, where files can be renamed even -<schemalist>
while there are file handles still open. Resolved this by using -
the Win32 API function CreateFile() instead of _wopen(), _wcreat() - <schema id="org.gtk.test" path="/tests/" gettext-domain="test">
and _wfopen() - <key name="greeting" type="s">
- <default l10n="messages">"Hello, earthlings"</default>
Patch initially created by John Emmas - <summary>A greeting</summary>
--- - <description>
glib/gstdio.c | 259 ++++++++++++++++++++++++++++++++++++++++++++++++++++------ - Greeting of the invading martians
1 file changed, 233 insertions(+), 26 deletions(-) - </description>
- </key>
diff --git a/glib/gstdio.c b/glib/gstdio.c - <key name="farewell" type="s">
index 6d763e1..c1d072f 100644 - <default l10n="messages">"So long"</default>
--- a/glib/gstdio.c - </key>
+++ b/glib/gstdio.c -
@@ -1045,6 +1045,11 @@ g_open (const gchar *filename, - <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.78.0/glib/gstdio.c glib-2.78.0-new/glib/gstdio.c
--- glib-2.78.0/glib/gstdio.c 2023-09-08 15:42:18.000000000 +0200
+++ glib-2.78.0-new/glib/gstdio.c 2023-09-19 11:45:02.396539056 +0200
@@ -1052,6 +1052,11 @@ g_open (const gchar *filename,
int mode) int mode)
{ {
#ifdef G_OS_WIN32 #ifdef G_OS_WIN32
@ -34,7 +248,7 @@ index 6d763e1..c1d072f 100644
wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL); wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
int retval; int retval;
int save_errno; int save_errno;
@@ -1055,12 +1060,114 @@ g_open (const gchar *filename, @@ -1062,12 +1067,114 @@ g_open (const gchar *filename,
return -1; return -1;
} }
@ -55,8 +269,7 @@ index 6d763e1..c1d072f 100644
+ g_free (wfilename); + g_free (wfilename);
+ return -1; + return -1;
+ } + }
+
- g_free (wfilename);
+ dwDesiredAccess |= GENERIC_READ; + dwDesiredAccess |= GENERIC_READ;
+ dwSharedAccess |= FILE_SHARE_WRITE; + dwSharedAccess |= FILE_SHARE_WRITE;
+ } + }
@ -68,7 +281,7 @@ index 6d763e1..c1d072f 100644
+ g_free (wfilename); + g_free (wfilename);
+ return -1; + return -1;
+ } + }
+
+ dwDesiredAccess |= GENERIC_WRITE; + dwDesiredAccess |= GENERIC_WRITE;
+ } + }
+ if (flags & _O_RDWR) + if (flags & _O_RDWR)
@ -133,7 +346,8 @@ index 6d763e1..c1d072f 100644
+ } + }
+ else + else
+ retval = _open_osfhandle((long)hFile, flags); + retval = _open_osfhandle((long)hFile, flags);
+
- g_free (wfilename);
+ if ((-1) != retval) + if ((-1) != retval)
+ { + {
+ /* We have a valid file handle. Set its translation mode to text or binary, as appropriate */ + /* We have a valid file handle. Set its translation mode to text or binary, as appropriate */
@ -144,7 +358,7 @@ index 6d763e1..c1d072f 100644
+ else + else
+ _setmode(retval, _O_BINARY); + _setmode(retval, _O_BINARY);
+ } + }
+
+ save_errno = errno; + save_errno = errno;
+ g_free (wfilename); + g_free (wfilename);
errno = save_errno; errno = save_errno;
@ -152,7 +366,7 @@ index 6d763e1..c1d072f 100644
return retval; return retval;
#else #else
int fd; int fd;
@@ -1108,6 +1215,8 @@ g_creat (const gchar *filename, @@ -1115,6 +1222,8 @@ g_creat (const gchar *filename,
int mode) int mode)
{ {
#ifdef G_OS_WIN32 #ifdef G_OS_WIN32
@ -161,7 +375,7 @@ index 6d763e1..c1d072f 100644
wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL); wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
int retval; int retval;
int save_errno; int save_errno;
@@ -1118,12 +1227,41 @@ g_creat (const gchar *filename, @@ -1125,12 +1234,41 @@ g_creat (const gchar *filename,
return -1; return -1;
} }
@ -172,8 +386,7 @@ index 6d763e1..c1d072f 100644
+ if (! (mode & _S_IWRITE)) + if (! (mode & _S_IWRITE))
+ dwFlagsAndAttributes = FILE_ATTRIBUTE_READONLY; /* Sets file to 'read only' after the file gets closed */ + dwFlagsAndAttributes = FILE_ATTRIBUTE_READONLY; /* Sets file to 'read only' after the file gets closed */
+ } + }
+
- g_free (wfilename);
+ hFile = CreateFileW(wfilename, (GENERIC_READ | GENERIC_WRITE), (FILE_SHARE_READ | FILE_SHARE_DELETE), + hFile = CreateFileW(wfilename, (GENERIC_READ | GENERIC_WRITE), (FILE_SHARE_READ | FILE_SHARE_DELETE),
+ NULL, CREATE_ALWAYS, dwFlagsAndAttributes, NULL); + NULL, CREATE_ALWAYS, dwFlagsAndAttributes, NULL);
+ +
@ -200,13 +413,14 @@ index 6d763e1..c1d072f 100644
+ retval = _open_osfhandle((long)hFile, _O_RDWR); + retval = _open_osfhandle((long)hFile, _O_RDWR);
+ save_errno = errno; + save_errno = errno;
+ g_free (wfilename); g_free (wfilename);
-
errno = save_errno; errno = save_errno;
+ +
return retval; return retval;
#else #else
return creat (filename, mode); return creat (filename, mode);
@@ -1565,34 +1703,102 @@ g_fopen (const gchar *filename, @@ -1572,34 +1710,102 @@ g_fopen (const gchar *filename,
const gchar *mode) const gchar *mode)
{ {
#ifdef G_OS_WIN32 #ifdef G_OS_WIN32
@ -263,7 +477,7 @@ index 6d763e1..c1d072f 100644
+ if (('c' == priv_mode[2]) || ('n' == priv_mode[2])) + if (('c' == priv_mode[2]) || ('n' == priv_mode[2]))
+ priv_mode[2] = '\0'; + priv_mode[2] = '\0';
+ else + else
+ { + {
+ if (0 == strcmp(priv_mode, "a+b")) + if (0 == strcmp(priv_mode, "a+b"))
+ flags = _O_RDWR | _O_CREAT | _O_APPEND | _O_BINARY; + flags = _O_RDWR | _O_CREAT | _O_APPEND | _O_BINARY;
+ else if (0 == strcmp(priv_mode, "a+t")) + else if (0 == strcmp(priv_mode, "a+t"))
@ -281,14 +495,14 @@ index 6d763e1..c1d072f 100644
+ errno = EINVAL; + errno = EINVAL;
+ goto out; + goto out;
+ } + }
+ } + }
+ } + }
+ if (2 == strlen(priv_mode)) + if (2 == strlen(priv_mode))
+ { + {
+ if (('c' == priv_mode[1]) || ('n' == priv_mode[1])) + if (('c' == priv_mode[1]) || ('n' == priv_mode[1]))
+ priv_mode[1] = '\0'; + priv_mode[1] = '\0';
+ else + else
+ { + {
+ if (0 == strcmp(priv_mode, "a+")) + if (0 == strcmp(priv_mode, "a+"))
+ flags = _O_RDWR | _O_CREAT | _O_APPEND; + flags = _O_RDWR | _O_CREAT | _O_APPEND;
+ else if (0 == strcmp(priv_mode, "ab")) + else if (0 == strcmp(priv_mode, "ab"))
@ -308,7 +522,7 @@ index 6d763e1..c1d072f 100644
+ errno = EINVAL; + errno = EINVAL;
+ goto out; + goto out;
+ } + }
+ } + }
+ } + }
+ if (1 == strlen(priv_mode)) + if (1 == strlen(priv_mode))
+ { + {
@ -337,6 +551,3 @@ index 6d763e1..c1d072f 100644
return retval; return retval;
#else #else
return fopen (filename, mode); return fopen (filename, mode);
--
1.7.11.4

View File

@ -0,0 +1,45 @@
From 25833cefda24c60af913d6f2d532b5afd608b821 Mon Sep 17 00:00:00 2001
From: Michael Catanzaro <mcatanzaro@redhat.com>
Date: Thu, 19 Sep 2024 18:35:53 +0100
Subject: [PATCH] gsocks4aproxy: Fix a single byte buffer overflow in connect
messages
`SOCKS4_CONN_MSG_LEN` failed to account for the length of the final nul
byte in the connect message, which is an addition in SOCKSv4a vs
SOCKSv4.
This means that the buffer for building and transmitting the connect
message could be overflowed if the username and hostname are both
`SOCKS4_MAX_LEN` (255) bytes long.
Proxy configurations are normally statically configured, so the username
is very unlikely to be near its maximum length, and hence this overflow
is unlikely to be triggered in practice.
(Commit message by Philip Withnall, diagnosis and fix by Michael
Catanzaro.)
Fixes: #3461
---
gio/gsocks4aproxy.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/gio/gsocks4aproxy.c b/gio/gsocks4aproxy.c
index 3dad118eb7..b3146d08fd 100644
--- a/gio/gsocks4aproxy.c
+++ b/gio/gsocks4aproxy.c
@@ -79,9 +79,9 @@ g_socks4a_proxy_init (GSocks4aProxy *proxy)
* +----+----+----+----+----+----+----+----+----+----+....+----+------+....+------+
* | VN | CD | DSTPORT | DSTIP | USERID |NULL| HOST | | NULL |
* +----+----+----+----+----+----+----+----+----+----+....+----+------+....+------+
- * 1 1 2 4 variable 1 variable
+ * 1 1 2 4 variable 1 variable 1
*/
-#define SOCKS4_CONN_MSG_LEN (9 + SOCKS4_MAX_LEN * 2)
+#define SOCKS4_CONN_MSG_LEN (10 + SOCKS4_MAX_LEN * 2)
static gint
set_connect_msg (guint8 *msg,
const gchar *hostname,
--
GitLab

View File

@ -0,0 +1,261 @@
From 9bcd65ba5fa1b92ff0fb8380faea335ccef56253 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
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>
Fixes: #3827
Backport 2.86: Changed the translatable error message to re-use an
existing translatable string, to avoid adding new translatable strings
to a stable branch. The re-used string doesnt perfectly match the
error, but its good enough given that no users will ever see it.
---
glib/gconvert.c | 36 +++++++++++++++++++++++++-----------
1 file changed, 25 insertions(+), 11 deletions(-)
diff --git a/glib/gconvert.c b/glib/gconvert.c
index 7ad8ca018f..367e9b4661 100644
--- a/glib/gconvert.c
+++ b/glib/gconvert.c
@@ -1336,8 +1336,9 @@ static const gchar hex[] = "0123456789ABCDEF";
/* Note: This escape function works on file: URIs, but if you want to
* escape something else, please read RFC-2396 */
static gchar *
-g_escape_uri_string (const gchar *string,
- UnsafeCharacterSet mask)
+g_escape_uri_string (const gchar *string,
+ UnsafeCharacterSet mask,
+ GError **error)
{
#define ACCEPTABLE(a) ((a)>=32 && (a)<128 && (acceptable[(a)-32] & use_mask))
@@ -1345,7 +1346,7 @@ g_escape_uri_string (const gchar *string,
gchar *q;
gchar *result;
int c;
- gint unacceptable;
+ size_t unacceptable;
UnsafeCharacterSet use_mask;
g_return_val_if_fail (mask == UNSAFE_ALL
@@ -1362,7 +1363,14 @@ g_escape_uri_string (const gchar *string,
if (!ACCEPTABLE (c))
unacceptable++;
}
-
+
+ if (unacceptable >= (G_MAXSIZE - (p - string)) / 2)
+ {
+ g_set_error_literal (error, G_CONVERT_ERROR, G_CONVERT_ERROR_BAD_URI,
+ _("Invalid hostname"));
+ return NULL;
+ }
+
result = g_malloc (p - string + unacceptable * 2 + 1);
use_mask = mask;
@@ -1387,12 +1395,13 @@ g_escape_uri_string (const gchar *string,
static gchar *
-g_escape_file_uri (const gchar *hostname,
- const gchar *pathname)
+g_escape_file_uri (const gchar *hostname,
+ const gchar *pathname,
+ GError **error)
{
char *escaped_hostname = NULL;
- char *escaped_path;
- char *res;
+ char *escaped_path = NULL;
+ char *res = NULL;
#ifdef G_OS_WIN32
char *p, *backslash;
@@ -1413,10 +1422,14 @@ g_escape_file_uri (const gchar *hostname,
if (hostname && *hostname != '\0')
{
- escaped_hostname = g_escape_uri_string (hostname, UNSAFE_HOST);
+ escaped_hostname = g_escape_uri_string (hostname, UNSAFE_HOST, error);
+ if (escaped_hostname == NULL)
+ goto out;
}
- escaped_path = g_escape_uri_string (pathname, UNSAFE_PATH);
+ escaped_path = g_escape_uri_string (pathname, UNSAFE_PATH, error);
+ if (escaped_path == NULL)
+ goto out;
res = g_strconcat ("file://",
(escaped_hostname) ? escaped_hostname : "",
@@ -1424,6 +1437,7 @@ g_escape_file_uri (const gchar *hostname,
escaped_path,
NULL);
+out:
#ifdef G_OS_WIN32
g_free ((char *) pathname);
#endif
@@ -1757,7 +1771,7 @@ g_filename_to_uri (const gchar *filename,
hostname = NULL;
#endif
- escaped_uri = g_escape_file_uri (hostname, filename);
+ escaped_uri = g_escape_file_uri (hostname, filename, error);
return escaped_uri;
}
--
GitLab
From 7e5489cb921d0531ee4ebc9938da30a02084b2fa Mon Sep 17 00:00:00 2001
From: Philip Withnall <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_inet_address_mask_new_from_string',
'fuzz_inet_address_new_from_string',
'fuzz_inet_socket_address_new_from_string',
--
GitLab

View File

@ -1,43 +1,39 @@
%?mingw_package_header %{?mingw_package_header}
# See https://fedoraproject.org/wiki/Packaging:Python_Appendix#Manual_byte_compilation
%global __python %{__python3}
Name: mingw-glib2 Name: mingw-glib2
Version: 2.70.1 Version: 2.78.6
Release: 9%{?dist} Release: 3%{?dist}
Summary: MinGW Windows GLib2 library Summary: MinGW Windows GLib2 library
License: LGPLv2+ License: LGPL-2.0-or-later
URL: http://www.gtk.org URL: http://www.gtk.org
# first two digits of version # first two digits of version
%global release_version %(echo %{version} | awk -F. '{print $1"."$2}') %global release_version %(echo %{version} | awk -F. '{print $1"."$2}')
Source0: http://download.gnome.org/sources/glib/%{release_version}/glib-%{version}.tar.xz Source0: http://download.gnome.org/sources/glib/%{release_version}/glib-%{version}.tar.xz
BuildArch: noarch BuildArch: noarch
ExclusiveArch: %{ix86} x86_64
BuildRequires: meson BuildRequires: meson
BuildRequires: gcc BuildRequires: gcc
BuildRequires: gcc-c++ BuildRequires: gcc-c++
BuildRequires: mingw32-filesystem >= 104 BuildRequires: mingw32-filesystem >= 107
BuildRequires: mingw32-gcc BuildRequires: mingw32-gcc
BuildRequires: mingw32-binutils BuildRequires: mingw32-binutils
BuildRequires: mingw32-win-iconv BuildRequires: mingw32-win-iconv
BuildRequires: mingw32-gettext BuildRequires: mingw32-gettext
BuildRequires: mingw32-libffi BuildRequires: mingw32-libffi
BuildRequires: mingw32-pcre BuildRequires: mingw32-pcre2
BuildRequires: mingw32-zlib BuildRequires: mingw32-zlib >= 1.2.13
BuildRequires: mingw64-filesystem >= 104 BuildRequires: mingw64-filesystem >= 107
BuildRequires: mingw64-gcc BuildRequires: mingw64-gcc
BuildRequires: mingw64-binutils BuildRequires: mingw64-binutils
BuildRequires: mingw64-win-iconv BuildRequires: mingw64-win-iconv
BuildRequires: mingw64-gettext BuildRequires: mingw64-gettext
BuildRequires: mingw64-libffi BuildRequires: mingw64-libffi
BuildRequires: mingw64-pcre BuildRequires: mingw64-pcre2
BuildRequires: mingw64-zlib BuildRequires: mingw64-zlib >= 1.2.13
# Native version required for msgfmt use in build # Native version required for msgfmt use in build
BuildRequires: gettext BuildRequires: gettext
@ -48,37 +44,22 @@ BuildRequires: python3-devel
# https://bugzilla.gnome.org/show_bug.cgi?id=674214 # https://bugzilla.gnome.org/show_bug.cgi?id=674214
Patch1: 0001-Use-CreateFile-on-Win32-to-make-sure-g_unlink-always.patch Patch1: 0001-Use-CreateFile-on-Win32-to-make-sure-g_unlink-always.patch
# https://issues.redhat.com/browse/RHEL-67089
# https://gitlab.gnome.org/GNOME/glib/-/issues/3461
Patch2: CVE-2024-52533-buffer-overflow-in-set_connect_msg.patch
# https://issues.redhat.com/browse/RHEL-131012
# https://gitlab.gnome.org/GNOME/glib/-/issues/3827
# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/4914
# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/4915
Patch3: CVE-2025-13601-gconvert-Error-out-if-g_escape_uri_string-would-overflow.patch
# Prefer the use of GCC constructors over DllMain # Prefer the use of GCC constructors over DllMain
# This prevents having to depend on DllMain in static libraries # This prevents having to depend on DllMain in static libraries
# http://lists.fedoraproject.org/pipermail/mingw/2013-March/006429.html # http://lists.fedoraproject.org/pipermail/mingw/2013-March/006429.html
# http://lists.fedoraproject.org/pipermail/mingw/2013-March/006469.html # http://lists.fedoraproject.org/pipermail/mingw/2013-March/006469.html
# https://bugzilla.gnome.org/show_bug.cgi?id=698118 # https://bugzilla.gnome.org/show_bug.cgi?id=698118
Patch2: glib-prefer-constructors-over-DllMain.patch #Patch5: glib-prefer-constructors-over-DllMain.patch
# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/5172
Patch3: mingw-glib2-2.70.1-CVE-2026-58015.patch
# CVE-2026-58014: one-byte heap under-read with g_key_file_get_locale_string_list()
# https://gitlab.gnome.org/GNOME/glib/-/merge_requests/5171
Patch4: mingw-glib2-2.70.1-CVE-2026-58014.patch
# https://github.com/GNOME/glib/commit/c9da977c178f
Patch5: mingw-glib2-2.70.1-CVE-2026-58016.patch
# https://github.com/GNOME/glib/commit/31f82e22e21bae520b7228f7f57d357fb20df8a4
Patch6: mingw-glib2-2.70.1-CVE-2025-14087.patch
# https://gitlab.gnome.org/GNOME/glib/-/issues/3918
Patch7: mingw-glib2-2.70.1-CVE-2026-58012.patch
# https://gitlab.gnome.org/GNOME/glib/-/work_items/3925
Patch8: mingw-glib2-2.70.1-CVE-2026-58013.patch
# https://gitlab.gnome.org/GNOME/glib/-/issues/3917
Patch9: mingw-glib2-2.70.1-CVE-2026-58011.patch
# https://gitlab.gnome.org/GNOME/glib/-/issues/3915
Patch10: mingw-glib2-2.70.1-CVE-2026-58010.patch
%description %description
MinGW Windows Glib2 library. MinGW Windows Glib2 library.
@ -87,8 +68,7 @@ MinGW Windows Glib2 library.
%package -n mingw32-glib2 %package -n mingw32-glib2
Summary: MinGW Windows Glib2 library for the win32 target Summary: MinGW Windows Glib2 library for the win32 target
# glib-genmarshal and glib-mkenums are written in Python # glib-genmarshal and glib-mkenums are written in Python
# plataform-python due: https://bugzilla.redhat.com/show_bug.cgi?id=1633614 Requires: python3
Requires: platform-python
%description -n mingw32-glib2 %description -n mingw32-glib2
MinGW Windows Glib2 library. MinGW Windows Glib2 library.
@ -105,8 +85,7 @@ Static version of the MinGW Windows GLib2 library.
%package -n mingw64-glib2 %package -n mingw64-glib2
Summary: MinGW Windows Glib2 library for the win64 target Summary: MinGW Windows Glib2 library for the win64 target
# glib-genmarshal and glib-mkenums are written in Python # glib-genmarshal and glib-mkenums are written in Python
# plataform-python due: https://bugzilla.redhat.com/show_bug.cgi?id=1633614 Requires: python3
Requires: platform-python
%description -n mingw64-glib2 %description -n mingw64-glib2
MinGW Windows Glib2 library. MinGW Windows Glib2 library.
@ -120,30 +99,25 @@ Requires: mingw64-gettext-static
Static version of the MinGW Windows GLib2 library. Static version of the MinGW Windows GLib2 library.
%?mingw_debug_package %{?mingw_debug_package}
%prep %prep
%setup -q -n glib-%{version} %autosetup -p1 -n glib-%{version}
%patch1 -p1
%patch2 -p1
%patch3 -p1
%patch4 -p1
%patch5 -p1
%patch6 -p1
%patch7 -p1
%patch8 -p1
%patch9 -p1
%patch10 -p1
%build %build
%mingw_meson --default-library=both \ export MINGW_BUILDDIR_SUFFIX=static
--buildtype=release %mingw_meson --default-library=static
%mingw_ninja
export MINGW_BUILDDIR_SUFFIX=shared
%mingw_meson --default-library=shared
%mingw_ninja %mingw_ninja
%install %install
export DESTDIR=$RPM_BUILD_ROOT export MINGW_BUILDDIR_SUFFIX=static
%mingw_ninja install %mingw_ninja_install
export MINGW_BUILDDIR_SUFFIX=shared
%mingw_ninja_install
# There's a small difference in the file glibconfig.h between the # There's a small difference in the file glibconfig.h between the
# shared and the static build: # shared and the static build:
@ -167,37 +141,39 @@ export DESTDIR=$RPM_BUILD_ROOT
# and -DGOBJECT_STATIC_COMPILATION to their CFLAGS to avoid compile failures # and -DGOBJECT_STATIC_COMPILATION to their CFLAGS to avoid compile failures
# Drop the folder which was temporary used for installing the static bits # Drop the folder which was temporary used for installing the static bits
rm -f $RPM_BUILD_ROOT/%{mingw32_libdir}/charset.alias rm -f %{buildroot}/%{mingw32_libdir}/charset.alias
rm -f $RPM_BUILD_ROOT/%{mingw64_libdir}/charset.alias rm -f %{buildroot}/%{mingw64_libdir}/charset.alias
# Drop the GDB helper files as we can't use the native Fedora GDB to debug Win32 programs # Drop the GDB helper files as we can't use the native Fedora GDB to debug Win32 programs
rm -rf $RPM_BUILD_ROOT%{mingw32_datadir}/gdb rm -rf %{buildroot}%{mingw32_datadir}/gdb
rm -rf $RPM_BUILD_ROOT%{mingw64_datadir}/gdb rm -rf %{buildroot}%{mingw64_datadir}/gdb
# Remove the gtk-doc documentation and manpages which duplicate Fedora native # Remove the gtk-doc documentation and manpages which duplicate Fedora native
rm -rf $RPM_BUILD_ROOT%{mingw32_mandir} rm -rf %{buildroot}%{mingw32_mandir}
rm -rf $RPM_BUILD_ROOT%{mingw32_datadir}/gtk-doc rm -rf %{buildroot}%{mingw32_datadir}/gtk-doc
rm -rf $RPM_BUILD_ROOT%{mingw64_mandir} rm -rf %{buildroot}%{mingw64_mandir}
rm -rf $RPM_BUILD_ROOT%{mingw64_datadir}/gtk-doc rm -rf %{buildroot}%{mingw64_datadir}/gtk-doc
# Bash-completion files aren't interesting for mingw # Bash-completion files aren't interesting for mingw
rm -rf $RPM_BUILD_ROOT%{mingw32_datadir}/bash-completion rm -rf %{buildroot}%{mingw32_datadir}/bash-completion
rm -rf $RPM_BUILD_ROOT%{mingw64_datadir}/bash-completion rm -rf %{buildroot}%{mingw64_datadir}/bash-completion
# The .def files are also of no use to other binaries # The .def files are also of no use to other binaries
rm -f $RPM_BUILD_ROOT%{mingw32_libdir}/*.def rm -f %{buildroot}%{mingw32_libdir}/*.def
rm -f $RPM_BUILD_ROOT%{mingw64_libdir}/*.def rm -f %{buildroot}%{mingw64_libdir}/*.def
# The gdbus-codegen pieces are already in the native glib2 package # The gdbus-codegen pieces are already in the native glib2 package
rm -f $RPM_BUILD_ROOT%{mingw32_bindir}/gdbus-codegen rm -f %{buildroot}%{mingw32_bindir}/gdbus-codegen
rm -rf $RPM_BUILD_ROOT%{mingw32_libdir}/gdbus-2.0 rm -rf %{buildroot}%{mingw32_libdir}/gdbus-2.0
sed -i 's|gdbus_codegen=.*|gdbus_codegen=%{_bindir}/gdbus-codegen|g' %{buildroot}%{mingw32_libdir}/pkgconfig/gio-2.0.pc
rm -f $RPM_BUILD_ROOT%{mingw64_bindir}/gdbus-codegen rm -f %{buildroot}%{mingw64_bindir}/gdbus-codegen
rm -rf $RPM_BUILD_ROOT%{mingw64_libdir}/gdbus-2.0 rm -rf %{buildroot}%{mingw64_libdir}/gdbus-2.0
sed -i 's|gdbus_codegen=.*|gdbus_codegen=%{_bindir}/gdbus-codegen|g' %{buildroot}%{mingw64_libdir}/pkgconfig/gio-2.0.pc
# Drop all .la files # Drop all .la files
find $RPM_BUILD_ROOT -name "*.la" -delete find %{buildroot} -name "*.la" -delete
%mingw_find_lang glib20 %mingw_find_lang glib20
@ -208,6 +184,7 @@ find $RPM_BUILD_ROOT -name "*.la" -delete
%py_byte_compile %{__python3} %{buildroot}%{mingw64_datadir}/glib-2.0/gdb %py_byte_compile %{__python3} %{buildroot}%{mingw64_datadir}/glib-2.0/gdb
%py_byte_compile %{__python3} %{buildroot}%{mingw64_datadir}/glib-2.0/codegen %py_byte_compile %{__python3} %{buildroot}%{mingw64_datadir}/glib-2.0/codegen
# Win32 # Win32
%files -n mingw32-glib2 -f mingw32-glib20.lang %files -n mingw32-glib2 -f mingw32-glib20.lang
%license COPYING %license COPYING
@ -312,65 +289,148 @@ find $RPM_BUILD_ROOT -name "*.la" -delete
%changelog %changelog
* Wed Jul 22 2026 RHEL Packaging Agent <redhat-ymir-agent@redhat.com> - 2.70.1-9 * Mon Dec 8 2025 Konstantin Kostiuk <kkostiuk@redhat.com> - 2.78.6-3
- Fix CVE-2026-58010: off-by-one error in gvs_tuple_is_normal() - Resolves: RHEL-131012 - CVE-2025-13601 mingw-glib2: Integer overflow in in g_escape_uri_string()
Resolves: RHEL-212164
* Wed Jul 22 2026 RHEL Packaging Agent <redhat-ymir-agent@redhat.com> - 2.70.1-8 * Tue Nov 26 2024 Konstantin Kostiuk <kkostiuk@redhat.com> - 2.78.6-2
- Fix CVE-2026-58011: g_date_time_add_full() range validation - Resolves: RHEL-67088 - CVE-2024-52533 mingw-glib2: buffer overflow in set_connect_msg()
Resolves: RHEL-212184
* Wed Jul 22 2026 RHEL Packaging Agent <redhat-ymir-agent@redhat.com> - 2.70.1-7 * Tue May 21 2024 Konstantin Kostiuk <kkostiuk@redhat.com> - 2.78.6-1
- Fix CVE-2026-58013: memcmp buffer over-read in giochannel - Bump glib2 version 2.78.6
Resolves: RHEL-212234 - Fix CVEs: CVE-2024-34397
- Resolves: RHEL-35776
* Wed Jul 22 2026 RHEL Packaging Agent <redhat-ymir-agent@redhat.com> - 2.70.1-6 * Thu Oct 26 2023 Konstantin Kostiuk <kkostiuk@redhat.com> - 2.78.0-1
- Fix CVE-2026-58012: buffer overflow in gregex substitutions - Bump glib2 version 2.78.0
Resolves: RHEL-212200 - Drop DesktopQE gating
- Fix CVEs: CVE-2023-32636, CVE-2023-29499, CVE-2023-32611, CVE-2023-32665, DoS
- Resolves: RHEL-5019
- Resolves: RHEL-5020
- Resolves: RHEL-5092
- Resolves: RHEL-5093
- Resolves: RHEL-5094
* Wed Jul 22 2026 RHEL Packaging Agent <redhat-ymir-agent@redhat.com> - 2.70.1-5 * Mon Aug 7 2023 Konstantin Kostiuk <kkostiuk@redhat.com> - 2.70.1-4
- Fix CVE-2025-14087: integer overflow in GVariant parser - Fix Glib2 build
Resolves: RHEL-154707 - Resolves: RHEL-1056
* Wed Jul 22 2026 RHEL Packaging Agent <redhat-ymir-agent@redhat.com> - 2.70.1-4 * Mon Aug 7 2023 Konstantin Kostiuk <kkostiuk@redhat.com> - 2.70.1-3
- Fix CVE-2026-58016: D-Bus introspection XML node nesting check - Update license to SPDX format
Resolves: RHEL-190617 - Resolves: RHEL-1056
* Wed Jul 22 2026 RHEL Packaging Agent <redhat-ymir-agent@redhat.com> - 2.70.1-3 * Mon Aug 08 2022 Konstantin Kostiuk <kkostiuk@redhat.com> - 2.70.1-2
- Fix CVE-2026-58014: one-byte heap under-read in mingw-glib2 - Rebuild for mingw-zlib update
Resolves: RHEL-190609 resolves: rhbz#2116278
* Mon Jul 20 2026 RHEL Packaging Agent <redhat-ymir-agent@redhat.com> - 2.70.1-2 * Mon Oct 04 2021 Richard W.M. Jones <rjones@redhat.com> - 2.66.7-4
- Fix CVE-2026-58015: D-Bus cookie context path traversal - Rebuild for changed mingw-libffi soname
Resolves: RHEL-212246 resolves: rhbz#2009943
* Thu Dec 23 2021 Yan Vugenfirer <yvugenfi@redhat.com> 2.70.1-1 * Mon Aug 09 2021 Mohan Boddu <mboddu@redhat.com> - 2.66.7-3
- Update to 2.70.1 - Rebuilt for IMA sigs, glibc 2.34, aarch64 flags
- Resolves: rhbz#2034959 Related: rhbz#1991688
* Thu Aug 05 2021 Uri Lublin <uril@redhat.com> - 2.66.7-2 * Fri Apr 16 2021 Mohan Boddu <mboddu@redhat.com> - 2.66.7-2
- Rebuilt - Rebuilt for RHEL 9 BETA on Apr 15th 2021. Related: rhbz#1947937
Resolves: rhbz#1939111 (CVE-2021-27219)
Resolves: rhbz#1935248
* Sun Feb 21 2021 Basil Salman <bsalman@redhat.com> - 2.66.7-1 * Fri Mar 05 2021 Sandro Mani <manisandro@gmail.com> - 2.66.7-1
- Update to 2.66.7 - Update to 2.66.7
- Rebuild from newer version that fixes CVE-2021-27219
- Resolves: rhbz#1928649
* Tue Feb 16 2021 Basil Salman <bsalman@redhat.com> - 2.66.4-1 * Tue Jan 26 2021 Fedora Release Engineering <releng@fedoraproject.org> - 2.66.2-2
- Update to 2.66.4 - Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild
- Dropped upstreamed patches
- Switched to meson
Resolves: rhbz#1928649
* Thu Sep 27 2018 Victor Toso <victortoso@redhat.com> - 2.56.1-3 * Mon Oct 19 2020 Sandro Mani <manisandro@gmail.com> - 2.66.2-1
- Use platform-python in Require - Update to 2.66.2
Related: rhbz#1633614
* Thu Aug 16 2018 Snir Sheriber <ssheribe@redhat.com> - 2.56.1-2 * Mon Oct 05 2020 Sandro Mani <manisandro@gmail.com> - 2.66.1-1
- ExclusiveArch: i686, x86_64 - Update to 2.66.1
Related: rhbz#1615874
* Tue Sep 15 2020 Sandro Mani <manisandro@gmail.com> - 2.66.0-1
- Update to 2.66.0
* Wed Aug 12 13:36:55 GMT 2020 Sandro Mani <manisandro@gmail.com> - 2.64.3-3
- Rebuild (mingw-gettext)
* Tue Jul 28 2020 Fedora Release Engineering <releng@fedoraproject.org> - 2.64.3-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild
* Fri May 22 2020 Sandro Mani <manisandro@gmail.com> - 2.64.3-1
- Update to 2.64.3
* Mon Apr 20 2020 Sandro Mani <manisandro@gmail.com> - 2.64.2-2
- Rebuild (gettext)
* Sat Apr 11 2020 Sandro Mani <manisandro@gmail.com> - 2.64.2-1
- Update to 2.64.2
* Thu Mar 12 2020 Sandro Mani <manisandro@gmail.com> - 2.64.1-1
- Update to 2.64.1
* Fri Mar 06 2020 Sandro Mani <manisandro@gmail.com> - 2.64.0-1
- Update to 2.64.0
* Tue Feb 25 2020 Sandro Mani <manisandro@gmail.com> - 2.63.6-1
- Update to 2.63.6
* Tue Feb 11 2020 Sandro Mani <manisandro@gmail.com> - 2.63.5-2
- Backport proposed patch for CVE-2020-6750
* Mon Feb 03 2020 Sandro Mani <manisandro@gmail.com> - 2.63.5-1
- Update to 2.63.5
* Wed Jan 29 2020 Fedora Release Engineering <releng@fedoraproject.org> - 2.63.4-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild
* Fri Jan 24 2020 Sandro Mani <manisandro@gmail.com> - 2.63.4-1
- Update to 2.63.4
* Mon Dec 16 2019 Sandro Mani <manisandro@gmail.com> - 2.63.3-1
- Update to 2.63.3
* Tue Dec 03 2019 Sandro Mani <manisandro@gmail.com> - 2.63.2-1
- Update to 2.63.2
* Tue Oct 08 2019 Sandro Mani <manisandro@gmail.com> - 2.63.0-2
- Rebuild (Changes/Mingw32GccDwarf2)
* Fri Oct 04 2019 Sandro Mani <manisandro@gmail.com> - 2.63.0-1
- Update to 2.63.0
* Mon Sep 16 2019 Sandro Mani <manisandro@gmail.com> - 2.62.0-1
- Update to 2.62.0
* Wed Sep 04 2019 Sandro Mani <manisandro@gmail.com> - 2.61.3-1
- Update to 2.61.3
* Thu Aug 15 2019 Fabiano Fidêncio <fidencio@redhat.com> - 2.61.2-1
- Update to 2.61.2
* Thu Jul 25 2019 Fedora Release Engineering <releng@fedoraproject.org> - 2.58.3-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild
* Fri Feb 01 2019 Fedora Release Engineering <releng@fedoraproject.org> - 2.58.3-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild
* Tue Jan 22 2019 Kalev Lember <klember@redhat.com> - 2.58.3-1
- Update to 2.58.3
* Tue Jan 08 2019 Kalev Lember <klember@redhat.com> - 2.58.2-1
- Update to 2.58.2
* Fri Sep 21 2018 Kalev Lember <klember@redhat.com> - 2.58.1-1
- Update to 2.58.1
* Thu Aug 02 2018 Thomas Sailer <t.sailer@alumni.ethz.ch> - 2.57.2-1
- Update to 2.57.2
* Thu Aug 02 2018 Thomas Sailer <t.sailer@alumni.ethz.ch> - 2.57.1-1
- Update to 2.57.1
* Fri Jul 13 2018 Fedora Release Engineering <releng@fedoraproject.org> - 2.56.1-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild
* Tue Jun 19 2018 Miro Hrončok <mhroncok@redhat.com> - 2.56.1-2
- Rebuilt for Python 3.7
* Mon May 28 2018 Thomas Sailer <t.sailer@alumni.ethz.ch> - 2.56.1-1 * Mon May 28 2018 Thomas Sailer <t.sailer@alumni.ethz.ch> - 2.56.1-1
- Update to 2.56.1 - Update to 2.56.1

View File

@ -1,6 +0,0 @@
--- !Policy
product_versions:
- rhel-8
decision_context: osci_compose_gate
rules:
- !PassingTestCaseRule {test_case_name: desktop-qe.desktop-ci.tier1-gating.functional}

View File

@ -1,80 +0,0 @@
From bc90511c1eb333e26e0bc0eaee62375d0e788db6 Mon Sep 17 00:00:00 2001
From: Erik van Pienbroek <epienbro@fedoraproject.org>
Date: Tue, 16 Apr 2013 11:42:11 +0200
Subject: [PATCH] win32: Prefer the use of constructors over DllMain
This prevents having to depend on DllMain in static libraries
Constructors are available in both the GCC build (GCC 2.7 and later)
and the MSVC build (MSVC 2008 and later using _Pragma, earlier
versions using #pragma)
---
glib/glib-init.c | 22 ++++++++++++++--------
1 file changed, 14 insertions(+), 8 deletions(-)
diff --git a/glib/glib-init.c b/glib/glib-init.c
index 0032ee8..dd6ccbf 100644
--- a/glib/glib-init.c
+++ b/glib/glib-init.c
@@ -223,12 +223,14 @@ glib_init (void)
#if defined (G_OS_WIN32)
+HMODULE glib_dll = NULL;
+
+#if defined (DLL_EXPORT)
+
BOOL WINAPI DllMain (HINSTANCE hinstDLL,
DWORD fdwReason,
LPVOID lpvReserved);
-HMODULE glib_dll;
-
BOOL WINAPI
DllMain (HINSTANCE hinstDLL,
DWORD fdwReason,
@@ -238,14 +240,6 @@ DllMain (HINSTANCE hinstDLL,
{
case DLL_PROCESS_ATTACH:
glib_dll = hinstDLL;
- g_crash_handler_win32_init ();
- g_clock_win32_init ();
-#ifdef THREADS_WIN32
- g_thread_win32_init ();
-#endif
- glib_init ();
- /* must go after glib_init */
- g_console_win32_init ();
break;
case DLL_THREAD_DETACH:
@@ -259,7 +256,10 @@ DllMain (HINSTANCE hinstDLL,
return TRUE;
}
-#elif defined (G_HAS_CONSTRUCTORS)
+#endif /* defined (DLL_EXPORT) */
+#endif /* defined (G_OS_WIN32) */
+
+#if defined (G_HAS_CONSTRUCTORS)
#ifdef G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA
#pragma G_DEFINE_CONSTRUCTOR_PRAGMA_ARGS(glib_init_ctor)
@@ -269,7 +266,15 @@ G_DEFINE_CONSTRUCTOR(glib_init_ctor)
static void
glib_init_ctor (void)
{
+#if defined (G_OS_WIN32)
+ g_clock_win32_init ();
+#ifdef THREADS_WIN32
+ g_thread_win32_init ();
+#endif /* defined (THREADS_WIN32) */
+#endif /* defined (G_OS_WIN32) */
glib_init ();
+ /* must go after glib_init */
+ g_console_win32_init ();
}
#else
--
1.8.2

View File

@ -1,65 +0,0 @@
From 074d82962028125c7886e5edcff1a58a508e0e61 Mon Sep 17 00:00:00 2001
From: Philip Withnall <pwithnall@gnome.org>
Date: Tue, 25 Nov 2025 19:02:56 +0000
Subject: [PATCH] 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>
Fixes: #3834
---
glib/gvariant-parser.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/glib/gvariant-parser.c b/glib/gvariant-parser.c
index bb5238bea..af6527d40 100644
--- a/glib/gvariant-parser.c
+++ b/glib/gvariant-parser.c
@@ -594,7 +594,7 @@ ast_resolve (AST *ast,
{
GVariant *value;
gchar *pattern;
- gint i, j = 0;
+ size_t i, j = 0;
pattern = ast_get_pattern (ast, error);
@@ -1555,9 +1555,9 @@ string_free (AST *ast)
* No leading/trailing space allowed. */
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)
@@ -1618,7 +1618,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);
@@ -1748,7 +1748,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);

View File

@ -1,106 +0,0 @@
From eb63e89e237d35fb1d3cb757ea97b4c8806269a0 Mon Sep 17 00:00:00 2001
From: Philip Withnall <pwithnall@gnome.org>
Date: Sun, 29 Mar 2026 19:10:41 +0100
Subject: [PATCH] gvariant: Fix an off-by-one error in an offset comparison
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This allows a single byte out-of-bounds read off the end of the
(potentially untrusted) byte array backing a `GVariant` when its
being checked for normal form.
I cant see how this could practically be exploited, but its certainly
a security bug as the `GVariant` normal form checking code is supposed
to be robust to malicious inputs.
Spotted by linhlhq as #YWH-PGM9867-190, and fix and reproducer provided
by them too, thanks. Confirmed and turned into a unit test by me.
Signed-off-by: Philip Withnall <pwithnall@gnome.org>
Fixes: #3915
---
glib/gvariant-serialiser.c | 2 +-
glib/tests/gvariant.c | 48 ++++++++++++++++++++++++++++++++++++++
2 files changed, 49 insertions(+), 1 deletion(-)
diff --git a/glib/gvariant-serialiser.c b/glib/gvariant-serialiser.c
index 832a8fdc2..1bf3e4688 100644
--- a/glib/gvariant-serialiser.c
+++ b/glib/gvariant-serialiser.c
@@ -1079,7 +1079,7 @@ gvs_tuple_is_normal (GVariantSerialised value)
while (offset & alignment)
{
- if (offset > value.size || value.data[offset] != '\0')
+ if (offset >= value.size || value.data[offset] != '\0')
return FALSE;
offset++;
}
diff --git a/glib/tests/gvariant.c b/glib/tests/gvariant.c
index 0110f2664..dd3af6941 100644
--- a/glib/tests/gvariant.c
+++ b/glib/tests/gvariant.c
@@ -5047,6 +5047,52 @@ test_normal_checking_tuple_offsets (void)
g_variant_unref (variant);
}
+/* This is a regression test that looping over the padding bytes in a short
+ * (non-normal) tuple doesnt overflow the input data.
+ *
+ * See https://gitlab.gnome.org/GNOME/glib/-/issues/3915 */
+static void
+test_normal_checking_tuple_offsets6 (void)
+{
+ /*
+ * Type: (ynqiuxthdsog) — 12 members, first member 'y' (byte) has
+ * alignment 0, second 'n' (int16) has alignment 1.
+ * With 1 byte of data (0x28), after reading the first byte member,
+ * offset=1, alignment check for 'n' requires offset to be even,
+ * so the while loop checks value.data[1] — but size is only 1.
+ *
+ * Use heap allocation via GBytes so ASan reports heap-buffer-overflow.
+ */
+ uint8_t *heap_data = NULL;
+ GBytes *bytes = NULL;
+ const GVariantType *data_type = G_VARIANT_TYPE ("(ynqiuxthdsog)");
+ GVariant *variant = NULL;
+ GVariant *normal_variant = NULL;
+ GVariant *expected = NULL;
+
+ g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/3915");
+
+ heap_data = g_malloc (1);
+ heap_data[0] = 0x28;
+ bytes = g_bytes_new_take (heap_data, 1);
+
+ variant = g_variant_new_from_bytes (data_type, bytes, FALSE);
+ g_assert_nonnull (variant);
+
+ g_assert_false (g_variant_is_normal_form (variant));
+
+ normal_variant = g_variant_get_normal_form (variant);
+ g_assert_nonnull (normal_variant);
+
+ expected = g_variant_new_parsed ("(byte 0x28, int16 0, uint16 0, 0, uint32 0, int64 0, uint64 0, handle 0, 0.0, '', objectpath '/', signature '')");
+ g_assert_cmpvariant (expected, variant);
+ g_assert_cmpvariant (expected, normal_variant);
+
+ g_variant_unref (expected);
+ g_variant_unref (normal_variant);
+ g_variant_unref (variant);
+}
+
/* Test that an empty object path is normalised successfully to the base object
* path, /. */
static void
@@ -5191,6 +5237,8 @@ main (int argc, char **argv)
test_normal_checking_array_offsets);
g_test_add_func ("/gvariant/normal-checking/tuple-offsets",
test_normal_checking_tuple_offsets);
+ g_test_add_func ("/gvariant/normal-checking/tuple-offsets6",
+ test_normal_checking_tuple_offsets6);
g_test_add_func ("/gvariant/normal-checking/empty-object-path",
test_normal_checking_empty_object_path);

View File

@ -1,122 +0,0 @@
From fbef21c7da7757239d6df411a24c7dbb345ab966 Mon Sep 17 00:00:00 2001
From: Philip Withnall <pwithnall@gnome.org>
Date: Sun, 29 Mar 2026 23:19:47 +0100
Subject: [PATCH 1/2] gdatetime: Factor out a couple of magic constants
This introduces no functional changes, it just makes the code a little
clearer.
Signed-off-by: Philip Withnall <pwithnall@gnome.org>
---
glib/gdatetime.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/glib/gdatetime.c b/glib/gdatetime.c
index a31afe713..029636c08 100644
--- a/glib/gdatetime.c
+++ b/glib/gdatetime.c
@@ -130,7 +130,7 @@ struct _GDateTime
gint interval;
/* 1 is 0001-01-01 in Proleptic Gregorian */
- gint32 days;
+ gint32 days; /* in range [MIN_DAYS, MAX_DAYS] */
gint ref_count; /* (atomic) */
};
@@ -172,6 +172,9 @@ struct _GDateTime
#define JULIAN_YEAR(d) ((d)->julian / 365.25)
#define DAYS_PER_PERIOD (G_GINT64_CONSTANT (2914695))
+#define MIN_DAYS 1 /* the days count for 0001-01-01 in Proleptic Gregorian */
+#define MAX_DAYS 3652059 /* the days count for 9999-12-31 in Proleptic Gregorian */
+
static const guint16 days_in_months[2][13] =
{
{ 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
@@ -781,7 +784,7 @@ g_date_time_from_instant (GTimeZone *tz,
datetime->days = instant / USEC_PER_DAY;
datetime->usec = instant % USEC_PER_DAY;
- if (datetime->days < 1 || 3652059 < datetime->days)
+ if (datetime->days < MIN_DAYS || datetime->days > MAX_DAYS)
{
g_date_time_unref (datetime);
datetime = NULL;
@@ -817,7 +820,7 @@ g_date_time_deal_with_date_change (GDateTime *datetime)
gint64 full_time;
gint64 usec;
- if (datetime->days < 1 || datetime->days > 3652059)
+ if (datetime->days < MIN_DAYS || datetime->days > MAX_DAYS)
return FALSE;
was_dst = g_time_zone_is_dst (datetime->tz, datetime->interval);
From 5f0c67435364fe682fe9dcc1d23645134a445a17 Mon Sep 17 00:00:00 2001
From: Philip Withnall <pwithnall@gnome.org>
Date: Sun, 29 Mar 2026 23:46:17 +0100
Subject: [PATCH 2/2] gdatetime: Add missing range validation to
g_date_time_add_full()
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Otherwise its possible to create a non-`NULL` but invalid `GDateTime`,
which breaks all kinds of internal assumptions.
Spotted by linhlhq as #YWH-PGM9867-191. Thanks to them for providing a
suggested fix and a test case, which I have adapted and validated.
Signed-off-by: Philip Withnall <pwithnall@gnome.org>
Fixes: #3917
---
glib/gdatetime.c | 4 +++-
glib/tests/gdatetime.c | 18 ++++++++++++++++++
2 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/glib/gdatetime.c b/glib/gdatetime.c
index 029636c08..883322891 100644
--- a/glib/gdatetime.c
+++ b/glib/gdatetime.c
@@ -2022,7 +2022,9 @@ g_date_time_add_full (GDateTime *datetime,
new->days = full_time / USEC_PER_DAY;
new->usec = full_time % USEC_PER_DAY;
- /* XXX validate */
+ /* Validate its still in the range 0001-01-01 to 9999-12-31 */
+ if (new->days < MIN_DAYS || new->days > MAX_DAYS)
+ g_clear_pointer (&new, g_date_time_unref);
return new;
}
diff --git a/glib/tests/gdatetime.c b/glib/tests/gdatetime.c
index 12f332b44..88041a684 100644
--- a/glib/tests/gdatetime.c
+++ b/glib/tests/gdatetime.c
@@ -1098,6 +1098,24 @@ test_GDateTime_add_full (void)
TEST_ADD_FULL (2010, 8, 25, 22, 45, 0,
0, 1, 6, 1, 25, 0,
2010, 10, 2, 0, 10, 0);
+
+#define TEST_ADD_FULL_ERROR(y,m,d,h,mi,s,ay,am,ad,ah,ami,as) G_STMT_START { \
+ GDateTime *dt; \
+ dt = g_date_time_new_utc (y, m, d, h, mi, s); \
+ g_assert_null (g_date_time_add_full (dt, ay, am, ad, ah, ami, as)); \
+ g_date_time_unref (dt); \
+} G_STMT_END
+
+ TEST_ADD_FULL_ERROR ( 1, 12, 1, 0, 0, 0,
+ -1, 0, 0, 0, 0, 0);
+ TEST_ADD_FULL_ERROR ( 1, 12, 1, 0, 0, 0,
+ 10000, 0, 0, 0, 0, 0);
+ TEST_ADD_FULL_ERROR ( 9999, 12, 1, 0, 0, 0,
+ -10000, 0, 0, 0, 0, 0);
+ TEST_ADD_FULL_ERROR ( 1, 12, 1, 0, 0, 0,
+ 0, 0, 3660001, 0, 0, 0);
+ TEST_ADD_FULL_ERROR ( 9999, 12, 1, 0, 0, 0,
+ 0, 0, -3660001, 0, 0, 0);
}
static void

View File

@ -1,221 +0,0 @@
From a9a4c378a05723eb164f193d585b6611e4646b65 Mon Sep 17 00:00:00 2001
From: Philip Withnall <pwithnall@gnome.org>
Date: Tue, 31 Mar 2026 16:13:57 +0100
Subject: [PATCH] gregex: Fix case changing substitutions with G_REGEX_RAW
In `G_REGEX_RAW` mode, the input string is treated as a byte array
(basically ASCII) rather than a unichar array. Accordingly, the case
changing code for substitutions needs to operate on bytes with
`G_REGEX_RAW`, rather than operating on unichars.
This fixes a potential buffer overflow when trying to do a case change
on a match of a set of bytes which are a truncated multi-byte UTF-8
encoding at the end of the input buffer.
Spotted by linhlhq as #YWH-PGM9867-193. I adapted their reproducer as
the unit test, but implemented the fix in `gregex.c` independently.
Signed-off-by: Philip Withnall <pwithnall@gnome.org>
Fixes: #3918
---
glib/gregex.c | 59 ++++++++++++++++++++++++++++++++++------------
glib/tests/regex.c | 53 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 97 insertions(+), 15 deletions(-)
diff --git a/glib/gregex.c b/glib/gregex.c
index a8a35a424..948df3f95 100644
--- a/glib/gregex.c
+++ b/glib/gregex.c
@@ -2655,19 +2655,25 @@ split_replacement (const gchar *replacement,
return g_list_reverse (list);
}
-/* Change the case of c based on change_case. */
-#define CHANGE_CASE(c, change_case) \
+/* Change the case of c based on change_case.
+ * g_ascii_to*() will happily pass through non-ASCII bytes unchanged. */
+#define UTF8_CHANGE_CASE(c, change_case) \
(((change_case) & CHANGE_CASE_LOWER_MASK) ? \
g_unichar_tolower (c) : \
g_unichar_toupper (c))
+#define RAW_CHANGE_CASE(c, change_case) \
+ (((change_case) & CHANGE_CASE_LOWER_MASK) ? \
+ g_ascii_tolower (c) : \
+ g_ascii_toupper (c))
+/* If @text_is_raw is set, @text might not be valid UTF-8 (but will be
+ * nul-terminated). */
static void
string_append (GString *string,
const gchar *text,
+ gboolean text_is_raw,
ChangeCase *change_case)
{
- gunichar c;
-
if (text[0] == '\0')
return;
@@ -2677,22 +2683,44 @@ string_append (GString *string,
}
else if (*change_case & CHANGE_CASE_SINGLE_MASK)
{
- c = g_utf8_get_char (text);
- g_string_append_unichar (string, CHANGE_CASE (c, *change_case));
- g_string_append (string, g_utf8_next_char (text));
+ if (!text_is_raw)
+ {
+ gunichar c = g_utf8_get_char (text);
+ g_string_append_unichar (string, UTF8_CHANGE_CASE (c, *change_case));
+ g_string_append (string, g_utf8_next_char (text));
+ }
+ else
+ {
+ g_string_append_c (string, RAW_CHANGE_CASE (text[0], *change_case));
+ g_string_append (string, text + 1);
+ }
+
*change_case = CHANGE_CASE_NONE;
}
else
{
- while (*text != '\0')
+ if (!text_is_raw)
{
- c = g_utf8_get_char (text);
- g_string_append_unichar (string, CHANGE_CASE (c, *change_case));
- text = g_utf8_next_char (text);
+ while (*text != '\0')
+ {
+ gunichar c = g_utf8_get_char (text);
+ g_string_append_unichar (string, UTF8_CHANGE_CASE (c, *change_case));
+ text = g_utf8_next_char (text);
+ }
+ }
+ else
+ {
+ while (*text != '\0')
+ {
+ char c = *text;
+ g_string_append_c (string, RAW_CHANGE_CASE (c, *change_case));
+ text++;
+ }
}
}
}
+/* @match_info is (nullable) */
static gboolean
interpolate_replacement (const GMatchInfo *match_info,
GString *result,
@@ -2702,6 +2730,7 @@ interpolate_replacement (const GMatchInfo *match_info,
InterpolationData *idata;
gchar *match;
ChangeCase change_case = CHANGE_CASE_NONE;
+ gboolean is_raw = (match_info != NULL && (match_info->regex->compile_opts & G_REGEX_RAW));
for (list = data; list; list = list->next)
{
@@ -2709,10 +2738,10 @@ interpolate_replacement (const GMatchInfo *match_info,
switch (idata->type)
{
case REPL_TYPE_STRING:
- string_append (result, idata->text, &change_case);
+ string_append (result, idata->text, is_raw, &change_case);
break;
case REPL_TYPE_CHARACTER:
- g_string_append_c (result, CHANGE_CASE (idata->c, change_case));
+ g_string_append_c (result, UTF8_CHANGE_CASE (idata->c, change_case));
if (change_case & CHANGE_CASE_SINGLE_MASK)
change_case = CHANGE_CASE_NONE;
break;
@@ -2720,7 +2749,7 @@ interpolate_replacement (const GMatchInfo *match_info,
match = g_match_info_fetch (match_info, idata->num);
if (match)
{
- string_append (result, match, &change_case);
+ string_append (result, match, is_raw, &change_case);
g_free (match);
}
break;
@@ -2728,7 +2757,7 @@ interpolate_replacement (const GMatchInfo *match_info,
match = g_match_info_fetch_named (match_info, idata->text);
if (match)
{
- string_append (result, match, &change_case);
+ string_append (result, match, is_raw, &change_case);
g_free (match);
}
break;
diff --git a/glib/tests/regex.c b/glib/tests/regex.c
index 88d12edf6..818d6d0a0 100644
--- a/glib/tests/regex.c
+++ b/glib/tests/regex.c
@@ -2183,6 +2183,58 @@ pcre_ge (guint64 major, guint64 minor)
return (pcre_major > major) || (pcre_major == major && pcre_minor >= minor);
}
+static void
+test_replace_raw_change_case (void)
+{
+ GError *local_error = NULL;
+ GRegex *regex = NULL;
+
+ g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/3918");
+ g_test_summary ("Test that case changes as part of a replacement are handled correctly in G_REGEX_RAW mode");
+
+ /*
+ * Match a multi-byte sequence in RAW mode. The pattern matches
+ * exactly 2 bytes. The subject contains a 4-byte UTF-8 lead (0xF4)
+ * followed by only one continuation byte, then NUL.
+ *
+ * The matched substring will be "\xf4\x80" (2 bytes, heap-allocated
+ * as 3-byte buffer with NUL). If the code regresses and tries to handle
+ * the replacement as UTF-8 then g_utf8_get_char() would see 0xF4 and try
+ * to read 4 bytes, going 1 byte past the NUL into OOB territory.
+ */
+ regex = g_regex_new ("..", G_REGEX_RAW, 0, &local_error);
+ g_assert_no_error (local_error);
+
+ /*
+ * Build a subject string with truncated UTF-8.
+ * \xF4 = 4-byte UTF-8 lead byte
+ * \x80 = continuation byte
+ * No 3rd/4th continuation bytes — the match is only 2 bytes.
+ *
+ * \U\0 = uppercase the entire match → triggers string_append()
+ * with case change on the 2-byte non-UTF-8 match.
+ */
+ char subject[] = "\xf4\x80";
+ char *result = g_regex_replace (regex, subject, -1, 0, "\\U\\0", 0, &local_error);
+ g_assert_no_error (local_error);
+
+ g_clear_pointer (&result, g_free);
+ g_clear_pointer (&regex, g_regex_unref);
+
+ /*
+ * Second variant: single-char case change \u with \0 backreference.
+ */
+ regex = g_regex_new (".", G_REGEX_RAW, 0, &local_error);
+ g_assert_no_error (local_error);
+
+ char subject2[] = "\xe6\xb0"; /* 3-byte UTF-8 lead, only 2 bytes */
+ result = g_regex_replace (regex, subject2, -1, 0, "\\u\\0", 0, &local_error);
+ g_assert_no_error (local_error);
+
+ g_clear_pointer (&result, g_free);
+ g_clear_pointer (&regex, g_regex_unref);
+}
+
int
main (int argc, char *argv[])
{
@@ -2200,6 +2252,7 @@ main (int argc, char *argv[])
g_test_add_func ("/regex/multiline", test_multiline);
g_test_add_func ("/regex/explicit-crlf", test_explicit_crlf);
g_test_add_func ("/regex/max-lookbehind", test_max_lookbehind);
+ g_test_add_func ("/regex/replace-raw-change-case", test_replace_raw_change_case);
/* TEST_NEW(pattern, compile_opts, match_opts) */
TEST_NEW("[A-Z]+", G_REGEX_CASELESS | G_REGEX_EXTENDED | G_REGEX_OPTIMIZE, G_REGEX_MATCH_NOTBOL | G_REGEX_MATCH_PARTIAL);

View File

@ -1,120 +0,0 @@
From 5e8a44975bddd21a762e58c6717f841e90594f03 Mon Sep 17 00:00:00 2001
From: Philip Withnall <pwithnall@gnome.org>
Date: Tue, 28 Apr 2026 16:45:14 +0100
Subject: [PATCH] giochannel: Fix memcmp() off the end of the buffer with long
terminators
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
If the line terminator is longer than a single byte, and the current
line extends to the end of the buffer, and the buffer (which is a
`GString`) is near a power of two in length (as thats how `GString`s
are allocated) its possible for the `memcmp()` which checks the
terminator to read off the end of the string buffer.
Fix that by checking the terminator length against the last character
before calling `memcmp()`. Add a unit test.
Spotted by linhlhq as #YWH-PGM9867-199. The fix is theirs (validated by
me), and the unit test is adapted from their proof of concept.
Signed-off-by: Philip Withnall <pwithnall@gnome.org>
Fixes: #3925
---
glib/giochannel.c | 3 ++-
glib/tests/io-channel.c | 60 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 62 insertions(+), 1 deletion(-)
diff --git a/glib/giochannel.c b/glib/giochannel.c
index e93c4b458..66b68e645 100644
--- a/glib/giochannel.c
+++ b/glib/giochannel.c
@@ -1830,7 +1830,8 @@ read_again:
{
if (channel->line_term)
{
- if (memcmp (channel->line_term, nextchar, line_term_len) == 0)
+ if ((size_t) (lastchar - nextchar) >= line_term_len &&
+ memcmp (channel->line_term, nextchar, line_term_len) == 0)
{
line_length = nextchar - use_buf->str;
got_term_len = line_term_len;
diff --git a/glib/tests/io-channel.c b/glib/tests/io-channel.c
index 4a1b10876..c619fb00f 100644
--- a/glib/tests/io-channel.c
+++ b/glib/tests/io-channel.c
@@ -69,6 +69,65 @@ test_read_line_embedded_nuls (void)
g_free (filename);
}
+static void
+test_read_line_long_terminator (void)
+{
+ uint8_t *test_data = NULL;
+ size_t test_data_len = 0;
+ int fd;
+ char *filename = NULL;
+ GIOChannel *channel = NULL;
+ GError *local_error = NULL;
+ char *line = NULL;
+ size_t line_length, terminator_pos;
+ const char *line_term;
+ int line_term_length;
+ GIOStatus status;
+
+ g_test_summary ("Test that reading a line when using a long terminator doesnt over-read the buffer.");
+ g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/work_items/3925");
+
+ /* Write out a temporary file containing 2047 bytes. This is enough to make it
+ * near the length of the GString buffer when read back in. */
+ fd = g_file_open_tmp ("glib-test-io-channel-XXXXXX", &filename, &local_error);
+ g_assert_no_error (local_error);
+ g_close (g_steal_fd (&fd), NULL);
+
+ test_data_len = 2047;
+ test_data = g_malloc (test_data_len);
+ memset (test_data, 'M', test_data_len);
+ g_file_set_contents (filename, (const gchar *) test_data, test_data_len, &local_error);
+ g_assert_no_error (local_error);
+
+ /* Create the channel. */
+ channel = g_io_channel_new_file (filename, "r", &local_error);
+ g_assert_no_error (local_error);
+
+ /* Use a long line terminator so it could potentially over-read the end of the buffer. */
+ g_io_channel_set_line_term (channel, "DEADBEEF", 8);
+
+ line_term = g_io_channel_get_line_term (channel, &line_term_length);
+ g_assert_cmpstr (line_term, ==, "DEADBEEF");
+ g_assert_cmpint (line_term_length, ==, 8);
+
+ g_io_channel_set_encoding (channel, "UTF-8", &local_error);
+ g_assert_no_error (local_error);
+
+ status = g_io_channel_read_line (channel, &line, &line_length,
+ &terminator_pos, &local_error);
+ g_assert_no_error (local_error);
+ g_assert_cmpint (status, ==, G_IO_STATUS_NORMAL);
+ g_assert_cmpuint (line_length, ==, 2047);
+ g_assert_cmpuint (terminator_pos, ==, 2047);
+ g_assert_cmpmem (line, line_length, test_data, test_data_len);
+
+ g_free (line);
+ g_io_channel_unref (channel);
+ g_free (test_data);
+ g_unlink (filename);
+ g_free (filename);
+}
+
int
main (int argc,
char *argv[])
@@ -76,6 +135,7 @@ main (int argc,
g_test_init (&argc, &argv, NULL);
g_test_add_func ("/io-channel/read-line/embedded-nuls", test_read_line_embedded_nuls);
+ g_test_add_func ("/io-channel/read-line/long-terminator", test_read_line_long_terminator);
return g_test_run ();
}

View File

@ -1,101 +0,0 @@
From 8e49ae633b6eaceff9881ea15c8bb48cf11c8a53 Mon Sep 17 00:00:00 2001
From: Philip Withnall <pwithnall@gnome.org>
Date: Sat, 11 Apr 2026 14:42:57 +0100
Subject: [PATCH] gkeyfile: Fix a one-byte heap under-read with
g_key_file_get_locale_string_list()
If this method was called on a key file key which has an empty value,
`len == 0` and this leads to a one-byte under-read off the start of the
key file buffer.
Spotted by linhlhq as #YWH-PGM9867-200. The suggested fix is theirs, and
the unit test is adapted from their report. I added the fuzzing test.
Signed-off-by: Philip Withnall <pwithnall@gnome.org>
Fixes: #3930
---
fuzzing/fuzz_key.c | 9 +++++++++
glib/gkeyfile.c | 2 +-
glib/tests/keyfile.c | 23 +++++++++++++++++++++++
3 files changed, 33 insertions(+), 1 deletion(-)
diff --git a/fuzzing/fuzz_key.c b/fuzzing/fuzz_key.c
index 9f1f9187e..285bad26f 100644
--- a/fuzzing/fuzz_key.c
+++ b/fuzzing/fuzz_key.c
@@ -6,11 +6,20 @@ test_parse (const gchar *data,
GKeyFileFlags flags)
{
GKeyFile *key = NULL;
+ char *comment = NULL;
+ char **list = NULL;
key = g_key_file_new ();
g_key_file_load_from_data (key, (const gchar*) data, size, G_KEY_FILE_NONE,
NULL);
+ /* Also try some additional parsing and see if it crashes */
+ comment = g_key_file_get_comment (key, "group", "key", NULL);
+ g_free (comment);
+
+ list = g_key_file_get_locale_string_list (key, "group", "key", "de", NULL, NULL);
+ g_strfreev (list);
+
g_key_file_free (key);
}
diff --git a/glib/gkeyfile.c b/glib/gkeyfile.c
index 17cf85660..76459daab 100644
--- a/glib/gkeyfile.c
+++ b/glib/gkeyfile.c
@@ -2407,7 +2407,7 @@ g_key_file_get_locale_string_list (GKeyFile *key_file,
}
len = strlen (value);
- if (value[len - 1] == key_file->list_separator)
+ if (len > 0 && value[len - 1] == key_file->list_separator)
value[len - 1] = '\0';
list_separator[0] = key_file->list_separator;
diff --git a/glib/tests/keyfile.c b/glib/tests/keyfile.c
index 1f5be8b38..17724bc15 100644
--- a/glib/tests/keyfile.c
+++ b/glib/tests/keyfile.c
@@ -800,6 +800,28 @@ test_locale_string_multiple_loads (void)
g_free (old_locale);
}
+static void
+test_locale_string_empty (void)
+{
+ GKeyFile *keyfile = NULL;
+ GError *local_error = NULL;
+ const char *data =
+ "[valid]\n"
+ "key1=\n";
+
+ g_test_summary ("Check that loading an empty translatable string works");
+ g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/3930");
+
+ keyfile = g_key_file_new ();
+
+ g_key_file_load_from_data (keyfile, data, -1, G_KEY_FILE_NONE, &local_error);
+ g_assert_no_error (local_error);
+
+ check_locale_string_list_value (keyfile, "valid", "key1", NULL, NULL);
+
+ g_key_file_free (keyfile);
+}
+
static void
test_lists (void)
{
@@ -1832,6 +1854,7 @@ main (int argc, char *argv[])
g_test_add_func ("/keyfile/number", test_number);
g_test_add_func ("/keyfile/locale-string", test_locale_string);
g_test_add_func ("/keyfile/locale-string/multiple-loads", test_locale_string_multiple_loads);
+ g_test_add_func ("/keyfile/locale-string/empty", test_locale_string_empty);
g_test_add_func ("/keyfile/lists", test_lists);
g_test_add_func ("/keyfile/lists-set-get", test_lists_set_get);
g_test_add_func ("/keyfile/group-remove", test_group_remove);

View File

@ -1,578 +0,0 @@
From a37a31d4088cf9563756dbbf0c3a7d78e43cb9ee Mon Sep 17 00:00:00 2001
From: Philip Withnall <pwithnall@gnome.org>
Date: Tue, 28 Apr 2026 15:47:30 +0100
Subject: [PATCH 1/5] gdbusauthmechanismsha1: Validate cookie context
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Without validation, the server could send a malicious context which
contains path traversal characters, allowing it to exfiltrate a SHA-1
hashed copy of arbitrary data from the clients file system.
To exploit this successfully would require the client to choose to
connect peer-to-peer to a malicious D-Bus server and to choose the SHA-1
authentication mechanism in preference to all the other mechanisms. This
is vanishingly unlikely.
Signed-off-by: Philip Withnall <pwithnall@gnome.org>
Fixes: #3931
---
gio/gdbusauthmechanismsha1.c | 36 ++++++++++++++++++++++++++++++++++++
1 file changed, 36 insertions(+)
diff --git a/gio/gdbusauthmechanismsha1.c b/gio/gdbusauthmechanismsha1.c
index 94fe0bce8..d2a045f4c 100644
--- a/gio/gdbusauthmechanismsha1.c
+++ b/gio/gdbusauthmechanismsha1.c
@@ -1160,6 +1160,34 @@ mechanism_client_initiate (GDBusAuthMechanism *mechanism,
return initial_response;
}
+/* Context names must be valid ASCII, nonzero length, and may not contain the
+ * characters slash ("/"), backslash ("\"), space (" "), newline ("\n"),
+ * carriage return ("\r"), tab ("\t"), or period (".").
+ *
+ * See https://dbus.freedesktop.org/doc/dbus-specification.html#auth-mechanisms-sha */
+static gboolean
+validate_cookie_context (const char *cookie_context)
+{
+ size_t i = 0;
+
+ g_return_val_if_fail (cookie_context != NULL, FALSE);
+
+ for (i = 0; cookie_context[i] != '\0'; i++)
+ {
+ if ((uint8_t) cookie_context[i] >= 128 ||
+ cookie_context[i] == '/' ||
+ cookie_context[i] == '\\' ||
+ cookie_context[i] == ' ' ||
+ cookie_context[i] == '\n' ||
+ cookie_context[i] == '\r' ||
+ cookie_context[i] == '\t' ||
+ cookie_context[i] == '.')
+ return FALSE;
+ }
+
+ return (i > 0);
+}
+
static void
mechanism_client_data_receive (GDBusAuthMechanism *mechanism,
const gchar *data,
@@ -1194,6 +1222,14 @@ mechanism_client_data_receive (GDBusAuthMechanism *mechanism,
}
cookie_context = tokens[0];
+ if (!validate_cookie_context (tokens[0]))
+ {
+ g_free (m->priv->reject_reason);
+ m->priv->reject_reason = g_strdup_printf ("Malformed cookie_context '%s'", tokens[0]);
+ m->priv->state = G_DBUS_AUTH_MECHANISM_STATE_REJECTED;
+ goto out;
+ }
+
cookie_id = g_ascii_strtoll (tokens[1], &endp, 10);
if (*endp != '\0')
{
From 5bf53b50de87f0ad037508e4bd0099c4d0519b4b Mon Sep 17 00:00:00 2001
From: Philip Withnall <pwithnall@gnome.org>
Date: Tue, 28 Apr 2026 15:49:54 +0100
Subject: [PATCH 2/5] gdbusauthmechanismsha1: Improve validation of cookie ID
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The D-Bus specification says the cookie ID has to be non-negative, but
we werent checking that (or checking that it was non-empty).
Signed-off-by: Philip Withnall <pwithnall@gnome.org>
---
gio/gdbusauthmechanismsha1.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/gio/gdbusauthmechanismsha1.c b/gio/gdbusauthmechanismsha1.c
index d2a045f4c..9f2d3ded6 100644
--- a/gio/gdbusauthmechanismsha1.c
+++ b/gio/gdbusauthmechanismsha1.c
@@ -1196,7 +1196,7 @@ mechanism_client_data_receive (GDBusAuthMechanism *mechanism,
GDBusAuthMechanismSha1 *m = G_DBUS_AUTH_MECHANISM_SHA1 (mechanism);
gchar **tokens;
const gchar *cookie_context;
- guint cookie_id;
+ int64_t cookie_id;
const gchar *server_challenge;
gchar *client_challenge;
gchar *endp;
@@ -1231,7 +1231,7 @@ mechanism_client_data_receive (GDBusAuthMechanism *mechanism,
}
cookie_id = g_ascii_strtoll (tokens[1], &endp, 10);
- if (*endp != '\0')
+ if (*endp != '\0' || endp == tokens[1] || cookie_id < 0 || cookie_id > UINT32_MAX)
{
g_free (m->priv->reject_reason);
m->priv->reject_reason = g_strdup_printf ("Malformed cookie_id '%s'", tokens[1]);
@@ -1241,7 +1241,7 @@ mechanism_client_data_receive (GDBusAuthMechanism *mechanism,
server_challenge = tokens[2];
error = NULL;
- cookie = keyring_lookup_entry (cookie_context, cookie_id, &error);
+ cookie = keyring_lookup_entry (cookie_context, (unsigned int) cookie_id, &error);
if (cookie == NULL)
{
g_free (m->priv->reject_reason);
From 2b185a1b6ff0fca50e3bf0032e81a09a4dbfd550 Mon Sep 17 00:00:00 2001
From: Philip Withnall <pwithnall@gnome.org>
Date: Tue, 28 Apr 2026 15:51:00 +0100
Subject: [PATCH 3/5] gdbusauthmechanism: Expose client reject reason as a new
vfunc
We can do this because `gdbusauthmechanism.h` is a private header.
Hook it up to the existing `reject_reason` code in each
`GDBusAuthMechanism` implementation, as all three implementations
currently intermingle reject reasons from the server and client code, so
there would currently be no benefit to having a separate server and
client implementation of `*_get_reject_reason()`.
This new private API will be used in a new unit test in the following
commit.
Signed-off-by: Philip Withnall <pwithnall@gnome.org>
---
gio/gdbusauthmechanism.c | 7 +++++++
gio/gdbusauthmechanism.h | 2 ++
gio/gdbusauthmechanismanon.c | 8 ++++----
gio/gdbusauthmechanismexternal.c | 8 ++++----
gio/gdbusauthmechanismsha1.c | 8 ++++----
5 files changed, 21 insertions(+), 12 deletions(-)
diff --git a/gio/gdbusauthmechanism.c b/gio/gdbusauthmechanism.c
index 897d41496..6ed7fb546 100644
--- a/gio/gdbusauthmechanism.c
+++ b/gio/gdbusauthmechanism.c
@@ -324,6 +324,13 @@ _g_dbus_auth_mechanism_client_data_send (GDBusAuthMechanism *mechanism,
return G_DBUS_AUTH_MECHANISM_GET_CLASS (mechanism)->client_data_send (mechanism, out_data_len);
}
+gchar *
+_g_dbus_auth_mechanism_client_get_reject_reason (GDBusAuthMechanism *mechanism)
+{
+ g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM (mechanism), NULL);
+ return G_DBUS_AUTH_MECHANISM_GET_CLASS (mechanism)->client_get_reject_reason (mechanism);
+}
+
void
_g_dbus_auth_mechanism_client_shutdown (GDBusAuthMechanism *mechanism)
{
diff --git a/gio/gdbusauthmechanism.h b/gio/gdbusauthmechanism.h
index cee87b0a2..5ab3e34c9 100644
--- a/gio/gdbusauthmechanism.h
+++ b/gio/gdbusauthmechanism.h
@@ -97,6 +97,7 @@ struct _GDBusAuthMechanismClass
gsize data_len);
gchar *(*client_data_send) (GDBusAuthMechanism *mechanism,
gsize *out_data_len);
+ gchar *(*client_get_reject_reason) (GDBusAuthMechanism *mechanism);
void (*client_shutdown) (GDBusAuthMechanism *mechanism);
};
@@ -144,6 +145,7 @@ void _g_dbus_auth_mechanism_client_data_receive (GDBus
gsize data_len);
gchar *_g_dbus_auth_mechanism_client_data_send (GDBusAuthMechanism *mechanism,
gsize *out_data_len);
+gchar *_g_dbus_auth_mechanism_client_get_reject_reason (GDBusAuthMechanism *mechanism);
void _g_dbus_auth_mechanism_client_shutdown (GDBusAuthMechanism *mechanism);
diff --git a/gio/gdbusauthmechanismanon.c b/gio/gdbusauthmechanismanon.c
index dd57826ff..ab947bba6 100644
--- a/gio/gdbusauthmechanismanon.c
+++ b/gio/gdbusauthmechanismanon.c
@@ -54,7 +54,7 @@ static void mechanism_server_data_receive (GDBusAuthMe
gsize data_len);
static gchar *mechanism_server_data_send (GDBusAuthMechanism *mechanism,
gsize *out_data_len);
-static gchar *mechanism_server_get_reject_reason (GDBusAuthMechanism *mechanism);
+static gchar *mechanism_server_or_client_get_reject_reason (GDBusAuthMechanism *mechanism);
static void mechanism_server_shutdown (GDBusAuthMechanism *mechanism);
static GDBusAuthMechanismState mechanism_client_get_state (GDBusAuthMechanism *mechanism);
static gchar *mechanism_client_initiate (GDBusAuthMechanism *mechanism,
@@ -100,12 +100,13 @@ _g_dbus_auth_mechanism_anon_class_init (GDBusAuthMechanismAnonClass *klass)
mechanism_class->server_initiate = mechanism_server_initiate;
mechanism_class->server_data_receive = mechanism_server_data_receive;
mechanism_class->server_data_send = mechanism_server_data_send;
- mechanism_class->server_get_reject_reason = mechanism_server_get_reject_reason;
+ mechanism_class->server_get_reject_reason = mechanism_server_or_client_get_reject_reason;
mechanism_class->server_shutdown = mechanism_server_shutdown;
mechanism_class->client_get_state = mechanism_client_get_state;
mechanism_class->client_initiate = mechanism_client_initiate;
mechanism_class->client_data_receive = mechanism_client_data_receive;
mechanism_class->client_data_send = mechanism_client_data_send;
+ mechanism_class->client_get_reject_reason = mechanism_server_or_client_get_reject_reason;
mechanism_class->client_shutdown = mechanism_client_shutdown;
}
@@ -219,12 +220,11 @@ mechanism_server_data_send (GDBusAuthMechanism *mechanism,
}
static gchar *
-mechanism_server_get_reject_reason (GDBusAuthMechanism *mechanism)
+mechanism_server_or_client_get_reject_reason (GDBusAuthMechanism *mechanism)
{
GDBusAuthMechanismAnon *m = G_DBUS_AUTH_MECHANISM_ANON (mechanism);
g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_ANON (mechanism), NULL);
- g_return_val_if_fail (m->priv->is_server && !m->priv->is_client, NULL);
g_return_val_if_fail (m->priv->state == G_DBUS_AUTH_MECHANISM_STATE_REJECTED, NULL);
/* can never end up here because we are never in the REJECTED state */
diff --git a/gio/gdbusauthmechanismexternal.c b/gio/gdbusauthmechanismexternal.c
index 182c57278..30adfc415 100644
--- a/gio/gdbusauthmechanismexternal.c
+++ b/gio/gdbusauthmechanismexternal.c
@@ -57,7 +57,7 @@ static void mechanism_server_data_receive (GDBusAuthMe
gsize data_len);
static gchar *mechanism_server_data_send (GDBusAuthMechanism *mechanism,
gsize *out_data_len);
-static gchar *mechanism_server_get_reject_reason (GDBusAuthMechanism *mechanism);
+static gchar *mechanism_server_or_client_get_reject_reason (GDBusAuthMechanism *mechanism);
static void mechanism_server_shutdown (GDBusAuthMechanism *mechanism);
static GDBusAuthMechanismState mechanism_client_get_state (GDBusAuthMechanism *mechanism);
static gchar *mechanism_client_initiate (GDBusAuthMechanism *mechanism,
@@ -103,12 +103,13 @@ _g_dbus_auth_mechanism_external_class_init (GDBusAuthMechanismExternalClass *kla
mechanism_class->server_initiate = mechanism_server_initiate;
mechanism_class->server_data_receive = mechanism_server_data_receive;
mechanism_class->server_data_send = mechanism_server_data_send;
- mechanism_class->server_get_reject_reason = mechanism_server_get_reject_reason;
+ mechanism_class->server_get_reject_reason = mechanism_server_or_client_get_reject_reason;
mechanism_class->server_shutdown = mechanism_server_shutdown;
mechanism_class->client_get_state = mechanism_client_get_state;
mechanism_class->client_initiate = mechanism_client_initiate;
mechanism_class->client_data_receive = mechanism_client_data_receive;
mechanism_class->client_data_send = mechanism_client_data_send;
+ mechanism_class->client_get_reject_reason = mechanism_server_or_client_get_reject_reason;
mechanism_class->client_shutdown = mechanism_client_shutdown;
}
@@ -285,12 +286,11 @@ mechanism_server_data_send (GDBusAuthMechanism *mechanism,
}
static gchar *
-mechanism_server_get_reject_reason (GDBusAuthMechanism *mechanism)
+mechanism_server_or_client_get_reject_reason (GDBusAuthMechanism *mechanism)
{
GDBusAuthMechanismExternal *m = G_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism);
g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_EXTERNAL (mechanism), NULL);
- g_return_val_if_fail (m->priv->is_server && !m->priv->is_client, NULL);
g_return_val_if_fail (m->priv->state == G_DBUS_AUTH_MECHANISM_STATE_REJECTED, NULL);
/* can never end up here because we are never in the REJECTED state */
diff --git a/gio/gdbusauthmechanismsha1.c b/gio/gdbusauthmechanismsha1.c
index 9f2d3ded6..d74f70387 100644
--- a/gio/gdbusauthmechanismsha1.c
+++ b/gio/gdbusauthmechanismsha1.c
@@ -111,7 +111,7 @@ static void mechanism_server_data_receive (GDBusAuthMe
gsize data_len);
static gchar *mechanism_server_data_send (GDBusAuthMechanism *mechanism,
gsize *out_data_len);
-static gchar *mechanism_server_get_reject_reason (GDBusAuthMechanism *mechanism);
+static gchar *mechanism_server_or_client_get_reject_reason (GDBusAuthMechanism *mechanism);
static void mechanism_server_shutdown (GDBusAuthMechanism *mechanism);
static GDBusAuthMechanismState mechanism_client_get_state (GDBusAuthMechanism *mechanism);
static gchar *mechanism_client_initiate (GDBusAuthMechanism *mechanism,
@@ -163,12 +163,13 @@ _g_dbus_auth_mechanism_sha1_class_init (GDBusAuthMechanismSha1Class *klass)
mechanism_class->server_initiate = mechanism_server_initiate;
mechanism_class->server_data_receive = mechanism_server_data_receive;
mechanism_class->server_data_send = mechanism_server_data_send;
- mechanism_class->server_get_reject_reason = mechanism_server_get_reject_reason;
+ mechanism_class->server_get_reject_reason = mechanism_server_or_client_get_reject_reason;
mechanism_class->server_shutdown = mechanism_server_shutdown;
mechanism_class->client_get_state = mechanism_client_get_state;
mechanism_class->client_initiate = mechanism_client_initiate;
mechanism_class->client_data_receive = mechanism_client_data_receive;
mechanism_class->client_data_send = mechanism_client_data_send;
+ mechanism_class->client_get_reject_reason = mechanism_server_or_client_get_reject_reason;
mechanism_class->client_shutdown = mechanism_client_shutdown;
}
@@ -1096,12 +1097,11 @@ mechanism_server_data_send (GDBusAuthMechanism *mechanism,
}
static gchar *
-mechanism_server_get_reject_reason (GDBusAuthMechanism *mechanism)
+mechanism_server_or_client_get_reject_reason (GDBusAuthMechanism *mechanism)
{
GDBusAuthMechanismSha1 *m = G_DBUS_AUTH_MECHANISM_SHA1 (mechanism);
g_return_val_if_fail (G_IS_DBUS_AUTH_MECHANISM_SHA1 (mechanism), NULL);
- g_return_val_if_fail (m->priv->is_server && !m->priv->is_client, NULL);
g_return_val_if_fail (m->priv->state == G_DBUS_AUTH_MECHANISM_STATE_REJECTED, NULL);
return g_strdup (m->priv->reject_reason);
From 0c526648c0346fd7287941817641d235ddf4998a Mon Sep 17 00:00:00 2001
From: Philip Withnall <pwithnall@gnome.org>
Date: Tue, 28 Apr 2026 15:52:53 +0100
Subject: [PATCH 4/5] tests: Add a unit test for GDBusAuthMechanismSha1 cookie
context parsing
This checks for regressions in the fixes from the previous few commits.
Signed-off-by: Philip Withnall <pwithnall@gnome.org>
Helps: #3931
---
gio/gdbusauthmechanismsha1.c | 2 +-
gio/tests/gdbus-auth-mechanism-sha1.c | 177 ++++++++++++++++++++++++++
gio/tests/meson.build | 1 +
3 files changed, 179 insertions(+), 1 deletion(-)
create mode 100644 gio/tests/gdbus-auth-mechanism-sha1.c
diff --git a/gio/gdbusauthmechanismsha1.c b/gio/gdbusauthmechanismsha1.c
index d74f70387..cb1a4f828 100644
--- a/gio/gdbusauthmechanismsha1.c
+++ b/gio/gdbusauthmechanismsha1.c
@@ -1174,7 +1174,7 @@ validate_cookie_context (const char *cookie_context)
for (i = 0; cookie_context[i] != '\0'; i++)
{
- if ((uint8_t) cookie_context[i] >= 128 ||
+ if ((guint8) cookie_context[i] >= 128 ||
cookie_context[i] == '/' ||
cookie_context[i] == '\\' ||
cookie_context[i] == ' ' ||
diff --git a/gio/tests/gdbus-auth-mechanism-sha1.c b/gio/tests/gdbus-auth-mechanism-sha1.c
new file mode 100644
index 000000000..abcdb4e3e
--- /dev/null
+++ b/gio/tests/gdbus-auth-mechanism-sha1.c
@@ -0,0 +1,177 @@
+/* GLib testing framework examples and tests
+ *
+ * Copyright (C) 2026 Philip Withnall
+ *
+ * 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/>.
+ *
+ * Author: Philip Withnall <pwithnall@gnome.org>
+ */
+
+#include <locale.h>
+#include <gio/gio.h>
+
+#include <string.h>
+#include <unistd.h>
+
+#include "gdbus-tests.h"
+
+#ifdef G_OS_UNIX
+#include <gio/gunixconnection.h>
+#include <gio/gnetworkingprivate.h>
+#include <gio/gunixsocketaddress.h>
+#include <gio/gunixfdlist.h>
+#endif
+
+#define GIO_COMPILATION 1
+#include "gdbusauthmechanism.h"
+#include "gdbusauthmechanismsha1.h"
+
+/* Vfunc wrappers copied from gdbusauthmechanism.c as they are not public. */
+static gboolean
+dbus_auth_mechanism_is_supported (GDBusAuthMechanism *mechanism)
+{
+ return G_DBUS_AUTH_MECHANISM_GET_CLASS (mechanism)->is_supported (mechanism);
+}
+
+static GDBusAuthMechanismState
+dbus_auth_mechanism_client_get_state (GDBusAuthMechanism *mechanism)
+{
+ return G_DBUS_AUTH_MECHANISM_GET_CLASS (mechanism)->client_get_state (mechanism);
+}
+
+static gchar *
+dbus_auth_mechanism_client_initiate (GDBusAuthMechanism *mechanism,
+ GDBusConnectionFlags conn_flags,
+ size_t *out_initial_response_len)
+{
+ return G_DBUS_AUTH_MECHANISM_GET_CLASS (mechanism)->client_initiate (mechanism,
+ conn_flags,
+ out_initial_response_len);
+}
+
+static void
+dbus_auth_mechanism_client_data_receive (GDBusAuthMechanism *mechanism,
+ const char *data,
+ size_t data_len)
+{
+ G_DBUS_AUTH_MECHANISM_GET_CLASS (mechanism)->client_data_receive (mechanism, data, data_len);
+}
+
+static char *
+dbus_auth_mechanism_client_get_reject_reason (GDBusAuthMechanism *mechanism)
+{
+ return G_DBUS_AUTH_MECHANISM_GET_CLASS (mechanism)->client_get_reject_reason (mechanism);
+}
+
+static void
+dbus_auth_mechanism_client_shutdown (GDBusAuthMechanism *mechanism)
+{
+ G_DBUS_AUTH_MECHANISM_GET_CLASS (mechanism)->client_shutdown (mechanism);
+}
+
+static void
+test_server_challenge_validation (void)
+{
+ const struct
+ {
+ const char *server_challenge;
+ const char *expected_reject_reason_prefix;
+ }
+ vectors[] = {
+ { "valid_context 123 456", "Problems looking up entry in keyring" },
+ { "invalid/context 123 456", "Malformed cookie_context" },
+ { "invalid.context 123 456", "Malformed cookie_context" },
+ { " 123 456", "Malformed cookie_context" },
+ { "😀 123 456", "Malformed cookie_context" },
+ { "invalid\ncontext 123 456", "Malformed cookie_context" },
+ { "invalid\rcontext 123 456", "Malformed cookie_context" },
+ { "invalid\tcontext 123 456", "Malformed cookie_context" },
+ { "invalid\\context 123 456", "Malformed cookie_context" },
+ { "valid_context 456", "Malformed cookie_id" },
+ { "valid_context 123notanumber 456", "Malformed cookie_id" },
+ { "valid_context -1 456", "Malformed cookie_id" },
+ { "valid_context 4294967296 456", "Malformed cookie_id" },
+ { "valid_context 123 ", "Malformed data" },
+ { "valid_context ", "Malformed data" },
+ };
+ GType mechanism_type;
+ GDBusConnection *connection = NULL;
+
+ g_test_summary ("Test that GDBusAuthMechanismSha1 rejects various malformed server data lines");
+
+ /* Briefly connect to the actual bus to ensure the GDBusAuth mechanisms are
+ * all registered. */
+ session_bus_up ();
+
+ connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
+ g_assert_nonnull (connection);
+ g_clear_object (&connection);
+
+ session_bus_down ();
+
+ /* Check that we now have the type ID for GDBusAuthMechanismSha1 */
+ mechanism_type = g_type_from_name ("GDBusAuthMechanismSha1");
+ g_assert_cmpint (mechanism_type, !=, 0);
+
+ for (size_t i = 0; i < G_N_ELEMENTS (vectors); i++)
+ {
+ GDBusAuthMechanism *mechanism = NULL;
+ char *data = NULL;
+ size_t data_len = 0;
+ char *reject_reason = NULL;
+
+ mechanism = g_object_new (mechanism_type, NULL);
+
+ if (!dbus_auth_mechanism_is_supported (mechanism))
+ {
+ g_test_skip ("Mechanism not supported");
+ g_clear_object (&mechanism);
+ return;
+ }
+
+ data = dbus_auth_mechanism_client_initiate (mechanism,
+ G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
+ &data_len);
+ g_free (data);
+
+ dbus_auth_mechanism_client_data_receive (mechanism, vectors[i].server_challenge, strlen (vectors[i].server_challenge));
+
+ g_assert_cmpint (dbus_auth_mechanism_client_get_state (mechanism), ==, G_DBUS_AUTH_MECHANISM_STATE_REJECTED);
+
+ reject_reason = dbus_auth_mechanism_client_get_reject_reason (mechanism);
+ g_assert_true (g_str_has_prefix (reject_reason, vectors[i].expected_reject_reason_prefix));
+ g_free (reject_reason);
+
+ dbus_auth_mechanism_client_shutdown (mechanism);
+
+ g_clear_object (&mechanism);
+ }
+}
+
+int
+main (int argc,
+ char *argv[])
+{
+ setlocale (LC_ALL, "C");
+
+ g_test_init (&argc, &argv, G_TEST_OPTION_ISOLATE_DIRS, NULL);
+
+ g_test_dbus_unset ();
+
+ g_test_add_func ("/gdbus/auth-mechanism-sha1/server-challenge-validation", test_server_challenge_validation);
+
+ return g_test_run ();
+}
diff --git a/gio/tests/meson.build b/gio/tests/meson.build
index 5dbfb8e60..c5380c16a 100644
--- a/gio/tests/meson.build
+++ b/gio/tests/meson.build
@@ -294,6 +294,7 @@ if host_machine.system() != 'windows'
'suite' : ['slow'],
},
'gdbus-auth' : {'extra_sources' : extra_sources},
+ 'gdbus-auth-mechanism-sha1': {'extra_sources' : extra_sources},
'gdbus-bz627724' : {'extra_sources' : extra_sources},
'gdbus-close-pending' : {'extra_sources' : extra_sources},
'gdbus-connection' : {'extra_sources' : extra_sources},
From 8c11c462af6ca9338e95ed3e4ce78d59df1c7474 Mon Sep 17 00:00:00 2001
From: RHEL Packaging Agent <redhat-ymir-agent@redhat.com>
Date: Mon, 20 Jul 2026 07:10:32 +0000
Subject: [PATCH 5/5] Fix: use GLib types instead of stdint.h types for
portability
Replace int64_t with gint64 and UINT32_MAX with G_MAXUINT32 to avoid
dependency on <stdint.h> which may not be included in older GLib builds.
---
gio/gdbusauthmechanismsha1.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/gio/gdbusauthmechanismsha1.c b/gio/gdbusauthmechanismsha1.c
index cb1a4f828..007c6b901 100644
--- a/gio/gdbusauthmechanismsha1.c
+++ b/gio/gdbusauthmechanismsha1.c
@@ -1196,7 +1196,7 @@ mechanism_client_data_receive (GDBusAuthMechanism *mechanism,
GDBusAuthMechanismSha1 *m = G_DBUS_AUTH_MECHANISM_SHA1 (mechanism);
gchar **tokens;
const gchar *cookie_context;
- int64_t cookie_id;
+ gint64 cookie_id;
const gchar *server_challenge;
gchar *client_challenge;
gchar *endp;
@@ -1231,7 +1231,7 @@ mechanism_client_data_receive (GDBusAuthMechanism *mechanism,
}
cookie_id = g_ascii_strtoll (tokens[1], &endp, 10);
- if (*endp != '\0' || endp == tokens[1] || cookie_id < 0 || cookie_id > UINT32_MAX)
+ if (*endp != '\0' || endp == tokens[1] || cookie_id < 0 || cookie_id > G_MAXUINT32)
{
g_free (m->priv->reject_reason);
m->priv->reject_reason = g_strdup_printf ("Malformed cookie_id '%s'", tokens[1]);

View File

@ -1,87 +0,0 @@
From 0cf6b5ef06f44a4b259a014870cdc02780cc8ba4 Mon Sep 17 00:00:00 2001
From: Philip Withnall <pwithnall@gnome.org>
Date: Thu, 16 Apr 2026 15:27:37 +0100
Subject: [PATCH] gdbusintrospection: Fix XML parser state handling for <node>
element nesting
The check for whether a `<node>` element in D-Bus introspection XML was
nested correctly was broken. `<node>` elements can only be at the top
level, or nested immediately within another `<node>` element.
Fix the check and add some unit tests for it.
Spotted by linhlhq as #YWH-PGM9867-204. The fix is mine, and the unit test
uses example XML strings adapted from their report.
Signed-off-by: Philip Withnall <pwithnall@gnome.org>
Fixes: #3932
---
gio/gdbusintrospection.c | 2 +-
gio/tests/gdbus-introspection.c | 33 +++++++++++++++++++++++++++++++++
2 files changed, 34 insertions(+), 1 deletion(-)
diff --git a/gio/gdbusintrospection.c b/gio/gdbusintrospection.c
index d6aa445d5..1e0cb81de 100644
--- a/gio/gdbusintrospection.c
+++ b/gio/gdbusintrospection.c
@@ -1270,7 +1270,7 @@ parser_start_element (GMarkupParseContext *context,
/* ---------------------------------------------------------------------------------------------------- */
if (strcmp (element_name, "node") == 0)
{
- if (!(g_slist_length (stack) >= 1 || strcmp (stack->next->data, "node") != 0))
+ if (stack->next != NULL && strcmp (stack->next->data, "node") != 0)
{
g_set_error_literal (error,
G_MARKUP_ERROR,
diff --git a/gio/tests/gdbus-introspection.c b/gio/tests/gdbus-introspection.c
index 50c0cc721..e2cdf0a25 100644
--- a/gio/tests/gdbus-introspection.c
+++ b/gio/tests/gdbus-introspection.c
@@ -297,6 +297,38 @@ test_extra_data (void)
g_dbus_node_info_unref (info);
}
+static void
+test_invalid (void)
+{
+ const struct
+ {
+ const char *xml;
+ GMarkupError expected_error_code;
+ }
+ vectors[] =
+ {
+ { "", G_MARKUP_ERROR_EMPTY },
+ { "<node><interface name=\"I\"><method name=\"M\"><node><interface name=\"I2\"></interface></node></method>", G_MARKUP_ERROR_INVALID_CONTENT },
+ { "<node><interface name=\"I\"><signal name=\"S\"><node><interface name=\"I2\"><signal name=\"S2\"></signal></interface></node></signal>", G_MARKUP_ERROR_INVALID_CONTENT },
+ { "<node><interface name=\"I\"><property name=\"P\" type=\"s\" access=\"read\"><node><interface name=\"I2\"></interface></node></property>", G_MARKUP_ERROR_INVALID_CONTENT },
+ { "<node><interface name=\"I\"><method name=\"M\"><arg type=\"\"><node><interface name=\"I2\"><method name=\"M2\"></method></interface></node></arg>", G_MARKUP_ERROR_INVALID_CONTENT },
+ };
+
+ for (size_t i = 0; i < G_N_ELEMENTS (vectors); i++)
+ {
+ GDBusNodeInfo *node;
+ GError *local_error = NULL;
+
+ g_test_message ("Testing parsing of %s gives an error", vectors[i].xml);
+
+ node = g_dbus_node_info_new_for_xml (vectors[i].xml, &local_error);
+ g_assert_error (local_error, G_MARKUP_ERROR, (int) vectors[i].expected_error_code);
+ g_assert_null (node);
+
+ g_clear_error (&local_error);
+ }
+}
+
/* ---------------------------------------------------------------------------------------------------- */
int
@@ -314,6 +346,7 @@ main (int argc,
g_test_add_func ("/gdbus/introspection-generate", test_generate);
g_test_add_func ("/gdbus/introspection-default-direction", test_default_direction);
g_test_add_func ("/gdbus/introspection-extra-data", test_extra_data);
+ g_test_add_func ("/gdbus/introspection-invalid", test_invalid);
ret = session_bus_run ();

View File

@ -1 +0,0 @@
SHA512 (glib-2.70.1.tar.xz) = 639317c98ab72ad853608ab4d395484daff135c0222556c51ca93fd8533c5759db14478beda964e4feb02bb2737a46a4eda25063f98a9c6ba6ae4bc5d74bf5e1