# Fixes a crash when parsing a malformed get_peers (or find_node) response throws
# an exception and fails to remove the corresponding transaction. Ticket #1622.
Index: libtorrent/src/dht/dht_server.cc
===================================================================
--- libtorrent/src/dht/dht_server.cc	(revision 1087)
+++ libtorrent/src/dht/dht_server.cc	(working copy)
@@ -335,36 +335,44 @@
   m_repliesReceived++;
   m_networkUp = true;
 
-  DhtTransaction* transaction = itr->second;
+  // Make sure transaction is erased even if an exception is thrown.
+  try {
+    DhtTransaction* transaction = itr->second;
 #ifdef USE_EXTRA_DEBUG
-  if (DhtTransaction::key(sa, transactionId) != transaction->key(transactionId))
-    throw internal_error("DhtServer::process_response key mismatch.");
+    if (DhtTransaction::key(sa, transactionId) != transaction->key(transactionId))
+      throw internal_error("DhtServer::process_response key mismatch.");
 #endif
 
-  // If we contact a node but its ID is not the one we expect, ignore the reply
-  // to prevent interference from rogue nodes.
-  if ((id != transaction->id() && transaction->id() != m_router->zero_id))
-    return;
+    // If we contact a node but its ID is not the one we expect, ignore the reply
+    // to prevent interference from rogue nodes.
+    if ((id != transaction->id() && transaction->id() != m_router->zero_id))
+      return;
 
-  const Object& response = request.get_key("r");
+    const Object& response = request.get_key("r");
 
-  switch (transaction->type()) {
-    case DhtTransaction::DHT_FIND_NODE:
-      parse_find_node_reply(transaction->as_find_node(), response.get_key_string("nodes"));
-      break;
+    switch (transaction->type()) {
+      case DhtTransaction::DHT_FIND_NODE:
+        parse_find_node_reply(transaction->as_find_node(), response.get_key_string("nodes"));
+        break;
 
-    case DhtTransaction::DHT_GET_PEERS:
-      parse_get_peers_reply(transaction->as_get_peers(), response);
-      break;
+      case DhtTransaction::DHT_GET_PEERS:
+        parse_get_peers_reply(transaction->as_get_peers(), response);
+        break;
 
-    // Nothing to do for DHT_PING and DHT_ANNOUNCE_PEER
-    default:
-      break;
+      // Nothing to do for DHT_PING and DHT_ANNOUNCE_PEER
+      default:
+        break;
+    }
+
+    // Mark node responsive only if all processing was successful, without errors.
+    m_router->node_replied(id, sa);
+
+  } catch (std::exception& e) {
+    delete itr->second;
+    m_transactions.erase(itr);
+    throw;
   }
 
-  // Mark node responsive only if all processing was successful, without errors.
-  m_router->node_replied(id, sa);
-
   delete itr->second;
   m_transactions.erase(itr);
 }
@@ -611,7 +619,17 @@
     else
       transaction->as_find_node()->complete(false);
 
-    find_node_next(transaction->as_find_node());
+    try {
+      find_node_next(transaction->as_find_node());
+
+    } catch (std::exception& e) {
+      if (!quick) {
+        delete itr->second;
+        m_transactions.erase(itr);
+      }
+
+      throw;
+    }
   }
 
   if (quick) {
