From c790e344ac265dbdc94307b609a15cc2d8ff5ffb Mon Sep 17 00:00:00 2001 From: Mathew Sutcliffe Date: Fri, 7 Jul 2017 14:25:52 +0100 Subject: [PATCH] BLACK_AUDIT macro for paranoid checks on data consistency Summary: Triggers a breakpoint when the debugger is attached to a debug build. Otherwise, logs a warning. Related: T101 Reviewers: kbasan, rwinklmeier Reviewed By: kbasan Subscribers: jenkins Tags: #swift_pilot_client Differential Revision: https://dev.swift-project.org/D35 --- src/blackmisc/verify.cpp | 41 ++++++++++++++++++++++++---------------- src/blackmisc/verify.h | 14 ++++++++++++-- 2 files changed, 37 insertions(+), 18 deletions(-) diff --git a/src/blackmisc/verify.cpp b/src/blackmisc/verify.cpp index 58f78821d..f4ae9c08b 100644 --- a/src/blackmisc/verify.cpp +++ b/src/blackmisc/verify.cpp @@ -9,7 +9,6 @@ #include "blackmisc/verify.h" #include "blackmisc/logmessage.h" - #include #ifdef BLACK_USE_CRASHPAD @@ -18,7 +17,7 @@ #if defined(Q_CC_MSVC) #include -#elif defined(Q_OS_UNIX) +#include #endif #if defined(Q_CC_CLANG) @@ -32,14 +31,36 @@ namespace BlackMisc namespace Private { // cppcheck-suppress unusedFunction - void failedVerify(const char *condition, const char *filename, int line, const char *context, const char *message) + void failedVerify(const char *condition, const char *filename, int line, const char *context, const char *message, bool audit) { Q_UNUSED(condition); Q_UNUSED(filename); Q_UNUSED(line); Q_UNUSED(context); Q_UNUSED(message); -#if defined(QT_NO_DEBUG) + Q_UNUSED(audit); + +#if defined(QT_DEBUG) +# if defined(Q_CC_MSVC) + if (!audit || IsDebuggerPresent()) + { + __debugbreak(); + return; + } +# elif defined(BLACK_HAS_BUILTIN_DEBUGGER) + __builtin_debugger(); +# elif defined(Q_PROCESSOR_X86) + __asm__ volatile("int $0x03"); +# elif defined(Q_PROCESSOR_ARM) + __asm__ volatile(".inst 0xe7f001f0"); +# elif defined(Q_OS_UNIX) + raise(SIGTRAP); +# else + Q_ASSERT(false); +# endif +#endif + +#if defined(QT_NO_DEBUG) || defined(Q_CC_MSVC) # if defined(BLACK_USE_CRASHPAD) CRASHPAD_SIMULATE_CRASH(); # endif @@ -51,18 +72,6 @@ namespace BlackMisc { CLogMessage(CLogCategory::verification()).warning("Failed to verify: %1 in %2 line %3") << condition << filename << line; } -#elif defined(Q_CC_MSVC) - __debugbreak(); -#elif defined(BLACK_HAS_BUILTIN_DEBUGGER) - __builtin_debugger(); -#elif defined(Q_PROCESSOR_X86) - __asm__ volatile("int $0x03"); -#elif defined(Q_PROCESSOR_ARM) - __asm__ volatile(".inst 0xe7f001f0"); -#elif defined(Q_OS_UNIX) - raise(SIGTRAP); -#else - Q_ASSERT(false); #endif } } diff --git a/src/blackmisc/verify.h b/src/blackmisc/verify.h index 259a84ef0..30ae7599c 100644 --- a/src/blackmisc/verify.h +++ b/src/blackmisc/verify.h @@ -30,7 +30,7 @@ namespace BlackMisc inline void noop() {} //! \private Called by BLACK_VERIFY when the condition is false. - BLACKMISC_EXPORT BLACK_NO_INLINE void failedVerify(const char *condition, const char *filename, int line, const char *context = nullptr, const char *message = nullptr); + BLACKMISC_EXPORT BLACK_NO_INLINE void failedVerify(const char *condition, const char *filename, int line, const char *context, const char *message, bool audit); } } @@ -39,8 +39,18 @@ namespace BlackMisc * In debug builds, triggers a debugger breakpoint. In release builds, generates a warning. */ //! @{ -#define BLACK_VERIFY_X(COND, WHERE, WHAT) ((COND) ? BlackMisc::Private::noop() : BlackMisc::Private::failedVerify(#COND, __FILE__, __LINE__, WHERE, WHAT)) +#define BLACK_VERIFY_X(COND, WHERE, WHAT) ((COND) ? BlackMisc::Private::noop() : BlackMisc::Private::failedVerify(#COND, __FILE__, __LINE__, WHERE, WHAT, false)) #define BLACK_VERIFY(COND) BLACK_VERIFY_X(COND, nullptr, nullptr) //! @} +/*! + * A weaker kind of verify. Indicative of a serious but recoverable problem originating in an external data source. + * In debug builds under debugging, triggers a debugger breakpoint. Otherwise generates a warning. + * Not a substitute for proper validation. A failed audit in production is suggestive of insufficient validation. + */ +//! @{ +#define BLACK_AUDIT_X(COND, WHERE, WHAT) ((COND) ? BlackMisc::Private::noop() : BlackMisc::Private::failedVerify(#COND, __FILE__, __LINE__, WHERE, WHAT, true)) +#define BLACK_AUDIT(COND) BLACK_AUDIT_X(COND, nullptr, nullptr) +//! @} + #endif