glib2/SOURCES/CVE-2026-58013.patch
2026-08-17 02:03:53 -04:00

171 lines
5.9 KiB
Diff
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

From 6f410cf0d43f8b7a03f5c504ca9b53c75266a21d Mon Sep 17 00:00:00 2001
From: Philip Withnall <pwithnall@gnome.org>
Date: Tue, 28 Apr 2026 16:45:14 +0100
Subject: [PATCH 1/2] 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 ();
}
From 9ddd99126dd21d53c874aa801bcee346ff09ca8d Mon Sep 17 00:00:00 2001
From: RHEL Packaging Agent <redhat-ymir-agent@redhat.com>
Date: Mon, 20 Jul 2026 07:12:52 +0000
Subject: [PATCH 2/2] Adapt test to use GLib types instead of C standard types
for compatibility with GLib 2.68.4
---
glib/tests/io-channel.c | 19 ++++++++++---------
1 file changed, 10 insertions(+), 9 deletions(-)
diff --git a/glib/tests/io-channel.c b/glib/tests/io-channel.c
index c619fb00f..afcea93f0 100644
--- a/glib/tests/io-channel.c
+++ b/glib/tests/io-channel.c
@@ -72,16 +72,16 @@ test_read_line_embedded_nuls (void)
static void
test_read_line_long_terminator (void)
{
- uint8_t *test_data = NULL;
- size_t test_data_len = 0;
- int fd;
- char *filename = NULL;
+ guint8 *test_data = NULL;
+ gsize test_data_len = 0;
+ gint fd;
+ gchar *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;
+ gchar *line = NULL;
+ gsize line_length, terminator_pos;
+ const gchar *line_term;
+ gint line_term_length;
GIOStatus status;
g_test_summary ("Test that reading a line when using a long terminator doesnt over-read the buffer.");
@@ -91,7 +91,8 @@ test_read_line_long_terminator (void)
* 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);
+ g_close (fd, NULL);
+ fd = -1;
test_data_len = 2047;
test_data = g_malloc (test_data_len);