Crypto++ 8.2
Free C&
trap.h
Go to the documentation of this file.
1// trap.h - written and placed in public domain by Jeffrey Walton.
2
3/// \file trap.h
4/// \brief Debugging and diagnostic assertions
5/// \details <tt>CRYPTOPP_ASSERT</tt> is the library's debugging and diagnostic
6/// assertion. <tt>CRYPTOPP_ASSERT</tt> is enabled by <tt>CRYPTOPP_DEBUG</tt>,
7/// <tt>DEBUG</tt> or <tt>_DEBUG</tt>.
8/// \details <tt>CRYPTOPP_ASSERT</tt> raises a <tt>SIGTRAP</tt> (Unix) or calls
9/// <tt>__debugbreak()</tt> (Windows). <tt>CRYPTOPP_ASSERT</tt> is only in
10/// effect when the user requests a debug configuration. Unlike Posix assert,
11/// <tt>NDEBUG</tt> (or failure to define it) does not affect the library.
12/// The traditional Posix define <tt>NDEBUG</tt> has no effect on
13/// <tt>CRYPTOPP_DEBUG</tt> or DebugTrapHandler.
14/// \since Crypto++ 5.6.5
15/// \sa DebugTrapHandler, <A
16/// HREF="http://github.com/weidai11/cryptopp/issues/277">Issue 277</A>,
17/// <A HREF="http://seclists.org/oss-sec/2016/q3/520">CVE-2016-7420</A>
18
19#ifndef CRYPTOPP_TRAP_H
20#define CRYPTOPP_TRAP_H
21
22#include "config.h"
23
24#if defined(CRYPTOPP_DEBUG)
25# include <iostream>
26# include <sstream>
27# if defined(UNIX_SIGNALS_AVAILABLE)
28# include "ossig.h"
29# elif defined(CRYPTOPP_WIN32_AVAILABLE) && !defined(__CYGWIN__)
30 extern "C" __declspec(dllimport) void __stdcall DebugBreak();
31 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
32# endif
33#endif // CRYPTOPP_DEBUG
34
35// ************** run-time assertion ***************
36
37#if defined(CRYPTOPP_DOXYGEN_PROCESSING)
38/// \brief Debugging and diagnostic assertion
39/// \details <tt>CRYPTOPP_ASSERT</tt> is the library's debugging and diagnostic
40/// assertion. <tt>CRYPTOPP_ASSERT</tt> is enabled by the preprocessor macros
41/// <tt>CRYPTOPP_DEBUG</tt>, <tt>DEBUG</tt> or <tt>_DEBUG</tt>.
42/// \details <tt>CRYPTOPP_ASSERT</tt> raises a <tt>SIGTRAP</tt> (Unix) or calls
43/// <tt>DebugBreak()</tt> (Windows). <tt>CRYPTOPP_ASSERT</tt> is only in effect
44/// when the user explicitly requests a debug configuration.
45/// \details If you want to ensure <tt>CRYPTOPP_ASSERT</tt> is inert, then <em>do
46/// not</em> define <tt>CRYPTOPP_DEBUG</tt>, <tt>DEBUG</tt> or <tt>_DEBUG</tt>.
47/// Avoiding the defines means <tt>CRYPTOPP_ASSERT</tt> is preprocessed into an
48/// empty string.
49/// \details The traditional Posix define <tt>NDEBUG</tt> has no effect on
50/// <tt>CRYPTOPP_DEBUG</tt>, <tt>CRYPTOPP_ASSERT</tt> or DebugTrapHandler.
51/// \details An example of using CRYPTOPP_ASSERT and DebugTrapHandler is shown
52/// below. The library's test program, <tt>cryptest.exe</tt> (from test.cpp),
53/// exercises the structure:
54/// <pre>
55/// \#if defined(CRYPTOPP_DEBUG) && defined(UNIX_SIGNALS_AVAILABLE)
56/// static const DebugTrapHandler g_dummyHandler;
57/// \#endif
58///
59/// int main(int argc, char* argv[])
60/// {
61/// CRYPTOPP_ASSERT(argv != nullptr);
62/// ...
63/// }
64/// </pre>
65/// \since Crypto++ 5.6.5
66/// \sa DebugTrapHandler, SignalHandler, <A
67/// HREF="http://github.com/weidai11/cryptopp/issues/277">Issue 277</A>,
68/// <A HREF="http://seclists.org/oss-sec/2016/q3/520">CVE-2016-7420</A>
69# define CRYPTOPP_ASSERT(exp) { ... }
70#endif
71
72#if defined(CRYPTOPP_DEBUG) && defined(UNIX_SIGNALS_AVAILABLE)
73# define CRYPTOPP_ASSERT(exp) { \
74 if (!(exp)) { \
75 std::ostringstream oss; \
76 oss << "Assertion failed: " << __FILE__ << "(" \
77 << __LINE__ << "): " << __func__ \
78 << std::endl; \
79 std::cerr << oss.str(); \
80 raise(SIGTRAP); \
81 } \
82 }
83#elif CRYPTOPP_DEBUG && defined(CRYPTOPP_WIN32_AVAILABLE) && !defined(__CYGWIN__)
84# define CRYPTOPP_ASSERT(exp) { \
85 if (!(exp)) { \
86 std::ostringstream oss; \
87 oss << "Assertion failed: " << __FILE__ << "(" \
88 << __LINE__ << "): " << __FUNCTION__ \
89 << std::endl; \
90 std::cerr << oss.str(); \
91 if (IsDebuggerPresent()) {DebugBreak();} \
92 } \
93 }
94#endif // DEBUG and Unix or Windows
95
96// Remove CRYPTOPP_ASSERT in non-debug builds.
97// Can't use CRYPTOPP_UNUSED due to circular dependency
98#ifndef CRYPTOPP_ASSERT
99# define CRYPTOPP_ASSERT(exp) (void)0
100#endif
101
102NAMESPACE_BEGIN(CryptoPP)
103
104// ************** SIGTRAP handler ***************
105
106#if (CRYPTOPP_DEBUG && defined(UNIX_SIGNALS_AVAILABLE)) || defined(CRYPTOPP_DOXYGEN_PROCESSING)
107/// \brief Default SIGTRAP handler
108/// \details DebugTrapHandler() can be used by a program to install an empty
109/// SIGTRAP handler. If present, the handler ensures there is a signal
110/// handler in place for <tt>SIGTRAP</tt> raised by
111/// <tt>CRYPTOPP_ASSERT</tt>. If <tt>CRYPTOPP_ASSERT</tt> raises
112/// <tt>SIGTRAP</tt> <em>without</em> a handler, then one of two things can
113/// occur. First, the OS might allow the program to continue. Second, the OS
114/// might terminate the program. OS X allows the program to continue, while
115/// some Linuxes terminate the program.
116/// \details If DebugTrapHandler detects another handler in place, then it will
117/// not install a handler. This ensures a debugger can gain control of the
118/// <tt>SIGTRAP</tt> signal without contention. It also allows multiple
119/// DebugTrapHandler to be created without contentious or unusual behavior.
120/// Though multiple DebugTrapHandler can be created, a program should only
121/// create one, if needed.
122/// \details A DebugTrapHandler is subject to C++ static initialization
123/// [dis]order. If you need to install a handler and it must be installed
124/// early, then reference the code associated with
125/// <tt>CRYPTOPP_INIT_PRIORITY</tt> in cryptlib.cpp and cpu.cpp.
126/// \details If you want to ensure <tt>CRYPTOPP_ASSERT</tt> is inert, then
127/// <em>do not</em> define <tt>CRYPTOPP_DEBUG</tt>, <tt>DEBUG</tt> or
128/// <tt>_DEBUG</tt>. Avoiding the defines means <tt>CRYPTOPP_ASSERT</tt>
129/// is processed into <tt>((void)(exp))</tt>.
130/// \details The traditional Posix define <tt>NDEBUG</tt> has no effect on
131/// <tt>CRYPTOPP_DEBUG</tt>, <tt>CRYPTOPP_ASSERT</tt> or DebugTrapHandler.
132/// \details An example of using \ref CRYPTOPP_ASSERT "CRYPTOPP_ASSERT" and
133/// DebugTrapHandler is shown below. The library's test program,
134/// <tt>cryptest.exe</tt> (from test.cpp), exercises the structure:
135/// <pre>
136/// \#if defined(CRYPTOPP_DEBUG) && defined(UNIX_SIGNALS_AVAILABLE)
137/// static const DebugTrapHandler g_dummyHandler;
138/// \#endif
139///
140/// int main(int argc, char* argv[])
141/// {
142/// CRYPTOPP_ASSERT(argv != nullptr);
143/// ...
144/// }
145/// </pre>
146/// \since Crypto++ 5.6.5
147/// \sa \ref CRYPTOPP_ASSERT "CRYPTOPP_ASSERT", SignalHandler, <A
148/// HREF="http://github.com/weidai11/cryptopp/issues/277">Issue 277</A>,
149/// <A HREF="http://seclists.org/oss-sec/2016/q3/520">CVE-2016-7420</A>
150
151#if defined(CRYPTOPP_DOXYGEN_PROCESSING)
152class DebugTrapHandler : public SignalHandler<SIGILL, false> { };
153#else
155#endif
156
157#endif // Linux, Unix and Documentation
158
159NAMESPACE_END
160
161#endif // CRYPTOPP_TRAP_H
Default SIGTRAP handler.
Definition: trap.h:152
Library configuration file.
Crypto++ library namespace.
Utility class for trapping OS signals.
Signal handler for Linux and Unix compatibles.
Definition: ossig.h:59