From ad23faaae69881bf4ac397b7b9997afafb6eb73d Mon Sep 17 00:00:00 2001 From: Salvador Fandino Date: Wed, 21 Oct 2015 15:03:02 +0200 Subject: [PATCH] _libssh2_error: Support allocating the error message MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before this patch "_libssh2_error" required the error message to be a static string. This patch adds a new function "_libssh2_error_flags" accepting an additional "flags" argument and specifically the flag "LIBSSH2_ERR_FLAG_DUP" indicating that the passed string must be duplicated into the heap. Then, the method "_libssh2_error" has been rewritten to use that new function under the hood. Signed-off-by: Salvador Fandino Signed-off-by: Salvador FandiƱo --- src/libssh2_priv.h | 5 +++++ src/misc.c | 28 ++++++++++++++++++++++++++-- src/misc.h | 1 + src/session.c | 5 +++++ 4 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/libssh2_priv.h b/src/libssh2_priv.h index 78d4ced..1023943 100644 --- a/src/libssh2_priv.h +++ b/src/libssh2_priv.h @@ -631,6 +631,7 @@ struct _LIBSSH2_SESSION /* Error tracking */ const char *err_msg; int err_code; + int err_flags; /* struct members for packet-level reading */ struct transportpacket packet; @@ -950,6 +951,10 @@ _libssh2_debug(LIBSSH2_SESSION * session, int context, const char *format, ...) /* Something very bad is going on */ #define LIBSSH2_MAC_INVALID -1 +/* Flags for _libssh2_error_flags */ +/* Error message is allocated on the heap */ +#define LIBSSH2_ERR_FLAG_DUP 1 + /* SSH Packet Types -- Defined by internet draft */ /* Transport Layer */ #define SSH_MSG_DISCONNECT 1 diff --git a/src/misc.c b/src/misc.c index 283daea..320df44 100644 --- a/src/misc.c +++ b/src/misc.c @@ -51,10 +51,29 @@ #include #include -int _libssh2_error(LIBSSH2_SESSION* session, int errcode, const char* errmsg) +int _libssh2_error_flags(LIBSSH2_SESSION* session, int errcode, const char* errmsg, int errflags) { - session->err_msg = errmsg; + if (session->err_flags & LIBSSH2_ERR_FLAG_DUP) + LIBSSH2_FREE(session, (char *)session->err_msg); + session->err_code = errcode; + session->err_flags = 0; + + if ((errmsg != NULL) && ((errflags & LIBSSH2_ERR_FLAG_DUP) != 0)) { + size_t len = strlen(errmsg); + char *copy = LIBSSH2_ALLOC(session, len + 1); + if (copy) { + memcpy(copy, errmsg, len + 1); + session->err_flags = LIBSSH2_ERR_FLAG_DUP; + session->err_msg = copy; + } + else + /* Out of memory: this code path is very unlikely */ + session->err_msg = "former error forgotten (OOM)"; + } + else + session->err_msg = errmsg; + #ifdef LIBSSH2DEBUG if((errcode == LIBSSH2_ERROR_EAGAIN) && !session->api_block_mode) /* if this is EAGAIN and we're in non-blocking mode, don't generate @@ -67,6 +86,11 @@ int _libssh2_error(LIBSSH2_SESSION* session, int errcode, const char* errmsg) return errcode; } +int _libssh2_error(LIBSSH2_SESSION* session, int errcode, const char* errmsg) +{ + return _libssh2_error_flags(session, errcode, errmsg, 0); +} + #ifdef WIN32 static int wsa2errno(void) { diff --git a/src/misc.h b/src/misc.h index f99b773..54ae546 100644 --- a/src/misc.h +++ b/src/misc.h @@ -49,6 +49,7 @@ struct list_node { struct list_head *head; }; +int _libssh2_error_flags(LIBSSH2_SESSION* session, int errcode, const char* errmsg, int errflags); int _libssh2_error(LIBSSH2_SESSION* session, int errcode, const char* errmsg); void _libssh2_list_init(struct list_head *head); diff --git a/src/session.c b/src/session.c index 9e9343f..cc77a7a 100644 --- a/src/session.c +++ b/src/session.c @@ -1058,6 +1058,11 @@ session_free(LIBSSH2_SESSION *session) LIBSSH2_FREE(session, session->server_hostkey); } + /* error string */ + if (session->err_msg && ((session->err_flags & LIBSSH2_ERR_FLAG_DUP) != 0)) { + LIBSSH2_FREE(session, (char *)session->err_msg); + } + LIBSSH2_FREE(session, session); return 0;