[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH] crash with callbacks
[Thread Prev] | [Thread Next]
- Subject: [PATCH] crash with callbacks
- From: Yanis Kurganov <YKurganov@xxxxxxxxxxxxxx>
- Reply-to: libssh@xxxxxxxxxx
- Date: Wed, 3 Dec 2014 12:30:38 +0000
- To: "'libssh@xxxxxxxxxx'" <libssh@xxxxxxxxxx>
I got a libssh crash ((((( 0.6.3 as well as master Imagine following situation: Init session #1... Do something in session #1... Init session #2... Destroy session #1... Do something in session #2... crash! The reason is LIBSSH_THREAD void *ssh_log_userdata; in libssh\src\log.c stores a pointer to OLD (destroyed) session #1 My patch fixes this. Example code also attached. Feel free to make more suitable fixes =)
Attachment:
0001-fix-crash-with-callbacks.patch
Description: 0001-fix-crash-with-callbacks.patch
#include <iostream> #include <string> #include <memory> #include <libssh/libssh.h> #include <libssh/callbacks.h> namespace { void log_callback(ssh_session /*session*/, int /*priority*/, const char* message, void* /*userdata*/) { std::cout << "SSH message: "; std::cout << message << std::endl; } struct my_ssh_wrap { ssh_session m_session; ssh_channel m_channel; ssh_callbacks_struct m_callbacs; my_ssh_wrap(const std::string& host, const std::string& port, const std::string& login, const std::string& password): m_session(ssh_new()), m_channel(NULL) { std::cout << "SSH library: "; std::cout << ssh_copyright() << std::endl; if (NULL == m_session) { throw std::runtime_error("ssh_new"); } m_callbacs.userdata = this; m_callbacs.auth_function = 0; m_callbacs.log_function = &log_callback; m_callbacs.connect_status_function = 0; m_callbacs.global_request_function = 0; ssh_callbacks_init(&m_callbacs); if (SSH_OK != ssh_set_callbacks(m_session, &m_callbacs)) { throw std::runtime_error("ssh_set_callbacks"); } int log_verbosity = SSH_LOG_PROTOCOL; ssh_options_set(m_session, SSH_OPTIONS_HOST, host.c_str()); ssh_options_set(m_session, SSH_OPTIONS_PORT_STR, port.c_str()); ssh_options_set(m_session, SSH_OPTIONS_USER, login.c_str()); ssh_options_set(m_session, SSH_OPTIONS_LOG_VERBOSITY, &log_verbosity); if (SSH_OK != ssh_connect(m_session)) { throw std::runtime_error("ssh_connect"); } std::cout << "SSH version: "; std::cout << ssh_get_version(m_session) << std::endl; if (const char* server_banner = ssh_get_serverbanner(m_session)) { std::cout << "SSH server banner: "; std::cout << server_banner << std::endl; } if (SSH_OK != ssh_userauth_password(m_session, NULL, password.c_str())) { throw std::runtime_error("ssh_userauth_password"); } if (NULL == (m_channel = ssh_channel_new(m_session))) { throw std::runtime_error("ssh_channel_new"); } if (SSH_OK != ssh_channel_open_session(m_channel)) { throw std::runtime_error("ssh_channel_open_session"); } if (SSH_OK != ssh_channel_request_pty_size(m_channel, "ansi", 500, 500)) { throw std::runtime_error("ssh_channel_request_pty"); } if (SSH_OK != ssh_channel_request_shell(m_channel)) { throw std::runtime_error("ssh_channel_request_shell"); } } ~my_ssh_wrap() { if (m_channel) { ssh_channel_close(m_channel); ssh_channel_free(m_channel); } if (m_session) { ssh_disconnect(m_session); ssh_free(m_session); } } void write(const std::string& data) { std::cout << "SSH write: "; std::cout << data << std::endl; int count = ssh_channel_write(m_channel, data.c_str(), data.size()); if (count < 0) { throw std::runtime_error("ssh_channel_write"); } std::cout << count; std::cout << " bytes written" << std::endl; } std::string read(int timeout) { char buffer[1024]; std::string result; const int absolute_timeout = timeout * 1000 + static_cast<int>(GetTickCount()); do { int count = ssh_channel_read_timeout(m_channel, buffer, sizeof(buffer), 0, 100); if (count < 0) { throw std::runtime_error("ssh_channel_read"); } else if (count > 0) { std::cout << count; std::cout << " bytes red" << std::endl; result.append(buffer, count); } } while (absolute_timeout - static_cast<int>(GetTickCount()) > 0); return result; } void scp(const std::string& data) { ssh_scp scp = ssh_scp_new(m_session, SSH_SCP_WRITE, "."); if (NULL == scp) { throw std::runtime_error("ssh_scp_new"); } if (SSH_OK != ssh_scp_init(scp)) { throw std::runtime_error("ssh_scp_init"); } if (SSH_OK != ssh_scp_push_file(scp, "command.sh", data.size(), 0755)) { throw std::runtime_error("ssh_scp_push_file"); } if (SSH_OK != ssh_scp_write(scp, data.c_str(), data.size())) { throw std::runtime_error("ssh_scp_write"); } ssh_scp_free(scp); } }; void dialog_shared(std::shared_ptr<my_ssh_wrap> session) { std::cout << session->read(1) << std::endl; session->write("stty -echo\n"); std::cout << session->read(1) << std::endl; session->write("uname\n"); std::cout << session->read(1) << std::endl; session->write("echo 1\n"); std::cout << session->read(1) << std::endl; } void dialog1(std::shared_ptr<my_ssh_wrap> session) { dialog_shared(session); session->scp("...first command..."); session->write("sh command.sh\n"); std::cout << session->read(10) << std::endl; } void dialog2(std::shared_ptr<my_ssh_wrap> session) { dialog_shared(session); session->scp("...second command..."); session->write("sh command.sh\n"); std::cout << session->read(10) << std::endl; } } int main(int argc, const char **argv) { std::shared_ptr<my_ssh_wrap> session1, session2; try { if(argc!=5) { std::cout << "Wrong usage" << std::endl; return 1; } session1 = std::make_shared<my_ssh_wrap>(argv[1], argv[2], argv[3], argv[4]); dialog1(session1); session2 = std::make_shared<my_ssh_wrap>(argv[1], argv[2], argv[3], argv[4]); session1.reset(); dialog2(session2); } catch (const std::exception& e) { std::cout << "Error during connection: "; std::cout << e.what() << std::endl; } return 0; }
Re: [PATCH] crash with callbacks | Andreas Schneider <asn@xxxxxxxxxxxxxx> |