diff --git a/glibc.spec b/glibc.spec index efaa79c241c3c64db054b5fe9d6e86a469d92082..c0a529cf568a780643da51d31079a80dbc5621fa 100644 --- a/glibc.spec +++ b/glibc.spec @@ -67,7 +67,7 @@ ############################################################################## Name: glibc Version: 2.38 -Release: 34 +Release: 35 Summary: The GNU libc libraries License: %{all_license} URL: http://www.gnu.org/software/glibc/ @@ -213,6 +213,7 @@ Patch123: 0010-Add-mremap-tests.patch Patch124: 0011-Update-syscall-lists-for-Linux-6.5.patch Patch125: 0012-resolv-Fix-tst-resolv-short-response-for-older-GCC-b.patch Patch126: Fix-name-space-violation-in-fortify-wrappers-bug-320.patch +Patch127: x86-Fix-bug-in-strchrnul-evex512-BZ-32078.patch #openEuler patch list Patch9000: turn-default-value-of-x86_rep_stosb_threshold_form_2K_to_1M.patch @@ -1446,6 +1447,9 @@ fi %endif %changelog +* Thu Aug 22 2024 Qingqing Li - 2.38-35 +- x86: Fix bug in strchrnul-evex512 [BZ #32078] + * Fri Aug 9 2024 taoyuxiang - 2.38-34 - Specify the GFDL version to GFDL-1.3-ONLY in spec diff --git a/x86-Fix-bug-in-strchrnul-evex512-BZ-32078.patch b/x86-Fix-bug-in-strchrnul-evex512-BZ-32078.patch new file mode 100644 index 0000000000000000000000000000000000000000..85af57b6a60a7ca9685d14d38e5f20d7b47a8786 --- /dev/null +++ b/x86-Fix-bug-in-strchrnul-evex512-BZ-32078.patch @@ -0,0 +1,162 @@ +From c005d1bd6f0e88ab4b822844d75d10c8978f5404 Mon Sep 17 00:00:00 2001 +From: Noah Goldstein +Date: Tue, 13 Aug 2024 23:29:14 +0800 +Subject: [PATCH] x86: Fix bug in strchrnul-evex512 [BZ #32078] + +Issue was we were expecting not matches with CHAR before the start of +the string in the page cross case. + +The check code in the page cross case: +``` + and $0xffffffffffffffc0,%rax + vmovdqa64 (%rax),%zmm17 + vpcmpneqb %zmm17,%zmm16,%k1 + vptestmb %zmm17,%zmm17,%k0{%k1} + kmovq %k0,%rax + inc %rax + shr %cl,%rax + je L(continue) +``` + +expects that all characters that neither match null nor CHAR will be +1s in `rax` prior to the `inc`. Then the `inc` will overflow all of +the 1s where no relevant match was found. + +This is incorrect in the page-cross case, as the +`vmovdqa64 (%rax),%zmm17` loads from before the start of the input +string. + +If there are matches with CHAR before the start of the string, `rax` +won't properly overflow. + +The fix is quite simple. Just replace: + +``` + inc %rax + shr %cl,%rax +``` +With: +``` + sar %cl,%rax + inc %rax +``` + +The arithmetic shift will clear any matches prior to the start of the +string while maintaining the signbit so the 1s can properly overflow +to zero in the case of no matches. +Reviewed-by: H.J. Lu + +(cherry picked from commit 7da08862471dfec6fdae731c2a5f351ad485c71f) +--- + string/test-strchr.c | 65 ++++++++++++++++++++- + sysdeps/x86_64/multiarch/strchr-evex-base.S | 8 +-- + 2 files changed, 68 insertions(+), 5 deletions(-) + +diff --git a/string/test-strchr.c b/string/test-strchr.c +index 933fc0bbba..2bfcf901fa 100644 +--- a/string/test-strchr.c ++++ b/string/test-strchr.c +@@ -248,6 +248,69 @@ check1 (void) + check_result (impl, s, c, exp_result); + } + ++static void ++check2 (void) ++{ ++ CHAR *s = (CHAR *) (buf1 + getpagesize () - 4 * sizeof (CHAR)); ++ CHAR *s_begin = (CHAR *) (buf1 + getpagesize () - 64); ++#ifndef USE_FOR_STRCHRNUL ++ CHAR *exp_result = NULL; ++#else ++ CHAR *exp_result = s + 1; ++#endif ++ CHAR val = 0x12; ++ for (; s_begin != s; ++s_begin) ++ *s_begin = val; ++ ++ s[0] = val + 1; ++ s[1] = 0; ++ s[2] = val + 1; ++ s[3] = val + 1; ++ ++ { ++ FOR_EACH_IMPL (impl, 0) ++ check_result (impl, s, val, exp_result); ++ } ++ s[3] = val; ++ { ++ FOR_EACH_IMPL (impl, 0) ++ check_result (impl, s, val, exp_result); ++ } ++ exp_result = s; ++ s[0] = val; ++ { ++ FOR_EACH_IMPL (impl, 0) ++ check_result (impl, s, val, exp_result); ++ } ++ ++ s[3] = val + 1; ++ { ++ FOR_EACH_IMPL (impl, 0) ++ check_result (impl, s, val, exp_result); ++ } ++ ++ s[0] = val + 1; ++ s[1] = val + 1; ++ s[2] = val + 1; ++ s[3] = val + 1; ++ s[4] = val; ++ exp_result = s + 4; ++ { ++ FOR_EACH_IMPL (impl, 0) ++ check_result (impl, s, val, exp_result); ++ } ++ s[4] = 0; ++#ifndef USE_FOR_STRCHRNUL ++ exp_result = NULL; ++#else ++ exp_result = s + 4; ++#endif ++ { ++ FOR_EACH_IMPL (impl, 0) ++ check_result (impl, s, val, exp_result); ++ } ++} ++ + int + test_main (void) + { +@@ -256,7 +319,7 @@ test_main (void) + test_init (); + + check1 (); +- ++ check2 (); + printf ("%20s", ""); + FOR_EACH_IMPL (impl, 0) + printf ("\t%s", impl->name); +diff --git a/sysdeps/x86_64/multiarch/strchr-evex-base.S b/sysdeps/x86_64/multiarch/strchr-evex-base.S +index 7209435caf..da6d0eafbb 100644 +--- a/sysdeps/x86_64/multiarch/strchr-evex-base.S ++++ b/sysdeps/x86_64/multiarch/strchr-evex-base.S +@@ -124,13 +124,13 @@ L(page_cross): + VPCMPNE %VMM(1), %VMM(0), %k1 + VPTEST %VMM(1), %VMM(1), %k0{%k1} + KMOV %k0, %VRAX +-# ifdef USE_AS_WCSCHR ++ sar %cl, %VRAX ++#ifdef USE_AS_WCSCHR + sub $VEC_MATCH_MASK, %VRAX +-# else ++#else + inc %VRAX +-# endif ++#endif + /* Ignore number of character for alignment adjustment. */ +- shr %cl, %VRAX + jz L(align_more) + + bsf %VRAX, %VRAX +-- +2.33.0 +