1 /*
2  * Copyright (c) 2011 ARM Ltd
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. The name of the company may not be used to endorse or promote
14  *    products derived from this software without specific prior written
15  *    permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED
18  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
22  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include <string.h>
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <stdarg.h>
33 
34 /* The macro LONG_TEST controls whether a short or a more comprehensive test
35    of strcmp should be performed.  */
36 #ifdef LONG_TEST
37 #ifndef BUFF_SIZE
38 #define BUFF_SIZE 1024
39 #endif
40 
41 #ifndef MAX_BLOCK_SIZE
42 #define MAX_BLOCK_SIZE 128
43 #endif
44 
45 #ifndef MAX_OFFSET
46 #define MAX_OFFSET 3
47 #endif
48 
49 #ifndef MAX_DIFF
50 #define MAX_DIFF 8
51 #endif
52 
53 #ifndef MAX_LEN
54 #define MAX_LEN 8
55 #endif
56 
57 #ifndef MAX_ZEROS
58 #define MAX_ZEROS 8
59 #endif
60 #else /* not defined LONG_TEST */
61 #ifndef BUFF_SIZE
62 #define BUFF_SIZE 1024
63 #endif
64 
65 #ifndef MAX_BLOCK_SIZE
66 #define MAX_BLOCK_SIZE 64
67 #endif
68 
69 #ifndef MAX_OFFSET
70 #define MAX_OFFSET 3
71 #endif
72 
73 #ifndef MAX_DIFF
74 #define MAX_DIFF 4
75 #endif
76 
77 #ifndef MAX_LEN
78 #define MAX_LEN 4
79 #endif
80 
81 #ifndef MAX_ZEROS
82 #define MAX_ZEROS 4
83 #endif
84 #endif /* not defined LONG_TEST */
85 
86 #if (MAX_OFFSET >= 26)
87 #error "MAX_OFFSET >= 26"
88 #endif
89 #if (MAX_OFFSET + MAX_BLOCK_SIZE + MAX_DIFF + MAX_LEN + MAX_ZEROS >= BUFF_SIZE)
90 #error "Buffer overrun: MAX_OFFSET + MAX_BLOCK_SIZE + MAX_DIFF + MAX_LEN + MAX_ZEROS >= BUFF_SIZE."
91 #endif
92 
93 
94 #define TOO_MANY_ERRORS 11
95 int errors = 0;
96 
97 const char *testname = "strcmp";
98 
99 void
print_error(char const * msg,...)100 print_error (char const* msg, ...)
101 {
102   errors++;
103   if (errors == TOO_MANY_ERRORS)
104     {
105       fprintf (stderr, "Too many errors.\n");
106     }
107   else if (errors < TOO_MANY_ERRORS)
108     {
109       va_list ap;
110       va_start (ap, msg);
111       vfprintf (stderr, msg, ap);
112       va_end (ap);
113     }
114   else
115     {
116       /* Further errors omitted.  */
117     }
118 }
119 
120 void
printbuf(char * buf,char * name)121 printbuf (char *buf, char *name)
122 {
123   int i;
124   printf ("\n %s=", name);
125   for (i = 0; i < BUFF_SIZE; i++)
126     if (buf[i] != 0)
127       printf ("(%d,%c)", i, buf[i]);
128     else
129       printf ("(%d,%s)", i, "\\0");
130   printf ("\n");
131 }
132 
133 int
main(void)134 main (void)
135 {
136   /* Allocate buffers to read and write from.  */
137   char src[BUFF_SIZE], dest[BUFF_SIZE];
138 
139   /* Fill the source buffer with non-null values, reproducable random data.  */
140   srand (1539);
141   unsigned i, j, zeros;
142   unsigned sa;
143   unsigned da;
144   unsigned n, m, len;
145   char *p;
146   int ret;
147 
148   /* Make calls to strcmp with block sizes ranging between 1 and
149      MAX_BLOCK_SIZE bytes, aligned and misaligned source and destination.  */
150   for (sa = 0; sa <= MAX_OFFSET; sa++)
151     for (da = 0; da <= MAX_OFFSET; da++)
152       for (n = 1; n <= MAX_BLOCK_SIZE; n++)
153 	{
154 	for (m = 1;  m < n + MAX_DIFF; m++)
155 	  for (len = 0; len < MAX_LEN; len++)
156 	    for  (zeros = 1; zeros < MAX_ZEROS; zeros++)
157 	    {
158 	      if (n - m > MAX_DIFF)
159 		continue;
160 	      /* Make a copy of the source.  */
161 	      j = 'A';
162 	      for (i = 0; i < BUFF_SIZE; i++)
163 		{
164 		  src[i] = j;
165 		  if (j++ == 'Z') j = 'A';
166 		  dest[i] = src[i];
167 		}
168 	      memcpy (dest + da, src + sa, n);
169 
170 	      /* Make src 0-terminated.  */
171 	      p = src + sa + n - 1;
172 	      for (i = 0; i < zeros; i++)
173 		{
174 		  *p++ = '\0';
175 		}
176 
177 	      /* Modify dest.  */
178 	      p = dest + da + m - 1;
179 	      for (j = 0; j < len; j++)
180 		*p++ = 'x';
181 	      /* Make dest 0-terminated.  */
182 	      *p = '\0';
183 
184 	      ret = strcmp (src + sa, dest + da);
185 
186 	      /* Check return value.  */
187 	      if (n == m)
188 		{
189 		  if (len == 0)
190 		    {
191 		      if (ret != 0)
192 			{
193 			print_error ("\nFailed: after %s of %u bytes "
194 				     "with src_align %u and dst_align %u, "
195 				     "dest after %d bytes is modified for %d bytes, "
196 				     "return value is %d, expected 0.\n",
197 				     testname, n, sa, da, m, len, ret);
198 			}
199 		    }
200 		  else
201 		    {
202 		      if (ret >= 0)
203 			print_error ("\nFailed: after %s of %u bytes "
204 				     "with src_align %u and dst_align %u, "
205 				     "dest after %d bytes is modified for %d bytes, "
206 				     "return value is %d, expected negative.\n",
207 				     testname, n, sa, da, m, len, ret);
208 		    }
209 		}
210 	      else if (m > n)
211 		{
212 		  if (ret >= 0)
213 		    {
214 		      print_error ("\nFailed: after %s of %u bytes "
215 				   "with src_align %u and dst_align %u, "
216 				   "dest after %d bytes is modified for %d bytes, "
217 				   "return value is %d, expected negative.\n",
218 				   testname, n, sa, da, m, len, ret);
219 		    }
220 		}
221 	      else  /* m < n */
222 		{
223 		  if (len == 0)
224 		    {
225 		      if (ret <= 0)
226 			print_error ("\nFailed: after %s of %u bytes "
227 				     "with src_align %u and dst_align %u, "
228 				     "dest after %d bytes is modified for %d bytes, "
229 				     "return value is %d, expected positive.\n",
230 				     testname, n, sa, da, m, len, ret);
231 		    }
232 		  else
233 		    {
234 		      if (ret >= 0)
235 			print_error ("\nFailed: after %s of %u bytes "
236 				     "with src_align %u and dst_align %u, "
237 				     "dest after %d bytes is modified for %d bytes, "
238 				     "return value is %d, expected negative.\n",
239 				     testname, n, sa, da, m, len, ret);
240 		    }
241 		}
242 	    }
243 	}
244 
245   /* Check some corner cases.  */
246   src[1] = 'A';
247   dest[1] = 'A';
248   src[2] = 'B';
249   dest[2] = 'B';
250   src[3] = 'C';
251   dest[3] = 'C';
252   src[4] = '\0';
253   dest[4] = '\0';
254 
255   src[0] = 0xc1;
256   dest[0] = 0x41;
257   ret = strcmp (src, dest);
258   if (ret <= 0)
259     print_error ("\nFailed: expected positive, return %d\n", ret);
260 
261   src[0] = 0x01;
262   dest[0] = 0x82;
263   ret = strcmp (src, dest);
264   if (ret >= 0)
265     print_error ("\nFailed: expected negative, return %d\n", ret);
266 
267   dest[0] = src[0] = 'D';
268   src[3] = 0xc1;
269   dest[3] = 0x41;
270   ret = strcmp (src, dest);
271   if (ret <= 0)
272     print_error ("\nFailed: expected positive, return %d\n", ret);
273 
274   src[3] = 0x01;
275   dest[3] = 0x82;
276   ret = strcmp (src, dest);
277   if (ret >= 0)
278     print_error ("\nFailed: expected negative, return %d\n", ret);
279 
280   printf ("\n");
281   if (errors != 0)
282     {
283       printf ("ERROR. FAILED.\n");
284       abort ();
285     }
286   exit (0);
287 }
288