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 static 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 #if 0
121 static void
122 printbuf (char *buf, char *name)
123 {
124   int i;
125   printf ("\n %s=", name);
126   for (i = 0; i < BUFF_SIZE; i++)
127     if (buf[i] != 0)
128       printf ("(%d,%c)", i, buf[i]);
129     else
130       printf ("(%d,%s)", i, "\\0");
131   printf ("\n");
132 }
133 #endif
134 
135 int
main(void)136 main (void)
137 {
138   /* Allocate buffers to read and write from.  */
139   char src[BUFF_SIZE], dest[BUFF_SIZE];
140 
141   /* Fill the source buffer with non-null values, reproducable random data.  */
142   srand (1539);
143   unsigned i, j, zeros;
144   unsigned sa;
145   unsigned da;
146   unsigned n, m, len;
147   char *p;
148   int ret;
149 
150   /* Make calls to strcmp with block sizes ranging between 1 and
151      MAX_BLOCK_SIZE bytes, aligned and misaligned source and destination.  */
152   for (sa = 0; sa <= MAX_OFFSET; sa++)
153     for (da = 0; da <= MAX_OFFSET; da++)
154       for (n = 1; n <= MAX_BLOCK_SIZE; n++)
155 	{
156 	for (m = 1;  m < n + MAX_DIFF; m++)
157 	  for (len = 0; len < MAX_LEN; len++)
158 	    for  (zeros = 1; zeros < MAX_ZEROS; zeros++)
159 	    {
160 	      if (n - m > MAX_DIFF)
161 		continue;
162 	      /* Make a copy of the source.  */
163 	      j = 'A';
164 	      for (i = 0; i < BUFF_SIZE; i++)
165 		{
166 		  src[i] = j;
167 		  if (j++ == 'Z') j = 'A';
168 		  dest[i] = src[i];
169 		}
170 	      memcpy (dest + da, src + sa, n);
171 
172 	      /* Make src 0-terminated.  */
173 	      p = src + sa + n - 1;
174 	      for (i = 0; i < zeros; i++)
175 		{
176 		  *p++ = '\0';
177 		}
178 
179 	      /* Modify dest.  */
180 	      p = dest + da + m - 1;
181 	      for (j = 0; j < len; j++)
182 		*p++ = 'x';
183 	      /* Make dest 0-terminated.  */
184 	      *p = '\0';
185 
186 	      ret = strcmp (src + sa, dest + da);
187 
188 	      /* Check return value.  */
189 	      if (n == m)
190 		{
191 		  if (len == 0)
192 		    {
193 		      if (ret != 0)
194 			{
195 			print_error ("\nFailed: after %s of %u bytes "
196 				     "with src_align %u and dst_align %u, "
197 				     "dest after %d bytes is modified for %d bytes, "
198 				     "return value is %d, expected 0.\n",
199 				     testname, n, sa, da, m, len, ret);
200 			}
201 		    }
202 		  else
203 		    {
204 		      if (ret >= 0)
205 			print_error ("\nFailed: after %s of %u bytes "
206 				     "with src_align %u and dst_align %u, "
207 				     "dest after %d bytes is modified for %d bytes, "
208 				     "return value is %d, expected negative.\n",
209 				     testname, n, sa, da, m, len, ret);
210 		    }
211 		}
212 	      else if (m > n)
213 		{
214 		  if (ret >= 0)
215 		    {
216 		      print_error ("\nFailed: after %s of %u bytes "
217 				   "with src_align %u and dst_align %u, "
218 				   "dest after %d bytes is modified for %d bytes, "
219 				   "return value is %d, expected negative.\n",
220 				   testname, n, sa, da, m, len, ret);
221 		    }
222 		}
223 	      else  /* m < n */
224 		{
225 		  if (len == 0)
226 		    {
227 		      if (ret <= 0)
228 			print_error ("\nFailed: after %s of %u bytes "
229 				     "with src_align %u and dst_align %u, "
230 				     "dest after %d bytes is modified for %d bytes, "
231 				     "return value is %d, expected positive.\n",
232 				     testname, n, sa, da, m, len, ret);
233 		    }
234 		  else
235 		    {
236 		      if (ret >= 0)
237 			print_error ("\nFailed: after %s of %u bytes "
238 				     "with src_align %u and dst_align %u, "
239 				     "dest after %d bytes is modified for %d bytes, "
240 				     "return value is %d, expected negative.\n",
241 				     testname, n, sa, da, m, len, ret);
242 		    }
243 		}
244 	    }
245 	}
246 
247   /* Check some corner cases.  */
248   src[1] = 'A';
249   dest[1] = 'A';
250   src[2] = 'B';
251   dest[2] = 'B';
252   src[3] = 'C';
253   dest[3] = 'C';
254   src[4] = '\0';
255   dest[4] = '\0';
256 
257   src[0] = 0xc1;
258   dest[0] = 0x41;
259   ret = strcmp (src, dest);
260   if (ret <= 0)
261     print_error ("\nFailed: expected positive, return %d\n", ret);
262 
263   src[0] = 0x01;
264   dest[0] = 0x82;
265   ret = strcmp (src, dest);
266   if (ret >= 0)
267     print_error ("\nFailed: expected negative, return %d\n", ret);
268 
269   dest[0] = src[0] = 'D';
270   src[3] = 0xc1;
271   dest[3] = 0x41;
272   ret = strcmp (src, dest);
273   if (ret <= 0)
274     print_error ("\nFailed: expected positive, return %d\n", ret);
275 
276   src[3] = 0x01;
277   dest[3] = 0x82;
278   ret = strcmp (src, dest);
279   if (ret >= 0)
280     print_error ("\nFailed: expected negative, return %d\n", ret);
281 
282   printf ("\n");
283   if (errors != 0)
284     {
285       printf ("ERROR. FAILED.\n");
286       abort ();
287     }
288   exit (0);
289 }
290