You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
89 lines
3.7 KiB
89 lines
3.7 KiB
2 years ago
|
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)
|