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 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 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 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 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 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 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 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 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 */ 167 HF_WEAK_WRAP(int, strcmp, const char* s1, const char* s2) { 168 return _strcmp(s1, s2, RET_CALL_CHAIN); 169 } 170 HF_WEAK_WRAP(int, strcasecmp, const char* s1, const char* s2) { 171 return _strcasecmp(s1, s2, RET_CALL_CHAIN); 172 } 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 } 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 } 179 HF_WEAK_WRAP(char*, strstr, const char* haystack, const char* needle) { 180 return _strstr(haystack, needle, RET_CALL_CHAIN); 181 } 182 HF_WEAK_WRAP(char*, strcasestr, const char* haystack, const char* needle) { 183 return _strcasestr(haystack, needle, RET_CALL_CHAIN); 184 } 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 } 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 } 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 */ 199 HF_WEAK_WRAP(int, ap_cstr_casecmp, const char* s1, const char* s2) { 200 return _strcasecmp(s1, s2, RET_CALL_CHAIN); 201 } 202 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 207 HF_WEAK_WRAP(const char*, ap_strcasestr, const char* s1, const char* s2) { 208 return _strcasestr(s1, s2, RET_CALL_CHAIN); 209 } 210 211 HF_WEAK_WRAP(int, apr_cstr_casecmp, const char* s1, const char* s2) { 212 return _strcasecmp(s1, s2, RET_CALL_CHAIN); 213 } 214 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 */ 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 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 230 HF_WEAK_WRAP(int, OPENSSL_strcasecmp, const char* s1, const char* s2) { 231 return _strcasecmp(s1, s2, RET_CALL_CHAIN); 232 } 233 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 */ 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 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 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 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 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 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 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