1 #include <ctype.h>
2 #include <inttypes.h>
3 #include <stdbool.h>
4 #include <stdint.h>
5 #include <unistd.h>
6
7 #include "libhfcommon/common.h"
8 #include "libhfuzz/instrument.h"
9
10 __attribute__((visibility("default"))) __attribute__((used))
11 const char* const LIBHFUZZ_module_memorycmp = "LIBHFUZZ_module_memorycmp";
12
13 #define RET_CALL_CHAIN (uintptr_t) __builtin_return_address(0)
14
HF_strcmp(const char * s1,const char * s2,uintptr_t addr)15 static inline int HF_strcmp(const char* s1, const char* s2, uintptr_t addr) {
16 size_t i;
17 for (i = 0; s1[i] == s2[i]; i++) {
18 if (s1[i] == '\0' || s2[i] == '\0') {
19 break;
20 }
21 }
22 instrumentUpdateCmpMap(addr, i);
23 return ((unsigned char)s1[i] - (unsigned char)s2[i]);
24 }
25
HF_strcasecmp(const char * s1,const char * s2,uintptr_t addr)26 static inline int HF_strcasecmp(const char* s1, const char* s2, uintptr_t addr) {
27 size_t i;
28 for (i = 0; tolower((unsigned char)s1[i]) == tolower((unsigned char)s2[i]); i++) {
29 if (s1[i] == '\0' || s2[i] == '\0') {
30 break;
31 }
32 }
33 instrumentUpdateCmpMap(addr, i);
34 return (tolower((unsigned char)s1[i]) - tolower((unsigned char)s2[i]));
35 }
36
HF_strncmp(const char * s1,const char * s2,size_t n,uintptr_t addr)37 static inline int HF_strncmp(const char* s1, const char* s2, size_t n, uintptr_t addr) {
38 size_t i;
39 for (i = 0; i < n; i++) {
40 if ((s1[i] != s2[i]) || s1[i] == '\0' || s2[i] == '\0') {
41 break;
42 }
43 }
44
45 instrumentUpdateCmpMap(addr, i);
46 if (i == n) {
47 return 0;
48 }
49 return (unsigned char)s1[i] - (unsigned char)s2[i];
50 }
51
HF_strncasecmp(const char * s1,const char * s2,size_t n,uintptr_t addr)52 static inline int HF_strncasecmp(const char* s1, const char* s2, size_t n, uintptr_t addr) {
53 size_t i;
54 for (i = 0; i < n; i++) {
55 if ((tolower((unsigned char)s1[i]) != tolower((unsigned char)s2[i])) || s1[i] == '\0' ||
56 s2[i] == '\0') {
57 break;
58 }
59 }
60
61 instrumentUpdateCmpMap(addr, i);
62 if (i == n) {
63 return 0;
64 }
65 return tolower((unsigned char)s1[i]) - tolower((unsigned char)s2[i]);
66 }
67
HF_strstr(const char * haystack,const char * needle,uintptr_t addr)68 static inline char* HF_strstr(const char* haystack, const char* needle, uintptr_t addr) {
69 size_t needle_len = __builtin_strlen(needle);
70 if (needle_len == 0) {
71 return (char*)haystack;
72 }
73
74 const char* h = haystack;
75 for (; (h = __builtin_strchr(h, needle[0])) != NULL; h++) {
76 if (HF_strncmp(h, needle, needle_len, addr) == 0) {
77 return (char*)h;
78 }
79 }
80 return NULL;
81 }
82
HF_strcasestr(const char * haystack,const char * needle,uintptr_t addr)83 static inline char* HF_strcasestr(const char* haystack, const char* needle, uintptr_t addr) {
84 size_t needle_len = __builtin_strlen(needle);
85 for (size_t i = 0; haystack[i]; i++) {
86 if (HF_strncasecmp(&haystack[i], needle, needle_len, addr) == 0) {
87 return (char*)(&haystack[i]);
88 }
89 }
90 return NULL;
91 }
92
HF_memcmp(const void * m1,const void * m2,size_t n,uintptr_t addr)93 static inline int HF_memcmp(const void* m1, const void* m2, size_t n, uintptr_t addr) {
94 const unsigned char* s1 = (const unsigned char*)m1;
95 const unsigned char* s2 = (const unsigned char*)m2;
96
97 size_t i;
98 for (i = 0; i < n; i++) {
99 if (s1[i] != s2[i]) {
100 break;
101 }
102 }
103
104 instrumentUpdateCmpMap(addr, i);
105 if (i == n) {
106 return 0;
107 }
108 return ((unsigned char)s1[i] - (unsigned char)s2[i]);
109 }
110
HF_memmem(const void * haystack,size_t haystacklen,const void * needle,size_t needlelen,uintptr_t addr)111 static inline void* HF_memmem(const void* haystack, size_t haystacklen, const void* needle,
112 size_t needlelen, uintptr_t addr) {
113 if (needlelen > haystacklen) {
114 return NULL;
115 }
116 if (needlelen == 0) {
117 return (void*)haystack;
118 }
119
120 const char* h = haystack;
121 for (size_t i = 0; i <= (haystacklen - needlelen); i++) {
122 if (HF_memcmp(&h[i], needle, needlelen, addr) == 0) {
123 return (void*)(&h[i]);
124 }
125 }
126 return NULL;
127 }
128
HF_strcpy(char * dest,const char * src,uintptr_t addr)129 static inline char* HF_strcpy(char* dest, const char* src, uintptr_t addr) {
130 size_t len = __builtin_strlen(src);
131 if (len > 0) {
132 uint32_t level = (sizeof(len) * 8) - __builtin_clzl(len);
133 instrumentUpdateCmpMap(addr, level);
134 }
135
136 return __builtin_memcpy(dest, src, len + 1);
137 }
138
139 /* Define a weak function x, as well as __wrap_x pointing to x */
140 #define XVAL(x) x
141 #define HF_WEAK_WRAP(ret, func, ...) \
142 _Pragma(HF__XSTR(weak func = __wrap_##func)) XVAL(ret) XVAL(__wrap_##func)(__VA_ARGS__)
143
144 /* Typical libc wrappers */
HF_WEAK_WRAP(int,strcmp,const char * s1,const char * s2)145 HF_WEAK_WRAP(int, strcmp, const char* s1, const char* s2) {
146 return HF_strcmp(s1, s2, RET_CALL_CHAIN);
147 }
HF_WEAK_WRAP(int,strcasecmp,const char * s1,const char * s2)148 HF_WEAK_WRAP(int, strcasecmp, const char* s1, const char* s2) {
149 return HF_strcasecmp(s1, s2, RET_CALL_CHAIN);
150 }
HF_WEAK_WRAP(int,strncmp,const char * s1,const char * s2,size_t n)151 HF_WEAK_WRAP(int, strncmp, const char* s1, const char* s2, size_t n) {
152 return HF_strncmp(s1, s2, n, RET_CALL_CHAIN);
153 }
HF_WEAK_WRAP(int,strncasecmp,const char * s1,const char * s2,size_t n)154 HF_WEAK_WRAP(int, strncasecmp, const char* s1, const char* s2, size_t n) {
155 return HF_strncasecmp(s1, s2, n, RET_CALL_CHAIN);
156 }
HF_WEAK_WRAP(char *,strstr,const char * haystack,const char * needle)157 HF_WEAK_WRAP(char*, strstr, const char* haystack, const char* needle) {
158 return HF_strstr(haystack, needle, RET_CALL_CHAIN);
159 }
HF_WEAK_WRAP(char *,strcasestr,const char * haystack,const char * needle)160 HF_WEAK_WRAP(char*, strcasestr, const char* haystack, const char* needle) {
161 return HF_strcasestr(haystack, needle, RET_CALL_CHAIN);
162 }
HF_WEAK_WRAP(int,memcmp,const void * m1,const void * m2,size_t n)163 HF_WEAK_WRAP(int, memcmp, const void* m1, const void* m2, size_t n) {
164 return HF_memcmp(m1, m2, n, RET_CALL_CHAIN);
165 }
HF_WEAK_WRAP(int,bcmp,const void * m1,const void * m2,size_t n)166 HF_WEAK_WRAP(int, bcmp, const void* m1, const void* m2, size_t n) {
167 return HF_memcmp(m1, m2, n, RET_CALL_CHAIN);
168 }
HF_WEAK_WRAP(void *,memmem,const void * haystack,size_t haystacklen,const void * needle,size_t needlelen)169 HF_WEAK_WRAP(
170 void*, memmem, const void* haystack, size_t haystacklen, const void* needle, size_t needlelen) {
171 return HF_memmem(haystack, haystacklen, needle, needlelen, RET_CALL_CHAIN);
172 }
HF_WEAK_WRAP(char *,strcpy,char * dest,const char * src)173 HF_WEAK_WRAP(char*, strcpy, char* dest, const char* src) {
174 return HF_strcpy(dest, src, RET_CALL_CHAIN);
175 }
176
177 /*
178 * Apache's httpd wrappers
179 */
HF_WEAK_WRAP(int,ap_cstr_casecmp,const char * s1,const char * s2)180 HF_WEAK_WRAP(int, ap_cstr_casecmp, const char* s1, const char* s2) {
181 return HF_strcasecmp(s1, s2, RET_CALL_CHAIN);
182 }
183
HF_WEAK_WRAP(int,ap_cstr_casecmpn,const char * s1,const char * s2,size_t n)184 HF_WEAK_WRAP(int, ap_cstr_casecmpn, const char* s1, const char* s2, size_t n) {
185 return HF_strncasecmp(s1, s2, n, RET_CALL_CHAIN);
186 }
187
HF_WEAK_WRAP(const char *,ap_strcasestr,const char * s1,const char * s2)188 HF_WEAK_WRAP(const char*, ap_strcasestr, const char* s1, const char* s2) {
189 return HF_strcasestr(s1, s2, RET_CALL_CHAIN);
190 }
191
HF_WEAK_WRAP(int,apr_cstr_casecmp,const char * s1,const char * s2)192 HF_WEAK_WRAP(int, apr_cstr_casecmp, const char* s1, const char* s2) {
193 return HF_strcasecmp(s1, s2, RET_CALL_CHAIN);
194 }
195
HF_WEAK_WRAP(int,apr_cstr_casecmpn,const char * s1,const char * s2,size_t n)196 HF_WEAK_WRAP(int, apr_cstr_casecmpn, const char* s1, const char* s2, size_t n) {
197 return HF_strncasecmp(s1, s2, n, RET_CALL_CHAIN);
198 }
199
200 /*
201 * *SSL wrappers
202 */
HF_WEAK_WRAP(int,CRYPTO_memcmp,const void * m1,const void * m2,size_t len)203 HF_WEAK_WRAP(int, CRYPTO_memcmp, const void* m1, const void* m2, size_t len) {
204 return HF_memcmp(m1, m2, len, RET_CALL_CHAIN);
205 }
206
HF_WEAK_WRAP(int,OPENSSL_memcmp,const void * m1,const void * m2,size_t len)207 HF_WEAK_WRAP(int, OPENSSL_memcmp, const void* m1, const void* m2, size_t len) {
208 return HF_memcmp(m1, m2, len, RET_CALL_CHAIN);
209 }
210
HF_WEAK_WRAP(int,OPENSSL_strcasecmp,const char * s1,const char * s2)211 HF_WEAK_WRAP(int, OPENSSL_strcasecmp, const char* s1, const char* s2) {
212 return HF_strcasecmp(s1, s2, RET_CALL_CHAIN);
213 }
214
HF_WEAK_WRAP(int,OPENSSL_strncasecmp,const char * s1,const char * s2,size_t len)215 HF_WEAK_WRAP(int, OPENSSL_strncasecmp, const char* s1, const char* s2, size_t len) {
216 return HF_strncasecmp(s1, s2, len, RET_CALL_CHAIN);
217 }
218
HF_WEAK_WRAP(int32_t,memcmpct,const void * s1,const void * s2,size_t len)219 HF_WEAK_WRAP(int32_t, memcmpct, const void* s1, const void* s2, size_t len) {
220 return HF_memcmp(s1, s2, len, RET_CALL_CHAIN);
221 }
222
223 /*
224 * libXML wrappers
225 */
HF_WEAK_WRAP(int,xmlStrncmp,const char * s1,const char * s2,int len)226 HF_WEAK_WRAP(int, xmlStrncmp, const char* s1, const char* s2, int len) {
227 if (len <= 0) {
228 return 0;
229 }
230 if (s1 == s2) {
231 return 0;
232 }
233 if (s1 == NULL) {
234 return -1;
235 }
236 if (s2 == NULL) {
237 return 1;
238 }
239 return HF_strncmp(s1, s2, (size_t)len, RET_CALL_CHAIN);
240 }
241
HF_WEAK_WRAP(int,xmlStrcmp,const char * s1,const char * s2)242 HF_WEAK_WRAP(int, xmlStrcmp, const char* s1, const char* s2) {
243 if (s1 == s2) {
244 return 0;
245 }
246 if (s1 == NULL) {
247 return -1;
248 }
249 if (s2 == NULL) {
250 return 1;
251 }
252 return HF_strcmp(s1, s2, RET_CALL_CHAIN);
253 }
254
HF_WEAK_WRAP(int,xmlStrEqual,const char * s1,const char * s2)255 HF_WEAK_WRAP(int, xmlStrEqual, const char* s1, const char* s2) {
256 if (s1 == s2) {
257 return 1;
258 }
259 if (s1 == NULL) {
260 return 0;
261 }
262 if (s2 == NULL) {
263 return 0;
264 }
265 if (HF_strcmp(s1, s2, RET_CALL_CHAIN) == 0) {
266 return 1;
267 }
268 return 0;
269 }
270
HF_WEAK_WRAP(int,xmlStrcasecmp,const char * s1,const char * s2)271 HF_WEAK_WRAP(int, xmlStrcasecmp, const char* s1, const char* s2) {
272 if (s1 == s2) {
273 return 0;
274 }
275 if (s1 == NULL) {
276 return -1;
277 }
278 if (s2 == NULL) {
279 return 1;
280 }
281 return HF_strcasecmp(s1, s2, RET_CALL_CHAIN);
282 }
283
HF_WEAK_WRAP(int,xmlStrncasecmp,const char * s1,const char * s2,int len)284 HF_WEAK_WRAP(int, xmlStrncasecmp, const char* s1, const char* s2, int len) {
285 if (len <= 0) {
286 return 0;
287 }
288 if (s1 == s2) {
289 return 0;
290 }
291 if (s1 == NULL) {
292 return -1;
293 }
294 if (s2 == NULL) {
295 return 1;
296 }
297 return HF_strncasecmp(s1, s2, (size_t)len, RET_CALL_CHAIN);
298 }
299
HF_WEAK_WRAP(const char *,xmlStrstr,const char * haystack,const char * needle)300 HF_WEAK_WRAP(const char*, xmlStrstr, const char* haystack, const char* needle) {
301 if (haystack == NULL) {
302 return NULL;
303 }
304 if (needle == NULL) {
305 return NULL;
306 }
307 return HF_strstr(haystack, needle, RET_CALL_CHAIN);
308 }
309
HF_WEAK_WRAP(const char *,xmlStrcasestr,const char * haystack,const char * needle)310 HF_WEAK_WRAP(const char*, xmlStrcasestr, const char* haystack, const char* needle) {
311 if (haystack == NULL) {
312 return NULL;
313 }
314 if (needle == NULL) {
315 return NULL;
316 }
317 return HF_strcasestr(haystack, needle, RET_CALL_CHAIN);
318 }
319
320 /*
321 * Samba wrappers
322 */
HF_WEAK_WRAP(int,memcmp_const_time,const void * s1,const void * s2,size_t n)323 HF_WEAK_WRAP(int, memcmp_const_time, const void* s1, const void* s2, size_t n) {
324 return HF_memcmp(s1, s2, n, RET_CALL_CHAIN);
325 }
326
HF_WEAK_WRAP(bool,strcsequal,const void * s1,const void * s2)327 HF_WEAK_WRAP(bool, strcsequal, const void* s1, const void* s2) {
328 if (s1 == s2) {
329 return true;
330 }
331 if (!s1 || !s2) {
332 return false;
333 }
334 return (HF_strcmp(s1, s2, RET_CALL_CHAIN) == 0);
335 }
336