Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:55:10

0001 // trap.h - written and placed in public domain by Jeffrey Walton.

0002 
0003 /// \file trap.h

0004 /// \brief Debugging and diagnostic assertions

0005 /// \details <tt>CRYPTOPP_ASSERT</tt> is the library's debugging and diagnostic

0006 ///  assertion. <tt>CRYPTOPP_ASSERT</tt> is enabled by <tt>CRYPTOPP_DEBUG</tt>,

0007 ///  <tt>DEBUG</tt> or <tt>_DEBUG</tt>.

0008 /// \details <tt>CRYPTOPP_ASSERT</tt> raises a <tt>SIGTRAP</tt> (Unix) or calls

0009 ///  <tt>DebugBreak()</tt> (Windows).

0010 /// \details <tt>CRYPTOPP_ASSERT</tt> is only in effect when the user requests a

0011 ///  debug configuration. <tt>NDEBUG</tt> (or failure to define it) does not

0012 ///  affect <tt>CRYPTOPP_ASSERT</tt>.

0013 /// \since Crypto++ 5.6.5

0014 /// \sa DebugTrapHandler, <A

0015 ///  HREF="http://github.com/weidai11/cryptopp/issues/277">Issue 277</A>,

0016 ///  <A HREF="http://seclists.org/oss-sec/2016/q3/520">CVE-2016-7420</A>

0017 
0018 #ifndef CRYPTOPP_TRAP_H
0019 #define CRYPTOPP_TRAP_H
0020 
0021 #include "config.h"
0022 
0023 #if defined(CRYPTOPP_DEBUG)
0024 #  include <iostream>
0025 #  include <sstream>
0026 #  if defined(UNIX_SIGNALS_AVAILABLE)
0027 #    include "ossig.h"
0028 #  elif defined(CRYPTOPP_WIN32_AVAILABLE) && !defined(__CYGWIN__)
0029      extern "C" __declspec(dllimport) void __stdcall DebugBreak();
0030      extern "C" __declspec(dllimport)  int __stdcall IsDebuggerPresent();
0031 #  endif
0032 #endif // CRYPTOPP_DEBUG

0033 
0034 // ************** run-time assertion ***************

0035 
0036 #if defined(CRYPTOPP_DOXYGEN_PROCESSING)
0037 /// \brief Debugging and diagnostic assertion

0038 /// \details <tt>CRYPTOPP_ASSERT</tt> is the library's debugging and diagnostic

0039 ///  assertion. <tt>CRYPTOPP_ASSERT</tt> is enabled by the preprocessor macros

0040 ///  <tt>CRYPTOPP_DEBUG</tt>, <tt>DEBUG</tt> or <tt>_DEBUG</tt>.

0041 /// \details <tt>CRYPTOPP_ASSERT</tt> raises a <tt>SIGTRAP</tt> (Unix) or calls

0042 ///  <tt>DebugBreak()</tt> (Windows). <tt>CRYPTOPP_ASSERT</tt> is only in effect

0043 ///  when the user explicitly requests a debug configuration.

0044 /// \details If you want to ensure <tt>CRYPTOPP_ASSERT</tt> is inert, then <em>do

0045 ///  not</em> define <tt>CRYPTOPP_DEBUG</tt>, <tt>DEBUG</tt> or <tt>_DEBUG</tt>.

0046 ///  Avoiding the defines means <tt>CRYPTOPP_ASSERT</tt> is preprocessed into an

0047 ///  empty string.

0048 /// \details The traditional Posix define <tt>NDEBUG</tt> has no effect on

0049 ///  <tt>CRYPTOPP_DEBUG</tt>, <tt>CRYPTOPP_ASSERT</tt> or DebugTrapHandler.

0050 /// \details An example of using CRYPTOPP_ASSERT and DebugTrapHandler is shown

0051 ///  below. The library's test program, <tt>cryptest.exe</tt> (from test.cpp),

0052 ///  exercises the structure:

0053 ///  <pre>

0054 ///   \#if defined(CRYPTOPP_DEBUG) && defined(UNIX_SIGNALS_AVAILABLE)

0055 ///   static const DebugTrapHandler g_dummyHandler;

0056 ///   \#endif

0057 ///

0058 ///   int main(int argc, char* argv[])

0059 ///   {

0060 ///      CRYPTOPP_ASSERT(argv != nullptr);

0061 ///      ...

0062 ///   }

0063 ///  </pre>

0064 /// \since Crypto++ 5.6.5

0065 /// \sa DebugTrapHandler, SignalHandler, <A

0066 ///  HREF="http://github.com/weidai11/cryptopp/issues/277">Issue 277</A>,

0067 ///  <A HREF="http://seclists.org/oss-sec/2016/q3/520">CVE-2016-7420</A>

