From 52b8c274f6addfca305ddaaae43fcfeb5c001d22 Mon Sep 17 00:00:00 2001 From: Fanda Vacek Date: Tue, 22 Oct 2024 15:34:38 +0200 Subject: [PATCH] Fix uncaught exception in FrameReader --- .../shv/chainpack/abstractstreamreader.h | 7 +--- .../include/shv/chainpack/exception.h | 7 +--- libshvchainpack/src/abstractstreamreader.cpp | 28 ++++++-------- libshvchainpack/src/exception.cpp | 37 +++++++------------ libshvchainpack/src/rpcdriver.cpp | 2 +- libshvcore/include/shv/core/exception.h | 3 -- libshvcoreqt/include/shv/coreqt/utils.h | 2 +- libshviotqt/src/rpc/localsocket.cpp | 19 +++++++--- libshviotqt/src/rpc/socket.cpp | 18 ++++++--- libshviotqt/src/rpc/websocket.cpp | 35 ++++++++++++------ 10 files changed, 79 insertions(+), 79 deletions(-) diff --git a/libshvchainpack/include/shv/chainpack/abstractstreamreader.h b/libshvchainpack/include/shv/chainpack/abstractstreamreader.h index ab26f539a..8f90ca3e4 100644 --- a/libshvchainpack/include/shv/chainpack/abstractstreamreader.h +++ b/libshvchainpack/include/shv/chainpack/abstractstreamreader.h @@ -7,19 +7,16 @@ namespace shv::chainpack { -class SHVCHAINPACK_DECL_EXPORT ParseException : public std::exception +class SHVCHAINPACK_DECL_EXPORT ParseException : public std::runtime_error { - using Super = std::exception; + using Super = std::runtime_error; public: ParseException(int err_code, const std::string &msg, long long pos, const std::string &dump); - const char *what() const noexcept override; int errCode() const; long long pos() const; - const std::string& msg() const; private: int m_errCode; - std::string m_msg; long long m_pos = -1; }; diff --git a/libshvchainpack/include/shv/chainpack/exception.h b/libshvchainpack/include/shv/chainpack/exception.h index 50c57ab8f..ae554ca80 100644 --- a/libshvchainpack/include/shv/chainpack/exception.h +++ b/libshvchainpack/include/shv/chainpack/exception.h @@ -9,8 +9,9 @@ namespace shv::chainpack { -class SHVCHAINPACK_DECL_EXPORT Exception : public std::exception +class SHVCHAINPACK_DECL_EXPORT Exception : public std::runtime_error { + using Super = std::runtime_error; public: static constexpr bool Throw = true; public: @@ -22,17 +23,13 @@ class SHVCHAINPACK_DECL_EXPORT Exception : public std::exception std::string message() const; std::string where() const; shv::chainpack::RpcValue data() const; - const char* what() const noexcept override; static void setAbortOnException(bool on); static bool isAbortOnException(); -protected: - void makeWhat(); protected: // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) static bool s_abortOnException; std::string m_msg; shv::chainpack::RpcValue m_data; - std::string m_what; std::string m_where; }; diff --git a/libshvchainpack/src/abstractstreamreader.cpp b/libshvchainpack/src/abstractstreamreader.cpp index 4db6f3ebf..2d380ac64 100644 --- a/libshvchainpack/src/abstractstreamreader.cpp +++ b/libshvchainpack/src/abstractstreamreader.cpp @@ -18,14 +18,18 @@ size_t unpack_underflow_handler(ccpcp_unpack_context *ctx) } ParseException::ParseException(int err_code, const std::string &msg, long long pos, const std::string &dump) - : m_errCode(err_code), m_msg(msg), m_pos(pos) + : Super([&msg, &dump, err_code, pos](){ + auto res = std::string("Parse error: ") + std::to_string(err_code) + " " + ccpcp_error_string(err_code) + + " at pos: " + std::to_string(pos) + + " - " + msg; + if (!dump.empty()) { + res += " near to:\n" + dump; + } + return res; + }()) + , m_errCode(err_code) + , m_pos(pos) { - m_msg = std::string("Parse error: ") + std::to_string(m_errCode) + " " + ccpcp_error_string(m_errCode) - + " at pos: " + std::to_string(m_pos) - + " - " + m_msg; - if (!dump.empty()) { - m_msg += " near to:\n" + dump; - } } int ParseException::errCode() const @@ -38,16 +42,6 @@ long long ParseException::pos() const return m_pos; } -const std::string& ParseException::msg() const -{ - return m_msg; -} - -const char *ParseException::what() const noexcept -{ - return m_msg.data(); -} - AbstractStreamReader::AbstractStreamReader(std::istream &in) : m_in(in) { diff --git a/libshvchainpack/src/exception.cpp b/libshvchainpack/src/exception.cpp index 024ac9172..c63b79a6d 100644 --- a/libshvchainpack/src/exception.cpp +++ b/libshvchainpack/src/exception.cpp @@ -19,17 +19,22 @@ Exception::Exception(const std::string& _msg, const std::string& _where, const c { } -Exception::Exception(const std::string &_msg, const RpcValue &_data, const std::string &_where, const char *_log_topic) - : m_msg(_msg) - , m_data(_data) - , m_where(_where) +Exception::Exception(const std::string &msg, const RpcValue &data, const std::string &where, const char *log_topic) + : Super([&msg, &data](){ + if(data.isValid()) { + return msg + " data: " + data.toCpon(); + } + return msg; + }()) + , m_msg(msg) + , m_data(data) + , m_where(where) { - makeWhat(); - if(isAbortOnException() || !_where.empty() || (_log_topic && *_log_topic)) { - if(_log_topic && *_log_topic) - nCError(_log_topic) << "SHV_EXCEPTION:" << _where << m_what; + if(isAbortOnException() || !where.empty() || (log_topic && *log_topic)) { + if(log_topic && *log_topic) + nCError(log_topic) << "SHV_EXCEPTION:" << where << what(); else - nError() << "SHV_EXCEPTION:" << _where << m_what; + nError() << "SHV_EXCEPTION:" << where << what(); } if(isAbortOnException()) std::abort(); @@ -50,12 +55,6 @@ shv::chainpack::RpcValue Exception::data() const return m_data; } - -const char *Exception::what() const noexcept -{ - return m_what.c_str(); -} - void Exception::Exception::setAbortOnException(bool on) { s_abortOnException = on; @@ -66,12 +65,4 @@ bool Exception::Exception::isAbortOnException() return s_abortOnException; } -void Exception::makeWhat() -{ - m_what = m_msg; - if(m_data.isValid()) { - m_what += " data: " + m_data.toCpon(); - } -} - } // namespace shv diff --git a/libshvchainpack/src/rpcdriver.cpp b/libshvchainpack/src/rpcdriver.cpp index d998f07b3..5ece0733b 100644 --- a/libshvchainpack/src/rpcdriver.cpp +++ b/libshvchainpack/src/rpcdriver.cpp @@ -70,7 +70,7 @@ void RpcDriver::onFrameDataRead(const std::string &frame_data) onRpcFrameReceived(std::move(frame)); } catch (const ParseException &e) { - logRpcDataW() << "ERROR - Rpc frame data corrupted:" << e.msg(); + logRpcDataW() << "ERROR - Rpc frame data corrupted:" << e.what(); //logRpcDataW() << "The error occured in data:\n" << shv::chainpack::utils::hexDump(m_readData.data(), 1024); onParseDataException(e); return; diff --git a/libshvcore/include/shv/core/exception.h b/libshvcore/include/shv/core/exception.h index 0ca930d3e..257ab5ca6 100644 --- a/libshvcore/include/shv/core/exception.h +++ b/libshvcore/include/shv/core/exception.h @@ -3,9 +3,6 @@ #include #include -#include -#include - #include namespace shv::core { diff --git a/libshvcoreqt/include/shv/coreqt/utils.h b/libshvcoreqt/include/shv/coreqt/utils.h index 43ec02636..04305aa7f 100644 --- a/libshvcoreqt/include/shv/coreqt/utils.h +++ b/libshvcoreqt/include/shv/coreqt/utils.h @@ -196,8 +196,8 @@ auto findLongestPrefix(const QMap& map, QString value) -> typena return map.end(); } -} +} } // namespace coreqt } // namespace shv diff --git a/libshviotqt/src/rpc/localsocket.cpp b/libshviotqt/src/rpc/localsocket.cpp index 267295a07..aff181190 100644 --- a/libshviotqt/src/rpc/localsocket.cpp +++ b/libshviotqt/src/rpc/localsocket.cpp @@ -1,5 +1,6 @@ #include +#include #include #include @@ -142,13 +143,19 @@ void LocalSocket::ignoreSslErrors() void LocalSocket::onDataReadyRead() { auto ba = m_socket->readAll(); - std::string_view escaped_data(ba.constData(), ba.size()); - for (auto rqid : m_frameReader->addData(escaped_data)) { - emit responseMetaReceived(rqid); + try { + std::string_view escaped_data(ba.constData(), ba.size()); + for (auto rqid : m_frameReader->addData(escaped_data)) { + emit responseMetaReceived(rqid); + } + emit dataChunkReceived(); + if (!m_frameReader->isEmpty()) { + emit readyRead(); + } } - emit dataChunkReceived(); - if (!m_frameReader->isEmpty()) { - emit readyRead(); + catch (const std::runtime_error &e) { + shvWarning() << "Corrupted meta data received:\n" << shv::chainpack::utils::hexDump(std::string_view(ba.constData(), std::min(ba.size(), static_cast(64)))); + emit error(QAbstractSocket::SocketError::UnknownSocketError); } } diff --git a/libshviotqt/src/rpc/socket.cpp b/libshviotqt/src/rpc/socket.cpp index 8b8531da8..07b655124 100644 --- a/libshviotqt/src/rpc/socket.cpp +++ b/libshviotqt/src/rpc/socket.cpp @@ -317,13 +317,19 @@ void TcpSocket::ignoreSslErrors() void TcpSocket::onDataReadyRead() { auto ba = m_socket->readAll(); - std::string_view data(ba.constData(), ba.size()); - for (auto rqid : m_frameReader->addData(data)) { - emit responseMetaReceived(rqid); + try { + std::string_view data(ba.constData(), ba.size()); + for (auto rqid : m_frameReader->addData(data)) { + emit responseMetaReceived(rqid); + } + emit dataChunkReceived(); + if (!m_frameReader->isEmpty()) { + emit readyRead(); + } } - emit dataChunkReceived(); - if (!m_frameReader->isEmpty()) { - emit readyRead(); + catch (const std::runtime_error &e) { + shvWarning() << "Corrupted meta data received:\n" << shv::chainpack::utils::hexDump(std::string_view(ba.constData(), std::min(ba.size(), static_cast(64)))); + emit error(QAbstractSocket::SocketError::UnknownSocketError); } } diff --git a/libshviotqt/src/rpc/websocket.cpp b/libshviotqt/src/rpc/websocket.cpp index b41ebefb6..0e55ab761 100644 --- a/libshviotqt/src/rpc/websocket.cpp +++ b/libshviotqt/src/rpc/websocket.cpp @@ -1,5 +1,6 @@ #include +#include #include #include @@ -83,25 +84,35 @@ void WebSocket::flushWriteBuffer() void WebSocket::onTextMessageReceived(const QString &message) { shvDebug() << "text message received:" << message; - auto ba = message.toUtf8(); - for (auto rqid : m_frameReader->addData(std::string_view(ba.constData(), ba.size()))) { - emit responseMetaReceived(rqid); + auto data = message.toUtf8(); + try { + for (auto rqid : m_frameReader->addData(std::string_view(data.constData(), data.size()))) { + emit responseMetaReceived(rqid); + } + emit dataChunkReceived(); + if (!m_frameReader->isEmpty()) { + emit readyRead(); + } } - emit dataChunkReceived(); - if (!m_frameReader->isEmpty()) { - emit readyRead(); + catch (const std::runtime_error &e) { + shvWarning() << "Corrupted meta data received:\n" << shv::chainpack::utils::hexDump(std::string_view(data.constData(), std::min(data.size(), static_cast(64)))); } } void WebSocket::onBinaryMessageReceived(const QByteArray &message) { - shvDebug() << "binary message received:" << message; - for (auto rqid : m_frameReader->addData(std::string_view(message.constData(), message.size()))) { - emit responseMetaReceived(rqid); + try { + shvDebug() << "binary message received:" << message; + for (auto rqid : m_frameReader->addData(std::string_view(message.constData(), message.size()))) { + emit responseMetaReceived(rqid); + } + emit dataChunkReceived(); + if (!m_frameReader->isEmpty()) { + emit readyRead(); + } } - emit dataChunkReceived(); - if (!m_frameReader->isEmpty()) { - emit readyRead(); + catch (const std::runtime_error &e) { + shvWarning() << "Corrupted meta data received:\n" << shv::chainpack::utils::hexDump(std::string_view(message.constData(), std::min(message.size(), static_cast(64)))); } }