0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-11-16 06:51:08 +01:00

ircd: Update exception macro to ensure format string checks.

This commit is contained in:
Jason Volk 2016-08-14 19:03:25 -07:00
parent a1ee5034a2
commit 029a83a17d
2 changed files with 55 additions and 36 deletions

View file

@ -32,9 +32,6 @@
#ifdef __cplusplus #ifdef __cplusplus
namespace ircd { namespace ircd {
IRCD_OVERLOAD(pass_name)
/** The root exception type. /** The root exception type.
* *
* All exceptions in the project inherit from this type. * All exceptions in the project inherit from this type.
@ -57,16 +54,24 @@ IRCD_OVERLOAD(pass_name)
struct exception struct exception
:std::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 /** Exception generator convenience macro
* *
* If you want to create your own exception type, you have found the right * 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. * Remember: the order of the catch blocks is important.
*/ */
#define IRCD_EXCEPTION(parent, name) \
struct name \ #define IRCD_EXCEPTION(parent, name) \
:parent \ struct name \
{ \ :parent \
template<class... A> \ { \
name(const pass_name_t &, A&&... a): \ name(const char *const fmt = " ", ...) noexcept AFP(2, 3) \
parent { pass_name, std::forward<A>(a)... } {} \ { \
\ va_list ap; \
template<class... A> \ va_start(ap, fmt); \
name(A&&... a): \ generate(#name, fmt, ap); \
parent { pass_name, #name, std::forward<A>(a)... } {} \ 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). * 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 * IRCD_EXCEPTION(ircd::error, error)
* redefine them. You can also inherit from these if appropriate.
*/ */
IRCD_EXCEPTION(exception, error) // throw ircd::error("something bad") 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")
} // namespace ircd } // namespace ircd
#endif // __cplusplus #endif // __cplusplus

View file

@ -27,22 +27,26 @@
using namespace ircd; using namespace ircd;
ssize_t
exception::exception(const pass_name_t, exception::generate(const char *const &fmt,
const char *const &name, va_list ap)
const char *const fmt,
...)
noexcept noexcept
{ {
va_list ap; return vsnprintf(buf, sizeof(buf), fmt, ap);
va_start(ap, fmt); }
ssize_t
exception::generate(const char *const &name,
const char *const &fmt,
va_list ap)
noexcept
{
size_t size(0); size_t size(0);
const bool empty(!fmt || !fmt[0] || fmt[0] == ' '); const bool empty(!fmt || !fmt[0] || fmt[0] == ' ');
size = rb_strlcpy(buf, name, sizeof(buf)); size = rb_strlcpy(buf, name, sizeof(buf));
size = rb_strlcat(buf, empty? "." : ": ", sizeof(buf)); size = rb_strlcat(buf, empty? "." : ": ", sizeof(buf));
if(size < 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;
} }