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