5.2.20
08/25/2019

[#255] ClientBase::disconnect( ConnectionError reason ) may cause an access violation!
Summary ClientBase::disconnect( ConnectionError reason ) may cause an access violation!
Queue gloox
Queue Version 1.0.13
Type Bug
State Unconfirmed
Priority 3. High
Owners js (at) camaya (dot) net
Requester matias (at) snellingen (dot) com
Created 09/23/2015 (1432 days ago)
Due
Updated 09/24/2015 (1431 days ago)
Assigned
Resolved

History
09/24/2015 07:13:54 AM matias (at) snellingen (dot) com Comment #3 Reply to this comment
The platform we use is Windows 8.1, we use native SChannel and we 
don't have support for zlib compiled in. The problem does not occur 
when disabling encryption. having compression enabled seems to not 
cause any problem.

The crash happens at:
e_status = DecryptMessage( &m_context, &buffer_desc, 0, 0 );

in

int SChannel::decrypt( const std::string& data )

Hope this helps and thanks for fast reply.

09/23/2015 07:57:50 AM Jakob Schröter Comment #2
Assigned to Jakob Schröter
Reply to this comment
Thanks for the report.
On which platform is this? Which encryption lib (OpenSSL, GNUTLS, 
Windows native SChannel, ...) do you use? Do you have support for zlib 
compiled in?
What happens if you disable encryption and/or compression?

ClientBase::setCompression( false );
ClientBase::setTls( TLSDisabled );

09/23/2015 06:39:13 AM matias (at) snellingen (dot) com Comment #1
State ⇒ Unconfirmed
Queue ⇒ gloox
Summary ⇒ ClientBase::disconnect( ConnectionError reason ) may cause an access violation!
Type ⇒ Bug
Priority ⇒ 3. High
Reply to this comment
Disconnect will cause an access violation inside one of these three methods:

  m_connection->cleanup();
  m_encryption->cleanup();
  m_compression->cleanup();

The bug can be produced by creating a lot of clients and disconnect them all.

Example for producing the bug:

std::vector<std::shared_ptr<gloox::Client>> clients;

// create and connect n amount of clients (100 usually works)
for (int i = 0; i < n; i++)
{
        // generate a dummy user
        test_user_jid.setUsername("dummy_user_" + std::to_string(i));
        std::cout << "Creating user: " << test_user_jid.username() << std::endl;
        auto jabber_client = std::shared_ptr<gloox::Client>(new 
gloox::Client(test_user_jid, test_password));
        std::async(std::launch::async, [jabber_client]
        {
                auto connect_result = jabber_client->connect();
                if (connect_result)
                {
                        std::cout << jabber_client->jid().username() << " disconnected" << 
std::endl;
                }
        });

        clients.push_back(jabber_client);
}

std::cout << "Do some work (sleep)" << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(1000));

// disconnect and delete all clients
for (auto itr = clients.begin(); itr != clients.end();)
{
        std::cout << "Deleting client for user: " << 
itr->get()->jid().username() << std::endl;
        itr->get()->disconnect();
        itr = clients.erase(itr);
}