From e8dfd7c3f3513c94978155c62e16547df7ae6976 Mon Sep 17 00:00:00 2001 From: Azure Linux Security Servicing Account Date: Fri, 6 Feb 2026 05:00:43 +0000 Subject: [PATCH] Patch glib for CVE-2026-1489 --- SPECS/glib/CVE-2026-1489.patch | 431 ++++++++++++++++++ SPECS/glib/glib.spec | 6 +- .../manifests/package/pkggen_core_aarch64.txt | 2 +- .../manifests/package/pkggen_core_x86_64.txt | 2 +- .../manifests/package/toolchain_aarch64.txt | 10 +- .../manifests/package/toolchain_x86_64.txt | 10 +- 6 files changed, 448 insertions(+), 13 deletions(-) create mode 100644 SPECS/glib/CVE-2026-1489.patch diff --git a/SPECS/glib/CVE-2026-1489.patch b/SPECS/glib/CVE-2026-1489.patch new file mode 100644 index 00000000000..32f7349ab2a --- /dev/null +++ b/SPECS/glib/CVE-2026-1489.patch @@ -0,0 +1,431 @@ +From 986f2a96d0ab202cc57d3e77ce2583cb3455765f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= +Date: Wed, 21 Jan 2026 22:00:17 +0100 +Subject: [PATCH 1/4] guniprop: Use size_t for output_marks length + +The input string length may overflow, and this would lead to wrong +behavior and invalid writes. + +Spotted by treeplus. +Thanks to the Sovereign Tech Resilience programme from the Sovereign +Tech Agency. + +ID: #YWH-PGM9867-171 +Closes: #3872 +--- + glib/guniprop.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/glib/guniprop.c b/glib/guniprop.c +index 61acad6..fa5d101 100644 +--- a/glib/guniprop.c ++++ b/glib/guniprop.c +@@ -772,13 +772,13 @@ get_locale_type (void) + return LOCALE_NORMAL; + } + +-static gint ++static size_t + output_marks (const char **p_inout, + char *out_buffer, + gboolean remove_dot) + { + const char *p = *p_inout; +- gint len = 0; ++ size_t len = 0; + + while (*p) + { +-- +2.45.4 + + +From c7ae9a22d5743b056151879fd18e182821b84a65 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= +Date: Wed, 21 Jan 2026 22:01:49 +0100 +Subject: [PATCH 2/4] guniprop: Do not convert size_t to gint + +We were correctly using size_t in output_special_case() since commit +362f92b69, but then we converted the value back to int + +Related to: #3872 +--- + glib/guniprop.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/glib/guniprop.c b/glib/guniprop.c +index fa5d101..4eb8734 100644 +--- a/glib/guniprop.c ++++ b/glib/guniprop.c +@@ -798,7 +798,7 @@ output_marks (const char **p_inout, + return len; + } + +-static gint ++static size_t + output_special_case (gchar *out_buffer, + int offset, + int type, +-- +2.45.4 + + +From 266b5b30fc61fbf190add844e035dee97a7f6258 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= +Date: Wed, 21 Jan 2026 22:04:22 +0100 +Subject: [PATCH 3/4] guniprop: Ensure we do not overflow size in + g_utf8_{strdown,gstrup}() + +While this is technically not a security issue, when repeatedly adding +to a size_t value, we can overflow and start from 0. + +Now, while being unlikely, technically an utf8 lower or upper string can +have a longer size than the input value, and if the output string is +bigger than G_MAXSIZE we'd end up cutting it silently. + +Let's instead assert each time we increase the output length +--- + glib/guniprop.c | 107 +++++++++++++++++++++++++++++++----------------- + 1 file changed, 69 insertions(+), 38 deletions(-) + +diff --git a/glib/guniprop.c b/glib/guniprop.c +index 4eb8734..b14354b 100644 +--- a/glib/guniprop.c ++++ b/glib/guniprop.c +@@ -772,14 +772,36 @@ get_locale_type (void) + return LOCALE_NORMAL; + } + +-static size_t +-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; +- size_t 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 size_t +-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'; +-- +2.45.4 + + +From f0296ac09f7ea89951bb4391bf486069406f8451 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= +Date: Fri, 23 Jan 2026 17:39:34 +0100 +Subject: [PATCH 4/4] glib/tests/unicode: Add test debug information when + parsing input files + +On case of failures makes it easier to understand on what line of the +source file we're at, as it might not be clear for non-ascii chars + +Signed-off-by: Azure Linux Security Servicing Account +Upstream-reference: https://gitlab.gnome.org/GNOME/glib/-/merge_requests/4984.patch +--- + glib/tests/unicode.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/glib/tests/unicode.c b/glib/tests/unicode.c +index 5d66977..9a3fba6 100644 +--- a/glib/tests/unicode.c ++++ b/glib/tests/unicode.c +@@ -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); + +-- +2.45.4 + diff --git a/SPECS/glib/glib.spec b/SPECS/glib/glib.spec index 0021a1ce02d..67ded841775 100644 --- a/SPECS/glib/glib.spec +++ b/SPECS/glib/glib.spec @@ -2,7 +2,7 @@ Summary: Low-level libraries useful for providing data structure handling for C. Name: glib Version: 2.78.6 -Release: 7%{?dist} +Release: 8%{?dist} License: LGPLv2+ Vendor: Microsoft Corporation Distribution: Azure Linux @@ -18,6 +18,7 @@ Patch5: CVE-2025-13601.patch Patch6: CVE-2025-14087.patch Patch7: CVE-2025-14512.patch Patch8: CVE-2026-1484.patch +Patch9: CVE-2026-1489.patch BuildRequires: cmake BuildRequires: gtk-doc BuildRequires: libffi-devel @@ -131,6 +132,9 @@ touch %{buildroot}%{_libdir}/gio/modules/giomodule.cache %doc %{_datadir}/gtk-doc/html/* %changelog +* Fri Feb 06 2026 Azure Linux Security Servicing Account - 2.78.6-8 +- Patch for CVE-2026-1489 + * Mon Feb 02 2026 Azure Linux Security Servicing Account - 2.78.6-7 - Patch for CVE-2026-1484 diff --git a/toolkit/resources/manifests/package/pkggen_core_aarch64.txt b/toolkit/resources/manifests/package/pkggen_core_aarch64.txt index 1a2d32c8094..0bff66348c8 100644 --- a/toolkit/resources/manifests/package/pkggen_core_aarch64.txt +++ b/toolkit/resources/manifests/package/pkggen_core_aarch64.txt @@ -208,7 +208,7 @@ libxml2-devel-2.11.5-8.azl3.aarch64.rpm docbook-dtd-xml-4.5-11.azl3.noarch.rpm docbook-style-xsl-1.79.1-14.azl3.noarch.rpm libsepol-3.6-2.azl3.aarch64.rpm -glib-2.78.6-7.azl3.aarch64.rpm +glib-2.78.6-8.azl3.aarch64.rpm libltdl-2.4.7-1.azl3.aarch64.rpm libltdl-devel-2.4.7-1.azl3.aarch64.rpm lua-5.4.6-1.azl3.aarch64.rpm diff --git a/toolkit/resources/manifests/package/pkggen_core_x86_64.txt b/toolkit/resources/manifests/package/pkggen_core_x86_64.txt index b5a0aa00789..6fe6e1564b9 100644 --- a/toolkit/resources/manifests/package/pkggen_core_x86_64.txt +++ b/toolkit/resources/manifests/package/pkggen_core_x86_64.txt @@ -208,7 +208,7 @@ libxml2-devel-2.11.5-8.azl3.x86_64.rpm docbook-dtd-xml-4.5-11.azl3.noarch.rpm docbook-style-xsl-1.79.1-14.azl3.noarch.rpm libsepol-3.6-2.azl3.x86_64.rpm -glib-2.78.6-7.azl3.x86_64.rpm +glib-2.78.6-8.azl3.x86_64.rpm libltdl-2.4.7-1.azl3.x86_64.rpm libltdl-devel-2.4.7-1.azl3.x86_64.rpm lua-5.4.6-1.azl3.x86_64.rpm diff --git a/toolkit/resources/manifests/package/toolchain_aarch64.txt b/toolkit/resources/manifests/package/toolchain_aarch64.txt index 5c571938f8c..314ac30db0e 100644 --- a/toolkit/resources/manifests/package/toolchain_aarch64.txt +++ b/toolkit/resources/manifests/package/toolchain_aarch64.txt @@ -122,11 +122,11 @@ gdbm-lang-1.23-1.azl3.aarch64.rpm gettext-0.22-1.azl3.aarch64.rpm gettext-debuginfo-0.22-1.azl3.aarch64.rpm gfortran-13.2.0-7.azl3.aarch64.rpm -glib-2.78.6-7.azl3.aarch64.rpm -glib-debuginfo-2.78.6-7.azl3.aarch64.rpm -glib-devel-2.78.6-7.azl3.aarch64.rpm -glib-doc-2.78.6-7.azl3.noarch.rpm -glib-schemas-2.78.6-7.azl3.aarch64.rpm +glib-2.78.6-8.azl3.aarch64.rpm +glib-debuginfo-2.78.6-8.azl3.aarch64.rpm +glib-devel-2.78.6-8.azl3.aarch64.rpm +glib-doc-2.78.6-8.azl3.noarch.rpm +glib-schemas-2.78.6-8.azl3.aarch64.rpm glibc-2.38-18.azl3.aarch64.rpm glibc-debuginfo-2.38-18.azl3.aarch64.rpm glibc-devel-2.38-18.azl3.aarch64.rpm diff --git a/toolkit/resources/manifests/package/toolchain_x86_64.txt b/toolkit/resources/manifests/package/toolchain_x86_64.txt index 0861a676436..48e30e2c34d 100644 --- a/toolkit/resources/manifests/package/toolchain_x86_64.txt +++ b/toolkit/resources/manifests/package/toolchain_x86_64.txt @@ -129,11 +129,11 @@ gdbm-lang-1.23-1.azl3.x86_64.rpm gettext-0.22-1.azl3.x86_64.rpm gettext-debuginfo-0.22-1.azl3.x86_64.rpm gfortran-13.2.0-7.azl3.x86_64.rpm -glib-2.78.6-7.azl3.x86_64.rpm -glib-debuginfo-2.78.6-7.azl3.x86_64.rpm -glib-devel-2.78.6-7.azl3.x86_64.rpm -glib-doc-2.78.6-7.azl3.noarch.rpm -glib-schemas-2.78.6-7.azl3.x86_64.rpm +glib-2.78.6-8.azl3.x86_64.rpm +glib-debuginfo-2.78.6-8.azl3.x86_64.rpm +glib-devel-2.78.6-8.azl3.x86_64.rpm +glib-doc-2.78.6-8.azl3.noarch.rpm +glib-schemas-2.78.6-8.azl3.x86_64.rpm glibc-2.38-18.azl3.x86_64.rpm glibc-debuginfo-2.38-18.azl3.x86_64.rpm glibc-devel-2.38-18.azl3.x86_64.rpm