• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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