Opened 5 years ago

#13294 new Bugs

Boost(1.57).Asio crashes after ssl stream is closed and stream is deleted.

Reported by: Andrey Borisov <andrey.borisov@…> Owned by: chris_kohlhoff
Milestone: To Be Determined Component: asio
Version: Boost 1.57.0 Severity: Showstopper
Keywords: asio ssl close crash Cc:

Description

The issue is found in boost asio v1.57 and is presents in 1.65.1. Windows, Visual Studio 2015

Our library uses boost asio ssl stream for secure TCP connection. We use dynamically created context and ssl stream:

std::shared_ptr<ssl_context> m_context;
std::shared_ptr<ssl_stream> m_stream;
...
m_context = std::make_shared<ssl_context>(TM_NS_ASIO::ssl::context::tlsv12);
m_stream = std::make_shared<ssl_stream>(*io_service, *m_context);

after handshake we start reading asynchronously:

m_stream->async_read_some(buffer, readHandler);

After that we just close the connection and remove objects:

m_stream->shutdown(ec);                
m_stream->lowest_layer().close(ec);

Than we destroy the stream and context:

m_stream.reset();
m_context.reset();

Close and destroy operation are performed in a context of io_service thread. And after the stream deletion the io_service gets the break assertion:

>       msvcp140d.dll!std::_Debug_message(const wchar_t * message, const wchar_t * file, unsigned int line) Line 17     C++
        tls_test.exe!std::_Vector_const_iterator<std::_Vector_val<std::_Simple_types<unsigned char> > >::operator*() Line 73    C++
        tls_test.exe!std::_Vector_iterator<std::_Vector_val<std::_Simple_types<unsigned char> > >::operator*() Line 332 C++
        tls_test.exe!boost::asio::detail::buffer_debug_check<std::_Vector_iterator<std::_Vector_val<std::_Simple_types<unsigned char> > > >::operator()() Line 532      C++
        tls_test.exe!std::_Invoker_functor::_Call<boost::asio::detail::buffer_debug_check<std::_Vector_iterator<std::_Vector_val<std::_Simple_types<unsigned char> > > > &>(boost::asio::detail::buffer_debug_check<std::_Vector_iterator<std::_Vector_val<std::_Simple_types<unsigned char> > > > & _Obj) Line 1377    C++
        tls_test.exe!std::invoke<boost::asio::detail::buffer_debug_check<std::_Vector_iterator<std::_Vector_val<std::_Simple_types<unsigned char> > > > &>(boost::asio::detail::buffer_debug_check<std::_Vector_iterator<std::_Vector_val<std::_Simple_types<unsigned char> > > > & _Obj) Line 1443     C++
        tls_test.exe!std::_Invoke_ret<void,boost::asio::detail::buffer_debug_check<std::_Vector_iterator<std::_Vector_val<std::_Simple_types<unsigned char> > > > &>(std::_Forced<void,1> __formal, boost::asio::detail::buffer_debug_check<std::_Vector_iterator<std::_Vector_val<std::_Simple_types<unsigned char> > > > & <_Vals_0>) Line 1461       C++
        tls_test.exe!std::_Func_impl<boost::asio::detail::buffer_debug_check<std::_Vector_iterator<std::_Vector_val<std::_Simple_types<unsigned char> > > >,std::allocator<int>,void>::_Do_call() Line 212      C++
        tls_test.exe!std::_Func_class<void>::operator()() Line 279      C++
        tls_test.exe!boost::asio::detail::buffer_cast_helper(const boost::asio::mutable_buffer & b) Line 146    C++
        tls_test.exe!boost::asio::buffer_cast<void const *>(const boost::asio::mutable_buffer & b) Line 427     C++
        tls_test.exe!boost::asio::detail::buffer_sequence_adapter<boost::asio::mutable_buffer,boost::asio::mutable_buffers_1>::validate(const boost::asio::mutable_buffers_1 & buffer_sequence) Line 207        C++
        tls_test.exe!boost::asio::detail::win_iocp_socket_recv_op<boost::asio::mutable_buffers_1,boost::asio::ssl::detail::io_op<boost::asio::basic_stream_socket<boost::asio::ip::tcp,boost::asio::stream_socket_service<boost::asio::ip::tcp> >,boost::asio::ssl::detail::read_op<boost::asio::mutable_buffers_1>,std::function<void __cdecl(boost::system::error_code const &,unsigned int)> > >::do_complete(boost::asio::detail::win_iocp_io_service * owner, boost::asio::detail::win_iocp_operation * base, const boost::system::error_code & result_ec, unsigned int bytes_transferred) Line 72 C++
        tls_test.exe!boost::asio::detail::win_iocp_operation::complete(boost::asio::detail::win_iocp_io_service & owner, const boost::system::error_code & ec, unsigned int bytes_transferred) Line 46  C++
        tls_test.exe!boost::asio::detail::win_iocp_io_service::do_one(bool block, boost::system::error_code & ec) Line 409      C++
        tls_test.exe!boost::asio::detail::win_iocp_io_service::run(boost::system::error_code & ec) Line 164     C++
        tls_test.exe!boost::asio::io_service::run(boost::system::error_code & ec) Line 67       C++

It occurs that completion operation is called after the stream and underlined socket was closed and deleted. The operation is a dynamically object, created by read_some, but it contains link to buffers that application set to it. In case of raw socket the buffers are user application buffers without checkers. In case of ssl the stream uses its internal buffer for TLS operations. And at the moment of the completion operation the stream and its buffers are not exist.

Change History (0)

Note: See TracTickets for help on using tickets.