Merge branch 'strfuncs_join_oob' into 'main'

strfuncs: Check for overflows when joining strings

See merge request GNOME/glib!4816
This commit is contained in:
Philip Withnall
2025-09-18 15:51:31 +00:00
2 changed files with 53 additions and 4 deletions

View File

@@ -581,7 +581,8 @@ g_strconcat (const gchar *string1, ...)
s = va_arg (args, gchar*);
while (s)
{
l += strlen (s);
if (!g_size_checked_add (&l, l, strlen (s)))
g_error ("%s: overflow concatenating strings", G_STRLOC);
s = va_arg (args, gchar*);
}
va_end (args);
@@ -2645,13 +2646,18 @@ g_strjoinv (const gchar *separator,
gsize i;
gsize len;
gsize separator_len;
gsize separators_len;
separator_len = strlen (separator);
/* First part, getting length */
len = 1 + strlen (str_array[0]);
for (i = 1; str_array[i] != NULL; i++)
len += strlen (str_array[i]);
len += separator_len * (i - 1);
if (!g_size_checked_add (&len, len, strlen (str_array[i])))
g_error ("%s: overflow joining strings", G_STRLOC);
if (!g_size_checked_mul (&separators_len, separator_len, (i - 1)) ||
!g_size_checked_add (&len, len, separators_len))
g_error ("%s: overflow joining strings", G_STRLOC);
/* Second part, building string */
string = g_new (gchar, len);
@@ -2706,7 +2712,9 @@ g_strjoin (const gchar *separator,
s = va_arg (args, gchar*);
while (s)
{
len += separator_len + strlen (s);
if (!g_size_checked_add (&len, len, separator_len) ||
!g_size_checked_add (&len, len, strlen (s)))
g_error ("%s: overflow joining strings", G_STRLOC);
s = va_arg (args, gchar*);
}
va_end (args);

View File

@@ -660,6 +660,46 @@ test_strconcat (void)
g_assert_null (g_strconcat (NULL, "bla", NULL));
}
/* Testing g_strjoinv() function with strings which cannot be joined in heap */
static void
test_strjoinv_overflow (void)
{
#if G_MAXSIZE > G_MAXUINT
g_test_skip ("Overflow joining strings requires G_MAXSIZE <= G_MAXUINT.");
#else
if (!g_test_undefined ())
return;
if (g_test_subprocess ())
{
/* compromise between memory consumption and performance */
const size_t count = 256;
gchar **array;
gchar *result;
gchar *string;
string = g_strnfill (G_MAXSIZE / ((count - 1) * 2), 'A');
array = g_malloc_n (count + 1, sizeof (*array));
for (size_t i = 0; i < count; i++)
array[i] = string;
array[count] = NULL;
result = g_strjoinv (string, array);
g_free (array);
g_free (result);
g_free (string);
}
else
{
g_test_trap_subprocess (NULL, 0, G_TEST_SUBPROCESS_DEFAULT);
g_test_trap_assert_failed ();
g_test_trap_assert_stderr ("*overflow joining strings*");
}
#endif
}
/* Testing g_strjoinv() function with various positive and negative cases */
static void
test_strjoinv (void)
@@ -2797,6 +2837,7 @@ main (int argc,
g_test_add_func ("/strfuncs/strip-context", test_strip_context);
g_test_add_func ("/strfuncs/strjoin", test_strjoin);
g_test_add_func ("/strfuncs/strjoinv", test_strjoinv);
g_test_add_func ("/strfuncs/strjoinv/overflow", test_strjoinv_overflow);
g_test_add_func ("/strfuncs/strlcat", test_strlcat);
g_test_add_func ("/strfuncs/strlcpy", test_strlcpy);
g_test_add_func ("/strfuncs/strncasecmp", test_strncasecmp);