1 /*
2  * SPDX-License-Identifier: BSD-3-Clause
3  *
4  * Copyright © 2021 Keith Packard
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above
14  *    copyright notice, this list of conditions and the following
15  *    disclaimer in the documentation and/or other materials provided
16  *    with the distribution.
17  *
18  * 3. Neither the name of the copyright holder nor the names of its
19  *    contributors may be used to endorse or promote products derived
20  *    from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
31  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
33  * OF THE POSSIBILITY OF SUCH DAMAGE.
34  */
35 
36 #define _GNU_SOURCE
37 #include <string.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <limits.h>
41 #include <stdint.h>
42 
43 #ifdef __arm__
44 void *__aeabi_memset(void *dest, size_t n, int c);
45 void *__aeabi_memset4(void *dest, size_t n, int c);
46 void *__aeabi_memset8(void *dest, size_t n, int c);
47 void __aeabi_memclr(void *dest, size_t n);
48 void __aeabi_memclr4(void *dest, size_t n);
49 void __aeabi_memclr8(void *dest, size_t n);
50 #endif
51 
52 static uint8_t crc_table[256];
53 
54 static uint8_t
crc8(uint8_t c)55 crc8(uint8_t c)
56 {
57     int i;
58     for (i = 0; i < 8; i++) {
59         if (c & 1)
60             c = 0x31 ^ (c >> 1);
61         else
62             c >>= 1;
63     }
64     return c;
65 }
66 
67 static void
init_crc(void)68 init_crc(void)
69 {
70     int i;
71     for (i = 0; i < 256; i++)
72         crc_table[i] = crc8((uint8_t) i);
73 }
74 
75 static char
expect(size_t pos)76 expect(size_t pos)
77 {
78     unsigned int i;
79     uint8_t     c = 0xff;
80     for (i = 0; i < sizeof(size_t); i++)
81         c ^= crc_table[(uint8_t) (pos >> (i * 8))];
82     return (char) c;
83 }
84 
85 size_t
check(char * label,void * buf,size_t size,size_t start,size_t end,int c)86 check(char *label, void *buf, size_t size, size_t start, size_t end, int c)
87 {
88     size_t      p;
89     size_t      error = 0;
90     char        *b = buf;
91 
92     for (p = 0; p < size; p++) {
93         char g = b[p];
94         char e = c;
95         if (p < start || end <= p)
96             e = expect(p);
97         if (g != e) {
98             fprintf(stderr, "%s(%zu, %zu):%zu expect 0x%02x got 0x%02x\n",
99                     label, start, end, p, (uint8_t) e, (uint8_t) g);
100             error++;
101         }
102     }
103     return error;
104 }
105 
106 size_t
randrange(size_t max)107 randrange(size_t max)
108 {
109     size_t      pot;
110     size_t      rnd;
111 
112     for (pot = 1; pot && pot < max; pot <<= 1)
113         ;
114 
115     for (;;) {
116         rnd = random() & (pot - 1);
117         if (rnd < max)
118             return rnd;
119     }
120 }
121 
122 
123 #define MAX_BUF         1024
124 
125 #define NEND            64
126 #define NSTART          64
127 
128 static char buf[MAX_BUF];
129 
130 static void
fill(void)131 fill(void)
132 {
133     size_t      p;
134 
135     for (p = 0; p < MAX_BUF; p++)
136         buf[p] = expect(p);
137 }
138 
139 static size_t
test(size_t start,size_t end,int c)140 test(size_t start, size_t end, int c)
141 {
142     size_t error = 0;
143     char *b = buf;
144     fill();
145     memset(b + start, c, end - start);
146     error += check("memset", buf, MAX_BUF, start, end, c);
147 
148     fill();
149     bzero(b + start, end - start);
150     error += check("bzero", buf, MAX_BUF, start, end, 0);
151 
152 #ifdef __arm__
153     fill();
154     __aeabi_memset(b + start, end - start, c);
155     error += check("__aeabi_memset", buf, MAX_BUF, start, end, c);
156 
157     fill();
158     __aeabi_memclr(b + start, end - start);
159     error += check("__aeabi_memclr", buf, MAX_BUF, start, end, 0);
160 
161     start &= ~3;
162     end &= ~3;
163 
164     fill();
165     __aeabi_memset4(b + start, end - start, c);
166     error += check("__aeabi_memset4", buf, MAX_BUF, start, end, c);
167 
168     fill();
169     __aeabi_memclr4(b + start, end - start);
170     error += check("__aeabi_memclr4", buf, MAX_BUF, start, end, 0);
171 
172     start &= ~7;
173     end &= ~7;
174 
175     fill();
176     __aeabi_memset8(b + start, end - start, c);
177     error += check("__aeabi_memset8", buf, MAX_BUF, start, end, c);
178 
179     fill();
180     __aeabi_memclr8(b + start, end - start);
181     error += check("__aeabi_memclr8", buf, MAX_BUF, start, end, 0);
182 #endif
183 
184     return error;
185 
186 }
187 
188 int
main(void)189 main(void)
190 {
191     size_t      error;
192     size_t      end;
193     size_t      start;
194 
195     int         nend;
196     int         nstart;
197     int         ret = 0;
198 
199     init_crc();
200     for (nend = 0; nend < NEND; nend++) {
201         end = randrange(MAX_BUF + 1);
202         for (nstart = 0; nstart < NSTART; nstart++) {
203             start = randrange(end + 1);
204             int c = randrange(INT_MAX);
205             error = test(start, end, c);
206             if (error)
207                 ret = 1;
208         }
209     }
210 
211     return ret;
212 }
213