89 lines
3.7 KiB
Diff
89 lines
3.7 KiB
Diff
commit bfdb731438206b0f70fe7afa890681155c30b419
|
|
Author: Stefan Liebler <stli@linux.ibm.com>
|
|
Date: Wed Nov 27 12:35:40 2019 +0100
|
|
|
|
S390: Fix handling of needles crossing a page in strstr z15 ifunc-variant. [BZ #25226]
|
|
|
|
If the specified needle crosses a page-boundary, the s390-z15 ifunc variant of
|
|
strstr truncates the needle which results in invalid results.
|
|
|
|
This is fixed by loading the needle beyond the page boundary to v18 instead of v16.
|
|
The bug is sometimes observable in test-strstr.c in check1 and check2 as the
|
|
haystack and needle is stored on stack. Thus the needle can be on a page boundary.
|
|
|
|
check2 is now extended to test haystack / needles located on stack, at end of page
|
|
and on two pages.
|
|
|
|
This bug was introduced with commit 6f47401bd5fc71209219779a0426170a9a7395b0
|
|
("S390: Add arch13 strstr ifunc variant.") and is already released in glibc 2.30.
|
|
|
|
diff --git a/string/test-strstr.c b/string/test-strstr.c
|
|
index 5861b01b73e4c315..e9e14c1ee605516e 100644
|
|
--- a/string/test-strstr.c
|
|
+++ b/string/test-strstr.c
|
|
@@ -138,16 +138,45 @@ check1 (void)
|
|
static void
|
|
check2 (void)
|
|
{
|
|
- const char s1[] = ", enable_static, \0, enable_shared, ";
|
|
+ const char s1_stack[] = ", enable_static, \0, enable_shared, ";
|
|
+ const size_t s1_byte_count = 18;
|
|
+ const char *s2_stack = &(s1_stack[s1_byte_count]);
|
|
+ const size_t s2_byte_count = 18;
|
|
char *exp_result;
|
|
- char *s2 = (void *) buf1 + page_size - 18;
|
|
+ const size_t page_size_real = getpagesize ();
|
|
|
|
- strcpy (s2, s1);
|
|
- exp_result = stupid_strstr (s1, s1 + 18);
|
|
+ /* Haystack at end of page. The following page is protected. */
|
|
+ char *s1_page_end = (void *) buf1 + page_size - s1_byte_count;
|
|
+ strcpy (s1_page_end, s1_stack);
|
|
+
|
|
+ /* Haystack which crosses a page boundary.
|
|
+ Note: page_size is at least 2 * getpagesize. See test_init. */
|
|
+ char *s1_page_cross = (void *) buf1 + page_size_real - 8;
|
|
+ strcpy (s1_page_cross, s1_stack);
|
|
+
|
|
+ /* Needle at end of page. The following page is protected. */
|
|
+ char *s2_page_end = (void *) buf2 + page_size - s2_byte_count;
|
|
+ strcpy (s2_page_end, s2_stack);
|
|
+
|
|
+ /* Needle which crosses a page boundary.
|
|
+ Note: page_size is at least 2 * getpagesize. See test_init. */
|
|
+ char *s2_page_cross = (void *) buf2 + page_size_real - 8;
|
|
+ strcpy (s2_page_cross, s2_stack);
|
|
+
|
|
+ exp_result = stupid_strstr (s1_stack, s2_stack);
|
|
FOR_EACH_IMPL (impl, 0)
|
|
{
|
|
- check_result (impl, s1, s1 + 18, exp_result);
|
|
- check_result (impl, s2, s1 + 18, exp_result);
|
|
+ check_result (impl, s1_stack, s2_stack, exp_result);
|
|
+ check_result (impl, s1_stack, s2_page_end, exp_result);
|
|
+ check_result (impl, s1_stack, s2_page_cross, exp_result);
|
|
+
|
|
+ check_result (impl, s1_page_end, s2_stack, exp_result);
|
|
+ check_result (impl, s1_page_end, s2_page_end, exp_result);
|
|
+ check_result (impl, s1_page_end, s2_page_cross, exp_result);
|
|
+
|
|
+ check_result (impl, s1_page_cross, s2_stack, exp_result);
|
|
+ check_result (impl, s1_page_cross, s2_page_end, exp_result);
|
|
+ check_result (impl, s1_page_cross, s2_page_cross, exp_result);
|
|
}
|
|
}
|
|
|
|
diff --git a/sysdeps/s390/strstr-arch13.S b/sysdeps/s390/strstr-arch13.S
|
|
index 929b026adfeba740..faa969849e09c2e1 100644
|
|
--- a/sysdeps/s390/strstr-arch13.S
|
|
+++ b/sysdeps/s390/strstr-arch13.S
|
|
@@ -164,7 +164,7 @@ ENTRY(STRSTR_ARCH13)
|
|
vfenezb %v19,%v18,%v18 /* Search zero in loaded needle bytes. */
|
|
veclb %v19,%v21 /* Zero index <= max loaded byte index? */
|
|
jle .Lneedle_loaded /* -> v18 contains full needle. */
|
|
- vl %v16,0(%r3) /* Load needle beyond page boundary. */
|
|
+ vl %v18,0(%r3) /* Load needle beyond page boundary. */
|
|
vfenezb %v19,%v18,%v18
|
|
j .Lneedle_loaded
|
|
END(STRSTR_ARCH13)
|