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