diff --git a/ChangeLog b/ChangeLog
index 44af8ec5de6169476025c47aa1c23b42ad4fa6d6..ce1773e0b8dfc53803adde8d1c107b0e8d69020b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+Changes in version 0.2.2.8-alpha - 2010-01-26
+  o Major bugfixes:
+    - Fix a memory corruption bug on bridges that occured during the
+      inclusion of stats data in extra-info descriptors. Also fix the
+      interface for geoip_get_bridge_stats* to prevent similar bugs in
+      the future. Diagnosis by Tas, patch by Karsten and Sebastian.
+      Fixes bug 1208; bugfix on 0.2.2.7-alpha.
+
+  o Minor bugfixes:
+    - Ignore OutboundBindAddress when connecting to localhost.
+      Connections to localhost need to come _from_ localhost, or else
+      local servers (like DNS and outgoing HTTP/SOCKS proxies) will often
+      refuse to listen.
+
+
 Changes in version 0.2.1.23 - 2010-0?-??
   o Major bugfixes (performance):
     - We were selecting our guards uniformly at random, and then weighting
@@ -17,6 +32,18 @@ Changes in version 0.2.1.23 - 2010-0?-??
 
 
 Changes in version 0.2.2.7-alpha - 2010-01-19
+  Tor 0.2.2.7-alpha fixes a huge client-side performance bug, as well
+  as laying the groundwork for further relay-side performance fixes. It
+  also starts cleaning up client behavior with respect to the EntryNodes,
+  ExitNodes, and StrictNodes config options.
+
+  This release also rotates two directory authority keys, due to a
+  security breach of some of the Torproject servers.
+
+  o Directory authority changes:
+    - Rotate keys (both v3 identity and relay identity) for moria1
+      and gabelmoo.
+
   o Major features (performance):
     - We were selecting our guards uniformly at random, and then weighting
       which of our guards we'd use uniformly at random. This imbalance
@@ -62,6 +89,11 @@ Changes in version 0.2.2.7-alpha - 2010-01-19
       fetch -- rather than just at startup and then they slowly rot as
       the network changes.
 
+  o Major bugfixes:
+    - Stop bridge directory authorities from answering dbg-stability.txt
+      directory queries, which would let people fetch a list of all
+      bridge identities they track. Bugfix on 0.2.1.6-alpha.
+
   o Minor features:
     - Log a notice when we get a new control connection. Now it's easier
       for security-conscious users to recognize when a local application
