Crypto++  8.8
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 
104 NAMESPACE_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)
154 class DebugTrapHandler : public SignalHandler<SIGTRAP, false> { };
155 #else
157 #endif
158 
159 #endif // Linux, Unix and Documentation
160 
161 NAMESPACE_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