Avoid duplicate IDs on unsigned integer overflow
authorArmin Burgmeier <armin@arbur.net>
Sun, 30 Oct 2011 15:05:29 +0000 (16:05 +0100)
committerArmin Burgmeier <armin@arbur.net>
Sun, 30 Oct 2011 15:12:14 +0000 (16:12 +0100)
2011-10-30  Armin Burgmeier  <armin@arbur.net>

* inc/server.hpp:
* inc/host.hpp: Choose the lowest possible user ID when a new user
joins instead of increasing the ID counter. This prevents possible
duplicate IDs in the case of an unsigned integer overflow (Vasiliy
Kulikov).

ChangeLog
inc/host.hpp
inc/server.hpp

index 9e35118..897d0d2 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2011-10-30  Armin Burgmeier  <armin@arbur.net>
+
+       * inc/server.hpp:
+       * inc/host.hpp: Choose the lowest possible user ID when a new user
+       joins instead of increasing the ID counter. This prevents possible
+       duplicate IDs in the case of an unsigned integer overflow (Vasiliy
+       Kulikov).
+
 2011-09-05  Vincent Untz  <vuntz@opensuse.org>
 
        * inc/encrypt.hpp:
index 5380ae7..1b91dd5 100644 (file)
@@ -82,7 +82,7 @@ basic_host<selector_type>::basic_host(const std::string& username, bool ipv6)
  : basic_object<selector_type>(),
    basic_local<selector_type>(),
    basic_server<selector_type>(ipv6),
-   self(new user(++ basic_server<selector_type>::id_counter, NULL) )
+   self(new user(1, NULL) )
 {
        self->login(username);
        basic_object<selector_type>::user_add(self);
@@ -94,7 +94,7 @@ basic_host<selector_type>::
  : basic_object<selector_type>(),
    basic_local<selector_type>(),
    basic_server<selector_type>(port, ipv6),
-   self(new user(++ basic_server<selector_type>::id_counter, NULL) )
+   self(new user(1, NULL) )
 {
        self->login(username);
        basic_object<selector_type>::user_add(self);
index 976d380..84240da 100644 (file)
@@ -225,7 +225,6 @@ protected:
        std::auto_ptr<tcp_server_socket> serv6_sock;
 
        bool use_ipv6;
-       unsigned int id_counter;
 
        dh_params params;
 
@@ -247,13 +246,13 @@ typedef basic_server<selector> server;
 
 template<typename selector_type>
 basic_server<selector_type>::basic_server(bool ipv6)
- : id_counter(0), use_ipv6(ipv6)
+ : use_ipv6(ipv6)
 {
 }
 
 template<typename selector_type>
 basic_server<selector_type>::basic_server(unsigned int port, bool ipv6)
- : id_counter(0), use_ipv6(ipv6)
+ : use_ipv6(ipv6)
 {
        reopen_impl(port, ipv6);
 }
@@ -408,10 +407,19 @@ template<typename selector_type>
 void basic_server<selector_type>::on_accept_event(tcp_server_socket& sock,
                                                   io_condition io)
 {
+       // Find a unique user ID
+       unsigned int last_id = 0;
+       for(typename basic_object<selector_type>::user_map::iterator iter = this->users.begin(); iter != this->users.end(); ++iter)
+       {
+               if(iter->second->get_id() != last_id + 1)
+                       break;
+               last_id = iter->second->get_id();
+       }
+
        // Get selector from base class
        selector_type& selector = basic_object<selector_type>::get_selector();
        connection_type* conn = new connection_type(selector);
-       std::auto_ptr<user> client(new user(++ id_counter, conn) );
+       std::auto_ptr<user> client(new user(last_id + 1, conn) );
 
        conn->recv_event().connect(
                sigc::bind(