1 #include "asan_impl.h"
2 #include "libc.h"
3 #include <endian.h>
4 #include <stdint.h>
5 #include <string.h>
6 
memcpy(void * restrict dest,const void * restrict src,size_t n)7 NO_ASAN void* memcpy(void* restrict dest, const void* restrict src, size_t n) {
8     unsigned char* d = dest;
9     const unsigned char* s = src;
10 
11 #ifdef __GNUC__
12 
13 #if __BYTE_ORDER == __LITTLE_ENDIAN
14 #define LS >>
15 #define RS <<
16 #else
17 #define LS <<
18 #define RS >>
19 #endif
20 
21     typedef uint32_t __attribute__((__may_alias__)) u32;
22     uint32_t w, x;
23 
24     for (; (uintptr_t)s % 4 && n; n--)
25         *d++ = *s++;
26 
27     if ((uintptr_t)d % 4 == 0) {
28         for (; n >= 16; s += 16, d += 16, n -= 16) {
29             *(u32*)(d + 0) = *(u32*)(s + 0);
30             *(u32*)(d + 4) = *(u32*)(s + 4);
31             *(u32*)(d + 8) = *(u32*)(s + 8);
32             *(u32*)(d + 12) = *(u32*)(s + 12);
33         }
34         if (n & 8) {
35             *(u32*)(d + 0) = *(u32*)(s + 0);
36             *(u32*)(d + 4) = *(u32*)(s + 4);
37             d += 8;
38             s += 8;
39         }
40         if (n & 4) {
41             *(u32*)(d + 0) = *(u32*)(s + 0);
42             d += 4;
43             s += 4;
44         }
45         if (n & 2) {
46             *d++ = *s++;
47             *d++ = *s++;
48         }
49         if (n & 1) {
50             *d = *s;
51         }
52         return dest;
53     }
54 
55     if (n >= 32)
56         switch ((uintptr_t)d % 4) {
57         case 1:
58             w = *(u32*)s;
59             *d++ = *s++;
60             *d++ = *s++;
61             *d++ = *s++;
62             n -= 3;
63             for (; n >= 17; s += 16, d += 16, n -= 16) {
64                 x = *(u32*)(s + 1);
65                 *(u32*)(d + 0) = (w LS 24) | (x RS 8);
66                 w = *(u32*)(s + 5);
67                 *(u32*)(d + 4) = (x LS 24) | (w RS 8);
68                 x = *(u32*)(s + 9);
69                 *(u32*)(d + 8) = (w LS 24) | (x RS 8);
70                 w = *(u32*)(s + 13);
71                 *(u32*)(d + 12) = (x LS 24) | (w RS 8);
72             }
73             break;
74         case 2:
75             w = *(u32*)s;
76             *d++ = *s++;
77             *d++ = *s++;
78             n -= 2;
79             for (; n >= 18; s += 16, d += 16, n -= 16) {
80                 x = *(u32*)(s + 2);
81                 *(u32*)(d + 0) = (w LS 16) | (x RS 16);
82                 w = *(u32*)(s + 6);
83                 *(u32*)(d + 4) = (x LS 16) | (w RS 16);
84                 x = *(u32*)(s + 10);
85                 *(u32*)(d + 8) = (w LS 16) | (x RS 16);
86                 w = *(u32*)(s + 14);
87                 *(u32*)(d + 12) = (x LS 16) | (w RS 16);
88             }
89             break;
90         case 3:
91             w = *(u32*)s;
92             *d++ = *s++;
93             n -= 1;
94             for (; n >= 19; s += 16, d += 16, n -= 16) {
95                 x = *(u32*)(s + 3);
96                 *(u32*)(d + 0) = (w LS 8) | (x RS 24);
97                 w = *(u32*)(s + 7);
98                 *(u32*)(d + 4) = (x LS 8) | (w RS 24);
99                 x = *(u32*)(s + 11);
100                 *(u32*)(d + 8) = (w LS 8) | (x RS 24);
101                 w = *(u32*)(s + 15);
102                 *(u32*)(d + 12) = (x LS 8) | (w RS 24);
103             }
104             break;
105         }
106     if (n & 16) {
107         *d++ = *s++;
108         *d++ = *s++;
109         *d++ = *s++;
110         *d++ = *s++;
111         *d++ = *s++;
112         *d++ = *s++;
113         *d++ = *s++;
114         *d++ = *s++;
115         *d++ = *s++;
116         *d++ = *s++;
117         *d++ = *s++;
118         *d++ = *s++;
119         *d++ = *s++;
120         *d++ = *s++;
121         *d++ = *s++;
122         *d++ = *s++;
123     }
124     if (n & 8) {
125         *d++ = *s++;
126         *d++ = *s++;
127         *d++ = *s++;
128         *d++ = *s++;
129         *d++ = *s++;
130         *d++ = *s++;
131         *d++ = *s++;
132         *d++ = *s++;
133     }
134     if (n & 4) {
135         *d++ = *s++;
136         *d++ = *s++;
137         *d++ = *s++;
138         *d++ = *s++;
139     }
140     if (n & 2) {
141         *d++ = *s++;
142         *d++ = *s++;
143     }
144     if (n & 1) {
145         *d = *s;
146     }
147     return dest;
148 #endif
149 
150     for (; n; n--)
151         *d++ = *s++;
152     return dest;
153 }
154 
155 __typeof(memcpy) __unsanitized_memcpy __attribute__((alias("memcpy")));
156 __asan_weak_alias(memcpy)
157