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