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