Fix handling of tail bytes of buffer in SSE2/SSSE3 x86-64 version strn{,case}cmp
[platform/upstream/glibc.git] / string / stratcliff.c
1 /* Test for string function add boundaries of usable memory.
2    Copyright (C) 1996,1997,1999-2003,2007,2009,2010
3    Free Software Foundation, Inc.
4    This file is part of the GNU C Library.
5    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
6
7    The GNU C Library is free software; you can redistribute it and/or
8    modify it under the terms of the GNU Lesser General Public
9    License as published by the Free Software Foundation; either
10    version 2.1 of the License, or (at your option) any later version.
11
12    The GNU C Library is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15    Lesser General Public License for more details.
16
17    You should have received a copy of the GNU Lesser General Public
18    License along with the GNU C Library; if not, write to the Free
19    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20    02111-1307 USA.  */
21
22 #define _GNU_SOURCE 1
23
24 /* Make sure we don't test the optimized inline functions if we want to
25    test the real implementation.  */
26 #undef __USE_STRING_INLINES
27
28 #include <errno.h>
29 #include <stdio.h>
30 #include <string.h>
31 #include <unistd.h>
32 #include <sys/mman.h>
33 #include <sys/param.h>
34
35 #ifndef CHAR
36 # define L(c) c
37 # define CHAR char
38 # define MEMSET memset
39 # define STRLEN strlen
40 # define STRNLEN strnlen
41 # define STRCHR strchr
42 # define STRRCHR strrchr
43 # define STRCPY strcpy
44 # define STRNCPY strncpy
45 # define MEMCMP memcmp
46 # define STPCPY stpcpy
47 # define STPNCPY stpncpy
48 # define MEMCPY memcpy
49 # define MEMPCPY mempcpy
50 # define MEMCHR memchr
51 # define STRCMP strcmp
52 # define STRNCMP strncmp
53 #endif
54
55
56 #define STRINGIFY(s) STRINGIFY2 (s)
57 #define STRINGIFY2(s) #s
58
59
60 static int
61 do_test (void)
62 {
63   int size = sysconf (_SC_PAGESIZE);
64   int nchars = size / sizeof (CHAR);
65   CHAR *adr;
66   CHAR *dest;
67   int result = 0;
68
69   adr = (CHAR *) mmap (NULL, 3 * size, PROT_READ | PROT_WRITE,
70                        MAP_PRIVATE | MAP_ANON, -1, 0);
71   dest = (CHAR *) mmap (NULL, 3 * size, PROT_READ | PROT_WRITE,
72                         MAP_PRIVATE | MAP_ANON, -1, 0);
73   if (adr == MAP_FAILED || dest == MAP_FAILED)
74     {
75       if (errno == ENOSYS)
76         puts ("No test, mmap not available.");
77       else
78         {
79           printf ("mmap failed: %m");
80           result = 1;
81         }
82     }
83   else
84     {
85       int inner, middle, outer;
86
87       mprotect (adr, size, PROT_NONE);
88       mprotect (adr + 2 * nchars, size, PROT_NONE);
89       adr += nchars;
90
91       mprotect (dest, size, PROT_NONE);
92       mprotect (dest + 2 * nchars, size, PROT_NONE);
93       dest += nchars;
94
95       MEMSET (adr, L('T'), nchars);
96
97       /* strlen/wcslen test */
98       for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer)
99         {
100           for (inner = MAX (outer, nchars - 64); inner < nchars; ++inner)
101             {
102               adr[inner] = L('\0');
103
104               if (STRLEN (&adr[outer]) != (size_t) (inner - outer))
105                 {
106                   printf ("%s flunked for outer = %d, inner = %d\n",
107                           STRINGIFY (STRLEN), outer, inner);
108                   result = 1;
109                 }
110
111               adr[inner] = L('T');
112             }
113         }
114
115       /* strnlen/wcsnlen test */
116       for (outer = nchars; outer >= MAX (0, nchars - 128); --outer)
117         {
118           for (inner = MAX (outer, nchars - 64); inner < nchars; ++inner)
119             {
120               adr[inner] = L('\0');
121
122               if (STRNLEN (&adr[outer], inner - outer + 1)
123                   != (size_t) (inner - outer))
124                 {
125                   printf ("%s flunked for outer = %d, inner = %d\n",
126                           STRINGIFY (STRNLEN), outer, inner);
127                   result = 1;
128                 }
129
130               adr[inner] = L('T');
131             }
132         }
133       for (outer = nchars; outer >= MAX (0, nchars - 128); --outer)
134         {
135           for (inner = MAX (outer, nchars - 64); inner <= nchars; ++inner)
136             {
137               if (STRNLEN (&adr[outer], inner - outer)
138                   != (size_t) (inner - outer))
139                 {
140                   printf ("%s flunked bounded for outer = %d, inner = %d\n",
141                           STRINGIFY (STRNLEN), outer, inner);
142                   result = 1;
143                 }
144             }
145         }
146
147       /* strchr/wcschr test */
148       for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer)
149         {
150           for (middle = MAX (outer, nchars - 64); middle < nchars; ++middle)
151             {
152               for (inner = middle; inner < nchars; ++inner)
153                 {
154                   adr[middle] = L('V');
155                   adr[inner] = L('\0');
156
157                   CHAR *cp = STRCHR (&adr[outer], L('V'));
158
159                   if ((inner == middle && cp != NULL)
160                       || (inner != middle
161                           && (cp - &adr[outer]) != middle - outer))
162                     {
163                       printf ("%s flunked for outer = %d, middle = %d, "
164                               "inner = %d\n",
165                               STRINGIFY (STRCHR), outer, middle, inner);
166                       result = 1;
167                     }
168
169                   adr[inner] = L('T');
170                   adr[middle] = L('T');
171                 }
172             }
173         }
174
175       /* Special test.  */
176       adr[nchars - 1] = L('\0');
177       if (STRCHR (&adr[nchars - 1], L('\n')) != NULL)
178         {
179           printf ("%s flunked test of empty string at end of page\n",
180                   STRINGIFY (STRCHR));
181           result = 1;
182         }
183
184       /* strrchr/wcsrchr test */
185       for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer)
186         {
187           for (middle = MAX (outer, nchars - 64); middle < nchars; ++middle)
188             {
189               for (inner = middle; inner < nchars; ++inner)
190                 {
191                   adr[middle] = L('V');
192                   adr[inner] = L('\0');
193
194                   CHAR *cp = STRRCHR (&adr[outer], L('V'));
195
196                   if ((inner == middle && cp != NULL)
197                       || (inner != middle
198                           && (cp - &adr[outer]) != middle - outer))
199                     {
200                       printf ("%s flunked for outer = %d, middle = %d, "
201                               "inner = %d\n",
202                               STRINGIFY (STRRCHR), outer, middle, inner);
203                       result = 1;
204                     }
205
206                   adr[inner] = L('T');
207                   adr[middle] = L('T');
208                 }
209             }
210         }
211
212       /* memchr test */
213       for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer)
214         {
215           for (middle = MAX (outer, nchars - 64); middle < nchars; ++middle)
216             {
217               adr[middle] = L('V');
218
219               CHAR *cp = MEMCHR (&adr[outer], L('V'), 3 * size);
220
221               if (cp - &adr[outer] != middle - outer)
222                 {
223                   printf ("%s flunked for outer = %d, middle = %d\n",
224                           STRINGIFY (MEMCHR), outer, middle);
225                   result = 1;
226                 }
227
228               adr[middle] = L('T');
229             }
230         }
231       for (outer = nchars; outer >= MAX (0, nchars - 128); --outer)
232         {
233           CHAR *cp = MEMCHR (&adr[outer], L('V'), nchars - outer);
234
235           if (cp != NULL)
236             {
237               printf ("%s flunked for outer = %d\n",
238                       STRINGIFY (MEMCHR), outer);
239               result = 1;
240             }
241         }
242
243       /* This function only exists for single-byte characters.  */
244 #ifndef WCSTEST
245       /* rawmemchr test */
246       for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer)
247         {
248           for (middle = MAX (outer, nchars - 64); middle < nchars; ++middle)
249             {
250               adr[middle] = L('V');
251
252               CHAR *cp = rawmemchr (&adr[outer], L('V'));
253
254               if (cp - &adr[outer] != middle - outer)
255                 {
256                   printf ("%s flunked for outer = %d, middle = %d\n",
257                           STRINGIFY (rawmemchr), outer, middle);
258                   result = 1;
259                 }
260
261               adr[middle] = L('T');
262             }
263         }
264 #endif
265
266       /* strcpy/wcscpy test */
267       for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer)
268         {
269           for (inner = MAX (outer, nchars - 64); inner < nchars; ++inner)
270             {
271               adr[inner] = L('\0');
272
273               if (STRCPY (dest, &adr[outer]) != dest
274                   || STRLEN (dest) != (size_t) (inner - outer))
275                 {
276                   printf ("%s flunked for outer = %d, inner = %d\n",
277                           STRINGIFY (STRCPY), outer, inner);
278                   result = 1;
279                 }
280
281               adr[inner] = L('T');
282             }
283         }
284
285       /* strcmp/wcscmp tests */
286       for (outer = 1; outer < 32; ++outer)
287         for (middle = 0; middle < 16; ++middle)
288           {
289             MEMSET (adr + middle, L('T'), 256);
290             adr[256] = L('\0');
291             MEMSET (dest + nchars - outer, L('T'), outer - 1);
292             dest[nchars - 1] = L('\0');
293
294             if (STRCMP (adr + middle, dest + nchars - outer) <= 0)
295               {
296                 printf ("%s 1 flunked for outer = %d, middle = %d\n",
297                         STRINGIFY (STRCMP), outer, middle);
298                 result = 1;
299               }
300
301             if (STRCMP (dest + nchars - outer, adr + middle) >= 0)
302               {
303                 printf ("%s 2 flunked for outer = %d, middle = %d\n",
304                         STRINGIFY (STRCMP), outer, middle);
305                 result = 1;
306               }
307           }
308
309       /* strncmp/wcsncmp tests */
310       for (outer = 1; outer < 32; ++outer)
311         for (middle = 0; middle < 16; ++middle)
312           {
313             MEMSET (adr + middle, L('T'), 256);
314             adr[256] = L('\0');
315             MEMSET (dest + nchars - outer, L('T'), outer - 1);
316             dest[nchars - 1] = L('U');
317
318             for (inner = 0; inner < outer; ++inner)
319               {
320                 if (STRNCMP (adr + middle, dest + nchars - outer, inner) != 0)
321                   {
322                     printf ("%s 1 flunked for outer = %d, middle = %d, "
323                             "inner = %d\n",
324                             STRINGIFY (STRNCMP), outer, middle, inner);
325                     result = 1;
326                   }
327
328                 if (STRNCMP (dest + nchars - outer, adr + middle, inner) != 0)
329                   {
330                     printf ("%s 2 flunked for outer = %d, middle = %d, "
331                             "inner = %d\n",
332                             STRINGIFY (STRNCMP), outer, middle, inner);
333                     result = 1;
334                   }
335               }
336
337             if (STRNCMP (adr + middle, dest + nchars - outer, outer) >= 0)
338               {
339                 printf ("%s 1 flunked for outer = %d, middle = %d, full\n",
340                         STRINGIFY (STRNCMP), outer, middle);
341                 result = 1;
342               }
343
344             if (STRNCMP (dest + nchars - outer, adr + middle, outer) <= 0)
345               {
346                 printf ("%s 2 flunked for outer = %d, middle = %d, full\n",
347                         STRINGIFY (STRNCMP), outer, middle);
348                 result = 1;
349               }
350           }
351
352       /* strncpy/wcsncpy tests */
353       adr[nchars - 1] = L('T');
354       for (outer = nchars; outer >= MAX (0, nchars - 128); --outer)
355         {
356           size_t len;
357
358           for (len = 0; len < nchars - outer; ++len)
359             {
360               if (STRNCPY (dest, &adr[outer], len) != dest
361                   || MEMCMP (dest, &adr[outer], len) != 0)
362                 {
363                   printf ("outer %s flunked for outer = %d, len = %Zd\n",
364                           STRINGIFY (STRNCPY), outer, len);
365                   result = 1;
366                 }
367             }
368         }
369       adr[nchars - 1] = L('\0');
370
371       for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer)
372         {
373           for (inner = MAX (outer, nchars - 64); inner < nchars; ++inner)
374             {
375               size_t len;
376
377               adr[inner] = L('\0');
378
379               for (len = 0; len < nchars - outer + 64; ++len)
380                 {
381                   if (STRNCPY (dest, &adr[outer], len) != dest
382                       || MEMCMP (dest, &adr[outer],
383                                  MIN (inner - outer, len)) != 0
384                       || (inner - outer < len
385                           && STRLEN (dest) != (inner - outer)))
386                     {
387                       printf ("%s flunked for outer = %d, inner = %d, "
388                               "len = %Zd\n",
389                               STRINGIFY (STRNCPY), outer, inner, len);
390                       result = 1;
391                     }
392                   if (STRNCPY (dest + 1, &adr[outer], len) != dest + 1
393                       || MEMCMP (dest + 1, &adr[outer],
394                                  MIN (inner - outer, len)) != 0
395                       || (inner - outer < len
396                           && STRLEN (dest + 1) != (inner - outer)))
397                     {
398                       printf ("%s+1 flunked for outer = %d, inner = %d, "
399                               "len = %Zd\n",
400                               STRINGIFY (STRNCPY), outer, inner, len);
401                       result = 1;
402                     }
403                 }
404
405               adr[inner] = L('T');
406             }
407         }
408
409       /* stpcpy/wcpcpy test */
410       for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer)
411         {
412           for (inner = MAX (outer, nchars - 64); inner < nchars; ++inner)
413             {
414               adr[inner] = L('\0');
415
416               if ((STPCPY (dest, &adr[outer]) - dest) != inner - outer)
417                 {
418                   printf ("%s flunked for outer = %d, inner = %d\n",
419                           STRINGIFY (STPCPY), outer, inner);
420                   result = 1;
421                 }
422
423               adr[inner] = L('T');
424             }
425         }
426
427       /* stpncpy/wcpncpy test */
428       adr[nchars - 1] = L('T');
429       for (outer = nchars; outer >= MAX (0, nchars - 128); --outer)
430         {
431           size_t len;
432
433           for (len = 0; len < nchars - outer; ++len)
434             {
435               if (STPNCPY (dest, &adr[outer], len) != dest + len
436                   || MEMCMP (dest, &adr[outer], len) != 0)
437                 {
438                   printf ("outer %s flunked for outer = %d, len = %Zd\n",
439                           STRINGIFY (STPNCPY), outer, len);
440                   result = 1;
441                 }
442             }
443         }
444       adr[nchars - 1] = L('\0');
445
446       for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer)
447         {
448           for (middle = MAX (outer, nchars - 64); middle < nchars; ++middle)
449             {
450               adr[middle] = L('\0');
451
452               for (inner = 0; inner < nchars - outer; ++ inner)
453                 {
454                   if ((STPNCPY (dest, &adr[outer], inner) - dest)
455                       != MIN (inner, middle - outer))
456                     {
457                       printf ("%s flunked for outer = %d, middle = %d, "
458                               "inner = %d\n",
459                               STRINGIFY (STPNCPY), outer, middle, inner);
460                       result = 1;
461                     }
462                 }
463
464               adr[middle] = L('T');
465             }
466         }
467
468       /* memcpy/wmemcpy test */
469       for (outer = nchars; outer >= MAX (0, nchars - 128); --outer)
470         for (inner = 0; inner < nchars - outer; ++inner)
471           if (MEMCPY (dest, &adr[outer], inner) !=  dest)
472             {
473               printf ("%s flunked for outer = %d, inner = %d\n",
474                       STRINGIFY (MEMCPY), outer, inner);
475               result = 1;
476             }
477
478       /* mempcpy/wmempcpy test */
479       for (outer = nchars; outer >= MAX (0, nchars - 128); --outer)
480         for (inner = 0; inner < nchars - outer; ++inner)
481           if (MEMPCPY (dest, &adr[outer], inner) !=  dest + inner)
482             {
483               printf ("%s flunked for outer = %d, inner = %d\n",
484                       STRINGIFY (MEMPCPY), outer, inner);
485               result = 1;
486             }
487
488       /* This function only exists for single-byte characters.  */
489 #ifndef WCSTEST
490       /* memccpy test */
491       memset (adr, '\0', nchars);
492       for (outer = nchars; outer >= MAX (0, nchars - 128); --outer)
493         for (inner = 0; inner < nchars - outer; ++inner)
494           if (memccpy (dest, &adr[outer], L('\1'), inner) != NULL)
495             {
496               printf ("memccpy flunked full copy for outer = %d, inner = %d\n",
497                       outer, inner);
498               result = 1;
499             }
500       for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer)
501         for (middle = 0; middle < nchars - outer; ++middle)
502           {
503             memset (dest, L('\2'), middle + 1);
504             for (inner = 0; inner < middle; ++inner)
505               {
506                 adr[outer + inner] = L('\1');
507
508                 if (memccpy (dest, &adr[outer], '\1', middle + 128)
509                     !=  dest + inner + 1)
510                   {
511                     printf ("\
512 memccpy flunked partial copy for outer = %d, middle = %d, inner = %d\n",
513                             outer, middle, inner);
514                     result = 1;
515                   }
516                 else if (dest[inner + 1] != L('\2'))
517                   {
518                     printf ("\
519 memccpy copied too much for outer = %d, middle = %d, inner = %d\n",
520                             outer, middle, inner);
521                     result = 1;
522                   }
523                 adr[outer + inner] = L('\0');
524               }
525           }
526 #endif
527     }
528
529   return result;
530 }
531
532 #define TEST_FUNCTION do_test ()
533 #include "../test-skeleton.c"