fuzz_http.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. /* Copyright (c) 2016, The Tor Project, Inc. */
  2. /* See LICENSE for licensing information */
  3. #include "orconfig.h"
  4. #define BUFFERS_PRIVATE
  5. #include "or.h"
  6. #include "backtrace.h"
  7. #include "buffers.h"
  8. #include "config.h"
  9. #include "connection.h"
  10. #include "directory.h"
  11. #include "torlog.h"
  12. /* Silence compiler warnings about a missing extern */
  13. extern const char tor_git_revision[];
  14. const char tor_git_revision[] = "";
  15. #define MAX_FUZZ_SIZE (2*MAX_HEADERS_SIZE + MAX_DIR_UL_SIZE)
  16. static int mock_get_options_calls = 0;
  17. static or_options_t *mock_options = NULL;
  18. static void
  19. reset_options(or_options_t *options, int *get_options_calls)
  20. {
  21. memset(options, 0, sizeof(or_options_t));
  22. options->TestingTorNetwork = 1;
  23. *get_options_calls = 0;
  24. }
  25. static const or_options_t*
  26. mock_get_options(void)
  27. {
  28. ++mock_get_options_calls;
  29. tor_assert(mock_options);
  30. return mock_options;
  31. }
  32. static void
  33. mock_connection_write_to_buf_impl_(const char *string, size_t len,
  34. connection_t *conn, int zlib)
  35. {
  36. log_debug(LD_GENERAL, "%sResponse:\n%zu\nConnection: %p\n%s\n",
  37. zlib ? "Compressed " : "", len, conn, string);
  38. }
  39. /* Read a directory command (including HTTP headers) from stdin, parse it, and
  40. * output what tor parsed */
  41. int
  42. main(int c, char** v)
  43. {
  44. /* Disable logging by default to speed up fuzzing. */
  45. int loglevel = LOG_ERR;
  46. /* Initialise logging first */
  47. init_logging(1);
  48. configure_backtrace_handler(get_version());
  49. for (int i = 1; i < c; ++i) {
  50. if (!strcmp(v[i], "--warn")) {
  51. loglevel = LOG_WARN;
  52. } else if (!strcmp(v[i], "--notice")) {
  53. loglevel = LOG_NOTICE;
  54. } else if (!strcmp(v[i], "--info")) {
  55. loglevel = LOG_INFO;
  56. } else if (!strcmp(v[i], "--debug")) {
  57. loglevel = LOG_DEBUG;
  58. }
  59. }
  60. {
  61. log_severity_list_t s;
  62. memset(&s, 0, sizeof(s));
  63. set_log_severity_config(loglevel, LOG_ERR, &s);
  64. /* ALWAYS log bug warnings. */
  65. s.masks[LOG_WARN-LOG_ERR] |= LD_BUG;
  66. add_stream_log(&s, "", fileno(stdout));
  67. }
  68. /* Make BUG() and nonfatal asserts crash */
  69. tor_set_failed_assertion_callback(abort);
  70. /* Set up fake variables */
  71. dir_connection_t dir_conn;
  72. int rv = -1;
  73. ssize_t data_size = -1;
  74. char *stdin_buf = tor_malloc(MAX_FUZZ_SIZE+1);
  75. /* directory_handle_command checks some tor options
  76. * just make them all 0 */
  77. mock_options = tor_malloc(sizeof(or_options_t));
  78. reset_options(mock_options, &mock_get_options_calls);
  79. MOCK(get_options, mock_get_options);
  80. /* Set up the fake connection */
  81. memset(&dir_conn, 0, sizeof(dir_connection_t));
  82. dir_conn.base_.type = CONN_TYPE_DIR;
  83. /* Set up fake response handler */
  84. MOCK(connection_write_to_buf_impl_, mock_connection_write_to_buf_impl_);
  85. /*
  86. afl extension - loop and reset state after parsing
  87. likely needs to reset the allocation data structures and counts as well
  88. #ifdef __AFL_HAVE_MANUAL_CONTROL
  89. while (__AFL_LOOP(1000)) {
  90. #endif
  91. */
  92. /* Initialise the data structures */
  93. memset(stdin_buf, 0, MAX_FUZZ_SIZE+1);
  94. /* Apparently tor sets this before directory_handle_command() is called. */
  95. dir_conn.base_.address = tor_strdup("replace-this-address.example.com");
  96. #ifdef __AFL_HAVE_MANUAL_CONTROL
  97. /* Tell AFL to pause and fork here - ignored if not using AFL */
  98. __AFL_INIT();
  99. #endif
  100. /* Read the data */
  101. data_size = read(STDIN_FILENO, stdin_buf, MAX_FUZZ_SIZE);
  102. tor_assert(data_size != -1);
  103. tor_assert(data_size <= MAX_FUZZ_SIZE);
  104. stdin_buf[data_size] = '\0';
  105. tor_assert(strlen(stdin_buf) >= 0);
  106. tor_assert(strlen(stdin_buf) <= MAX_FUZZ_SIZE);
  107. log_debug(LD_GENERAL, "Input-Length:\n%zu\n", data_size);
  108. log_debug(LD_GENERAL, "Input:\n%s\n", stdin_buf);
  109. /* Copy the stdin data into the buffer */
  110. tor_assert(data_size >= 0);
  111. dir_conn.base_.inbuf = buf_new_with_data(stdin_buf, (size_t)data_size);
  112. if (!dir_conn.base_.inbuf) {
  113. log_debug(LD_GENERAL, "Zero-Length-Input\n");
  114. return 0;
  115. }
  116. /* Parse the headers */
  117. rv = directory_handle_command(&dir_conn);
  118. /* TODO: check the output is correctly parsed based on the input */
  119. /* Report the parsed origin address */
  120. if (dir_conn.base_.address) {
  121. log_debug(LD_GENERAL, "Address:\n%s\n", dir_conn.base_.address);
  122. }
  123. log_debug(LD_GENERAL, "Result:\n%d\n", rv);
  124. /* Reset */
  125. tor_free(dir_conn.base_.address);
  126. buf_free(dir_conn.base_.inbuf);
  127. dir_conn.base_.inbuf = NULL;
  128. /*
  129. #ifdef __AFL_HAVE_MANUAL_CONTROL
  130. }
  131. #endif
  132. */
  133. /* Cleanup */
  134. tor_free(mock_options);
  135. UNMOCK(get_options);
  136. UNMOCK(connection_write_to_buf_impl_);
  137. tor_free(stdin_buf);
  138. }