| commit 5373c90f2ea3c3fa9931a684c9b81c648dfbe8d7 |
| Author: Noah Goldstein <goldstein.w.n@gmail.com> |
| Date: Tue Feb 15 20:27:21 2022 -0600 |
| |
| x86: Fix bug in strncmp-evex and strncmp-avx2 [BZ #28895] |
| |
| Logic can read before the start of `s1` / `s2` if both `s1` and `s2` |
| are near the start of a page. To avoid having the result contimated by |
| these comparisons the `strcmp` variants would mask off these |
| comparisons. This was missing in the `strncmp` variants causing |
| the bug. This commit adds the masking to `strncmp` so that out of |
| range comparisons don't affect the result. |
| |
| test-strcmp, test-strncmp, test-wcscmp, and test-wcsncmp all pass as |
| well a full xcheck on x86_64 linux. |
| Reviewed-by: H.J. Lu <hjl.tools@gmail.com> |
| |
| (cherry picked from commit e108c02a5e23c8c88ce66d8705d4a24bb6b9a8bf) |
| |
| diff --git a/string/test-strncmp.c b/string/test-strncmp.c |
| index 97e831d88fd24316..56e23670ae7f90e4 100644 |
| |
| |
| @@ -438,13 +438,23 @@ check3 (void) |
| static void |
| check4 (void) |
| { |
| - const CHAR *s1 = L ("abc"); |
| - CHAR *s2 = STRDUP (s1); |
| + /* To trigger bug 28895; We need 1) both s1 and s2 to be within 32 bytes of |
| + the end of the page. 2) For there to be no mismatch/null byte before the |
| + first page cross. 3) For length (`n`) to be large enough for one string to |
| + cross the page. And 4) for there to be either mismatch/null bytes before |
| + the start of the strings. */ |
| + |
| + size_t size = 10; |
| + size_t addr_mask = (getpagesize () - 1) ^ (sizeof (CHAR) - 1); |
| + CHAR *s1 = (CHAR *)(buf1 + (addr_mask & 0xffa)); |
| + CHAR *s2 = (CHAR *)(buf2 + (addr_mask & 0xfed)); |
| + int exp_result; |
| |
| + STRCPY (s1, L ("tst-tlsmod%")); |
| + STRCPY (s2, L ("tst-tls-manydynamic73mod")); |
| + exp_result = SIMPLE_STRNCMP (s1, s2, size); |
| FOR_EACH_IMPL (impl, 0) |
| - check_result (impl, s1, s2, SIZE_MAX, 0); |
| - |
| - free (s2); |
| + check_result (impl, s1, s2, size, exp_result); |
| } |
| |
| int |
| diff --git a/sysdeps/x86_64/multiarch/strcmp-avx2.S b/sysdeps/x86_64/multiarch/strcmp-avx2.S |
| index cdded412a70bad10..f9bdc5ccd03aa1f9 100644 |
| |
| |
| @@ -661,6 +661,7 @@ L(ret8): |
| # ifdef USE_AS_STRNCMP |
| .p2align 4,, 10 |
| L(return_page_cross_end_check): |
| + andl %r10d, %ecx |
| tzcntl %ecx, %ecx |
| leal -VEC_SIZE(%rax, %rcx), %ecx |
| cmpl %ecx, %edx |
| diff --git a/sysdeps/x86_64/multiarch/strcmp-evex.S b/sysdeps/x86_64/multiarch/strcmp-evex.S |
| index ed56af8ecdad48b2..0dfa62bd149c02b4 100644 |
| |
| |
| @@ -689,6 +689,7 @@ L(ret8): |
| # ifdef USE_AS_STRNCMP |
| .p2align 4,, 10 |
| L(return_page_cross_end_check): |
| + andl %r10d, %ecx |
| tzcntl %ecx, %ecx |
| leal -VEC_SIZE(%rax, %rcx, SIZE_OF_CHAR), %ecx |
| # ifdef USE_AS_WCSCMP |