Fix: logging: unhandled error in *_FMT macros
authorJérémie Galarneau <jeremie.galarneau@efficios.com>
Thu, 13 Apr 2023 18:31:33 +0000 (14:31 -0400)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Tue, 18 Apr 2023 14:36:50 +0000 (10:36 -0400)
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 <jeremie.galarneau@efficios.com>
Change-Id: I7f4a066b418a9d544a679f773df7e94640755f47

src/common/error.cpp
src/common/error.hpp

index 0bb088066466cb1ea331e849305ed783cdd990fc..cafb15f92948b8ee209fae25422ff9459a6da382 100644 (file)
@@ -16,6 +16,7 @@
 #include <lttng/lttng-error.h>
 
 #include <inttypes.h>
+#include <iostream>
 #include <pthread.h>
 #include <stdlib.h>
 #include <string.h>
@@ -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();
+}
index 7ce643411c8fd7567fd53e0dab26a1c87866b6c8..93616718f65dd89481492d39bf7ef0fe8ba1d261 100644 (file)
@@ -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
This page took 0.027746 seconds and 4 git commands to generate.