From c4dd9d5257716255b1989e12b1411b122d2b3036 Mon Sep 17 00:00:00 2001 From: Jaroslav Rohel Date: Thu, 19 Oct 2023 12:16:01 +0200 Subject: [PATCH] Allow only safe types to be passed to libdnf5::Error and SystemError ctors Exceptions were generated in the code, in which a pointer to text was passed that was no longer in memory at the time the exception was handled. To prevent this from happening again, passing only defined "safe" types is now allowed. --- include/libdnf5/common/exception.hpp | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/include/libdnf5/common/exception.hpp b/include/libdnf5/common/exception.hpp index 0e541e1f3b..d817aba053 100644 --- a/include/libdnf5/common/exception.hpp +++ b/include/libdnf5/common/exception.hpp @@ -27,6 +27,7 @@ along with libdnf. If not, see . #include #include +#include #define LIBDNF_LOCATION \ { __FILE__, __LINE__, __PRETTY_FUNCTION__ } @@ -122,6 +123,20 @@ class UserAssertionError : public std::logic_error { }; +// The exception stores the passed arguments and uses them in the catch phase. +// The problem is that the value to which the saved argument points may no longer be in memory - +// is destroyed when the program leaves the scope of the variable with the value. +// A safer solution than passing a pointer to memory is to use "std::string" and pass it by value. +// +// "Concept" defines safe types that can be passed by value as arguments to the "libdnf5::Error" +// and "libdnf5::SystemError" exception constructors. +// Pointers to void are allowed because they are not dereferenced, but their value is printed. +template +concept AllowedErrorArgTypes = + std::is_arithmetic_v || std::is_base_of_v || std::is_null_pointer_v || + std::is_same_v || std::is_same_v; + + /// Base class for libdnf exceptions. Virtual methods `get_name()` and /// `get_domain_name()` should always return the exception's class name and its /// namespace (including enclosing class names in case the exception is nested in @@ -132,7 +147,7 @@ class Error : public std::runtime_error { /// /// @param format The format string for the message. /// @param args The format arguments. - template + template explicit Error(BgettextMessage format, Args... args) : std::runtime_error(b_gettextmsg_get_id(format)), format(format), @@ -172,7 +187,7 @@ class SystemError : public Error { /// @param error_code The `errno` of the error. /// @param format The format string for the message. /// @param args The format arguments. - template + template explicit SystemError(int error_code, BgettextMessage format, Args... args) : Error(format, std::forward(args)...), error_code(error_code),