|  | @@ -4,6 +4,7 @@
 | 
	
		
			
				|  |  |  #include "orconfig.h"
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  #define BUFFERS_PRIVATE
 | 
	
		
			
				|  |  | +#define DIRECTORY_PRIVATE
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  #include "or.h"
 | 
	
		
			
				|  |  |  #include "backtrace.h"
 | 
	
	
		
			
				|  | @@ -13,11 +14,7 @@
 | 
	
		
			
				|  |  |  #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)
 | 
	
		
			
				|  |  | +#include "fuzzing.h"
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static int mock_get_options_calls = 0;
 | 
	
		
			
				|  |  |  static or_options_t *mock_options = NULL;
 | 
	
	
		
			
				|  | @@ -47,101 +44,45 @@ mock_connection_write_to_buf_impl_(const char *string, size_t len,
 | 
	
		
			
				|  |  |              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)
 | 
	
		
			
				|  |  | +fuzz_init(void)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  | -  /* 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_);
 | 
	
		
			
				|  |  | +  return 0;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -/*
 | 
	
		
			
				|  |  | -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
 | 
	
		
			
				|  |  | -*/
 | 
	
		
			
				|  |  | +int
 | 
	
		
			
				|  |  | +fuzz_cleanup(void)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +  tor_free(mock_options);
 | 
	
		
			
				|  |  | +  UNMOCK(get_options);
 | 
	
		
			
				|  |  | +  UNMOCK(connection_write_to_buf_impl_);
 | 
	
		
			
				|  |  | +  return 0;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  /* Initialise the data structures */
 | 
	
		
			
				|  |  | -  memset(stdin_buf, 0, MAX_FUZZ_SIZE+1);
 | 
	
		
			
				|  |  | +int
 | 
	
		
			
				|  |  | +fuzz_main(const uint8_t *stdin_buf, size_t data_size)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +  dir_connection_t dir_conn;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +  /* Set up the fake connection */
 | 
	
		
			
				|  |  | +  memset(&dir_conn, 0, sizeof(dir_connection_t));
 | 
	
		
			
				|  |  | +  dir_conn.base_.type = CONN_TYPE_DIR;
 | 
	
		
			
				|  |  |    /* 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);
 | 
	
		
			
				|  |  | +  dir_conn.base_.inbuf = buf_new_with_data((char*)stdin_buf, 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);
 | 
	
		
			
				|  |  | +  int rv = directory_handle_command(&dir_conn);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    /* TODO: check the output is correctly parsed based on the input */
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -152,23 +93,10 @@ likely needs to reset the allocation data structures and counts as well
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    log_debug(LD_GENERAL, "Result:\n%d\n", rv);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  /* Reset */
 | 
	
		
			
				|  |  | +  /* 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);
 | 
	
		
			
				|  |  | +  return 0;
 | 
	
		
			
				|  |  |  }
 |