From 029a83a17d2727bbb891f11a9867888587811577 Mon Sep 17 00:00:00 2001 From: Jason Volk Date: Sun, 14 Aug 2016 19:03:25 -0700 Subject: [PATCH] ircd: Update exception macro to ensure format string checks. --- include/ircd/exception.h | 69 ++++++++++++++++++++++++---------------- ircd/exception.cc | 22 +++++++------ 2 files changed, 55 insertions(+), 36 deletions(-) diff --git a/include/ircd/exception.h b/include/ircd/exception.h index 6ddfe9ea4..af94f239e 100644 --- a/include/ircd/exception.h +++ b/include/ircd/exception.h @@ -32,9 +32,6 @@ #ifdef __cplusplus namespace ircd { - -IRCD_OVERLOAD(pass_name) - /** The root exception type. * * All exceptions in the project inherit from this type. @@ -57,16 +54,24 @@ IRCD_OVERLOAD(pass_name) struct exception :std::exception { - char buf[1024]; + protected: + char buf[BUFSIZE]; - const char *what() const noexcept override { return buf; } + ssize_t generate(const char *const &name, const char *const &fmt, va_list ap) noexcept; + ssize_t generate(const char *const &fmt, va_list ap) noexcept; - exception(const pass_name_t, const char *const &name = "exception", const char *fmt = " ", ...) noexcept AFP(4, 5); + public: + const char *what() const noexcept override + { + return buf; + } + + exception() noexcept + { + buf[0] = '\0'; + } }; - -// Disambiguates the constructors in the macro below. - /** Exception generator convenience macro * * If you want to create your own exception type, you have found the right @@ -98,30 +103,40 @@ struct exception * * Remember: the order of the catch blocks is important. */ -#define IRCD_EXCEPTION(parent, name) \ -struct name \ -:parent \ -{ \ - template \ - name(const pass_name_t &, A&&... a): \ - parent { pass_name, std::forward(a)... } {} \ - \ - template \ - name(A&&... a): \ - parent { pass_name, #name, std::forward(a)... } {} \ + +#define IRCD_EXCEPTION(parent, name) \ +struct name \ +:parent \ +{ \ + name(const char *const fmt = " ", ...) noexcept AFP(2, 3) \ + { \ + va_list ap; \ + va_start(ap, fmt); \ + generate(#name, fmt, ap); \ + va_end(ap); \ + } \ }; +#define IRCD_EXCEPTION_HIDENAME(parent, name) \ +struct name \ +:parent \ +{ \ + name(const char *const fmt = " ", ...) noexcept AFP(2, 3) \ + { \ + va_list ap; \ + va_start(ap, fmt); \ + generate(fmt, ap); \ + va_end(ap); \ + } \ +}; -/** Generic base exceptions. +/** Root error exception type. Inherit from this. * List your own exception somewhere else (unless you're overhauling libircd). + * example, in your namespace: * - * These are useful for random places and spare you the effort of having to - * redefine them. You can also inherit from these if appropriate. + * IRCD_EXCEPTION(ircd::error, error) */ -IRCD_EXCEPTION(exception, error) // throw ircd::error("something bad") -IRCD_EXCEPTION(error, not_found) // throw ircd::not_found("looks like a 404") -IRCD_EXCEPTION(error, access_denied) // throw ircd::access_denied("you didn't say the magic word") - +IRCD_EXCEPTION(exception, error) // throw ircd::error("something bad") } // namespace ircd #endif // __cplusplus diff --git a/ircd/exception.cc b/ircd/exception.cc index 7a35f1e6b..934bf93da 100644 --- a/ircd/exception.cc +++ b/ircd/exception.cc @@ -27,22 +27,26 @@ using namespace ircd; - -exception::exception(const pass_name_t, - const char *const &name, - const char *const fmt, - ...) +ssize_t +exception::generate(const char *const &fmt, + va_list ap) noexcept { - va_list ap; - va_start(ap, fmt); + return vsnprintf(buf, sizeof(buf), fmt, ap); +} +ssize_t +exception::generate(const char *const &name, + const char *const &fmt, + va_list ap) +noexcept +{ size_t size(0); const bool empty(!fmt || !fmt[0] || fmt[0] == ' '); size = rb_strlcpy(buf, name, sizeof(buf)); size = rb_strlcat(buf, empty? "." : ": ", sizeof(buf)); if(size < sizeof(buf)) - vsnprintf(buf + size, sizeof(buf) - size, fmt, ap); + size += vsnprintf(buf + size, sizeof(buf) - size, fmt, ap); - va_end(ap); + return size; }