Back to index

glibc  2.9
stratcliff.c
Go to the documentation of this file.
00001 /* Test for string function add boundaries of usable memory.
00002    Copyright (C) 1996,1997,1999-2002,2003,2007 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
00005 
00006    The GNU C Library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Lesser General Public
00008    License as published by the Free Software Foundation; either
00009    version 2.1 of the License, or (at your option) any later version.
00010 
00011    The GNU C Library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Lesser General Public License for more details.
00015 
00016    You should have received a copy of the GNU Lesser General Public
00017    License along with the GNU C Library; if not, write to the Free
00018    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00019    02111-1307 USA.  */
00020 
00021 #define _GNU_SOURCE 1
00022 
00023 /* Make sure we don't test the optimized inline functions if we want to
00024    test the real implementation.  */
00025 #undef __USE_STRING_INLINES
00026 
00027 #include <errno.h>
00028 #include <stdio.h>
00029 #include <string.h>
00030 #include <unistd.h>
00031 #include <sys/mman.h>
00032 #include <sys/param.h>
00033 
00034 #ifndef CHAR
00035 # define L(c) c
00036 # define CHAR char
00037 # define MEMSET memset
00038 # define STRLEN strlen
00039 # define STRNLEN strnlen
00040 # define STRCHR strchr
00041 # define STRRCHR strrchr
00042 # define STRCPY strcpy
00043 # define STRNCPY strncpy
00044 # define MEMCMP memcmp
00045 # define STPCPY stpcpy
00046 # define STPNCPY stpncpy
00047 # define MEMCPY memcpy
00048 # define MEMPCPY mempcpy
00049 #endif
00050 
00051 
00052 #define STRINGIFY(s) STRINGIFY2 (s)
00053 #define STRINGIFY2(s) #s
00054 
00055 
00056 static int
00057 do_test (void)
00058 {
00059   int size = sysconf (_SC_PAGESIZE);
00060   int nchars = size / sizeof (CHAR);
00061   CHAR *adr;
00062   CHAR *dest;
00063   int result = 0;
00064 
00065   adr = (CHAR *) mmap (NULL, 3 * size, PROT_READ | PROT_WRITE,
00066                      MAP_PRIVATE | MAP_ANON, -1, 0);
00067   dest = (CHAR *) mmap (NULL, 3 * size, PROT_READ | PROT_WRITE,
00068                      MAP_PRIVATE | MAP_ANON, -1, 0);
00069   if (adr == MAP_FAILED || dest == MAP_FAILED)
00070     {
00071       if (errno == ENOSYS)
00072         puts ("No test, mmap not available.");
00073       else
00074         {
00075           printf ("mmap failed: %m");
00076           result = 1;
00077         }
00078     }
00079   else
00080     {
00081       int inner, middle, outer;
00082 
00083       mprotect (adr, size, PROT_NONE);
00084       mprotect (adr + 2 * nchars, size, PROT_NONE);
00085       adr += nchars;
00086 
00087       mprotect (dest, size, PROT_NONE);
00088       mprotect (dest + 2 * nchars, size, PROT_NONE);
00089       dest += nchars;
00090 
00091       MEMSET (adr, L('T'), nchars);
00092 
00093       /* strlen/wcslen test */
00094       for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer)
00095         {
00096           for (inner = MAX (outer, nchars - 64); inner < nchars; ++inner)
00097            {
00098              adr[inner] = L('\0');
00099 
00100              if (STRLEN (&adr[outer]) != (size_t) (inner - outer))
00101               {
00102                 printf ("%s flunked for outer = %d, inner = %d\n",
00103                        STRINGIFY (STRLEN), outer, inner);
00104                 result = 1;
00105               }
00106 
00107              adr[inner] = L('T');
00108            }
00109         }
00110 
00111       /* strnlen/wcsnlen test */
00112       for (outer = nchars; outer >= MAX (0, nchars - 128); --outer)
00113         {
00114           for (inner = MAX (outer, nchars - 64); inner < nchars; ++inner)
00115            {
00116              adr[inner] = L('\0');
00117 
00118              if (STRNLEN (&adr[outer], inner - outer + 1)
00119                 != (size_t) (inner - outer))
00120               {
00121                 printf ("%s flunked for outer = %d, inner = %d\n",
00122                        STRINGIFY (STRNLEN), outer, inner);
00123                 result = 1;
00124               }
00125 
00126              adr[inner] = L('T');
00127            }
00128         }
00129       for (outer = nchars; outer >= MAX (0, nchars - 128); --outer)
00130         {
00131           for (inner = MAX (outer, nchars - 64); inner < nchars; ++inner)
00132            {
00133              if (STRNLEN (&adr[outer], inner - outer + 1)
00134                 != (size_t) (inner - outer + 1))
00135               {
00136                 printf ("%s flunked bounded for outer = %d, inner = %d\n",
00137                        STRINGIFY (STRNLEN), outer, inner);
00138                 result = 1;
00139               }
00140            }
00141         }
00142 
00143       /* strchr/wcschr test */
00144       for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer)
00145         {
00146          for (middle = MAX (outer, nchars - 64); middle < nchars; ++middle)
00147            {
00148              for (inner = middle; inner < nchars; ++inner)
00149               {
00150                 adr[middle] = L('V');
00151                 adr[inner] = L('\0');
00152 
00153                 CHAR *cp = STRCHR (&adr[outer], L('V'));
00154 
00155                 if ((inner == middle && cp != NULL)
00156                     || (inner != middle
00157                        && (cp - &adr[outer]) != middle - outer))
00158                   {
00159                     printf ("%s flunked for outer = %d, middle = %d, "
00160                            "inner = %d\n",
00161                            STRINGIFY (STRCHR), outer, middle, inner);
00162                     result = 1;
00163                   }
00164 
00165                 adr[inner] = L('T');
00166                 adr[middle] = L('T');
00167               }
00168            }
00169         }
00170 
00171       /* Special test.  */
00172       adr[nchars - 1] = L('\0');
00173       if (STRCHR (&adr[nchars - 1], L('\n')) != NULL)
00174        {
00175          printf ("%s flunked test of empty string at end of page\n",
00176                 STRINGIFY (STRCHR));
00177          result = 1;
00178        }
00179 
00180       /* strrchr/wcsrchr test */
00181       for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer)
00182         {
00183          for (middle = MAX (outer, nchars - 64); middle < nchars; ++middle)
00184            {
00185              for (inner = middle; inner < nchars; ++inner)
00186               {
00187                 adr[middle] = L('V');
00188                 adr[inner] = L('\0');
00189 
00190                 CHAR *cp = STRRCHR (&adr[outer], L('V'));
00191 
00192                 if ((inner == middle && cp != NULL)
00193                     || (inner != middle
00194                        && (cp - &adr[outer]) != middle - outer))
00195                   {
00196                     printf ("%s flunked for outer = %d, middle = %d, "
00197                            "inner = %d\n",
00198                            STRINGIFY (STRRCHR), outer, middle, inner);
00199                     result = 1;
00200                   }
00201 
00202                 adr[inner] = L('T');
00203                 adr[middle] = L('T');
00204               }
00205            }
00206         }
00207 
00208       /* This function only exists for single-byte characters.  */
00209 #ifndef WCSTEST
00210       /* rawmemchr test */
00211       for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer)
00212         {
00213          for (middle = MAX (outer, nchars - 64); middle < nchars; ++middle)
00214            {
00215              adr[middle] = L('V');
00216 
00217              CHAR *cp = rawmemchr (&adr[outer], L('V'));
00218 
00219              if (cp - &adr[outer] != middle - outer)
00220               {
00221                 printf ("%s flunked for outer = %d, middle = %d\n",
00222                        STRINGIFY (rawmemchr), outer, middle);
00223                 result = 1;
00224               }
00225 
00226              adr[middle] = L('T');
00227            }
00228         }
00229 #endif
00230 
00231       /* strcpy/wcscpy test */
00232       for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer)
00233         {
00234           for (inner = MAX (outer, nchars - 64); inner < nchars; ++inner)
00235            {
00236              adr[inner] = L('\0');
00237 
00238              if (STRCPY (dest, &adr[outer]) != dest
00239                 || STRLEN (dest) != (size_t) (inner - outer))
00240               {
00241                 printf ("%s flunked for outer = %d, inner = %d\n",
00242                        STRINGIFY (STRCPY), outer, inner);
00243                 result = 1;
00244               }
00245 
00246              adr[inner] = L('T');
00247            }
00248         }
00249 
00250       /* strncpy tests */
00251       adr[nchars - 1] = L('T');
00252       for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer)
00253        {
00254          size_t len;
00255 
00256          for (len = 0; len < nchars - outer; ++len)
00257            {
00258              if (STRNCPY (dest, &adr[outer], len) != dest
00259                 || MEMCMP (dest, &adr[outer], len) != 0)
00260               {
00261                 printf ("outer %s flunked for outer = %d, len = %Zd\n",
00262                        STRINGIFY (STRNCPY), outer, len);
00263                 result = 1;
00264               }
00265            }
00266         }
00267       adr[nchars - 1] = L('\0');
00268 
00269       for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer)
00270         {
00271           for (inner = MAX (outer, nchars - 64); inner < nchars; ++inner)
00272            {
00273              size_t len;
00274 
00275              adr[inner] = L('\0');
00276 
00277              for (len = 0; len < nchars - outer + 64; ++len)
00278               {
00279                 if (STRNCPY (dest, &adr[outer], len) != dest
00280                     || MEMCMP (dest, &adr[outer],
00281                              MIN (inner - outer, len)) != 0
00282                     || (inner - outer < len
00283                        && STRLEN (dest) != (inner - outer)))
00284                   {
00285                     printf ("%s flunked for outer = %d, inner = %d, "
00286                            "len = %Zd\n",
00287                            STRINGIFY (STRNCPY), outer, inner, len);
00288                     result = 1;
00289                   }
00290                 if (STRNCPY (dest + 1, &adr[outer], len) != dest + 1
00291                     || MEMCMP (dest + 1, &adr[outer],
00292                              MIN (inner - outer, len)) != 0
00293                     || (inner - outer < len
00294                        && STRLEN (dest + 1) != (inner - outer)))
00295                   {
00296                     printf ("%s+1 flunked for outer = %d, inner = %d, "
00297                            "len = %Zd\n",
00298                            STRINGIFY (STRNCPY), outer, inner, len);
00299                     result = 1;
00300                   }
00301               }
00302 
00303              adr[inner] = L('T');
00304            }
00305         }
00306 
00307       /* stpcpy/wcpcpy test */
00308       for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer)
00309         {
00310           for (inner = MAX (outer, nchars - 64); inner < nchars; ++inner)
00311            {
00312              adr[inner] = L('\0');
00313 
00314              if ((STPCPY (dest, &adr[outer]) - dest) != inner - outer)
00315               {
00316                 printf ("%s flunked for outer = %d, inner = %d\n",
00317                        STRINGIFY (STPCPY), outer, inner);
00318                 result = 1;
00319               }
00320 
00321              adr[inner] = L('T');
00322            }
00323         }
00324 
00325       /* stpncpy/wcpncpy test */
00326       for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer)
00327         {
00328           for (middle = MAX (outer, nchars - 64); middle < nchars; ++middle)
00329            {
00330              adr[middle] = L('\0');
00331 
00332              for (inner = 0; inner < nchars - outer; ++ inner)
00333               {
00334                 if ((STPNCPY (dest, &adr[outer], inner) - dest)
00335                     != MIN (inner, middle - outer))
00336                   {
00337                     printf ("%s flunked for outer = %d, middle = %d, "
00338                            "inner = %d\n",
00339                            STRINGIFY (STPNCPY), outer, middle, inner);
00340                     result = 1;
00341                   }
00342               }
00343 
00344              adr[middle] = L('T');
00345            }
00346         }
00347 
00348       /* memcpy/wmemcpy test */
00349       for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer)
00350        for (inner = 0; inner < nchars - outer; ++inner)
00351          if (MEMCPY (dest, &adr[outer], inner) !=  dest)
00352            {
00353              printf ("%s flunked for outer = %d, inner = %d\n",
00354                     STRINGIFY (MEMCPY), outer, inner);
00355              result = 1;
00356            }
00357 
00358       /* mempcpy/wmempcpy test */
00359       for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer)
00360        for (inner = 0; inner < nchars - outer; ++inner)
00361          if (MEMPCPY (dest, &adr[outer], inner) !=  dest + inner)
00362            {
00363              printf ("%s flunked for outer = %d, inner = %d\n",
00364                     STRINGIFY (MEMPCPY), outer, inner);
00365              result = 1;
00366            }
00367 
00368       /* This function only exists for single-byte characters.  */
00369 #ifndef WCSTEST
00370       /* memccpy test */
00371       memset (adr, '\0', nchars);
00372       for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer)
00373        for (inner = 0; inner < nchars - outer; ++inner)
00374          if (memccpy (dest, &adr[outer], L('\1'), inner) != NULL)
00375            {
00376              printf ("memccpy flunked full copy for outer = %d, inner = %d\n",
00377                     outer, inner);
00378              result = 1;
00379            }
00380       for (outer = nchars - 1; outer >= MAX (0, nchars - 128); --outer)
00381        for (middle = 0; middle < nchars - outer; ++middle)
00382          {
00383            memset (dest, L('\2'), middle + 1);
00384            for (inner = 0; inner < middle; ++inner)
00385              {
00386               adr[outer + inner] = L('\1');
00387 
00388               if (memccpy (dest, &adr[outer], '\1', middle + 128)
00389                   !=  dest + inner + 1)
00390                 {
00391                   printf ("\
00392 memccpy flunked partial copy for outer = %d, middle = %d, inner = %d\n",
00393                          outer, middle, inner);
00394                   result = 1;
00395                 }
00396               else if (dest[inner + 1] != L('\2'))
00397                 {
00398                   printf ("\
00399 memccpy copied too much for outer = %d, middle = %d, inner = %d\n",
00400                          outer, middle, inner);
00401                   result = 1;
00402                 }
00403               adr[outer + inner] = L('\0');
00404              }
00405          }
00406 #endif
00407     }
00408 
00409   return result;
00410 }
00411 
00412 #define TEST_FUNCTION do_test ()
00413 #include "../test-skeleton.c"