1 /* Test strncmp and wcsncmp 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 #define TEST_LEN (getpagesize () * 3)
20 #define MIN_PAGE_SIZE (TEST_LEN + 2 * getpagesize ())
21 
22 #define TEST_MAIN
23 #ifdef WIDE
24 # define TEST_NAME "wcsncmp"
25 #else
26 # define TEST_NAME "strncmp"
27 #endif
28 #define TIMEOUT (5 * 60)
29 #include "test-string.h"
30 
31 #ifdef WIDE
32 # include <wchar.h>
33 
34 # define L(str) L##str
35 # define STRNCMP wcsncmp
36 # define STRCPY wcscpy
37 # define STRDUP wcsdup
38 # define MEMCPY wmemcpy
39 # define SIMPLE_STRNCMP simple_wcsncmp
40 # define CHAR wchar_t
41 # define UCHAR wchar_t
42 # define CHARBYTES 4
43 # define CHAR__MAX WCHAR_MAX
44 # define CHAR__MIN WCHAR_MIN
45 
46 /* Wcsncmp uses signed semantics for comparison, not unsigned.
47    Avoid using substraction since possible overflow */
48 int
simple_wcsncmp(const CHAR * s1,const CHAR * s2,size_t n)49 simple_wcsncmp (const CHAR *s1, const CHAR *s2, size_t n)
50 {
51   wchar_t c1, c2;
52 
53   while (n--)
54     {
55       c1 = *s1++;
56       c2 = *s2++;
57       if (c1 == L('\0') || c1 != c2)
58 	return c1 > c2 ? 1 : (c1 < c2 ? -1 : 0);
59     }
60   return 0;
61 }
62 
63 #else
64 # define L(str) str
65 # define STRNCMP strncmp
66 # define STRCPY strcpy
67 # define STRDUP strdup
68 # define MEMCPY memcpy
69 # define SIMPLE_STRNCMP simple_strncmp
70 # define CHAR char
71 # define UCHAR unsigned char
72 # define CHARBYTES 1
73 # define CHAR__MAX CHAR_MAX
74 # define CHAR__MIN CHAR_MIN
75 
76 /* Strncmp uses unsigned semantics for comparison. */
77 int
simple_strncmp(const char * s1,const char * s2,size_t n)78 simple_strncmp (const char *s1, const char *s2, size_t n)
79 {
80   int ret = 0;
81 
82   while (n-- && (ret = *(unsigned char *) s1 - * (unsigned char *) s2++) == 0
83 	 && *s1++);
84   return ret;
85 }
86 
87 #endif
88 
89 typedef int (*proto_t) (const CHAR *, const CHAR *, size_t);
90 
91 IMPL (STRNCMP, 1)
92 
93 
94 static int
check_result(impl_t * impl,const CHAR * s1,const CHAR * s2,size_t n,int exp_result)95 check_result (impl_t *impl, const CHAR *s1, const CHAR *s2, size_t n,
96 	     int exp_result)
97 {
98   int result = CALL (impl, s1, s2, n);
99   if ((exp_result == 0 && result != 0)
100       || (exp_result < 0 && result >= 0)
101       || (exp_result > 0 && result <= 0))
102     {
103       error (0, 0, "Wrong result in function %s %d %d", impl->name,
104 	     result, exp_result);
105       ret = 1;
106       return -1;
107     }
108 
109   return 0;
110 }
111 
112 static void
do_one_test(impl_t * impl,const CHAR * s1,const CHAR * s2,size_t n,int exp_result)113 do_one_test (impl_t *impl, const CHAR *s1, const CHAR *s2, size_t n,
114 	     int exp_result)
115 {
116   if (check_result (impl, s1, s2, n, exp_result) < 0)
117     return;
118 }
119 
120 static void
do_test_limit(size_t align1,size_t align2,size_t len,size_t n,int max_char,int exp_result)121 do_test_limit (size_t align1, size_t align2, size_t len, size_t n, int max_char,
122 	 int exp_result)
123 {
124   size_t i, align_n;
125   CHAR *s1, *s2;
126 
127   align1 &= ~(CHARBYTES - 1);
128   align2 &= ~(CHARBYTES - 1);
129 
130   if (n == 0)
131     {
132       s1 = (CHAR *) (buf1 + page_size);
133       s2 = (CHAR *) (buf2 + page_size);
134 
135       FOR_EACH_IMPL (impl, 0)
136 	do_one_test (impl, s1, s2, n, 0);
137 
138       return;
139     }
140 
141   align1 &= 15;
142   align2 &= 15;
143   align_n = (page_size - n * CHARBYTES) & 15;
144 
145   s1 = (CHAR *) (buf1 + page_size - n * CHARBYTES);
146   s2 = (CHAR *) (buf2 + page_size - n * CHARBYTES);
147 
148   if (align1 < align_n)
149     s1 = (CHAR *) ((char *) s1 - (align_n - align1));
150 
151   if (align2 < align_n)
152     s2 = (CHAR *) ((char *) s2 - (align_n - align2));
153 
154   for (i = 0; i < n; i++)
155     s1[i] = s2[i] = 1 + 23 * i % max_char;
156 
157   if (len < n)
158     {
159       s1[len] = 0;
160       s2[len] = 0;
161       if (exp_result < 0)
162 	s2[len] = 32;
163       else if (exp_result > 0)
164 	s1[len] = 64;
165     }
166 
167   FOR_EACH_IMPL (impl, 0)
168     do_one_test (impl, s1, s2, n, exp_result);
169 }
170 
171 static void
do_test_n(size_t align1,size_t align2,size_t len,size_t n,int n_in_bounds,int max_char,int exp_result)172 do_test_n (size_t align1, size_t align2, size_t len, size_t n, int n_in_bounds,
173            int max_char, int exp_result)
174 {
175   size_t i, buf_bound;
176   CHAR *s1, *s2, *s1_end, *s2_end;
177 
178   align1 &= ~(CHARBYTES - 1);
179   align2 &= ~(CHARBYTES - 1);
180 
181   if (n == 0)
182     return;
183 
184   buf_bound = n_in_bounds ? n : len;
185 
186   align1 &= getpagesize () - 1;
187   if (align1 + (buf_bound + 2) * CHARBYTES >= page_size)
188     return;
189 
190   align2 &= getpagesize () - 1;
191   if (align2 + (buf_bound + 2) * CHARBYTES >= page_size)
192     return;
193 
194   s1 = (CHAR *)(buf1 + align1);
195   s2 = (CHAR *)(buf2 + align2);
196 
197   if (n_in_bounds)
198     {
199       s1[n] = 24 + exp_result;
200       s2[n] = 23;
201     }
202 
203   for (i = 0; i < buf_bound; i++)
204     s1[i] = s2[i] = 1 + (23 << ((CHARBYTES - 1) * 8)) * i % max_char;
205 
206   s1[len] = 0;
207   s2[len] = 0;
208   if (exp_result < 0)
209     s2[len] = 32;
210   else if (exp_result > 0)
211     s1[len] = 64;
212   if (len >= n)
213     s2[n - 1] -= exp_result;
214 
215   /* Ensure that both s1 and s2 are valid null terminated strings. This is
216    * required by the standard. */
217   s1_end = (CHAR *)(buf1 + MIN_PAGE_SIZE - CHARBYTES);
218   s2_end = (CHAR *)(buf2 + MIN_PAGE_SIZE - CHARBYTES);
219   *s1_end = 0;
220   *s2_end = 0;
221 
222   FOR_EACH_IMPL (impl, 0)
223     do_one_test (impl, s1, s2, n, exp_result);
224 }
225 
226 static void
do_test(size_t align1,size_t align2,size_t len,size_t n,int max_char,int exp_result)227 do_test (size_t align1, size_t align2, size_t len, size_t n, int max_char,
228          int exp_result)
229 {
230   do_test_n (align1, align2, len, n, 1, max_char, exp_result);
231 }
232 
233 static void
do_page_test(size_t offset1,size_t offset2,CHAR * s2)234 do_page_test (size_t offset1, size_t offset2, CHAR *s2)
235 {
236   CHAR *s1;
237   int exp_result;
238 
239   if (offset1 * CHARBYTES  >= page_size || offset2 * CHARBYTES >= page_size)
240     return;
241 
242   s1 = (CHAR *) buf1;
243   s1 += offset1;
244   s2 += offset2;
245 
246   exp_result= *s1;
247 
248   FOR_EACH_IMPL (impl, 0)
249     {
250       check_result (impl, s1, s2, page_size, -exp_result);
251       check_result (impl, s2, s1, page_size, exp_result);
252     }
253 }
254 
255 static void
do_random_tests(void)256 do_random_tests (void)
257 {
258   size_t i, j, n, align1, align2, pos, len1, len2, size;
259   int result;
260   long r;
261   UCHAR *p1 = (UCHAR *) (buf1 + page_size - 512 * CHARBYTES);
262   UCHAR *p2 = (UCHAR *) (buf2 + page_size - 512 * CHARBYTES);
263 
264   for (n = 0; n < ITERATIONS; n++)
265     {
266       align1 = random () & 31;
267       if (random () & 1)
268 	align2 = random () & 31;
269       else
270 	align2 = align1 + (random () & 24);
271       pos = random () & 511;
272       size = random () & 511;
273       j = align1 > align2 ? align1 : align2;
274       if (pos + j >= 511)
275 	pos = 510 - j - (random () & 7);
276       len1 = random () & 511;
277       if (pos >= len1 && (random () & 1))
278 	len1 = pos + (random () & 7);
279       if (len1 + j >= 512)
280 	len1 = 511 - j - (random () & 7);
281       if (pos >= len1)
282 	len2 = len1;
283       else
284 	len2 = len1 + (len1 != 511 - j ? random () % (511 - j - len1) : 0);
285       j = (pos > len2 ? pos : len2) + align1 + 64;
286       if (j > 512)
287 	j = 512;
288       for (i = 0; i < j; ++i)
289 	{
290 	  p1[i] = random () & 255;
291 	  if (i < len1 + align1 && !p1[i])
292 	    {
293 	      p1[i] = random () & 255;
294 	      if (!p1[i])
295 		p1[i] = 1 + (random () & 127);
296 	    }
297 	}
298       for (i = 0; i < j; ++i)
299 	{
300 	  p2[i] = random () & 255;
301 	  if (i < len2 + align2 && !p2[i])
302 	    {
303 	      p2[i] = random () & 255;
304 	      if (!p2[i])
305 		p2[i] = 1 + (random () & 127);
306 	    }
307 	}
308 
309       result = 0;
310       MEMCPY (p2 + align2, p1 + align1, pos);
311       if (pos < len1)
312 	{
313 	  if (p2[align2 + pos] == p1[align1 + pos])
314 	    {
315 	      p2[align2 + pos] = random () & 255;
316 	      if (p2[align2 + pos] == p1[align1 + pos])
317 		p2[align2 + pos] = p1[align1 + pos] + 3 + (random () & 127);
318 	    }
319 
320 	  if (pos < size)
321 	    {
322 	      if (p1[align1 + pos] < p2[align2 + pos])
323 		result = -1;
324 	      else
325 		result = 1;
326 	    }
327 	}
328       p1[len1 + align1] = 0;
329       p2[len2 + align2] = 0;
330 
331       FOR_EACH_IMPL (impl, 1)
332 	{
333 	  r = CALL (impl, (CHAR *) (p1 + align1), (CHAR *) (p2 + align2), size);
334 	  /* Test whether on 64-bit architectures where ABI requires
335 	     callee to promote has the promotion been done.  */
336 	  asm ("" : "=g" (r) : "0" (r));
337 	  if ((r == 0 && result)
338 	      || (r < 0 && result >= 0)
339 	      || (r > 0 && result <= 0))
340 	    {
341 	      error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %zd, %zd, %zd, %zd, %zd) %ld != %d, p1 %p p2 %p",
342 		     n, impl->name, align1, align2, len1, len2, pos, size, r, result, p1, p2);
343 	      ret = 1;
344 	    }
345 	}
346     }
347 }
348 
349 static void
check1(void)350 check1 (void)
351 {
352   CHAR *s1 = (CHAR *) (buf1 + 0xb2c);
353   CHAR *s2 = (CHAR *) (buf1 + 0xfd8);
354   size_t i, offset;
355   int exp_result;
356 
357   STRCPY(s1, L("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrs"));
358   STRCPY(s2, L("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkLMNOPQRSTUV"));
359 
360   /* Check possible overflow bug for wcsncmp */
361   s1[4] = CHAR__MAX;
362   s2[4] = CHAR__MIN;
363 
364   for (offset = 0; offset < 6; offset++)
365     {
366       for (i = 0; i < 80; i++)
367 	{
368 	  exp_result = SIMPLE_STRNCMP (s1 + offset, s2 + offset, i);
369 	  FOR_EACH_IMPL (impl, 0)
370 	    check_result (impl, s1 + offset, s2 + offset, i, exp_result);
371 	}
372     }
373 }
374 
375 static void
check2(void)376 check2 (void)
377 {
378   size_t i;
379   CHAR *s1, *s2;
380 
381   s1 = (CHAR *) buf1;
382   for (i = 0; i < (page_size / CHARBYTES) - 1; i++)
383     s1[i] = 23;
384   s1[i] = 0;
385 
386   s2 = STRDUP (s1);
387 
388   for (i = 0; i < 64; ++i)
389     do_page_test ((3988 / CHARBYTES) + i, (2636 / CHARBYTES), s2);
390 
391   free (s2);
392 }
393 
394 static void
check3(void)395 check3 (void)
396 {
397   /* To trigger bug 25933, we need a size that is equal to the vector
398      length times 4. In the case of AVX2 for Intel, we need 32 * 4.  We
399      make this test generic and run it for all architectures as additional
400      boundary testing for such related algorithms.  */
401   size_t size = 32 * 4;
402   CHAR *s1 = (CHAR *) (buf1 + (BUF1PAGES - 1) * page_size);
403   CHAR *s2 = (CHAR *) (buf2 + (BUF1PAGES - 1) * page_size);
404   int exp_result;
405 
406   memset (s1, 'a', page_size);
407   memset (s2, 'a', page_size);
408   s1[(page_size / CHARBYTES) - 1] = (CHAR) 0;
409 
410   /* Iterate over a size that is just below where we expect the bug to
411      trigger up to the size we expect will trigger the bug e.g. [99-128].
412      Likewise iterate the start of two strings between 30 and 31 bytes
413      away from the boundary to simulate alignment changes.  */
414   for (size_t s = 99; s <= size; s++)
415     for (size_t s1a = 30; s1a < 32; s1a++)
416       for (size_t s2a = 30; s2a < 32; s2a++)
417 	{
418 	  CHAR *s1p = s1 + (page_size / CHARBYTES - s) - s1a;
419 	  CHAR *s2p = s2 + (page_size / CHARBYTES - s) - s2a;
420 	  exp_result = SIMPLE_STRNCMP (s1p, s2p, s);
421 	  FOR_EACH_IMPL (impl, 0)
422 	    check_result (impl, s1p, s2p, s, exp_result);
423 	}
424 }
425 
426 static void
check4(void)427 check4 (void)
428 {
429   /* To trigger bug 28895; We need 1) both s1 and s2 to be within 32 bytes of
430      the end of the page. 2) For there to be no mismatch/null byte before the
431      first page cross. 3) For length (`n`) to be large enough for one string to
432      cross the page. And 4) for there to be either mismatch/null bytes before
433      the start of the strings.  */
434 
435   size_t size = 10;
436   size_t addr_mask = (getpagesize () - 1) ^ (sizeof (CHAR) - 1);
437   CHAR *s1 = (CHAR *)(buf1 + (addr_mask & 0xffa));
438   CHAR *s2 = (CHAR *)(buf2 + (addr_mask & 0xfed));
439   int exp_result;
440 
441   STRCPY (s1, L ("tst-tlsmod%"));
442   STRCPY (s2, L ("tst-tls-manydynamic73mod"));
443   exp_result = SIMPLE_STRNCMP (s1, s2, size);
444   FOR_EACH_IMPL (impl, 0)
445   check_result (impl, s1, s2, size, exp_result);
446 }
447 
448 static void
check5(void)449 check5 (void)
450 {
451   const CHAR *s1 = L ("abc");
452   CHAR *s2 = STRDUP (s1);
453 
454   FOR_EACH_IMPL (impl, 0)
455     check_result (impl, s1, s2, SIZE_MAX, 0);
456 
457   free (s2);
458 }
459 
460 static void
check_overflow(void)461 check_overflow (void)
462 {
463   size_t i, j, of_mask, of_idx;
464   const size_t of_masks[]
465       = { ULONG_MAX, LONG_MIN, ULONG_MAX - (ULONG_MAX >> 2),
466           ((size_t)LONG_MAX) >> 1 };
467   const size_t test_len = MIN(TEST_LEN, 3 * 4096);
468   for (of_idx = 0; of_idx < sizeof (of_masks) / sizeof (of_masks[0]); ++of_idx)
469     {
470       of_mask = of_masks[of_idx];
471       for (j = 0; j < 160; ++j)
472         {
473           for (i = 1; i <= 161; i += (32 / sizeof (CHAR)))
474             {
475               do_test_n (j, 0, i, of_mask, 0, 127, 0);
476               do_test_n (j, 0, i, of_mask, 0, 127, 1);
477               do_test_n (j, 0, i, of_mask, 0, 127, -1);
478 
479               do_test_n (j, 0, i, of_mask - j / 2, 0, 127, 0);
480               do_test_n (j, 0, i, of_mask - j * 2, 0, 127, 1);
481               do_test_n (j, 0, i, of_mask - j, 0, 127, -1);
482 
483               do_test_n (j / 2, j, i, of_mask, 0, 127, 0);
484               do_test_n (j / 2, j, i, of_mask, 0, 127, 1);
485               do_test_n (j / 2, j, i, of_mask, 0, 127, -1);
486 
487               do_test_n (j / 2, j, i, of_mask - j, 0, 127, 0);
488               do_test_n (j / 2, j, i, of_mask - j / 2, 0, 127, 1);
489               do_test_n (j / 2, j, i, of_mask - j * 2, 0, 127, -1);
490 
491               do_test_n (0, j, i, of_mask - j * 2, 0, 127, 0);
492               do_test_n (0, j, i, of_mask - j, 0, 127, 1);
493               do_test_n (0, j, i, of_mask - j / 2, 0, 127, -1);
494 
495               do_test_n (getpagesize () - j - 1, 0, i, of_mask, 0, 127, 0);
496               do_test_n (getpagesize () - j - 1, 0, i, of_mask, 0, 127, 1);
497               do_test_n (getpagesize () - j - 1, 0, i, of_mask, 0, 127, -1);
498 
499               do_test_n (getpagesize () - j - 1, 0, i, of_mask - j / 2, 0, 127,
500                          0);
501               do_test_n (getpagesize () - j - 1, 0, i, of_mask - j * 2, 0, 127,
502                          1);
503               do_test_n (getpagesize () - j - 1, 0, i, of_mask - j, 0, 127,
504                          -1);
505 
506               do_test_n (getpagesize () - j - 1, getpagesize () - 2 * j - 1, i,
507                          of_mask, 0, 127, 0);
508               do_test_n (getpagesize () - j - 1, getpagesize () - 2 * j - 1, i,
509                          of_mask, 0, 127, 1);
510               do_test_n (getpagesize () - j - 1, getpagesize () - 2 * j - 1, i,
511                          of_mask, 0, 127, -1);
512 
513               do_test_n (getpagesize () - j - 1, getpagesize () - 2 * j - 1, i,
514                          of_mask - j, 0, 127, 0);
515               do_test_n (getpagesize () - j - 1, getpagesize () - 2 * j - 1, i,
516                          of_mask - j / 2, 0, 127, 1);
517               do_test_n (getpagesize () - j - 1, getpagesize () - 2 * j - 1, i,
518                          of_mask - j * 2, 0, 127, -1);
519             }
520 
521           for (i = 1; i < test_len; i += i)
522             {
523               do_test_n (j, 0, i - 1, of_mask, 0, 127, 0);
524               do_test_n (j, 0, i - 1, of_mask, 0, 127, 1);
525               do_test_n (j, 0, i - 1, of_mask, 0, 127, -1);
526 
527               do_test_n (j, 0, i - 1, of_mask - j / 2, 0, 127, 0);
528               do_test_n (j, 0, i - 1, of_mask - j * 2, 0, 127, 1);
529               do_test_n (j, 0, i - 1, of_mask - j, 0, 127, -1);
530 
531               do_test_n (j / 2, j, i - 1, of_mask, 0, 127, 0);
532               do_test_n (j / 2, j, i - 1, of_mask, 0, 127, 1);
533               do_test_n (j / 2, j, i - 1, of_mask, 0, 127, -1);
534 
535               do_test_n (j / 2, j, i - 1, of_mask - j, 0, 127, 0);
536               do_test_n (j / 2, j, i - 1, of_mask - j / 2, 0, 127, 1);
537               do_test_n (j / 2, j, i - 1, of_mask - j * 2, 0, 127, -1);
538 
539               do_test_n (0, j, i - 1, of_mask - j * 2, 0, 127, 0);
540               do_test_n (0, j, i - 1, of_mask - j, 0, 127, 1);
541               do_test_n (0, j, i - 1, of_mask - j / 2, 0, 127, -1);
542 
543               do_test_n (getpagesize () - j - 1, 0, i - 1, of_mask, 0, 127, 0);
544               do_test_n (getpagesize () - j - 1, 0, i - 1, of_mask, 0, 127, 1);
545               do_test_n (getpagesize () - j - 1, 0, i - 1, of_mask, 0, 127,
546                          -1);
547 
548               do_test_n (getpagesize () - j - 1, 0, i - 1, of_mask - j / 2, 0,
549                          127, 0);
550               do_test_n (getpagesize () - j - 1, 0, i - 1, of_mask - j * 2, 0,
551                          127, 1);
552               do_test_n (getpagesize () - j - 1, 0, i - 1, of_mask - j, 0, 127,
553                          -1);
554 
555               do_test_n (getpagesize () - j - 1, getpagesize () - 2 * j - 1,
556                          i - 1, of_mask, 0, 127, 0);
557               do_test_n (getpagesize () - j - 1, getpagesize () - 2 * j - 1,
558                          i - 1, of_mask, 0, 127, 1);
559               do_test_n (getpagesize () - j - 1, getpagesize () - 2 * j - 1,
560                          i - 1, of_mask, 0, 127, -1);
561 
562               do_test_n (getpagesize () - j - 1, getpagesize () - 2 * j - 1,
563                          i - 1, of_mask - j, 0, 127, 0);
564               do_test_n (getpagesize () - j - 1, getpagesize () - 2 * j - 1,
565                          i - 1, of_mask - j / 2, 0, 127, 1);
566               do_test_n (getpagesize () - j - 1, getpagesize () - 2 * j - 1,
567                          i - 1, of_mask - j * 2, 0, 127, -1);
568             }
569         }
570     }
571 }
572 
573 int
test_main(void)574 test_main (void)
575 {
576   size_t i, j, k;
577   const size_t test_len = MIN(TEST_LEN, 3 * 4096);
578   test_init ();
579 
580   check1 ();
581   check2 ();
582   check3 ();
583   check4 ();
584   check5 ();
585 
586   printf ("%23s", "");
587   FOR_EACH_IMPL (impl, 0)
588     printf ("\t%s", impl->name);
589   putchar ('\n');
590 
591   for (i =0; i < 16; ++i)
592     {
593       do_test (0, 0, 8, i, 127, 0);
594       do_test (0, 0, 8, i, 127, -1);
595       do_test (0, 0, 8, i, 127, 1);
596       do_test (i, i, 8, i, 127, 0);
597       do_test (i, i, 8, i, 127, 1);
598       do_test (i, i, 8, i, 127, -1);
599       do_test (i, 2 * i, 8, i, 127, 0);
600       do_test (2 * i, i, 8, i, 127, 1);
601       do_test (i, 3 * i, 8, i, 127, -1);
602       do_test (0, 0, 8, i, 255, 0);
603       do_test (0, 0, 8, i, 255, -1);
604       do_test (0, 0, 8, i, 255, 1);
605       do_test (i, i, 8, i, 255, 0);
606       do_test (i, i, 8, i, 255, 1);
607       do_test (i, i, 8, i, 255, -1);
608       do_test (i, 2 * i, 8, i, 255, 0);
609       do_test (2 * i, i, 8, i, 255, 1);
610       do_test (i, 3 * i, 8, i, 255, -1);
611     }
612 
613   for (i = 1; i < 8; ++i)
614     {
615       do_test (0, 0, 8 << i, 16 << i, 127, 0);
616       do_test (0, 0, 8 << i, 16 << i, 127, 1);
617       do_test (0, 0, 8 << i, 16 << i, 127, -1);
618       do_test (0, 0, 8 << i, 16 << i, 255, 0);
619       do_test (0, 0, 8 << i, 16 << i, 255, 1);
620       do_test (0, 0, 8 << i, 16 << i, 255, -1);
621       do_test (8 - i, 2 * i, 8 << i, 16 << i, 127, 0);
622       do_test (8 - i, 2 * i, 8 << i, 16 << i, 127, 1);
623       do_test (2 * i, i, 8 << i, 16 << i, 255, 0);
624       do_test (2 * i, i, 8 << i, 16 << i, 255, 1);
625     }
626 
627   do_test_limit (0, 0, 0, 0, 127, 0);
628   do_test_limit (4, 0, 21, 20, 127, 0);
629   do_test_limit (0, 4, 21, 20, 127, 0);
630   do_test_limit (8, 0, 25, 24, 127, 0);
631   do_test_limit (0, 8, 25, 24, 127, 0);
632 
633   for (i = 0; i < 8; ++i)
634     {
635       do_test_limit (0, 0, 17 - i, 16 - i, 127, 0);
636       do_test_limit (0, 0, 17 - i, 16 - i, 255, 0);
637       do_test_limit (0, 0, 15 - i, 16 - i, 127, 0);
638       do_test_limit (0, 0, 15 - i, 16 - i, 127, 1);
639       do_test_limit (0, 0, 15 - i, 16 - i, 127, -1);
640       do_test_limit (0, 0, 15 - i, 16 - i, 255, 0);
641       do_test_limit (0, 0, 15 - i, 16 - i, 255, 1);
642       do_test_limit (0, 0, 15 - i, 16 - i, 255, -1);
643     }
644 
645   for (j = 0; j < 160; ++j)
646     {
647       for (i = 0; i < test_len;)
648         {
649           do_test_n (getpagesize () - j - 1, 0, i, i + 1, 0, 127, 0);
650           do_test_n (getpagesize () - j - 1, 0, i, i + 1, 0, 127, 1);
651           do_test_n (getpagesize () - j - 1, 0, i, i + 1, 0, 127, -1);
652 
653           do_test_n (getpagesize () - j - 1, 0, i, i, 0, 127, 0);
654           do_test_n (getpagesize () - j - 1, 0, i, i - 1, 0, 127, 0);
655 
656           do_test_n (getpagesize () - j - 1, 0, i, ULONG_MAX, 0, 127, 0);
657           do_test_n (getpagesize () - j - 1, 0, i, ULONG_MAX, 0, 127, 1);
658           do_test_n (getpagesize () - j - 1, 0, i, ULONG_MAX, 0, 127, -1);
659 
660           do_test_n (getpagesize () - j - 1, 0, i, ULONG_MAX - i, 0, 127, 0);
661           do_test_n (getpagesize () - j - 1, 0, i, ULONG_MAX - i, 0, 127, 1);
662           do_test_n (getpagesize () - j - 1, 0, i, ULONG_MAX - i, 0, 127, -1);
663 
664           do_test_n (getpagesize () - j - 1, j, i, i + 1, 0, 127, 0);
665           do_test_n (getpagesize () - j - 1, j, i, i + 1, 0, 127, 1);
666           do_test_n (getpagesize () - j - 1, j, i, i + 1, 0, 127, -1);
667 
668           do_test_n (getpagesize () - j - 1, j, i, i, 0, 127, 0);
669           do_test_n (getpagesize () - j - 1, j, i, i - 1, 0, 127, 0);
670 
671           do_test_n (getpagesize () - j - 1, j, i, ULONG_MAX, 0, 127, 0);
672           do_test_n (getpagesize () - j - 1, j, i, ULONG_MAX, 0, 127, 1);
673           do_test_n (getpagesize () - j - 1, j, i, ULONG_MAX, 0, 127, -1);
674 
675           do_test_n (getpagesize () - j - 1, j, i, ULONG_MAX - i, 0, 127, 0);
676           do_test_n (getpagesize () - j - 1, j, i, ULONG_MAX - i, 0, 127, 1);
677           do_test_n (getpagesize () - j - 1, j, i, ULONG_MAX - i, 0, 127, -1);
678 
679           do_test_n (0, getpagesize () - j - 1, i, i + 1, 0, 127, 0);
680           do_test_n (0, getpagesize () - j - 1, i, i + 1, 0, 127, 1);
681           do_test_n (0, getpagesize () - j - 1, i, i + 1, 0, 127, -1);
682 
683           do_test_n (0, getpagesize () - j - 1, i, i, 0, 127, 0);
684           do_test_n (0, getpagesize () - j - 1, i, i - 1, 0, 127, 0);
685 
686           do_test_n (0, getpagesize () - j - 1, i, ULONG_MAX, 0, 127, 0);
687           do_test_n (0, getpagesize () - j - 1, i, ULONG_MAX, 0, 127, 1);
688           do_test_n (0, getpagesize () - j - 1, i, ULONG_MAX, 0, 127, -1);
689 
690           do_test_n (0, getpagesize () - j - 1, i, ULONG_MAX - i, 0, 127, 0);
691           do_test_n (0, getpagesize () - j - 1, i, ULONG_MAX - i, 0, 127, 1);
692           do_test_n (0, getpagesize () - j - 1, i, ULONG_MAX - i, 0, 127, -1);
693 
694           do_test_n (j, getpagesize () - j - 1, i, i + 1, 0, 127, 0);
695           do_test_n (j, getpagesize () - j - 1, i, i + 1, 0, 127, 1);
696           do_test_n (j, getpagesize () - j - 1, i, i + 1, 0, 127, -1);
697 
698           do_test_n (j, getpagesize () - j - 1, i, i, 0, 127, 0);
699           do_test_n (j, getpagesize () - j - 1, i, i - 1, 0, 127, 0);
700 
701           do_test_n (j, getpagesize () - j - 1, i, ULONG_MAX, 0, 127, 0);
702           do_test_n (j, getpagesize () - j - 1, i, ULONG_MAX, 0, 127, 1);
703           do_test_n (j, getpagesize () - j - 1, i, ULONG_MAX, 0, 127, -1);
704 
705           do_test_n (j, getpagesize () - j - 1, i, ULONG_MAX - i, 0, 127, 0);
706           do_test_n (j, getpagesize () - j - 1, i, ULONG_MAX - i, 0, 127, 1);
707           do_test_n (j, getpagesize () - j - 1, i, ULONG_MAX - i, 0, 127, -1);
708 
709           for (k = 2; k <= 128; k += k)
710             {
711               do_test (getpagesize () - k, getpagesize () - j - 1, i - 1, i,
712                        127, 0);
713               do_test (getpagesize () - k - 1, getpagesize () - j - 1, i - 1,
714                        i, 127, 0);
715               do_test (getpagesize () - k, getpagesize () - j - 1, i + 1, i,
716                        127, 0);
717               do_test (getpagesize () - k - 1, getpagesize () - j - 1, i + 1,
718                        i, 127, 0);
719               do_test (getpagesize () - k, getpagesize () - j - 1, i, i, 127,
720                        0);
721               do_test (getpagesize () - k - 1, getpagesize () - j - 1, i, i,
722                        127, 0);
723               do_test (getpagesize () - k, getpagesize () - j - 1, i + 1, i,
724                        127, -1);
725               do_test (getpagesize () - k - 1, getpagesize () - j - 1, i + 1,
726                        i, 127, -1);
727               do_test (getpagesize () - k, getpagesize () - j - 1, i + 1, i,
728                        127, 1);
729               do_test (getpagesize () - k - 1, getpagesize () - j - 1, i + 1,
730                        i, 127, 1);
731             }
732 
733           if (i < 32)
734             {
735               i += 1;
736             }
737           else if (i < 161)
738             {
739               i += 7;
740             }
741           else if (i + 161 < test_len)
742             {
743               i += 31;
744               i *= 17;
745               i /= 16;
746               if (i + 161 > test_len)
747                 {
748                   i = test_len - 160;
749                 }
750             }
751           else if (i + 32 < test_len)
752             {
753               i += 7;
754             }
755           else
756             {
757               i += 1;
758             }
759         }
760     }
761 
762   check_overflow ();
763   do_random_tests ();
764   return ret;
765 }
766 
767 #include <support/test-driver.c>
768