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 #ifndef BUFF_SIZE
35 #define BUFF_SIZE 1024
36 #endif
37
38 #ifndef START_COPY
39 #define START_COPY 256
40 #endif
41
42 #ifndef MAX_BLOCK_SIZE
43 #define MAX_BLOCK_SIZE 128
44 #endif
45
46 #ifndef MAX_OFFSET
47 #define MAX_OFFSET 3
48 #endif
49
50 #if (START_COPY + MAX_OFFSET + MAX_BLOCK_SIZE >= BUFF_SIZE)
51 #error "Buffer overrun: START_COPY + MAX_OFFSET + MAX_BLOCK_SIZE >= BUFF_SIZE."
52 #endif
53
54 #define TOO_MANY_ERRORS 11
55 int errors = 0;
56
57 void
print_error(char const * msg,...)58 print_error (char const* msg, ...)
59 {
60 errors++;
61 if (errors == TOO_MANY_ERRORS)
62 {
63 fprintf (stderr, "Too many errors.\n");
64 }
65 else if (errors < TOO_MANY_ERRORS)
66 {
67 va_list ap;
68 va_start (ap, msg);
69 vfprintf (stderr, msg, ap);
70 va_end (ap);
71 }
72 else
73 {
74 /* Further errors omitted. */
75 }
76 }
77
78 int
main(void)79 main (void)
80 {
81 /* Allocate buffers to read and write from. */
82 char src[BUFF_SIZE], dest[BUFF_SIZE], backup_src[BUFF_SIZE];
83
84 /* Fill the source buffer with non-null values, reproducable random data. */
85 srand (1539);
86 int i;
87 unsigned j;
88 unsigned sa;
89 unsigned da;
90 unsigned n;
91 for (i = 0; i < BUFF_SIZE; i++)
92 {
93 src[i] = (char)rand () | 1;
94 backup_src[i] = src[i];
95 }
96
97 /* Make calls to memcpy with block sizes ranging between 1 and
98 MAX_BLOCK_SIZE bytes, aligned and misaligned source and destination. */
99 for (sa = 0; sa <= MAX_OFFSET; sa++)
100 for (da = 0; da <= MAX_OFFSET; da++)
101 for (n = 1; n <= MAX_BLOCK_SIZE; n++)
102 {
103 printf (".");
104 /* Zero dest so we can check it properly after the copying. */
105 for (j = 0; j < BUFF_SIZE; j++)
106 dest[j] = 0;
107
108 void *ret = memcpy (dest + START_COPY + da, src + sa, n);
109
110 /* Check return value. */
111 if (ret != (dest + START_COPY + da))
112 print_error ("\nFailed: wrong return value in memcpy of %u bytes "
113 "with src_align %u and dst_align %u. "
114 "Return value and dest should be the same"
115 "(ret is %p, dest is %p)\n",
116 n, sa, da, ret, dest + START_COPY + da);
117
118 /* Check that content of the destination buffer
119 is the same as the source buffer, and
120 memory outside destination buffer is not modified. */
121 for (j = 0; j < BUFF_SIZE; j++)
122 if (j < START_COPY + da)
123 {
124 if (dest[j] != 0)
125 print_error ("\nFailed: after memcpy of %u bytes "
126 "with src_align %u and dst_align %u, "
127 "byte %u before the start of dest is not 0.\n",
128 n, sa, da, START_COPY - j);
129 }
130 else if (j < START_COPY + da + n)
131 {
132 i = j - START_COPY - da;
133 if (dest[j] != (src + sa)[i])
134 print_error ("\nFailed: after memcpy of %u bytes "
135 "with src_align %u and dst_align %u, "
136 "byte %u in dest and src are not the same.\n",
137 n, sa, da, i);
138 }
139 else if (dest[j] != 0)
140 {
141 print_error ("\nFailed: after memcpy of %u bytes "
142 "with src_align %u and dst_align %u, "
143 "byte %u after the end of dest is not 0.\n",
144 n, sa, da, j - START_COPY - da - n);
145 }
146
147 /* Check src is not modified. */
148 for (j = 0; j < BUFF_SIZE; j++)
149 if (src[i] != backup_src[i])
150 print_error ("\nFailed: after memcpy of %u bytes "
151 "with src_align %u and dst_align %u, "
152 "byte %u of src is modified.\n",
153 n, sa, da, j);
154 }
155
156 printf ("\n");
157 if (errors != 0)
158 abort ();
159
160 exit (0);
161 }
162