tor

The Tor anonymity network
git clone https://git.dasho.dev/tor.git
Log | Files | Refs | README | LICENSE

fuzz_strops.c (6211B)


      1 /* Copyright (c) 2018-2021, The Tor Project, Inc. */
      2 /* See LICENSE for licensing information */
      3 
      4 /**
      5 * \file fuzz_strops.c
      6 * \brief Fuzzers for various string encoding/decoding operations
      7 **/
      8 
      9 #include "orconfig.h"
     10 
     11 #include "lib/cc/torint.h"
     12 #include "lib/ctime/di_ops.h"
     13 #include "lib/encoding/binascii.h"
     14 #include "lib/encoding/cstring.h"
     15 #include "lib/encoding/kvline.h"
     16 #include "lib/encoding/confline.h"
     17 #include "lib/malloc/malloc.h"
     18 #include "lib/log/escape.h"
     19 #include "lib/log/util_bug.h"
     20 #include "lib/intmath/muldiv.h"
     21 
     22 #include "test/fuzz/fuzzing.h"
     23 
     24 #include <stdio.h>
     25 #include <string.h>
     26 
     27 int
     28 fuzz_init(void)
     29 {
     30  return 0;
     31 }
     32 
     33 int
     34 fuzz_cleanup(void)
     35 {
     36  return 0;
     37 }
     38 
     39 typedef struct chunk_t {
     40  uint8_t *buf;
     41  size_t len;
     42 } chunk_t;
     43 
     44 #define chunk_free(ch)                          \
     45  FREE_AND_NULL(chunk_t, chunk_free_, (ch))
     46 
     47 static chunk_t *
     48 chunk_new(size_t len)
     49 {
     50  chunk_t *ch = tor_malloc(sizeof(chunk_t));
     51  ch->buf = tor_malloc(len);
     52  ch->len = len;
     53  return ch;
     54 }
     55 static void
     56 chunk_free_(chunk_t *ch)
     57 {
     58  if (!ch)
     59    return;
     60  tor_free(ch->buf);
     61  tor_free(ch);
     62 }
     63 static bool
     64 chunk_eq(const chunk_t *a, const chunk_t *b)
     65 {
     66  return a->len == b->len && fast_memeq(a->buf, b->buf, a->len);
     67 }
     68 
     69 static chunk_t *
     70 b16_dec(const chunk_t *inp)
     71 {
     72  chunk_t *ch = chunk_new(CEIL_DIV(inp->len, 2));
     73  int r = base16_decode((char *)ch->buf, ch->len, (char *)inp->buf, inp->len);
     74  if (r >= 0) {
     75    ch->len = r;
     76  } else {
     77    chunk_free(ch);
     78  }
     79  return ch;
     80 }
     81 static chunk_t *
     82 b16_enc(const chunk_t *inp)
     83 {
     84  chunk_t *ch = chunk_new(inp->len * 2 + 1);
     85  base16_encode((char *)ch->buf, ch->len, (char*)inp->buf, inp->len);
     86  return ch;
     87 }
     88 
     89 static chunk_t *
     90 b32_dec(const chunk_t *inp)
     91 {
     92  chunk_t *ch = chunk_new(inp->len);//XXXX
     93  int r = base32_decode((char *)ch->buf, ch->len, (char *)inp->buf, inp->len);
     94  if (r >= 0) {
     95    ch->len = r;
     96  } else {
     97    chunk_free(ch);
     98  }
     99  return ch;
    100 }
    101 static chunk_t *
    102 b32_enc(const chunk_t *inp)
    103 {
    104  chunk_t *ch = chunk_new(base32_encoded_size(inp->len));
    105  base32_encode((char *)ch->buf, ch->len, (char*)inp->buf, inp->len);
    106  ch->len = strlen((char *) ch->buf);
    107  return ch;
    108 }
    109 
    110 static chunk_t *
    111 b64_dec(const chunk_t *inp)
    112 {
    113  chunk_t *ch = chunk_new(inp->len);//XXXX This could be shorter.
    114  int r = base64_decode((char *)ch->buf, ch->len, (char *)inp->buf, inp->len);
    115  if (r >= 0) {
    116    ch->len = r;
    117  } else {
    118    chunk_free(ch);
    119  }
    120  return ch;
    121 }
    122 static chunk_t *
    123 b64_enc(const chunk_t *inp)
    124 {
    125  chunk_t *ch = chunk_new(BASE64_BUFSIZE(inp->len));
    126  base64_encode((char *)ch->buf, ch->len, (char *)inp->buf, inp->len, 0);
    127  ch->len = strlen((char *) ch->buf);
    128  return ch;
    129 }
    130 
    131 static chunk_t *
    132 c_dec(const chunk_t *inp)
    133 {
    134  char *s = tor_memdup_nulterm(inp->buf, inp->len);
    135  chunk_t *ch = tor_malloc(sizeof(chunk_t));
    136  char *r = NULL;
    137  (void) unescape_string(s, &r, &ch->len);
    138  tor_free(s);
    139  ch->buf = (uint8_t*) r;
    140  if (!ch->buf) {
    141    tor_free(ch);
    142  }
    143  return ch;
    144 }
    145 static chunk_t *
    146 c_enc(const chunk_t *inp)
    147 {
    148  char *s = tor_memdup_nulterm(inp->buf, inp->len);
    149  chunk_t *ch = tor_malloc(sizeof(chunk_t));
    150  ch->buf = (uint8_t*)esc_for_log(s);
    151  tor_free(s);
    152  ch->len = strlen((char*)ch->buf);
    153  return ch;
    154 }
    155 
    156 static int kv_flags = 0;
    157 static config_line_t *
    158 kv_dec(const chunk_t *inp)
    159 {
    160  char *s = tor_memdup_nulterm(inp->buf, inp->len);
    161  config_line_t *res = kvline_parse(s, kv_flags);
    162  tor_free(s);
    163  return res;
    164 }
    165 static chunk_t *
    166 kv_enc(const config_line_t *inp)
    167 {
    168  char *s = kvline_encode(inp, kv_flags);
    169  if (!s)
    170    return NULL;
    171  chunk_t *res = tor_malloc(sizeof(chunk_t));
    172  res->buf = (uint8_t*)s;
    173  res->len = strlen(s);
    174  return res;
    175 }
    176 
    177 /* Given an encoder function, a decoder function, and a function to free
    178 * the decoded object, check whether any string that successfully decoded
    179 * will then survive an encode-decode-encode round-trip unchanged.
    180 */
    181 #define ENCODE_ROUNDTRIP(E,D,FREE)              \
    182  STMT_BEGIN {                                  \
    183    bool err = false;                           \
    184    a = D(&inp);                                \
    185    if (!a)                                     \
    186      return 0;                                 \
    187    b = E(a);                                   \
    188    tor_assert(b);                              \
    189    c = D(b);                                   \
    190    tor_assert(c);                              \
    191    d = E(c);                                   \
    192    tor_assert(d);                              \
    193    if (!chunk_eq(b,d)) {                       \
    194      printf("Unequal chunks: %s\n",            \
    195             hex_str((char*)b->buf, b->len));   \
    196      printf("             vs %s\n",            \
    197             hex_str((char*)d->buf, d->len));   \
    198      err = true;                               \
    199    }                                           \
    200    FREE(a);                                    \
    201    chunk_free(b);                              \
    202    FREE(c);                                    \
    203    chunk_free(d);                              \
    204    tor_assert(!err);                           \
    205  } STMT_END
    206 
    207 int
    208 fuzz_main(const uint8_t *stdin_buf, size_t data_size)
    209 {
    210  if (!data_size)
    211    return 0;
    212 
    213  chunk_t inp = { (uint8_t*)stdin_buf, data_size };
    214  chunk_t *b=NULL,*d=NULL;
    215  void *a=NULL,*c=NULL;
    216 
    217  switch (stdin_buf[0]) {
    218    case 0:
    219      ENCODE_ROUNDTRIP(b16_enc, b16_dec, chunk_free_);
    220      break;
    221    case 1:
    222      ENCODE_ROUNDTRIP(b32_enc, b32_dec, chunk_free_);
    223      break;
    224    case 2:
    225      ENCODE_ROUNDTRIP(b64_enc, b64_dec, chunk_free_);
    226      break;
    227    case 3:
    228      ENCODE_ROUNDTRIP(c_enc, c_dec, chunk_free_);
    229      break;
    230    case 5:
    231      kv_flags = KV_QUOTED|KV_OMIT_KEYS;
    232      ENCODE_ROUNDTRIP(kv_enc, kv_dec, config_free_lines_);
    233      break;
    234    case 6:
    235      kv_flags = 0;
    236      ENCODE_ROUNDTRIP(kv_enc, kv_dec, config_free_lines_);
    237      break;
    238    case 7:
    239      kv_flags = KV_OMIT_VALS;
    240      ENCODE_ROUNDTRIP(kv_enc, kv_dec, config_free_lines_);
    241      break;
    242    case 8:
    243      kv_flags = KV_QUOTED;
    244      ENCODE_ROUNDTRIP(kv_enc, kv_dec, config_free_lines_);
    245      break;
    246    case 9:
    247      kv_flags = KV_QUOTED|KV_OMIT_VALS;
    248      ENCODE_ROUNDTRIP(kv_enc, kv_dec, config_free_lines_);
    249      break;
    250    }
    251 
    252  return 0;
    253 }