diff --git a/acinclude.m4 b/acinclude.m4
index 766ca1e62e3135521ad38cc194063de0d74b7ba4..3db25aa59a3a76e243bfaded0772170b28f6c3dd 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -26,8 +26,10 @@ AC_DEFUN([TOR_DEFINE_CODEPATH],
   else
    if test -d "$1/lib"; then
      TOR_LDFLAGS_$2="-L$1/lib"
+     TOR_LIBDIR_$2="$1/lib"
    else
      TOR_LDFLAGS_$2="-L$1"
+     TOR_LIBDIR_$2="$1"
    fi
    if test -d "$1/include"; then
      TOR_CPPFLAGS_$2="-I$1/include"
diff --git a/configure.in b/configure.in
index a8890ff04914dc79d7df39932bd381ba685ea184..9a965031433b0b6346cfb256b2cba22076ca3fb8 100644
--- a/configure.in
+++ b/configure.in
@@ -4,7 +4,7 @@ dnl Copyright (c) 2007-2008, The Tor Project, Inc.
 dnl See LICENSE for licensing information
 
 AC_INIT
-AM_INIT_AUTOMAKE(tor, 0.2.2.7-alpha)
+AM_INIT_AUTOMAKE(tor, 0.2.2.8-alpha)
 AM_CONFIG_HEADER(orconfig.h)
 
 AC_CANONICAL_HOST
@@ -41,6 +41,10 @@ AC_ARG_ENABLE(openbsd-malloc,
    AS_HELP_STRING(--enable-openbsd-malloc, Use malloc code from openbsd.  Linux only))
 AC_ARG_ENABLE(instrument-downloads,
    AS_HELP_STRING(--enable-instrument-downloads, Instrument downloads of directory resources etc.))
+AC_ARG_ENABLE(static-openssl,
+   AS_HELP_STRING(--enable-static-openssl, Link against a static openssl library. Requires --with-openssl-dir))
+AC_ARG_ENABLE(static-libevent,
+   AS_HELP_STRING(--enable-static-libevent, Link against a static libevent library. Requires --with-libevent-dir))
 
 if test x$enable_buf_freelists != xno; then
   AC_DEFINE(ENABLE_BUF_FREELISTS, 1,
@@ -87,6 +91,8 @@ esac
 
 AC_ARG_ENABLE(gcc-warnings,
      AS_HELP_STRING(--enable-gcc-warnings, enable verbose warnings))
+AC_ARG_ENABLE(gcc-warnings-advisory,
+     AS_HELP_STRING(--enable-gcc-warnings-advisory, [enable verbose warnings, excluding -Werror]))
 
 AC_ARG_ENABLE(local-appdata,
    AS_HELP_STRING(--enable-local-appdata, default to host local application data paths on Windows))
@@ -279,8 +285,21 @@ LIBS="$save_LIBS"
 LDFLAGS="$save_LDFLAGS"
 CPPFLAGS="$save_CPPFLAGS"
 
+
 AM_CONDITIONAL(USE_EXTERNAL_EVDNS, test x$ac_cv_header_event2_dns_h = xyes)
 
+if test "$enable_static_libevent" = "yes"; then
+   if test "$tor_cv_library_libevent_dir" = "(system)"; then
+     AC_MSG_ERROR("You must specify an explicit --with-libevent-dir=x option when using --enable-static-libevent")
+   else
+     TOR_LIBEVENT_LIBS="$TOR_LIBDIR_libevent/libevent.a"
+   fi
+else
+     TOR_LIBEVENT_LIBS="-levent"
+fi
+AC_SUBST(TOR_LIBEVENT_LIBS)
+
+
 dnl ------------------------------------------------------
 dnl Where do you live, openssl?  And how do we call you?
 
@@ -306,6 +325,19 @@ TOR_SEARCH_LIBRARY(openssl, $tryssldir, [-lssl -lcrypto $TOR_LIB_GDI],
 
 dnl XXXX check for OPENSSL_VERSION_NUMBER == SSLeay()
 
+echo "tor_cv_library_openssl_dir is $tor_cv_library_openssl_dir"
+if test "$enable_static_openssl" = "yes"; then
+   if test "$tor_cv_library_openssl_dir" = "(system)"; then
+     AC_MSG_ERROR("You must specify an explicit --with-openssl-dir=x option when using --enable-static-openssl")
+   else
+     TOR_OPENSSL_LIBS="$TOR_LIBDIR_openssl/libcrypto.a $TOR_LIBDIR_openssl/libssl.a"
+   fi
+else
+     TOR_OPENSSL_LIBS="-lcrypto -lssl"
+fi
+echo "TOR_OPENSSL_LIBS=$TOR_OPENSSL_LIBS"
+AC_SUBST(TOR_OPENSSL_LIBS)
+
 dnl ------------------------------------------------------
 dnl Where do you live, zlib?  And how do we call you?
 
@@ -774,11 +806,12 @@ if test "$GCC" = yes; then
 else
   CFLAGS="$CFLAGS -g -O"
   enable_gcc_warnings=no
+  enable_gcc_warnings_advisory=no
 fi
 
 # Add some more warnings which we use in development but not in the
 # released versions.  (Some relevant gcc versions can't handle these.)
-if test x$enable_gcc_warnings = xyes; then
+if test x$enable_gcc_warnings = xyes || test x$enable_gcc_warnings_advisory = xyes; then
 
   AC_COMPILE_IFELSE(AC_LANG_PROGRAM([], [
 #if !defined(__GNUC__) || (__GNUC__ < 4)
@@ -801,7 +834,10 @@ if test x$enable_gcc_warnings = xyes; then
                     have_shorten64_flag=no)
   CFLAGS="$save_CFLAGS"
 
-  CFLAGS="$CFLAGS -W -Wfloat-equal -Wundef -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes -Wwrite-strings -Wredundant-decls -Wchar-subscripts -Wcomment -Wformat=2 -Wwrite-strings -Wmissing-declarations -Wredundant-decls -Wnested-externs -Wbad-function-cast -Wswitch-enum -Werror"
+  CFLAGS="$CFLAGS -W -Wfloat-equal -Wundef -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes -Wwrite-strings -Wredundant-decls -Wchar-subscripts -Wcomment -Wformat=2 -Wwrite-strings -Wmissing-declarations -Wredundant-decls -Wnested-externs -Wbad-function-cast -Wswitch-enum"
+  if test x$enable_gcc_warnings = xyes; then
+    CFLAGS="$CFLAGS -Werror"
+  fi
 
   # Disabled, so we can use mallinfo(): -Waggregate-return
 
diff --git a/contrib/tor-mingw.nsi.in b/contrib/tor-mingw.nsi.in
index 83bcf50b88f9a7b1abf38faa8626d880c6406598..71caa78b786c83ec1676d6d388722038f3159220 100644
--- a/contrib/tor-mingw.nsi.in
+++ b/contrib/tor-mingw.nsi.in
@@ -8,7 +8,7 @@
 !include "LogicLib.nsh"
 !include "FileFunc.nsh"
 !insertmacro GetParameters
-!define VERSION "0.2.2.7-alpha"
+!define VERSION "0.2.2.8-alpha"
 !define INSTALLER "tor-${VERSION}-win32.exe"
 !define WEBSITE "https://www.torproject.org/"
 !define LICENSE "LICENSE"
diff --git a/debian/changelog b/debian/changelog
index 6e75116ff0879ef418a2bdd98d0291e160c043f4..4a378ac47f07ae1a28bb8d2814bc2f6b4c67d3a9 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+tor (0.2.2.8-alpha-1) experimental; urgency=low
+
+  * New upstream version.
+
+ -- Peter Palfrader <weasel@debian.org>  Fri, 29 Jan 2010 23:22:35 +0100
+
 tor (0.2.2.7-alpha-2) experimental; urgency=low
 
   * debian/rules: Minor cleanup (use a single variable for making up our
diff --git a/src/common/log.c b/src/common/log.c
index ef65be8a3d4fb90840b80eaeeea5a18dd2a11108..dfea58f47cef225e380fa6bb1865b928bfeb8433 100644
--- a/src/common/log.c
+++ b/src/common/log.c
@@ -678,13 +678,11 @@ add_file_log(const log_severity_list_t *severity, const char *filename)
   logfiles->needs_close = 1;
   lf = logfiles;
   _log_global_min_severity = get_min_log_level();
-  UNLOCK_LOGS();
 
   if (log_tor_version(lf, 0) < 0) {
-    LOCK_LOGS();
     delete_log(lf);
-    UNLOCK_LOGS();
   }
+  UNLOCK_LOGS();
 
   return 0;
 }
diff --git a/src/common/tortls.c b/src/common/tortls.c
index 86f07a270a71d93dfa9aa44b4ae22eb29a8fdfc2..4bb2291b1f3f52dea41f9192067b7b7fc98f05d8 100644
--- a/src/common/tortls.c
+++ b/src/common/tortls.c
@@ -201,6 +201,8 @@ tls_log_errors(tor_tls_t *tls, int severity, int domain, const char *doing)
     if (!state)
       state = (st>=0)?ssl_state_to_string(st):"---";
     if (!msg) msg = "(null)";
+    if (!lib) lib = "(null)";
+    if (!func) func = "(null)";
     if (doing) {
       log(severity, domain, "TLS error while %s%s%s: %s (in %s:%s:%s)",
           doing, addr?" with ":"", addr?addr:"",
diff --git a/src/or/Makefile.am b/src/or/Makefile.am
index 3dc1889a903654d4ab2a14245f3f5ba5b7a5693b..cfa8a035ad9ee6fd6f0cf926658bd4a91940210d 100644
--- a/src/or/Makefile.am
+++ b/src/or/Makefile.am
@@ -43,7 +43,7 @@ AM_CPPFLAGS = -DSHARE_DATADIR="\"$(datadir)\"" \
 tor_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ @TOR_LDFLAGS_libevent@
 tor_LDADD = ./libtor.a ../common/libor.a ../common/libor-crypto.a \
 	../common/libor-event.a \
-	-lz -lm -levent -lssl -lcrypto @TOR_LIB_WS32@ @TOR_LIB_GDI@
+	-lz -lm @TOR_LIBEVENT_LIBS@ @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@
 
 noinst_HEADERS = or.h eventdns.h eventdns_tor.h micro-revision.i
 
diff --git a/src/or/connection.c b/src/or/connection.c
index 6506cf81fd68fc6dc3138d3d1a2b85b1b139d2dd..eeb25c1828c24977bdf0581d5b1e75c837754fc8 100644
--- a/src/or/connection.c
+++ b/src/or/connection.c
@@ -1236,7 +1236,7 @@ connection_connect(connection_t *conn, const char *address,
     return -1;
   }
 
-  if (options->OutboundBindAddress) {
+  if (options->OutboundBindAddress && !tor_addr_is_loopback(addr)) {
     struct sockaddr_in ext_addr;
 
     memset(&ext_addr, 0, sizeof(ext_addr));
diff --git a/src/or/control.c b/src/or/control.c
index be1e921f31405f22894342dc8e4d5ae0ec45eb57..13a5f46b114994a3983b3a0b8bc952f1fd3939e3 100644
--- a/src/or/control.c
+++ b/src/or/control.c
@@ -1755,10 +1755,10 @@ getinfo_helper_events(control_connection_t *control_conn,
                  "information", question);
       }
     } else if (!strcmp(question, "status/clients-seen")) {
-      char *bridge_stats = geoip_get_bridge_stats_controller(time(NULL));
+      const char *bridge_stats = geoip_get_bridge_stats_controller(time(NULL));
       if (!bridge_stats)
         return -1;
-      *answer = bridge_stats;
+      *answer = tor_strdup(bridge_stats);
     } else {
       return 0;
     }
diff --git a/src/or/directory.c b/src/or/directory.c
index 30c08b84b246de0ad0c31914b29b7ef1bfe08f9e..ef0816eb41961c43553f30d7255ccbffbec0ec16 100644
--- a/src/or/directory.c
+++ b/src/or/directory.c
@@ -2334,7 +2334,8 @@ client_likes_consensus(networkstatus_t *v, const char *want_url)
       want_len = DIGEST_LEN;
 
     if (base16_decode(want_digest, DIGEST_LEN, d, want_len*2) < 0) {
-      log_warn(LD_DIR,"Failed to decode requested authority digest %s.", d);
+      log_fn(LOG_PROTOCOL_WARN, LD_DIR,
+             "Failed to decode requested authority digest %s.", d);
       continue;
     };
 
diff --git a/src/or/eventdns.c b/src/or/eventdns.c
index 83bff671aa91fdc970664035923d7cf6e8543408..06add11b1da99d3e2f7083801458534d03ee2389 100644
--- a/src/or/eventdns.c
+++ b/src/or/eventdns.c
@@ -1293,8 +1293,8 @@ server_port_read(struct evdns_server_port *s) {
 static void
 server_port_flush(struct evdns_server_port *port)
 {
-	while (port->pending_replies) {
-		struct server_request *req = port->pending_replies;
+	struct server_request *req = port->pending_replies;
+	while (req) {
 		ssize_t r = sendto(port->socket, req->response, req->response_len, 0,
                        (struct sockaddr*) &req->addr, (socklen_t)req->addrlen);
 		if (r < 0) {
@@ -1306,6 +1306,9 @@ server_port_flush(struct evdns_server_port *port)
 		if (server_request_free(req)) {
 			/* we released the last reference to req->port. */
 			return;
+		} else {
+			assert(port->pending_replies != req);
+			req = port->pending_replies;
 		}
 	}
 
@@ -2238,6 +2241,21 @@ evdns_resume(void)
 	return 0;
 }
 
+static int
+sockaddr_is_loopback(const struct sockaddr *addr)
+{
+	static const char LOOPBACK_S6[16] =
+	    "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1";
+	if (addr->sa_family == AF_INET) {
+		struct sockaddr_in *sin = (struct sockaddr_in *)addr;
+		return (ntohl(sin->sin_addr.s_addr) & 0xff000000) == 0x7f000000;
+	} else if (addr->sa_family == AF_INET6) {
+		struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr;
+		return !memcmp(sin6->sin6_addr.s6_addr, LOOPBACK_S6, 16);
+	}
+	return 0;
+}
+
 static int
 _evdns_nameserver_add_impl(const struct sockaddr *address,
 						   socklen_t addrlen) {
@@ -2279,7 +2297,8 @@ _evdns_nameserver_add_impl(const struct sockaddr *address,
 	fcntl(ns->socket, F_SETFL, O_NONBLOCK);
 #endif
 
-	if (global_bind_addr_is_set) {
+	if (global_bind_addr_is_set &&
+	    !sockaddr_is_loopback((struct sockaddr*)&global_bind_address)) {
 		if (bind(ns->socket, (struct sockaddr *)&global_bind_address,
 				 global_bind_addrlen) < 0) {
 			log(EVDNS_LOG_DEBUG, "Couldn't bind to outgoing address.");
diff --git a/src/or/geoip.c b/src/or/geoip.c
index a00280e39dafa079a77b80d12b126fbe1270e9d1..7208b89865b742657f4e2e96fc1c7d84d0ebc32f 100644
--- a/src/or/geoip.c
+++ b/src/or/geoip.c
@@ -1254,7 +1254,7 @@ load_bridge_stats(time_t now)
 
 /** Return most recent bridge statistics for inclusion in extra-info
  * descriptors, or NULL if we don't have recent bridge statistics. */
-char *
+const char *
 geoip_get_bridge_stats_extrainfo(time_t now)
 {
   load_bridge_stats(now);
@@ -1263,7 +1263,7 @@ geoip_get_bridge_stats_extrainfo(time_t now)
 
 /** Return most recent bridge statistics to be returned to controller
  * clients, or NULL if we don't have recent bridge statistics. */
-char *
+const char *
 geoip_get_bridge_stats_controller(time_t now)
 {
   load_bridge_stats(now);
diff --git a/src/or/microdesc.c b/src/or/microdesc.c
index c1f447c5df0604b0339f0f26529eb9ff32ad341d..f29611f930da236d465f329bfe6b328110e767f8 100644
--- a/src/or/microdesc.c
+++ b/src/or/microdesc.c
@@ -56,10 +56,11 @@ HT_GENERATE(microdesc_map, microdesc_t, node,
  * On success, return the total number of bytes written, and set
  * *<b>annotation_len_out</b> to the number of bytes written as
  * annotations. */
-static size_t
+static ssize_t
 dump_microdescriptor(FILE *f, microdesc_t *md, size_t *annotation_len_out)
 {
-  size_t r = 0;
+  ssize_t r = 0;
+  size_t written;
   /* XXXX drops unkown annotations. */
   if (md->last_listed) {
     char buf[ISO_TIME_LEN+1];
@@ -74,7 +75,14 @@ dump_microdescriptor(FILE *f, microdesc_t *md, size_t *annotation_len_out)
   }
 
   md->off = (off_t) ftell(f);
-  fwrite(md->body, 1, md->bodylen, f);
+  written = fwrite(md->body, 1, md->bodylen, f);
+  if (written != md->bodylen) {
+    log_warn(LD_DIR,
+             "Couldn't dump microdescriptor (wrote %lu out of %lu): %s",
+             (unsigned long)written, (unsigned long)md->bodylen,
+             strerror(ferror(f)));
+    return -1;
+  }
   r += md->bodylen;
   return r;
 }
@@ -142,7 +150,7 @@ microdescs_add_list_to_cache(microdesc_cache_t *cache,
   open_file_t *open_file = NULL;
   FILE *f = NULL;
   //  int n_added = 0;
-  size_t size = 0;
+  ssize_t size = 0;
 
   if (where == SAVED_NOWHERE && !no_save) {
     f = start_writing_to_stdio_file(cache->journal_fname,
@@ -171,6 +179,11 @@ microdescs_add_list_to_cache(microdesc_cache_t *cache,
     if (f) {
       size_t annotation_len;
       size = dump_microdescriptor(f, md, &annotation_len);
+      if (size < 0) {
+        /* XXX handle errors from dump_microdescriptor() */
+        /* log?  return -1?  die?  coredump the universe? */
+        continue;
+      }
       md->saved_location = SAVED_IN_JOURNAL;
       cache->journal_len += size;
     } else {
@@ -269,7 +282,7 @@ microdesc_cache_rebuild(microdesc_cache_t *cache)
   FILE *f;
   microdesc_t **mdp;
   smartlist_t *wrote;
-  size_t size;
+  ssize_t size;
   off_t off = 0;
   int orig_size, new_size;
 
@@ -292,6 +305,11 @@ microdesc_cache_rebuild(microdesc_cache_t *cache)
       continue;
 
     size = dump_microdescriptor(f, md, &annotation_len);
+    if (size < 0) {
+      /* XXX handle errors from dump_microdescriptor() */
+      /* log?  return -1?  die?  coredump the universe? */
+      continue;
+    }
     md->off = off + annotation_len;
     off += size;
     if (md->saved_location != SAVED_IN_CACHE) {
diff --git a/src/or/or.h b/src/or/or.h
index 091d819f792704ac76c6015c93425d7364a274f0..e0b86387faff78b2ee3439f2a4d92d8c6c32269e 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -4137,8 +4137,8 @@ void geoip_entry_stats_init(time_t now);
 void geoip_entry_stats_write(time_t now);
 void geoip_bridge_stats_init(time_t now);
 time_t geoip_bridge_stats_write(time_t now);
-char *geoip_get_bridge_stats_extrainfo(time_t);
-char *geoip_get_bridge_stats_controller(time_t);
+const char *geoip_get_bridge_stats_extrainfo(time_t);
+const char *geoip_get_bridge_stats_controller(time_t);
 
 /********************************* hibernate.c **********************/
 
diff --git a/src/or/router.c b/src/or/router.c
index e14f237728befbd8e29093dd77666852f3f341fc..257bca935bc5e9bc677dd2b668da4c639515053e 100644
--- a/src/or/router.c
+++ b/src/or/router.c
@@ -1382,6 +1382,7 @@ router_rebuild_descriptor(int force)
   if (extrainfo_dump_to_string(ei->cache_info.signed_descriptor_body,
                                ei_size, ei, get_identity_key()) < 0) {
     log_warn(LD_BUG, "Couldn't generate extra-info descriptor.");
+    routerinfo_free(ri);
     extrainfo_free(ei);
     return -1;
   }
@@ -1398,6 +1399,8 @@ router_rebuild_descriptor(int force)
   if (router_dump_router_to_string(ri->cache_info.signed_descriptor_body, 8192,
                                    ri, get_identity_key())<0) {
     log_warn(LD_BUG, "Couldn't generate router descriptor.");
+    routerinfo_free(ri);
+    extrainfo_free(ei);
     return -1;
   }
   ri->cache_info.signed_descriptor_len =
@@ -1895,6 +1898,10 @@ extrainfo_dump_to_string(char *s, size_t maxlen, extrainfo_t *extrainfo,
                         extrainfo->nickname, identity,
                         published, bandwidth_usage);
 
+  tor_free(bandwidth_usage);
+  if (result<0)
+    return -1;
+
   if (options->ExtraInfoStatistics && write_stats_to_extrainfo) {
     char *contents = NULL;
     log_info(LD_GENERAL, "Adding stats to extra-info descriptor.");
@@ -1907,6 +1914,7 @@ extrainfo_dump_to_string(char *s, size_t maxlen, extrainfo_t *extrainfo,
         log_warn(LD_DIR, "Could not write dirreq-stats to extra-info "
                  "descriptor.");
         s[pos] = '\0';
+        write_stats_to_extrainfo = 0;
       }
       tor_free(contents);
     }
@@ -1919,6 +1927,7 @@ extrainfo_dump_to_string(char *s, size_t maxlen, extrainfo_t *extrainfo,
         log_warn(LD_DIR, "Could not write entry-stats to extra-info "
                  "descriptor.");
         s[pos] = '\0';
+        write_stats_to_extrainfo = 0;
       }
       tor_free(contents);
     }
@@ -1931,6 +1940,7 @@ extrainfo_dump_to_string(char *s, size_t maxlen, extrainfo_t *extrainfo,
         log_warn(LD_DIR, "Could not write buffer-stats to extra-info "
                  "descriptor.");
         s[pos] = '\0';
+        write_stats_to_extrainfo = 0;
       }
       tor_free(contents);
     }
@@ -1943,17 +1953,14 @@ extrainfo_dump_to_string(char *s, size_t maxlen, extrainfo_t *extrainfo,
         log_warn(LD_DIR, "Could not write exit-stats to extra-info "
                  "descriptor.");
         s[pos] = '\0';
+        write_stats_to_extrainfo = 0;
       }
       tor_free(contents);
     }
   }
 
-  tor_free(bandwidth_usage);
-  if (result<0)
-    return -1;
-
-  if (should_record_bridge_info(options)) {
-    char *bridge_stats = geoip_get_bridge_stats_extrainfo(now);
+  if (should_record_bridge_info(options) && write_stats_to_extrainfo) {
+    const char *bridge_stats = geoip_get_bridge_stats_extrainfo(now);
     if (bridge_stats) {
       size_t pos = strlen(s);
       if (strlcpy(s + pos, bridge_stats, maxlen - strlen(s)) !=
@@ -1961,8 +1968,8 @@ extrainfo_dump_to_string(char *s, size_t maxlen, extrainfo_t *extrainfo,
         log_warn(LD_DIR, "Could not write bridge-stats to extra-info "
                  "descriptor.");
         s[pos] = '\0';
+        write_stats_to_extrainfo = 0;
       }
-      tor_free(bridge_stats);
     }
   }
 
@@ -1984,6 +1991,7 @@ extrainfo_dump_to_string(char *s, size_t maxlen, extrainfo_t *extrainfo,
       log_err(LD_BUG,
               "We just generated an extrainfo descriptor we can't parse.");
       log_err(LD_BUG, "Descriptor was: <<%s>>", s);
+      tor_free(s_dup);
       return -1;
     }
     tor_free(s_dup);
diff --git a/src/test/Makefile.am b/src/test/Makefile.am
index cdb5d85c28cc4d213b2562a53d808e93340e5704..7df13da51e514e8454eadb613c9bafd660bb8993 100644
--- a/src/test/Makefile.am
+++ b/src/test/Makefile.am
@@ -25,6 +25,6 @@ test_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ \
         @TOR_LDFLAGS_libevent@
 test_LDADD = ../or/libtor.a ../common/libor.a ../common/libor-crypto.a \
 	../common/libor-event.a \
-	-lz -lm -levent -lssl -lcrypto @TOR_LIB_WS32@ @TOR_LIB_GDI@
+	-lz -lm @TOR_LIBEVENT_LIBS@ @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@
 
 noinst_HEADERS = tinytest.h tinytest_macros.h test.h
diff --git a/src/test/test_util.c b/src/test/test_util.c
index ba0f8cdf2db7345da0d7c84d211e2db2b3212493..ad8d82b4c0b48af3978c4eee750d26a2fd8b378b 100644
--- a/src/test/test_util.c
+++ b/src/test/test_util.c
@@ -420,11 +420,12 @@ _thread_test_func(void* _s)
     cp = &_thread2_name;
     count = &t2_count;
   }
-  tor_mutex_acquire(m);
 
   tor_snprintf(buf, sizeof(buf), "%lu", tor_get_thread_id());
   *cp = tor_strdup(buf);
 
+  tor_mutex_acquire(m);
+
   for (i=0; i<10000; ++i) {
     tor_mutex_acquire(_thread_test_mutex);
     strmap_set(_thread_test_strmap, "last to run", *cp);
diff --git a/src/tools/Makefile.am b/src/tools/Makefile.am
index 39c8277ccd8754fb930e2b083879cc025c76b0ba..be03f8d892308f02f004cb88d6e90ede36d2464a 100644
--- a/src/tools/Makefile.am
+++ b/src/tools/Makefile.am
@@ -3,16 +3,16 @@ noinst_PROGRAMS =  tor-checkkey
 
 tor_resolve_SOURCES = tor-resolve.c
 tor_resolve_LDFLAGS = @TOR_LDFLAGS_libevent@
-tor_resolve_LDADD = ../common/libor.a -lm @TOR_LIB_WS32@
+tor_resolve_LDADD = ../common/libor.a -lm @TOR_LIBEVENT_LIBS@ @TOR_LIB_WS32@
 
 tor_gencert_SOURCES = tor-gencert.c
 tor_gencert_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ \
         @TOR_LDFLAGS_libevent@
 tor_gencert_LDADD = ../common/libor.a ../common/libor-crypto.a \
-        -lm -lz -lcrypto @TOR_LIB_WS32@ @TOR_LIB_GDI@
+        -lm -lz @TOR_LIBEVENT_LIBS@ @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@
 
 tor_checkkey_SOURCES = tor-checkkey.c
 tor_checkkey_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ \
         @TOR_LDFLAGS_libevent@
 tor_checkkey_LDADD = ../common/libor.a ../common/libor-crypto.a \
-        -lm -lz -lcrypto @TOR_LIB_WS32@ @TOR_LIB_GDI@
+        -lm -lz @TOR_LIBEVENT_LIBS@ @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@
diff --git a/src/win32/orconfig.h b/src/win32/orconfig.h
index 67e21ae22b66de154d08ca289e621c3c35585849..f6f6ae81852bd1ada081405661ccabf9a049fc4f 100644
--- a/src/win32/orconfig.h
+++ b/src/win32/orconfig.h
@@ -226,5 +226,5 @@
 #define USING_TWOS_COMPLEMENT
 
 /* Version number of package */
-#define VERSION "0.2.2.7-alpha"
+#define VERSION "0.2.2.8-alpha"