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