Add memrchr tests
[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,2011
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       /* These functions only exist 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
265       /* memrchr test */
266       for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer)
267         {
268           for (middle = MAX (outer, nchars - 64); middle < nchars; ++middle)
269             {
270               adr[middle] = L('V');
271
272               CHAR *cp = memrchr (&adr[outer], L('V'), nchars - outer);
273
274               if (cp - &adr[outer] != middle - outer)
275                 {
276                   printf ("%s flunked for outer = %d, middle = %d\n",
277                           STRINGIFY (memrchr), outer, middle);
278                   result = 1;
279                 }
280
281               adr[middle] = L('T');
282             }
283         }
284       for (outer = nchars; outer >= MAX (0, nchars - 128); --outer)
285         {
286           CHAR *cp = memrchr (&adr[outer], L('V'), nchars - outer);
287
288           if (cp != NULL)
289             {
290               printf ("%s flunked for outer = %d\n",
291                       STRINGIFY (memrchr), outer);
292               result = 1;
293             }
294         }
295 #endif
296
297       /* strcpy/wcscpy test */
298       for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer)
299         {
300           for (inner = MAX (outer, nchars - 64); inner < nchars; ++inner)
301             {
302               adr[inner] = L('\0');
303
304               if (STRCPY (dest, &adr[outer]) != dest
305                   || STRLEN (dest) != (size_t) (inner - outer))
306                 {
307                   printf ("%s flunked for outer = %d, inner = %d\n",
308                           STRINGIFY (STRCPY), outer, inner);
309                   result = 1;
310                 }
311
312               adr[inner] = L('T');
313             }
314         }
315
316       /* strcmp/wcscmp tests */
317       for (outer = 1; outer < 32; ++outer)
318         for (middle = 0; middle < 16; ++middle)
319           {
320             MEMSET (adr + middle, L('T'), 256);
321             adr[256] = L('\0');
322             MEMSET (dest + nchars - outer, L('T'), outer - 1);
323             dest[nchars - 1] = L('\0');
324
325             if (STRCMP (adr + middle, dest + nchars - outer) <= 0)
326               {
327                 printf ("%s 1 flunked for outer = %d, middle = %d\n",
328                         STRINGIFY (STRCMP), outer, middle);
329                 result = 1;
330               }
331
332             if (STRCMP (dest + nchars - outer, adr + middle) >= 0)
333               {
334                 printf ("%s 2 flunked for outer = %d, middle = %d\n",
335                         STRINGIFY (STRCMP), outer, middle);
336                 result = 1;
337               }
338           }
339
340       /* strncmp/wcsncmp tests */
341       for (outer = 1; outer < 32; ++outer)
342         for (middle = 0; middle < 16; ++middle)
343           {
344             MEMSET (adr + middle, L('T'), 256);
345             adr[256] = L('\0');
346             MEMSET (dest + nchars - outer, L('T'), outer - 1);
347             dest[nchars - 1] = L('U');
348
349             for (inner = 0; inner < outer; ++inner)
350               {
351                 if (STRNCMP (adr + middle, dest + nchars - outer, inner) != 0)
352                   {
353                     printf ("%s 1 flunked for outer = %d, middle = %d, "
354                             "inner = %d\n",
355                             STRINGIFY (STRNCMP), outer, middle, inner);
356                     result = 1;
357                   }
358
359                 if (STRNCMP (dest + nchars - outer, adr + middle, inner) != 0)
360                   {
361                     printf ("%s 2 flunked for outer = %d, middle = %d, "
362                             "inner = %d\n",
363                             STRINGIFY (STRNCMP), outer, middle, inner);
364                     result = 1;
365                   }
366               }
367
368             if (STRNCMP (adr + middle, dest + nchars - outer, outer) >= 0)
369               {
370                 printf ("%s 1 flunked for outer = %d, middle = %d, full\n",
371                         STRINGIFY (STRNCMP), outer, middle);
372                 result = 1;
373               }
374
375             if (STRNCMP (dest + nchars - outer, adr + middle, outer) <= 0)
376               {
377                 printf ("%s 2 flunked for outer = %d, middle = %d, full\n",
378                         STRINGIFY (STRNCMP), outer, middle);
379                 result = 1;
380               }
381           }
382
383       /* strncpy/wcsncpy tests */
384       adr[nchars - 1] = L('T');
385       for (outer = nchars; outer >= MAX (0, nchars - 128); --outer)
386         {
387           size_t len;
388
389           for (len = 0; len < nchars - outer; ++len)
390             {
391               if (STRNCPY (dest, &adr[outer], len) != dest
392                   || MEMCMP (dest, &adr[outer], len) != 0)
393                 {
394                   printf ("outer %s flunked for outer = %d, len = %Zd\n",
395                           STRINGIFY (STRNCPY), outer, len);
396                   result = 1;
397                 }
398             }
399         }
400       adr[nchars - 1] = L('\0');
401
402       for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer)
403         {
404           for (inner = MAX (outer, nchars - 64); inner < nchars; ++inner)
405             {
406               size_t len;
407
408               adr[inner] = L('\0');
409
410               for (len = 0; len < nchars - outer + 64; ++len)
411                 {
412                   if (STRNCPY (dest, &adr[outer], len) != dest
413                       || MEMCMP (dest, &adr[outer],
414                                  MIN (inner - outer, len)) != 0
415                       || (inner - outer < len
416                           && STRLEN (dest) != (inner - outer)))
417                     {
418                       printf ("%s flunked for outer = %d, inner = %d, "
419                               "len = %Zd\n",
420                               STRINGIFY (STRNCPY), outer, inner, len);
421                       result = 1;
422                     }
423                   if (STRNCPY (dest + 1, &adr[outer], len) != dest + 1
424                       || MEMCMP (dest + 1, &adr[outer],
425                                  MIN (inner - outer, len)) != 0
426                       || (inner - outer < len
427                           && STRLEN (dest + 1) != (inner - outer)))
428                     {
429                       printf ("%s+1 flunked for outer = %d, inner = %d, "
430                               "len = %Zd\n",
431                               STRINGIFY (STRNCPY), outer, inner, len);
432                       result = 1;
433                     }
434                 }
435
436               adr[inner] = L('T');
437             }
438         }
439
440       /* stpcpy/wcpcpy test */
441       for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer)
442         {
443           for (inner = MAX (outer, nchars - 64); inner < nchars; ++inner)
444             {
445               adr[inner] = L('\0');
446
447               if ((STPCPY (dest, &adr[outer]) - dest) != inner - outer)
448                 {
449                   printf ("%s flunked for outer = %d, inner = %d\n",
450                           STRINGIFY (STPCPY), outer, inner);
451                   result = 1;
452                 }
453
454               adr[inner] = L('T');
455             }
456         }
457
458       /* stpncpy/wcpncpy test */
459       adr[nchars - 1] = L('T');
460       for (outer = nchars; outer >= MAX (0, nchars - 128); --outer)
461         {
462           size_t len;
463
464           for (len = 0; len < nchars - outer; ++len)
465             {
466               if (STPNCPY (dest, &adr[outer], len) != dest + len
467                   || MEMCMP (dest, &adr[outer], len) != 0)
468                 {
469                   printf ("outer %s flunked for outer = %d, len = %Zd\n",
470                           STRINGIFY (STPNCPY), outer, len);
471                   result = 1;
472                 }
473             }
474         }
475       adr[nchars - 1] = L('\0');
476
477       for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer)
478         {
479           for (middle = MAX (outer, nchars - 64); middle < nchars; ++middle)
480             {
481               adr[middle] = L('\0');
482
483               for (inner = 0; inner < nchars - outer; ++ inner)
484                 {
485                   if ((STPNCPY (dest, &adr[outer], inner) - dest)
486                       != MIN (inner, middle - outer))
487                     {
488                       printf ("%s flunked for outer = %d, middle = %d, "
489                               "inner = %d\n",
490                               STRINGIFY (STPNCPY), outer, middle, inner);
491                       result = 1;
492                     }
493                 }
494
495               adr[middle] = L('T');
496             }
497         }
498
499       /* memcpy/wmemcpy test */
500       for (outer = nchars; outer >= MAX (0, nchars - 128); --outer)
501         for (inner = 0; inner < nchars - outer; ++inner)
502           if (MEMCPY (dest, &adr[outer], inner) !=  dest)
503             {
504               printf ("%s flunked for outer = %d, inner = %d\n",
505                       STRINGIFY (MEMCPY), outer, inner);
506               result = 1;
507             }
508
509       /* mempcpy/wmempcpy test */
510       for (outer = nchars; outer >= MAX (0, nchars - 128); --outer)
511         for (inner = 0; inner < nchars - outer; ++inner)
512           if (MEMPCPY (dest, &adr[outer], inner) !=  dest + inner)
513             {
514               printf ("%s flunked for outer = %d, inner = %d\n",
515                       STRINGIFY (MEMPCPY), outer, inner);
516               result = 1;
517             }
518
519       /* This function only exists for single-byte characters.  */
520 #ifndef WCSTEST
521       /* memccpy test */
522       memset (adr, '\0', nchars);
523       for (outer = nchars; outer >= MAX (0, nchars - 128); --outer)
524         for (inner = 0; inner < nchars - outer; ++inner)
525           if (memccpy (dest, &adr[outer], L('\1'), inner) != NULL)
526             {
527               printf ("memccpy flunked full copy for outer = %d, inner = %d\n",
528                       outer, inner);
529               result = 1;
530             }
531       for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer)
532         for (middle = 0; middle < nchars - outer; ++middle)
533           {
534             memset (dest, L('\2'), middle + 1);
535             for (inner = 0; inner < middle; ++inner)
536               {
537                 adr[outer + inner] = L('\1');
538
539                 if (memccpy (dest, &adr[outer], '\1', middle + 128)
540                     !=  dest + inner + 1)
541                   {
542                     printf ("\
543 memccpy flunked partial copy for outer = %d, middle = %d, inner = %d\n",
544                             outer, middle, inner);
545                     result = 1;
546                   }
547                 else if (dest[inner + 1] != L('\2'))
548                   {
549                     printf ("\
550 memccpy copied too much for outer = %d, middle = %d, inner = %d\n",
551                             outer, middle, inner);
552                     result = 1;
553                   }
554                 adr[outer + inner] = L('\0');
555               }
556           }
557 #endif
558     }
559
560   return result;
561 }
562
563 #define TEST_FUNCTION do_test ()
564 #include "../test-skeleton.c"