Home | History | Annotate | Download | only in libhfuzz
      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