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