File glib2-CVE-2026-1489.patch of Package glib2.42480
diff -urp glib-2.78.6.orig/glib/guniprop.c glib-2.78.6/glib/guniprop.c
--- glib-2.78.6.orig/glib/guniprop.c 2024-05-08 12:53:54.000000000 -0500
+++ glib-2.78.6/glib/guniprop.c 2026-01-27 14:59:20.788273960 -0600
@@ -772,14 +772,36 @@ get_locale_type (void)
return LOCALE_NORMAL;
}
-static gint
-output_marks (const char **p_inout,
- char *out_buffer,
- gboolean remove_dot)
+G_ALWAYS_INLINE static inline void
+increase_size (size_t *sizeptr, size_t add)
+{
+ g_assert (G_MAXSIZE - *(sizeptr) >= add);
+ *(sizeptr) += add;
+}
+
+G_ALWAYS_INLINE static inline void
+append_utf8_char_to_buffer (gunichar c,
+ char *out_buffer,
+ size_t *in_out_len)
+{
+ gint utf8_len;
+ char *buffer;
+
+ buffer = out_buffer ? out_buffer + *(in_out_len) : NULL;
+ utf8_len = g_unichar_to_utf8 (c, buffer);
+
+ g_assert (utf8_len >= 0);
+ increase_size (in_out_len, utf8_len);
+}
+
+static void
+append_mark (const char **p_inout,
+ char *out_buffer,
+ size_t *in_out_len,
+ gboolean remove_dot)
{
const char *p = *p_inout;
- gint len = 0;
-
+
while (*p)
{
gunichar c = g_utf8_get_char (p);
@@ -787,7 +809,7 @@ output_marks (const char **p_inout,
if (ISMARK (TYPE (c)))
{
if (!remove_dot || c != 0x307 /* COMBINING DOT ABOVE */)
- len += g_unichar_to_utf8 (c, out_buffer ? out_buffer + len : NULL);
+ append_utf8_char_to_buffer (c, out_buffer, in_out_len);
p = g_utf8_next_char (p);
}
else
@@ -795,14 +817,14 @@ output_marks (const char **p_inout,
}
*p_inout = p;
- return len;
}
-static gint
-output_special_case (gchar *out_buffer,
- int offset,
- int type,
- int which)
+static void
+append_special_case (char *out_buffer,
+ size_t *in_out_len,
+ int offset,
+ int type,
+ int which)
{
const gchar *p = special_case_table + offset;
gint len;
@@ -814,10 +836,12 @@ output_special_case (gchar *out_buffer,
p += strlen (p) + 1;
len = strlen (p);
+ g_assert (len < G_MAXSIZE - *in_out_len);
+
if (out_buffer)
- memcpy (out_buffer, p, len);
+ memcpy (out_buffer + *in_out_len, p, len);
- return len;
+ increase_size (in_out_len, len);
}
static gsize
@@ -858,11 +882,13 @@ real_toupper (const gchar *str,
decomp_len = g_unichar_fully_decompose (c, FALSE, decomp, G_N_ELEMENTS (decomp));
for (i=0; i < decomp_len; i++)
{
+
if (decomp[i] != 0x307 /* COMBINING DOT ABOVE */)
- len += g_unichar_to_utf8 (g_unichar_toupper (decomp[i]), out_buffer ? out_buffer + len : NULL);
+ append_utf8_char_to_buffer (g_unichar_toupper (decomp[i]),
+ out_buffer, &len);
}
-
- len += output_marks (&p, out_buffer ? out_buffer + len : NULL, TRUE);
+
+ append_mark (&p, out_buffer, &len, TRUE);
continue;
}
@@ -875,17 +901,17 @@ real_toupper (const gchar *str,
if (locale_type == LOCALE_TURKIC && c == 'i')
{
/* i => LATIN CAPITAL LETTER I WITH DOT ABOVE */
- len += g_unichar_to_utf8 (0x130, out_buffer ? out_buffer + len : NULL);
+ append_utf8_char_to_buffer (0x130, out_buffer, &len);
}
else if (c == 0x0345) /* COMBINING GREEK YPOGEGRAMMENI */
{
/* Nasty, need to move it after other combining marks .. this would go away if
* we normalized first.
*/
- len += output_marks (&p, out_buffer ? out_buffer + len : NULL, FALSE);
+ append_mark (&p, out_buffer, &len, TRUE);
/* And output as GREEK CAPITAL LETTER IOTA */
- len += g_unichar_to_utf8 (0x399, out_buffer ? out_buffer + len : NULL);
+ append_utf8_char_to_buffer (0x399, out_buffer, &len);
}
else if (IS (t,
OR (G_UNICODE_LOWERCASE_LETTER,
@@ -896,8 +922,8 @@ real_toupper (const gchar *str,
if (val >= 0x1000000)
{
- len += output_special_case (out_buffer ? out_buffer + len : NULL, val - 0x1000000, t,
- t == G_UNICODE_LOWERCASE_LETTER ? 0 : 1);
+ append_special_case (out_buffer, &len, val - 0x1000000, t,
+ t == G_UNICODE_LOWERCASE_LETTER ? 0 : 1);
}
else
{
@@ -917,7 +943,7 @@ real_toupper (const gchar *str,
/* Some lowercase letters, e.g., U+000AA, FEMININE ORDINAL INDICATOR,
* do not have an uppercase equivalent, in which case val will be
* zero. */
- len += g_unichar_to_utf8 (val ? val : c, out_buffer ? out_buffer + len : NULL);
+ append_utf8_char_to_buffer (val ? val : c, out_buffer, &len);
}
}
else
@@ -927,7 +953,7 @@ real_toupper (const gchar *str,
if (out_buffer)
memcpy (out_buffer + len, last, char_len);
- len += char_len;
+ increase_size (&len, char_len);
}
}
@@ -965,6 +991,8 @@ g_utf8_strup (const gchar *str,
* We use a two pass approach to keep memory management simple
*/
result_len = real_toupper (str, len, NULL, locale_type);
+ g_assert (result_len < G_MAXSIZE);
+
result = g_malloc (result_len + 1);
real_toupper (str, len, result, locale_type);
result[result_len] = '\0';
@@ -1022,14 +1050,15 @@ real_tolower (const gchar *str,
{
/* I + COMBINING DOT ABOVE => i (U+0069)
* LATIN CAPITAL LETTER I WITH DOT ABOVE => i (U+0069) */
- len += g_unichar_to_utf8 (0x0069, out_buffer ? out_buffer + len : NULL);
+ append_utf8_char_to_buffer (0x0069, out_buffer, &len);
+
if (combining_dot)
p = g_utf8_next_char (p);
}
else
{
/* I => LATIN SMALL LETTER DOTLESS I */
- len += g_unichar_to_utf8 (0x131, out_buffer ? out_buffer + len : NULL);
+ append_utf8_char_to_buffer (0x131, out_buffer, &len);
}
}
/* Introduce an explicit dot above when lowercasing capital I's and J's
@@ -1037,19 +1066,19 @@ real_tolower (const gchar *str,
else if (locale_type == LOCALE_LITHUANIAN &&
(c == 0x00cc || c == 0x00cd || c == 0x0128))
{
- len += g_unichar_to_utf8 (0x0069, out_buffer ? out_buffer + len : NULL);
- len += g_unichar_to_utf8 (0x0307, out_buffer ? out_buffer + len : NULL);
+ append_utf8_char_to_buffer (0x0069, out_buffer, &len);
+ append_utf8_char_to_buffer (0x0307, out_buffer, &len);
switch (c)
{
case 0x00cc:
- len += g_unichar_to_utf8 (0x0300, out_buffer ? out_buffer + len : NULL);
+ append_utf8_char_to_buffer (0x0300, out_buffer, &len);
break;
case 0x00cd:
- len += g_unichar_to_utf8 (0x0301, out_buffer ? out_buffer + len : NULL);
+ append_utf8_char_to_buffer (0x0301, out_buffer, &len);
break;
case 0x0128:
- len += g_unichar_to_utf8 (0x0303, out_buffer ? out_buffer + len : NULL);
+ append_utf8_char_to_buffer (0x0303, out_buffer, &len);
break;
}
}
@@ -1058,8 +1087,8 @@ real_tolower (const gchar *str,
c == 'J' || c == G_UNICHAR_FULLWIDTH_J || c == 0x012e) &&
has_more_above (p))
{
- len += g_unichar_to_utf8 (g_unichar_tolower (c), out_buffer ? out_buffer + len : NULL);
- len += g_unichar_to_utf8 (0x0307, out_buffer ? out_buffer + len : NULL);
+ append_utf8_char_to_buffer (g_unichar_tolower (c), out_buffer, &len);
+ append_utf8_char_to_buffer (0x0307, out_buffer, &len);
}
else if (c == 0x03A3) /* GREEK CAPITAL LETTER SIGMA */
{
@@ -1082,7 +1111,7 @@ real_tolower (const gchar *str,
else
val = 0x3c2; /* GREEK SMALL FINAL SIGMA */
- len += g_unichar_to_utf8 (val, out_buffer ? out_buffer + len : NULL);
+ append_utf8_char_to_buffer (val, out_buffer, &len);
}
else if (IS (t,
OR (G_UNICODE_UPPERCASE_LETTER,
@@ -1093,7 +1122,7 @@ real_tolower (const gchar *str,
if (val >= 0x1000000)
{
- len += output_special_case (out_buffer ? out_buffer + len : NULL, val - 0x1000000, t, 0);
+ append_special_case (out_buffer, &len, val - 0x1000000, t, 0);
}
else
{
@@ -1112,7 +1141,7 @@ real_tolower (const gchar *str,
/* Not all uppercase letters are guaranteed to have a lowercase
* equivalent. If this is the case, val will be zero. */
- len += g_unichar_to_utf8 (val ? val : c, out_buffer ? out_buffer + len : NULL);
+ append_utf8_char_to_buffer (val ? val : c, out_buffer, &len);
}
}
else
@@ -1122,7 +1151,7 @@ real_tolower (const gchar *str,
if (out_buffer)
memcpy (out_buffer + len, last, char_len);
- len += char_len;
+ increase_size (&len, char_len);
}
}
@@ -1159,6 +1188,8 @@ g_utf8_strdown (const gchar *str,
* We use a two pass approach to keep memory management simple
*/
result_len = real_tolower (str, len, NULL, locale_type);
+ g_assert (result_len < G_MAXSIZE);
+
result = g_malloc (result_len + 1);
real_tolower (str, len, result, locale_type);
result[result_len] = '\0';
diff -urp glib-2.78.6.orig/glib/tests/unicode.c glib-2.78.6/glib/tests/unicode.c
--- glib-2.78.6.orig/glib/tests/unicode.c 2024-05-08 12:53:54.000000000 -0500
+++ glib-2.78.6/glib/tests/unicode.c 2026-01-27 14:59:20.790496661 -0600
@@ -600,6 +600,7 @@ test_casemap_and_casefold (void)
const char *locale;
const char *test;
const char *expected;
+ size_t line = 0;
char *convert;
char *current_locale = setlocale (LC_CTYPE, NULL);
char *old_lc_all, *old_lc_messages, *old_lang;
@@ -620,6 +621,7 @@ test_casemap_and_casefold (void)
while (fgets (buffer, sizeof (buffer), infile))
{
+ line++;
if (buffer[0] == '#')
continue;
@@ -662,6 +664,9 @@ test_casemap_and_casefold (void)
convert = g_utf8_strup (test, -1);
expected = strings[4][0] ? strings[4] : test;
+ g_test_message ("Converting '%s' => '%s' (line %" G_GSIZE_FORMAT ")",
+ test, expected, line);
+
g_assert_cmpstr (convert, ==, expected);
g_free (convert);
@@ -681,9 +686,11 @@ test_casemap_and_casefold (void)
infile = fopen (filename, "r");
g_assert (infile != NULL);
+ line = 0;
while (fgets (buffer, sizeof (buffer), infile))
{
+ line++;
if (buffer[0] == '#')
continue;
@@ -693,6 +700,9 @@ test_casemap_and_casefold (void)
test = strings[0];
convert = g_utf8_casefold (test, -1);
+ g_test_message ("Converting '%s' => '%s' (line %" G_GSIZE_FORMAT ")",
+ test, strings[1], line);
+
g_assert_cmpstr (convert, ==, strings[1]);
g_free (convert);
Only in glib-2.78.6/glib/tests: unicode.c.orig