[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> |