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