1 /* Test for string function add boundaries of usable memory.
2    Copyright (C) 1996,1997,1999,2000,2001,2002 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, write to the Free
18    Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19    02110-1301 USA.  */
20 
21 #define _GNU_SOURCE 1
22 #define __USE_GNU
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 MAX
36 #define MAX(a, b) ((a) > (b) ? (a) : (b))
37 #endif
38 
39 int
40 main (int argc, char *argv[])
41 {
42   int size = sysconf (_SC_PAGESIZE);
43   char *adr, *dest;
44   int result = 0;
45 
46   adr = (char *) mmap (NULL, 3 * size, PROT_READ | PROT_WRITE,
47 		       MAP_PRIVATE | MAP_ANON, -1, 0);
48   dest = (char *) mmap (NULL, 3 * size, PROT_READ | PROT_WRITE,
49 			MAP_PRIVATE | MAP_ANON, -1, 0);
50   if (adr == MAP_FAILED || dest == MAP_FAILED)
51     {
52       if (errno == ENOSYS)
53         puts ("No test, mmap not available.");
54       else
55         {
56           printf ("mmap failed: %m");
57           result = 1;
58         }
59     }
60   else
61     {
62       int inner, middle, outer;
63 
64       mprotect(adr, size, PROT_NONE);
65       mprotect(adr + 2 * size, size, PROT_NONE);
66       adr += size;
67 
68       mprotect(dest, size, PROT_NONE);
69       mprotect(dest + 2 * size, size, PROT_NONE);
70       dest += size;
71 
72       memset (adr, 'T', size);
73 
74       /* strlen test */
75       for (outer = size - 1; outer >= MAX (0, size - 128); --outer)
76         {
77           for (inner = MAX (outer, size - 64); inner < size; ++inner)
78 	    {
79 	      adr[inner] = '\0';
80 
81 	      if (strlen (&adr[outer]) != (size_t) (inner - outer))
82 		{
83 		  printf ("strlen flunked for outer = %d, inner = %d\n",
84 			  outer, inner);
85 		  result = 1;
86 		}
87 
88 	      adr[inner] = 'T';
89 	    }
90         }
91 
92       /* strchr test */
93       for (outer = size - 1; outer >= MAX (0, size - 128); --outer)
94         {
95 	  for (middle = MAX (outer, size - 64); middle < size; ++middle)
96 	    {
97 	      for (inner = middle; inner < size; ++inner)
98 		{
99 		  char *cp;
100 		  adr[middle] = 'V';
101 		  adr[inner] = '\0';
102 
103 		  cp = strchr (&adr[outer], 'V');
104 
105 		  if ((inner == middle && cp != NULL)
106 		      || (inner != middle
107 			  && (cp - &adr[outer]) != middle - outer))
108 		    {
109 		      printf ("strchr flunked for outer = %d, middle = %d, "
110 			      "inner = %d\n", outer, middle, inner);
111 		      result = 1;
112 		    }
113 
114 		  adr[inner] = 'T';
115 		  adr[middle] = 'T';
116 		}
117 	    }
118         }
119 
120       /* Special test.  */
121       adr[size - 1] = '\0';
122       if (strchr (&adr[size - 1], '\n') != NULL)
123 	{
124 	  puts ("strchr flunked for test of empty string at end of page");
125 	  result = 1;
126 	}
127 
128       /* strrchr test */
129       for (outer = size - 1; outer >= MAX (0, size - 128); --outer)
130         {
131 	  for (middle = MAX (outer, size - 64); middle < size; ++middle)
132 	    {
133 	      for (inner = middle; inner < size; ++inner)
134 		{
135 		  char *cp;
136 		  adr[middle] = 'V';
137 		  adr[inner] = '\0';
138 
139 		  cp = strrchr (&adr[outer], 'V');
140 
141 		  if ((inner == middle && cp != NULL)
142 		      || (inner != middle
143 			  && (cp - &adr[outer]) != middle - outer))
144 		    {
145 		      printf ("strrchr flunked for outer = %d, middle = %d, "
146 			      "inner = %d\n", outer, middle, inner);
147 		      result = 1;
148 		    }
149 
150 		  adr[inner] = 'T';
151 		  adr[middle] = 'T';
152 		}
153 	    }
154         }
155 
156 #ifndef __FreeBSD__
157       /* rawmemchr test */
158       for (outer = size - 1; outer >= MAX (0, size - 128); --outer)
159         {
160 	  for (middle = MAX (outer, size - 64); middle < size; ++middle)
161 	    {
162 	      char *cp;
163 	      adr[middle] = 'V';
164 
165 	      cp = (char *) rawmemchr (&adr[outer], 'V');
166 
167 	      if (cp - &adr[outer] != middle - outer)
168 		{
169 		  printf ("rawmemchr flunked for outer = %d, middle = %d\n",
170 			  outer, middle);
171 		  result = 1;
172 		}
173 
174 	      adr[middle] = 'T';
175 	    }
176         }
177 #endif
178 
179       /* strcpy test */
180       for (outer = size - 1; outer >= MAX (0, size - 128); --outer)
181         {
182           for (inner = MAX (outer, size - 64); inner < size; ++inner)
183 	    {
184 	      adr[inner] = '\0';
185 
186 	      if (strcpy (dest, &adr[outer]) != dest
187 		  || strlen (dest) != (size_t) (inner - outer))
188 		{
189 		  printf ("strcpy flunked for outer = %d, inner = %d\n",
190 			  outer, inner);
191 		  result = 1;
192 		}
193 
194 	      adr[inner] = 'T';
195 	    }
196         }
197 
198       /* strncpy tests */
199       adr[size-1] = 'T';
200       for (outer = size - 1; outer >= MAX (0, size - 128); --outer)
201 	{
202 	  size_t len;
203 
204 	  for (len = 0; len < size - outer; ++len)
205 	    {
206 	      if (strncpy (dest, &adr[outer], len) != dest
207 		  || memcmp (dest, &adr[outer], len) != 0)
208 		{
209 		  printf ("outer strncpy flunked for outer = %d, len = %Zd\n",
210 			  outer, len);
211 		  result = 1;
212 		}
213 	    }
214         }
215       adr[size-1] = '\0';
216 
217       for (outer = size - 1; outer >= MAX (0, size - 128); --outer)
218         {
219           for (inner = MAX (outer, size - 64); inner < size; ++inner)
220 	    {
221 	      size_t len;
222 
223 	      adr[inner] = '\0';
224 
225 	      for (len = 0; len < size - outer + 64; ++len)
226 		{
227 		  if (strncpy (dest, &adr[outer], len) != dest
228 		      || memcmp (dest, &adr[outer],
229 				 MIN (inner - outer, len)) != 0
230 		      || (inner - outer < len
231 			  && strlen (dest) != (inner - outer)))
232 		    {
233 		      printf ("strncpy flunked for outer = %d, inner = %d, len = %Zd\n",
234 			      outer, inner, len);
235 		      result = 1;
236 		    }
237 		  if (strncpy (dest + 1, &adr[outer], len) != dest + 1
238 		      || memcmp (dest + 1, &adr[outer],
239 				 MIN (inner - outer, len)) != 0
240 		      || (inner - outer < len
241 			  && strlen (dest + 1) != (inner - outer)))
242 		    {
243 		      printf ("strncpy+1 flunked for outer = %d, inner = %d, len = %Zd\n",
244 			      outer, inner, len);
245 		      result = 1;
246 		    }
247 		}
248 
249 	      adr[inner] = 'T';
250 	    }
251         }
252 
253 #ifndef __FreeBSD__
254       /* stpcpy test */
255       for (outer = size - 1; outer >= MAX (0, size - 128); --outer)
256         {
257           for (inner = MAX (outer, size - 64); inner < size; ++inner)
258 	    {
259 	      adr[inner] = '\0';
260 
261 	      if ((stpcpy (dest, &adr[outer]) - dest) != inner - outer)
262 		{
263 		  printf ("stpcpy flunked for outer = %d, inner = %d\n",
264 			  outer, inner);
265 		  result = 1;
266 		}
267 
268 	      adr[inner] = 'T';
269 	    }
270         }
271 
272       /* stpncpy test */
273       for (outer = size - 1; outer >= MAX (0, size - 128); --outer)
274         {
275           for (middle = MAX (outer, size - 64); middle < size; ++middle)
276 	    {
277 	      adr[middle] = '\0';
278 
279 	      for (inner = 0; inner < size - outer; ++ inner)
280 		{
281 		  if ((stpncpy (dest, &adr[outer], inner) - dest)
282 		      != MIN (inner, middle - outer))
283 		    {
284 		      printf ("stpncpy flunked for outer = %d, middle = %d, "
285 			      "inner = %d\n", outer, middle, inner);
286 		      result = 1;
287 		    }
288 		}
289 
290 	      adr[middle] = 'T';
291 	    }
292         }
293 #endif
294 
295       /* memcpy test */
296       for (outer = size - 1; outer >= MAX (0, size - 128); --outer)
297 	for (inner = 0; inner < size - outer; ++inner)
298 	  if (memcpy (dest, &adr[outer], inner) !=  dest)
299 	    {
300 	      printf ("memcpy flunked for outer = %d, inner = %d\n",
301 		      outer, inner);
302 	      result = 1;
303 	    }
304 
305 #ifndef __FreeBSD__
306       /* mempcpy test */
307       for (outer = size - 1; outer >= MAX (0, size - 128); --outer)
308 	for (inner = 0; inner < size - outer; ++inner)
309 	  if (mempcpy (dest, &adr[outer], inner) !=  dest + inner)
310 	    {
311 	      printf ("mempcpy flunked for outer = %d, inner = %d\n",
312 		      outer, inner);
313 	      result = 1;
314 	    }
315 #endif
316     }
317 
318   return result;
319 }
320