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