1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
|
From b0969fa53a28b4ab2159806bf6c99a98999502ee Mon Sep 17 00:00:00 2001
From: Noah Goldstein <goldstein.w.n@gmail.com>
Date: Tue, 20 Sep 2022 17:58:04 -0700
Subject: [PATCH] x86: Fix wcsnlen-avx2 page cross length comparison [BZ
#29591]
Previous implementation was adjusting length (rsi) to match
bytes (eax), but since there is no bound to length this can cause
overflow.
Fix is to just convert the byte-count (eax) to length by dividing by
sizeof (wchar_t) before the comparison.
Conflict:adapt context.
Reference:https://sourceware.org/git/?p=glibc.git;a=commit;h=b0969fa53a28b4ab2159806bf6c99a98999502ee
Full check passes on x86-64 and build succeeds w/ and w/o multiarch.
---
string/test-strnlen.c | 70 +++++++++++++++-----------
sysdeps/x86_64/multiarch/strlen-avx2.S | 7 +--
2 files changed, 43 insertions(+), 34 deletions(-)
diff --git a/string/test-strnlen.c b/string/test-strnlen.c
index 4a9375112a..5cbaf4b734 100644
--- a/string/test-strnlen.c
+++ b/string/test-strnlen.c
@@ -73,7 +73,7 @@ do_test (size_t align, size_t len, size_t maxlen, int max_char)
{
size_t i;
- align &= 63;
+ align &= (getpagesize () / sizeof (CHAR) - 1);
if ((align + len) * sizeof (CHAR) >= page_size)
return;
@@ -90,36 +90,50 @@ do_test (size_t align, size_t len, size_t maxlen, int max_char)
static void
do_overflow_tests (void)
{
- size_t i, j, len;
+ size_t i, j, al_idx, repeats, len;
const size_t one = 1;
uintptr_t buf_addr = (uintptr_t) buf1;
+ const size_t alignments[] = { 0, 1, 7, 9, 31, 33, 63, 65, 95, 97, 127, 129 };
- for (i = 0; i < 750; ++i)
+ for (al_idx = 0; al_idx < sizeof (alignments) / sizeof (alignments[0]);
+ al_idx++)
{
- do_test (0, i, SIZE_MAX - i, BIG_CHAR);
- do_test (0, i, i - buf_addr, BIG_CHAR);
- do_test (0, i, -buf_addr - i, BIG_CHAR);
- do_test (0, i, SIZE_MAX - buf_addr - i, BIG_CHAR);
- do_test (0, i, SIZE_MAX - buf_addr + i, BIG_CHAR);
-
- len = 0;
- for (j = 8 * sizeof(size_t) - 1; j ; --j)
- {
- len |= one << j;
- do_test (0, i, len - i, BIG_CHAR);
- do_test (0, i, len + i, BIG_CHAR);
- do_test (0, i, len - buf_addr - i, BIG_CHAR);
- do_test (0, i, len - buf_addr + i, BIG_CHAR);
-
- do_test (0, i, ~len - i, BIG_CHAR);
- do_test (0, i, ~len + i, BIG_CHAR);
- do_test (0, i, ~len - buf_addr - i, BIG_CHAR);
- do_test (0, i, ~len - buf_addr + i, BIG_CHAR);
-
- do_test (0, i, -buf_addr, BIG_CHAR);
- do_test (0, i, j - buf_addr, BIG_CHAR);
- do_test (0, i, -buf_addr - j, BIG_CHAR);
- }
+ for (repeats = 0; repeats < 2; ++repeats)
+ {
+ size_t align = repeats ? (getpagesize () - alignments[al_idx])
+ : alignments[al_idx];
+ align /= sizeof (CHAR);
+ for (i = 0; i < 750; ++i)
+ {
+ do_test (align, i, SIZE_MAX, BIG_CHAR);
+
+ do_test (align, i, SIZE_MAX - i, BIG_CHAR);
+ do_test (align, i, i - buf_addr, BIG_CHAR);
+ do_test (align, i, -buf_addr - i, BIG_CHAR);
+ do_test (align, i, SIZE_MAX - buf_addr - i, BIG_CHAR);
+ do_test (align, i, SIZE_MAX - buf_addr + i, BIG_CHAR);
+
+ len = 0;
+ for (j = 8 * sizeof (size_t) - 1; j; --j)
+ {
+ len |= one << j;
+ do_test (align, i, len, BIG_CHAR);
+ do_test (align, i, len - i, BIG_CHAR);
+ do_test (align, i, len + i, BIG_CHAR);
+ do_test (align, i, len - buf_addr - i, BIG_CHAR);
+ do_test (align, i, len - buf_addr + i, BIG_CHAR);
+
+ do_test (align, i, ~len - i, BIG_CHAR);
+ do_test (align, i, ~len + i, BIG_CHAR);
+ do_test (align, i, ~len - buf_addr - i, BIG_CHAR);
+ do_test (align, i, ~len - buf_addr + i, BIG_CHAR);
+
+ do_test (align, i, -buf_addr, BIG_CHAR);
+ do_test (align, i, j - buf_addr, BIG_CHAR);
+ do_test (align, i, -buf_addr - j, BIG_CHAR);
+ }
+ }
+ }
}
}
diff --git a/sysdeps/x86_64/multiarch/strlen-avx2.S b/sysdeps/x86_64/multiarch/strlen-avx2.S
index 0593fb303b..b9b58ef599 100644
--- a/sysdeps/x86_64/multiarch/strlen-avx2.S
+++ b/sysdeps/x86_64/multiarch/strlen-avx2.S
@@ -544,14 +544,11 @@ L(return_vzeroupper):
L(cross_page_less_vec):
tzcntl %eax, %eax
# ifdef USE_AS_WCSLEN
- /* NB: Multiply length by 4 to get byte count. */
- sall $2, %esi
+ /* NB: Divide by 4 to convert from byte-count to length. */
+ shrl $2, %eax
# endif
cmpq %rax, %rsi
cmovb %esi, %eax
-# ifdef USE_AS_WCSLEN
- shrl $2, %eax
-# endif
VZEROUPPER_RETURN
# endif
--
2.33.0
|