From 6aa97beda32bb337370858862f4efe2f3372619f Mon Sep 17 00:00:00 2001 From: Tobias Stoeckmann Date: Mon, 7 Jul 2025 20:52:24 +0200 Subject: [PATCH] gstring: Fix g_string_sized_new segmentation fault If glib is compiled with -Dglib_assert=false, i.e. no asserts enabled, then g_string_sized_new(G_MAXSIZE) leads to a segmentation fault due to an out of boundary write. This happens because the overflow check was moved into g_string_maybe_expand which is not called by g_string_sized_new. By assuming that string->allocated_len is always larger than string->len (and the code would be in huge trouble if that is not true), the G_UNLIKELY check in g_string_maybe_expand can be rephrased to avoid a potential G_MAXSIZE overflow. This in turn leads to 150-200 bytes smaller compiled library depending on gcc and clang versions, and one less check for the most common code paths. Reverts https://gitlab.gnome.org/GNOME/glib/-/merge_requests/4655 and reorders internal g_string_maybe_expand check to still fix CVE-2025-6052. CVE: CVE-2025-6052 Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/glib/-/commit/6aa97beda32bb337370858862f4efe2f3372619f] Signed-off-by: Peter Marko --- glib/gstring.c | 10 +++++----- glib/tests/string.c | 18 ++++++++++++++++++ 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/glib/gstring.c b/glib/gstring.c index 010a8e976..24c4bfb40 100644 --- a/glib/gstring.c +++ b/glib/gstring.c @@ -78,6 +78,10 @@ static void g_string_expand (GString *string, gsize len) { + /* Detect potential overflow */ + if G_UNLIKELY ((G_MAXSIZE - string->len - 1) < len) + g_error ("adding %" G_GSIZE_FORMAT " to string would overflow", len); + string->allocated_len = g_nearest_pow (string->len + len + 1); /* If the new size is bigger than G_MAXSIZE / 2, only allocate enough * memory for this string and don't over-allocate. @@ -92,11 +96,7 @@ static inline void g_string_maybe_expand (GString *string, gsize len) { - /* Detect potential overflow */ - if G_UNLIKELY ((G_MAXSIZE - string->len - 1) < len) - g_error ("adding %" G_GSIZE_FORMAT " to string would overflow", len); - - if (G_UNLIKELY (string->len + len >= string->allocated_len)) + if (G_UNLIKELY (len >= string->allocated_len - string->len)) g_string_expand (string, len); } diff --git a/glib/tests/string.c b/glib/tests/string.c index aa363c57a..e3bc4a02e 100644 --- a/glib/tests/string.c +++ b/glib/tests/string.c @@ -743,6 +743,23 @@ test_string_new_take_null (void) g_string_free (g_steal_pointer (&string), TRUE); } +static void +test_string_sized_new (void) +{ + + if (g_test_subprocess ()) + { + GString *string = g_string_sized_new (G_MAXSIZE); + g_string_free (string, TRUE); + } + else + { + g_test_trap_subprocess (NULL, 0, G_TEST_SUBPROCESS_DEFAULT); + g_test_trap_assert_failed (); + g_test_trap_assert_stderr ("*string would overflow*"); + } +} + int main (int argc, char *argv[]) @@ -772,6 +789,7 @@ main (int argc, g_test_add_func ("/string/test-string-steal", test_string_steal); g_test_add_func ("/string/test-string-new-take", test_string_new_take); g_test_add_func ("/string/test-string-new-take/null", test_string_new_take_null); + g_test_add_func ("/string/sized-new", test_string_sized_new); return g_test_run(); }