mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2026-07-10 10:36:30 +02:00
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.
This commit is contained in:
+5
-5
@@ -68,6 +68,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.
|
||||
@@ -82,11 +86,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);
|
||||
}
|
||||
|
||||
|
||||
@@ -801,6 +801,23 @@ test_string_copy (void)
|
||||
g_string_free (string2, 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[])
|
||||
@@ -831,6 +848,7 @@ main (int argc,
|
||||
g_test_add_func ("/string/new-take", test_string_new_take);
|
||||
g_test_add_func ("/string/new-take/null", test_string_new_take_null);
|
||||
g_test_add_func ("/string/copy", test_string_copy);
|
||||
g_test_add_func ("/string/sized-new", test_string_sized_new);
|
||||
|
||||
return g_test_run();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user