fuzz_strops.c 5.9 KB

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