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