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 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 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 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 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 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 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 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 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 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 */ 143 HF_WEAK_WRAP(int, strcmp, const char* s1, const char* s2) { 144 return HF_strcmp(s1, s2, RET_CALL_CHAIN); 145 } 146 HF_WEAK_WRAP(int, strcasecmp, const char* s1, const char* s2) { 147 return HF_strcasecmp(s1, s2, RET_CALL_CHAIN); 148 } 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 } 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 } 155 HF_WEAK_WRAP(char*, strstr, const char* haystack, const char* needle) { 156 return HF_strstr(haystack, needle, RET_CALL_CHAIN); 157 } 158 HF_WEAK_WRAP(char*, strcasestr, const char* haystack, const char* needle) { 159 return HF_strcasestr(haystack, needle, RET_CALL_CHAIN); 160 } 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 } 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 } 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 } 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 */ 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 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 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 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 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 */ 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 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 209 HF_WEAK_WRAP(int, OPENSSL_strcasecmp, const char* s1, const char* s2) { 210 return HF_strcasecmp(s1, s2, RET_CALL_CHAIN); 211 } 212 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 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 */ 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 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 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 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 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 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 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 */ 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 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