[tor-commits] [tor/master] Add a fuzzer for the http used in our directory protocol

nickm at torproject.org nickm at torproject.org
Mon Jan 30 13:45:47 UTC 2017


commit a967d568dcab10d6b1e03d2ffb96743e415393c0
Author: teor <teor2345 at gmail.com>
Date:   Tue Dec 13 19:16:03 2016 -0500

    Add a fuzzer for the http used in our directory protocol
    
    (Teor wrote the code, nick extracted it.  It won't compile yet.)
---
 src/test/fuzz/fuzz_http.c | 174 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 174 insertions(+)

diff --git a/src/test/fuzz/fuzz_http.c b/src/test/fuzz/fuzz_http.c
new file mode 100644
index 0000000..abf5de8
--- /dev/null
+++ b/src/test/fuzz/fuzz_http.c
@@ -0,0 +1,174 @@
+/* Copyright (c) 2016, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#include "orconfig.h"
+
+#define BUFFERS_PRIVATE
+
+#include "or.h"
+#include "backtrace.h"
+#include "buffers.h"
+#include "config.h"
+#include "connection.h"
+#include "directory.h"
+#include "torlog.h"
+
+/* Silence compiler warnings about a missing extern */
+extern const char tor_git_revision[];
+const char tor_git_revision[] = "";
+
+#define MAX_FUZZ_SIZE (2*MAX_HEADERS_SIZE + MAX_DIR_UL_SIZE)
+
+static int mock_get_options_calls = 0;
+static or_options_t *mock_options = NULL;
+
+static void
+reset_options(or_options_t *options, int *get_options_calls)
+{
+  memset(options, 0, sizeof(or_options_t));
+  options->TestingTorNetwork = 1;
+
+  *get_options_calls = 0;
+}
+
+static const or_options_t*
+mock_get_options(void)
+{
+  ++mock_get_options_calls;
+  tor_assert(mock_options);
+  return mock_options;
+}
+
+static void
+mock_connection_write_to_buf_impl_(const char *string, size_t len,
+                                   connection_t *conn, int zlib)
+{
+  log_debug(LD_GENERAL, "%sResponse:\n%zu\nConnection: %p\n%s\n",
+            zlib ? "Compressed " : "", len, conn, string);
+}
+
+/* Read a directory command (including HTTP headers) from stdin, parse it, and
+ * output what tor parsed */
+int
+main(int c, char** v)
+{
+  /* Disable logging by default to speed up fuzzing. */
+  int loglevel = LOG_ERR;
+
+  /* Initialise logging first */
+  init_logging(1);
+  configure_backtrace_handler(get_version());
+
+  for (int i = 1; i < c; ++i) {
+    if (!strcmp(v[i], "--warn")) {
+      loglevel = LOG_WARN;
+    } else if (!strcmp(v[i], "--notice")) {
+      loglevel = LOG_NOTICE;
+    } else if (!strcmp(v[i], "--info")) {
+      loglevel = LOG_INFO;
+    } else if (!strcmp(v[i], "--debug")) {
+      loglevel = LOG_DEBUG;
+    }
+  }
+
+  {
+    log_severity_list_t s;
+    memset(&s, 0, sizeof(s));
+    set_log_severity_config(loglevel, LOG_ERR, &s);
+    /* ALWAYS log bug warnings. */
+    s.masks[LOG_WARN-LOG_ERR] |= LD_BUG;
+    add_stream_log(&s, "", fileno(stdout));
+  }
+
+  /* Make BUG() and nonfatal asserts crash */
+  tor_set_failed_assertion_callback(abort);
+
+  /* Set up fake variables */
+  dir_connection_t dir_conn;
+  int rv = -1;
+  ssize_t data_size = -1;
+  char *stdin_buf = tor_malloc(MAX_FUZZ_SIZE+1);
+
+  /* directory_handle_command checks some tor options
+   * just make them all 0 */
+  mock_options = tor_malloc(sizeof(or_options_t));
+  reset_options(mock_options, &mock_get_options_calls);
+  MOCK(get_options, mock_get_options);
+
+  /* Set up the fake connection */
+  memset(&dir_conn, 0, sizeof(dir_connection_t));
+  dir_conn.base_.type = CONN_TYPE_DIR;
+
+  /* Set up fake response handler */
+  MOCK(connection_write_to_buf_impl_, mock_connection_write_to_buf_impl_);
+
+/*
+afl extension - loop and reset state after parsing
+likely needs to reset the allocation data structures and counts as well
+#ifdef __AFL_HAVE_MANUAL_CONTROL
+  while (__AFL_LOOP(1000)) {
+#endif
+*/
+
+  /* Initialise the data structures */
+  memset(stdin_buf, 0, MAX_FUZZ_SIZE+1);
+
+  /* Apparently tor sets this before directory_handle_command() is called. */
+  dir_conn.base_.address = tor_strdup("replace-this-address.example.com");
+
+#ifdef __AFL_HAVE_MANUAL_CONTROL
+  /* Tell AFL to pause and fork here - ignored if not using AFL */
+  __AFL_INIT();
+#endif
+
+  /* Read the data */
+  data_size = read(STDIN_FILENO, stdin_buf, MAX_FUZZ_SIZE);
+  tor_assert(data_size != -1);
+  tor_assert(data_size <= MAX_FUZZ_SIZE);
+  stdin_buf[data_size] = '\0';
+  tor_assert(strlen(stdin_buf) >= 0);
+  tor_assert(strlen(stdin_buf) <= MAX_FUZZ_SIZE);
+
+  log_debug(LD_GENERAL, "Input-Length:\n%zu\n", data_size);
+  log_debug(LD_GENERAL, "Input:\n%s\n", stdin_buf);
+
+  /* Copy the stdin data into the buffer */
+  tor_assert(data_size >= 0);
+  dir_conn.base_.inbuf = buf_new_with_data(stdin_buf, (size_t)data_size);
+  if (!dir_conn.base_.inbuf) {
+    log_debug(LD_GENERAL, "Zero-Length-Input\n");
+    return 0;
+  }
+
+  /* Parse the headers */
+  rv = directory_handle_command(&dir_conn);
+
+  /* TODO: check the output is correctly parsed based on the input */
+
+  /* Report the parsed origin address */
+  if (dir_conn.base_.address) {
+    log_debug(LD_GENERAL, "Address:\n%s\n", dir_conn.base_.address);
+  }
+
+  log_debug(LD_GENERAL, "Result:\n%d\n", rv);
+
+  /* Reset */
+  tor_free(dir_conn.base_.address);
+
+  buf_free(dir_conn.base_.inbuf);
+  dir_conn.base_.inbuf = NULL;
+
+/*
+#ifdef __AFL_HAVE_MANUAL_CONTROL
+  }
+#endif
+*/
+
+  /* Cleanup */
+  tor_free(mock_options);
+  UNMOCK(get_options);
+
+  UNMOCK(connection_write_to_buf_impl_);
+
+  tor_free(stdin_buf);
+}





More information about the tor-commits mailing list