fuzz_strops.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. /* Copyright (c) 2018-2019, 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. static chunk_t *
  78. b32_dec(const chunk_t *inp)
  79. {
  80. chunk_t *ch = chunk_new(inp->len);//XXXX
  81. int r = base32_decode((char *)ch->buf, ch->len, (char *)inp->buf, inp->len);
  82. if (r >= 0) {
  83. ch->len = r;
  84. } else {
  85. chunk_free(ch);
  86. }
  87. return ch;
  88. }
  89. static chunk_t *
  90. b32_enc(const chunk_t *inp)
  91. {
  92. chunk_t *ch = chunk_new(base32_encoded_size(inp->len));
  93. base32_encode((char *)ch->buf, ch->len, (char*)inp->buf, inp->len);
  94. ch->len = strlen((char *) ch->buf);
  95. return ch;
  96. }
  97. static chunk_t *
  98. b64_dec(const chunk_t *inp)
  99. {
  100. chunk_t *ch = chunk_new(inp->len);//XXXX This could be shorter.
  101. int r = base64_decode((char *)ch->buf, ch->len, (char *)inp->buf, inp->len);
  102. if (r >= 0) {
  103. ch->len = r;
  104. } else {
  105. chunk_free(ch);
  106. }
  107. return ch;
  108. }
  109. static chunk_t *
  110. b64_enc(const chunk_t *inp)
  111. {
  112. chunk_t *ch = chunk_new(BASE64_BUFSIZE(inp->len));
  113. base64_encode((char *)ch->buf, ch->len, (char *)inp->buf, inp->len, 0);
  114. ch->len = strlen((char *) ch->buf);
  115. return ch;
  116. }
  117. static chunk_t *
  118. c_dec(const chunk_t *inp)
  119. {
  120. char *s = tor_memdup_nulterm(inp->buf, inp->len);
  121. chunk_t *ch = tor_malloc(sizeof(chunk_t));
  122. char *r = NULL;
  123. (void) unescape_string(s, &r, &ch->len);
  124. tor_free(s);
  125. ch->buf = (uint8_t*) r;
  126. if (!ch->buf) {
  127. tor_free(ch);
  128. }
  129. return ch;
  130. }
  131. static chunk_t *
  132. c_enc(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. ch->buf = (uint8_t*)esc_for_log(s);
  137. tor_free(s);
  138. ch->len = strlen((char*)ch->buf);
  139. return ch;
  140. }
  141. static int kv_flags = 0;
  142. static config_line_t *
  143. kv_dec(const chunk_t *inp)
  144. {
  145. char *s = tor_memdup_nulterm(inp->buf, inp->len);
  146. config_line_t *res = kvline_parse(s, kv_flags);
  147. tor_free(s);
  148. return res;
  149. }
  150. static chunk_t *
  151. kv_enc(const config_line_t *inp)
  152. {
  153. char *s = kvline_encode(inp, kv_flags);
  154. if (!s)
  155. return NULL;
  156. chunk_t *res = tor_malloc(sizeof(chunk_t));
  157. res->buf = (uint8_t*)s;
  158. res->len = strlen(s);
  159. return res;
  160. }
  161. /* Given an encoder function, a decoder function, and a function to free
  162. * the decoded object, check whether any string that successfully decoded
  163. * will then survive an encode-decode-encode round-trip unchanged.
  164. */
  165. #define ENCODE_ROUNDTRIP(E,D,FREE) \
  166. STMT_BEGIN { \
  167. bool err = false; \
  168. a = D(&inp); \
  169. if (!a) \
  170. return 0; \
  171. b = E(a); \
  172. tor_assert(b); \
  173. c = D(b); \
  174. tor_assert(c); \
  175. d = E(c); \
  176. tor_assert(d); \
  177. if (!chunk_eq(b,d)) { \
  178. printf("Unequal chunks: %s\n", \
  179. hex_str((char*)b->buf, b->len)); \
  180. printf(" vs %s\n", \
  181. hex_str((char*)d->buf, d->len)); \
  182. err = true; \
  183. } \
  184. FREE(a); \
  185. chunk_free(b); \
  186. FREE(c); \
  187. chunk_free(d); \
  188. tor_assert(!err); \
  189. } STMT_END
  190. int
  191. fuzz_main(const uint8_t *stdin_buf, size_t data_size)
  192. {
  193. if (!data_size)
  194. return 0;
  195. chunk_t inp = { (uint8_t*)stdin_buf, data_size };
  196. chunk_t *b=NULL,*d=NULL;
  197. void *a=NULL,*c=NULL;
  198. switch (stdin_buf[0]) {
  199. case 0:
  200. ENCODE_ROUNDTRIP(b16_enc, b16_dec, chunk_free_);
  201. break;
  202. case 1:
  203. ENCODE_ROUNDTRIP(b32_enc, b32_dec, chunk_free_);
  204. break;
  205. case 2:
  206. ENCODE_ROUNDTRIP(b64_enc, b64_dec, chunk_free_);
  207. break;
  208. case 3:
  209. ENCODE_ROUNDTRIP(c_enc, c_dec, chunk_free_);
  210. break;
  211. case 5:
  212. kv_flags = KV_QUOTED|KV_OMIT_KEYS;
  213. ENCODE_ROUNDTRIP(kv_enc, kv_dec, config_free_lines_);
  214. break;
  215. case 6:
  216. kv_flags = 0;
  217. ENCODE_ROUNDTRIP(kv_enc, kv_dec, config_free_lines_);
  218. break;
  219. case 7:
  220. kv_flags = KV_OMIT_VALS;
  221. ENCODE_ROUNDTRIP(kv_enc, kv_dec, config_free_lines_);
  222. break;
  223. case 8:
  224. kv_flags = KV_QUOTED;
  225. ENCODE_ROUNDTRIP(kv_enc, kv_dec, config_free_lines_);
  226. break;
  227. case 9:
  228. kv_flags = KV_QUOTED|KV_OMIT_VALS;
  229. ENCODE_ROUNDTRIP(kv_enc, kv_dec, config_free_lines_);
  230. break;
  231. }
  232. return 0;
  233. }