0068 #  define CRYPTOPP_ASSERT(exp) { ... }
0069 #endif
0070 
0071 #if defined(CRYPTOPP_DEBUG)
0072 # if defined(UNIX_SIGNALS_AVAILABLE) || defined(__CYGWIN__)
0073 #  define CRYPTOPP_ASSERT(exp) {                                  \
0074     if (!(exp)) {                                                 \
0075       std::ostringstream oss;                                     \
0076       oss << "Assertion failed: " << __FILE__ << "("              \
0077           << __LINE__ << "): " << __func__                        \
0078           << std::endl;                                           \
0079       std::cout << std::flush;                                    \
0080       std::cerr << oss.str();                                     \
0081       raise(SIGTRAP);                                             \
0082     }                                                             \
0083   }
0084 # elif CRYPTOPP_DEBUG && defined(CRYPTOPP_WIN32_AVAILABLE)
0085 #  define CRYPTOPP_ASSERT(exp) {                                  \
0086     if (!(exp)) {                                                 \
0087       std::ostringstream oss;                                     \
0088       oss << "Assertion failed: " << __FILE__ << "("              \
0089           << __LINE__ << "): " << __FUNCTION__                    \
0090           << std::endl;                                           \
0091       std::cout << std::flush;                                    \
0092       std::cerr << oss.str();                                     \
0093       if (IsDebuggerPresent()) {DebugBreak();}                    \
0094     }                                                             \
0095   }
0096 # endif // Unix or Windows

0097 #endif  // CRYPTOPP_DEBUG

0098 
0099 // Remove CRYPTOPP_ASSERT in non-debug builds.

0100 #ifndef CRYPTOPP_ASSERT
0101 #  define CRYPTOPP_ASSERT(exp) (void)0
0102 #endif
0103 
0104 NAMESPACE_BEGIN(CryptoPP)
0105 
0106 // ************** SIGTRAP handler ***************

0107 
0108 #if (CRYPTOPP_DEBUG && defined(UNIX_SIGNALS_AVAILABLE)) || defined(CRYPTOPP_DOXYGEN_PROCESSING)
0109 /// \brief Default SIGTRAP handler

0110 /// \details DebugTrapHandler() can be used by a program to install an empty

0111 ///  SIGTRAP handler. If present, the handler ensures there is a signal

0112 ///  handler in place for <tt>SIGTRAP</tt> raised by

0113 ///  <tt>CRYPTOPP_ASSERT</tt>. If <tt>CRYPTOPP_ASSERT</tt> raises

0114 ///  <tt>SIGTRAP</tt> <em>without</em> a handler, then one of two things can

0115 ///  occur. First, the OS might allow the program to continue. Second, the OS

0116 ///  might terminate the program. OS X allows the program to continue, while

0117 ///  some Linuxes terminate the program.

0118 /// \details If DebugTrapHandler detects another handler in place, then it will

0119 ///  not install a handler. This ensures a debugger can gain control of the

0120 ///  <tt>SIGTRAP</tt> signal without contention. It also allows multiple

0121 ///  DebugTrapHandler to be created without contentious or unusual behavior.

0122 ///  Though multiple DebugTrapHandler can be created, a program should only

0123 ///  create one, if needed.

0124 /// \details A DebugTrapHandler is subject to C++ static initialization

0125 ///  [dis]order. If you need to install a handler and it must be installed

0126 ///  early, then reference the code associated with

0127 ///  <tt>CRYPTOPP_INIT_PRIORITY</tt> in cryptlib.cpp and cpu.cpp.

0128 /// \details If you want to ensure <tt>CRYPTOPP_ASSERT</tt> is inert, then

0129 ///  <em>do not</em> define <tt>CRYPTOPP_DEBUG</tt>, <tt>DEBUG</tt> or

0130 ///  <tt>_DEBUG</tt>. Avoiding the defines means <tt>CRYPTOPP_ASSERT</tt>

0131 ///  is processed into <tt>((void)0)</tt>.

0132 /// \details The traditional Posix define <tt>NDEBUG</tt> has no effect on

0133 ///  <tt>CRYPTOPP_DEBUG</tt>, <tt>CRYPTOPP_ASSERT</tt> or DebugTrapHandler.

0134 /// \details An example of using \ref CRYPTOPP_ASSERT "CRYPTOPP_ASSERT" and

0135 ///  DebugTrapHandler is shown below. The library's test program,

0136 ///  <tt>cryptest.exe</tt> (from test.cpp), exercises the structure:

0137 ///  <pre>

0138 ///   \#if defined(CRYPTOPP_DEBUG) && defined(UNIX_SIGNALS_AVAILABLE)

0139 ///   const DebugTrapHandler g_dummyHandler;

0140 ///   \#endif

0141 ///

0142 ///   int main(int argc, char* argv[])

0143 ///   {

0144 ///      CRYPTOPP_ASSERT(argv != nullptr);

0145 ///      ...

0146 ///   }

0147 ///  </pre>

0148 /// \since Crypto++ 5.6.5

0149 /// \sa \ref CRYPTOPP_ASSERT "CRYPTOPP_ASSERT", SignalHandler, <A

0150 ///  HREF="http://github.com/weidai11/cryptopp/issues/277">Issue 277</A>,

0151 ///  <A HREF="http://seclists.org/oss-sec/2016/q3/520">CVE-2016-7420</A>

0152 
0153 #if defined(CRYPTOPP_DOXYGEN_PROCESSING)
0154 class DebugTrapHandler : public SignalHandler<SIGTRAP, false> { };
0155 #else
0156 typedef SignalHandler<SIGTRAP, false> DebugTrapHandler;
0157 #endif
0158 
0159 #endif  // Linux, Unix and Documentation

0160 
0161 NAMESPACE_END
0162 
0163 #endif // CRYPTOPP_TRAP_H