net/tls: Refactored re-throwing exceptions so that the original exception class is retained. With the old code, a socket_exception was re-thrown as vmime::exception.

IMAPFolder.cpp: Fixed a use-after-free in case of an exception in close().
This commit is contained in:
Jacek Piszczek 2021-02-24 13:53:39 -05:00
parent 47c6f35f5a
commit 39a0cfbcc3
6 changed files with 21 additions and 19 deletions

View File

@ -34,6 +34,7 @@
namespace vmime {
typedef std::exception_ptr exception_ptr;
/** Base class for VMime exceptions.
*/

View File

@ -80,7 +80,11 @@ IMAPFolder::~IMAPFolder() {
if (store) {
if (m_open) {
close(false);
try {
close(false);
} catch (...) {
// Ignore exception here to make sure unregisterFolder is called
}
}
store->unregisterFolder(this);

View File

@ -66,7 +66,7 @@ TLSSocket_GnuTLS::TLSSocket_GnuTLS(
: m_session(session),
m_wrapped(sok),
m_connected(false),
m_ex(NULL),
m_ex(nullptr),
m_status(0),
m_errno(0) {
@ -407,7 +407,7 @@ ssize_t TLSSocket_GnuTLS::gnutlsPushFunc(
// Workaround for non-portable behaviour when throwing C++ exceptions
// from C functions (GNU TLS)
sok->m_ex = e.clone();
sok->m_ex = std::current_exception();
return -1;
}
}
@ -440,7 +440,7 @@ ssize_t TLSSocket_GnuTLS::gnutlsPullFunc(
// Workaround for non-portable behaviour when throwing C++ exceptions
// from C functions (GNU TLS)
sok->m_ex = e.clone();
sok->m_ex = std::current_exception();
return -1;
}
}
@ -525,18 +525,15 @@ shared_ptr <security::cert::certificateChain> TLSSocket_GnuTLS::getPeerCertifica
void TLSSocket_GnuTLS::throwException() {
if (m_ex) {
throw *m_ex;
if (!!m_ex) {
std::rethrow_exception(m_ex);
}
}
void TLSSocket_GnuTLS::resetException() {
if (m_ex) {
delete m_ex;
m_ex = NULL;
}
m_ex = nullptr;
}

View File

@ -109,7 +109,7 @@ private:
byte_t m_buffer[65536];
exception* m_ex;
exception_ptr m_ex;
unsigned int m_status;
int m_errno;

View File

@ -104,7 +104,7 @@ TLSSocket_OpenSSL::TLSSocket_OpenSSL(
m_connected(false),
m_ssl(0),
m_status(0),
m_ex() {
m_ex(nullptr) {
}
@ -309,7 +309,7 @@ size_t TLSSocket_OpenSSL::receiveRaw(byte_t* buffer, const size_t count) {
ERR_clear_error();
int rc = SSL_read(m_ssl, buffer, static_cast <int>(count));
if (m_ex.get()) {
if (!!m_ex) {
internalThrow();
}
@ -379,7 +379,7 @@ size_t TLSSocket_OpenSSL::sendRawNonBlocking(const byte_t* buffer, const size_t
ERR_clear_error();
int rc = SSL_write(m_ssl, buffer, static_cast <int>(count));
if (m_ex.get()) {
if (!!m_ex) {
internalThrow();
}
@ -511,8 +511,8 @@ shared_ptr <security::cert::certificateChain> TLSSocket_OpenSSL::getPeerCertific
void TLSSocket_OpenSSL::internalThrow() {
if (m_ex.get()) {
throw *m_ex;
if (!!m_ex) {
std::rethrow_exception(m_ex);
}
}
@ -630,7 +630,7 @@ int TLSSocket_OpenSSL::bio_write(BIO* bio, const char* buf, int len) {
} catch (exception& e) {
// Workaround for passing C++ exceptions from C BIO functions
sok->m_ex.reset(e.clone());
sok->m_ex = std::current_exception();
return -1;
}
}
@ -667,7 +667,7 @@ int TLSSocket_OpenSSL::bio_read(BIO* bio, char* buf, int len) {
} catch (exception& e) {
// Workaround for passing C++ exceptions from C BIO functions
sok->m_ex.reset(e.clone());
sok->m_ex = std::current_exception();
return -1;
}
}

View File

@ -125,7 +125,7 @@ private:
unsigned int m_status;
// Last exception thrown from C BIO functions
scoped_ptr <exception> m_ex;
exception_ptr m_ex;
};