1 | /* Test and measure memchr functions. |
2 | Copyright (C) 1999-2022 Free Software Foundation, Inc. |
3 | This file is part of the GNU C Library. |
4 | |
5 | The GNU C Library is free software; you can redistribute it and/or |
6 | modify it under the terms of the GNU Lesser General Public |
7 | License as published by the Free Software Foundation; either |
8 | version 2.1 of the License, or (at your option) any later version. |
9 | |
10 | The GNU C Library is distributed in the hope that it will be useful, |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | Lesser General Public License for more details. |
14 | |
15 | You should have received a copy of the GNU Lesser General Public |
16 | License along with the GNU C Library; if not, see |
17 | <https://www.gnu.org/licenses/>. */ |
18 | |
19 | #include <assert.h> |
20 | #include <support/xunistd.h> |
21 | |
22 | #define TEST_MAIN |
23 | #define TEST_NAME "rawmemchr" |
24 | #include "test-string.h" |
25 | |
26 | typedef char *(*proto_t) (const char *, int); |
27 | char *simple_rawmemchr (const char *, int); |
28 | |
29 | IMPL (simple_rawmemchr, 0) |
30 | IMPL (rawmemchr, 1) |
31 | |
32 | char * |
33 | simple_rawmemchr (const char *s, int c) |
34 | { |
35 | while (1) |
36 | if (*s++ == (char) c) |
37 | return (char *) s - 1; |
38 | return NULL; |
39 | } |
40 | |
41 | static void |
42 | do_one_test (impl_t *impl, const char *s, int c, char *exp_res) |
43 | { |
44 | char *res = CALL (impl, s, c); |
45 | if (res != exp_res) |
46 | { |
47 | error (status: 0, errnum: 0, format: "Wrong result in function %s %p %p" , impl->name, |
48 | res, exp_res); |
49 | ret = 1; |
50 | return; |
51 | } |
52 | } |
53 | |
54 | static void |
55 | do_test_bz29234 (void) |
56 | { |
57 | size_t i, j; |
58 | char *ptr_start; |
59 | char *buf = xmmap (addr: 0, length: 8192, PROT_READ | PROT_WRITE, |
60 | MAP_PRIVATE | MAP_ANONYMOUS, fd: -1); |
61 | |
62 | memset (buf, -1, 8192); |
63 | |
64 | ptr_start = buf + 4096 - 8; |
65 | |
66 | /* Out of range matches before the start of a page. */ |
67 | memset (ptr_start - 8, 0x1, 8); |
68 | |
69 | for (j = 0; j < 8; ++j) |
70 | { |
71 | for (i = 0; i < 128; ++i) |
72 | { |
73 | ptr_start[i + j] = 0x1; |
74 | |
75 | FOR_EACH_IMPL (impl, 0) |
76 | do_one_test (impl, s: (char *) (ptr_start + j), c: 0x1, |
77 | exp_res: ptr_start + i + j); |
78 | |
79 | ptr_start[i + j] = 0xff; |
80 | } |
81 | } |
82 | |
83 | xmunmap (addr: buf, length: 8192); |
84 | } |
85 | |
86 | static void |
87 | do_test (size_t align, size_t pos, size_t len, int seek_char) |
88 | { |
89 | size_t i; |
90 | char *result; |
91 | |
92 | align &= getpagesize () - 1; |
93 | if (align + len >= page_size) |
94 | return; |
95 | |
96 | for (i = 0; i < len; ++i) |
97 | { |
98 | buf1[align + i] = 1 + 23 * i % 127; |
99 | if (buf1[align + i] == seek_char) |
100 | buf1[align + i] = seek_char + 1; |
101 | } |
102 | buf1[align + len] = 0; |
103 | |
104 | assert (pos < len); |
105 | |
106 | buf1[align + pos] = seek_char; |
107 | buf1[align + len] = -seek_char; |
108 | result = (char *) (buf1 + align + pos); |
109 | |
110 | FOR_EACH_IMPL (impl, 0) |
111 | do_one_test (impl, s: (char *) (buf1 + align), c: seek_char, exp_res: result); |
112 | } |
113 | |
114 | static void |
115 | do_random_tests (void) |
116 | { |
117 | size_t i, j, n, align, pos, len; |
118 | int seek_char; |
119 | char *result; |
120 | unsigned char *p = buf1 + page_size - 512; |
121 | |
122 | for (n = 0; n < ITERATIONS; n++) |
123 | { |
124 | align = random () & 15; |
125 | pos = random () & 511; |
126 | if (pos + align >= 512) |
127 | pos = 511 - align - (random () & 7); |
128 | len = random () & 511; |
129 | if (len + align >= 512) |
130 | len = 512 - align - (random () & 7); |
131 | if (pos >= len) |
132 | continue; |
133 | seek_char = random () & 255; |
134 | j = len + align + 64; |
135 | if (j > 512) |
136 | j = 512; |
137 | |
138 | for (i = 0; i < j; i++) |
139 | { |
140 | if (i == pos + align) |
141 | p[i] = seek_char; |
142 | else |
143 | { |
144 | p[i] = random () & 255; |
145 | if (i < pos + align && p[i] == seek_char) |
146 | p[i] = seek_char + 13; |
147 | } |
148 | } |
149 | |
150 | if (align) |
151 | { |
152 | p[align - 1] = seek_char; |
153 | if (align > 4) |
154 | p[align - 4] = seek_char; |
155 | } |
156 | |
157 | assert (pos < len); |
158 | size_t r = random (); |
159 | if ((r & 31) == 0) |
160 | len = ~(uintptr_t) (p + align) - ((r >> 5) & 31); |
161 | result = (char *) (p + pos + align); |
162 | |
163 | FOR_EACH_IMPL (impl, 1) |
164 | if (CALL (impl, (char *) (p + align), seek_char) != result) |
165 | { |
166 | error (status: 0, errnum: 0, format: "Iteration %zd - wrong result in function %s (%zd, %d, %zd, %zd) %p != %p, p %p" , |
167 | n, impl->name, align, seek_char, len, pos, |
168 | CALL (impl, (char *) (p + align), seek_char), |
169 | result, p); |
170 | ret = 1; |
171 | } |
172 | |
173 | if (align) |
174 | { |
175 | p[align - 1] = seek_char; |
176 | if (align > 4) |
177 | p[align - 4] = seek_char; |
178 | } |
179 | } |
180 | } |
181 | |
182 | int |
183 | test_main (void) |
184 | { |
185 | size_t i; |
186 | |
187 | test_init (); |
188 | |
189 | printf (format: "%20s" , "" ); |
190 | FOR_EACH_IMPL (impl, 0) |
191 | printf (format: "\t%s" , impl->name); |
192 | putchar (c: '\n'); |
193 | |
194 | for (i = 1; i < 7; ++i) |
195 | { |
196 | do_test (align: 0, pos: 16 << i, len: 2048, seek_char: 23); |
197 | do_test (align: i, pos: 64, len: 256, seek_char: 23); |
198 | do_test (align: 0, pos: 16 << i, len: 2048, seek_char: 0); |
199 | do_test (align: i, pos: 64, len: 256, seek_char: 0); |
200 | |
201 | do_test (align: getpagesize () - i, pos: 64, len: 256, seek_char: 23); |
202 | do_test (align: getpagesize () - i, pos: 64, len: 256, seek_char: 0); |
203 | } |
204 | for (i = 1; i < 32; ++i) |
205 | { |
206 | do_test (align: 0, pos: i, len: i + 1, seek_char: 23); |
207 | do_test (align: 0, pos: i, len: i + 1, seek_char: 0); |
208 | |
209 | do_test (align: getpagesize () - 7, pos: i, len: i + 1, seek_char: 23); |
210 | do_test (align: getpagesize () - i / 2, pos: i, len: i + 1, seek_char: 23); |
211 | do_test (align: getpagesize () - i, pos: i, len: i + 1, seek_char: 23); |
212 | } |
213 | |
214 | do_random_tests (); |
215 | do_test_bz29234 (); |
216 | return ret; |
217 | } |
218 | |
219 | #include <support/test-driver.c> |
220 | |