From: Jérémie Galarneau Date: Thu, 13 Apr 2023 18:31:33 +0000 (-0400) Subject: Fix: logging: unhandled error in *_FMT macros X-Git-Url: https://git.liburcu.org/?p=lttng-tools.git;a=commitdiff_plain;h=003f455dab0204dd3f066ecdbea0470035f8181f Fix: logging: unhandled error in *_FMT macros Coverity reports: 1508779 Uncaught exception If the exception is ever thrown, the program will crash. In lttng::​sessiond::​rotation_thread::​_thread_function(): A C++ exception is thrown but never caught (CWE-248) The *_FMT macros, which use fmtlib, don't handle the case where fmt::format throws. This can happen, in particular, when an invalid format string is used. The macros are modified to log the exception and abort. Signed-off-by: Jérémie Galarneau Change-Id: I7f4a066b418a9d544a679f773df7e94640755f47 --- diff --git a/src/common/error.cpp b/src/common/error.cpp index 0bb088066..cafb15f92 100644 --- a/src/common/error.cpp +++ b/src/common/error.cpp @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -452,3 +453,12 @@ void lttng_abort_on_error(void) abort(); } } + +[[noreturn]] void +lttng::logging::details::die_formatting_exception(const char *format, + const std::exception& formatting_exception) +{ + std::cerr << "Error occurred while formatting logging message: msg=`" << format + << "`: " << formatting_exception.what(); + abort(); +} diff --git a/src/common/error.hpp b/src/common/error.hpp index 7ce643411..93616718f 100644 --- a/src/common/error.hpp +++ b/src/common/error.hpp @@ -242,6 +242,7 @@ static inline void __lttng_print_check_abort(enum lttng_error_level type) /* * Version using GNU strerror_r, for linux with appropriate defines. */ +const char *error_get_str(int32_t code); #define PERROR(call, args...) \ do { \ char *_perror_buf; \ @@ -251,11 +252,44 @@ static inline void __lttng_print_check_abort(enum lttng_error_level type) } while (0); #endif -#define DBG_FMT(format_str, args...) DBG("%s", fmt::format(format_str, ##args).c_str()) -#define WARN_FMT(format_str, args...) WARN("%s", fmt::format(format_str, ##args).c_str()) -#define ERR_FMT(format_str, args...) ERR("%s", fmt::format(format_str, ##args).c_str()) +namespace lttng { +namespace logging { +namespace details { +[[noreturn]] void die_formatting_exception(const char *format, + const std::exception& formatting_exception); +} /* namespace details */ +} /* namespace logging */ +} /* namespace lttng */ -const char *error_get_str(int32_t code); +#define DBG_FMT(format_str, args...) \ + do { \ + try { \ + DBG("%s", fmt::format(format_str, ##args).c_str()); \ + } catch (const std::exception& _formatting_exception) { \ + lttng::logging::details::die_formatting_exception(format_str, \ + _formatting_exception); \ + } \ + } while (0); + +#define WARN_FMT(format_str, args...) \ + do { \ + try { \ + WARN("%s", fmt::format(format_str, ##args).c_str()); \ + } catch (const std::exception& _formatting_exception) { \ + lttng::logging::details::die_formatting_exception(format_str, \ + _formatting_exception); \ + } \ + } while (0); + +#define ERR_FMT(format_str, args...) \ + do { \ + try { \ + ERR("%s", fmt::format(format_str, ##args).c_str()); \ + } catch (const std::exception& _formatting_exception) { \ + lttng::logging::details::die_formatting_exception(format_str, \ + _formatting_exception); \ + } \ + } while (0); /* * Function that format the time and return the reference of log_time.str to