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:
parent
a1ee5034a2
commit
029a83a17d
2 changed files with 55 additions and 36 deletions
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue