File glib2-CVE-2026-1489.patch of Package glib2.42479
diff -urp glib-2.62.6.orig/glib/guniprop.c glib-2.62.6/glib/guniprop.c
--- glib-2.62.6.orig/glib/guniprop.c 2020-03-18 08:16:11.000000000 -0500
+++ glib-2.62.6/glib/guniprop.c 2026-01-27 16:36:12.873445041 -0600
@@ -746,14 +746,36 @@ get_locale_type (void)
return LOCALE_NORMAL;
}
-static gint
-output_marks (const char **p_inout,
- char *out_buffer,
- gboolean remove_dot)
+__attribute__ ((__always_inline__)) static inline void
+increase_size (size_t *sizeptr, size_t add)
+{
+ g_assert (G_MAXSIZE - *(sizeptr) >= add);
+ *(sizeptr) += add;
+}
+
+__attribute__ ((__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);
@@ -761,7 +783,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
@@ -769,14 +791,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;
@@ -788,10 +810,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
@@ -832,11 +856,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;
}
@@ -849,17 +875,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,
@@ -870,8 +896,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
{
@@ -891,7 +917,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
@@ -901,7 +927,7 @@ real_toupper (const gchar *str,
if (out_buffer)
memcpy (out_buffer + len, last, char_len);
- len += char_len;
+ increase_size (&len, char_len);
}
}
@@ -939,6 +965,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';
@@ -993,13 +1021,13 @@ real_tolower (const gchar *str,
if (g_utf8_get_char (p) == 0x0307)
{
/* I + COMBINING 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);
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
@@ -1007,19 +1035,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;
}
}
@@ -1028,8 +1056,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 */
{
@@ -1052,7 +1080,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,
@@ -1063,7 +1091,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
{
@@ -1082,7 +1110,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
@@ -1092,7 +1120,7 @@ real_tolower (const gchar *str,
if (out_buffer)
memcpy (out_buffer + len, last, char_len);
- len += char_len;
+ increase_size (&len, char_len);
}
}
@@ -1129,6 +1157,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';