From d470d177913bb3cb5530c9ae38ed56d7c13bb44b Mon Sep 17 00:00:00 2001 From: kgv Date: Fri, 15 Mar 2019 13:16:06 +0300 Subject: [PATCH] Added building option OCCT_DEBUG_SANITIZE_EXCEPTIONS for performing expensive checks When this option is ON, opencascade::handle throws std::runtime_error() on NULL pointer dereference, and Standard_OutOfRange_Raise_if throws std::runtime_error() instead of Standard_OutOfRange to detect cases when broken code remains hidden by exception handling. --- CMakeLists.txt | 11 +++++++++++ adm/cmake/vardescr.cmake | 4 ++++ src/OSD/OSD_signal.cxx | 8 ++++++-- src/Standard/Standard_Handle.hxx | 26 ++++++++++++++++++++++++-- src/Standard/Standard_OutOfRange.hxx | 5 ++++- 5 files changed, 49 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index dc64c3c2bd..3768892b5f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -91,6 +91,17 @@ if (NOT DEFINED BUILD_RELEASE_DISABLE_EXCEPTIONS) set (BUILD_RELEASE_DISABLE_EXCEPTIONS ON CACHE BOOL "${BUILD_RELEASE_DISABLE_EXCEPTIONS_DESCR}") endif() +# option enabling extra exceptions (OCCT_DEBUG_SANITIZE_EXCEPTIONS) +if (NOT DEFINED BUILD_ENABLE_SANITIZE_EXCEPTIONS) + set (BUILD_ENABLE_SANITIZE_EXCEPTIONS OFF CACHE BOOL "${BUILD_ENABLE_SANITIZE_EXCEPTIONS_DESCR}") +endif() + +if (BUILD_ENABLE_SANITIZE_EXCEPTIONS) + add_definitions (-DOCCT_DEBUG_SANITIZE_EXCEPTIONS) +endif() +# DEBUG +add_definitions (-DOCCT_DEBUG_SANITIZE_EXCEPTIONS) + # option to enable or disable use of precompiled headers if (NOT DEFINED BUILD_USE_PCH) set (BUILD_USE_PCH OFF CACHE BOOL "${BUILD_USE_PCH_DESCR}") diff --git a/adm/cmake/vardescr.cmake b/adm/cmake/vardescr.cmake index 29fa030815..6a8f2cf067 100644 --- a/adm/cmake/vardescr.cmake +++ b/adm/cmake/vardescr.cmake @@ -33,6 +33,10 @@ set (BUILD_RELEASE_DISABLE_EXCEPTIONS_DESCR Defines No_Exception macros for Release builds when enabled (default). These exceptions are always enabled in Debug builds, but disable in Release for better performance") +set (BUILD_ENABLE_SANITIZE_EXCEPTIONS_DESCR +"Enables extra exceptions for detecting broken code. Should NOT be used for production. +Defines OCCT_DEBUG_SANITIZE_EXCEPTIONS macros when enabled (OFF by default).") + set (BUILD_ENABLE_FPE_SIGNAL_HANDLER_DESCR "Enable/Disable the floating point exceptions (FPE) during DRAW execution only. Corresponding environment variable (CSF_FPE) can be changed manually diff --git a/src/OSD/OSD_signal.cxx b/src/OSD/OSD_signal.cxx index 79031e6287..c9eba4cd48 100644 --- a/src/OSD/OSD_signal.cxx +++ b/src/OSD/OSD_signal.cxx @@ -93,10 +93,14 @@ static LONG _osd_debug ( void ); //# define _OSD_FPX ( _EM_INVALID | _EM_DENORMAL | _EM_ZERODIVIDE | _EM_OVERFLOW | _EM_UNDERFLOW ) # define _OSD_FPX ( _EM_INVALID | _EM_DENORMAL | _EM_ZERODIVIDE | _EM_OVERFLOW ) +#ifdef OCCT_DEBUG_SANITIZE_EXCEPTIONS + #define THROW_OR_JUMP(Type,Message) throw std::runtime_error (Message) +#else #ifdef OCC_CONVERT_SIGNALS -#define THROW_OR_JUMP(Type,Message) Type::NewInstance(Message)->Jump() + #define THROW_OR_JUMP(Type,Message) Type::NewInstance(Message)->Jump() #else -#define THROW_OR_JUMP(Type,Message) throw Type(Message) + #define THROW_OR_JUMP(Type,Message) throw Type(Message) +#endif #endif //======================================================================= diff --git a/src/Standard/Standard_Handle.hxx b/src/Standard/Standard_Handle.hxx index 9e7a3a6a5e..e22e4bc869 100644 --- a/src/Standard/Standard_Handle.hxx +++ b/src/Standard/Standard_Handle.hxx @@ -20,6 +20,10 @@ #include +#ifdef OCCT_DEBUG_SANITIZE_EXCEPTIONS + #include +#endif + class Standard_Transient; //! Namespace opencascade is intended for low-level template classes and functions @@ -181,10 +185,28 @@ namespace opencascade { T* get() const { return static_cast(this->entity); } //! Member access operator (note non-const) - T* operator-> () const { return static_cast(this->entity); } + T* operator-> () const + { + #ifdef OCCT_DEBUG_SANITIZE_EXCEPTIONS + if (entity == 0) + { + throw std::runtime_error ("null pointer exception"); + } + #endif + return static_cast(this->entity); + } //! Dereferencing operator (note non-const) - T& operator* () const { return *get(); } + T& operator* () const + { + #ifdef OCCT_DEBUG_SANITIZE_EXCEPTIONS + if (entity == 0) + { + throw std::runtime_error ("null pointer exception"); + } + #endif + return *get(); + } //! Check for equality template diff --git a/src/Standard/Standard_OutOfRange.hxx b/src/Standard/Standard_OutOfRange.hxx index 0d2cf80a95..68ad9be015 100644 --- a/src/Standard/Standard_OutOfRange.hxx +++ b/src/Standard/Standard_OutOfRange.hxx @@ -25,7 +25,10 @@ class Standard_OutOfRange; DEFINE_STANDARD_HANDLE(Standard_OutOfRange, Standard_RangeError) -#if !defined No_Exception && !defined No_Standard_OutOfRange +#ifdef OCCT_DEBUG_SANITIZE_EXCEPTIONS +#define Standard_OutOfRange_Raise_if(CONDITION, MESSAGE) \ + if (CONDITION) throw std::runtime_error (MESSAGE); +#elif !defined No_Exception && !defined No_Standard_OutOfRange #if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2)) // suppress false-positive warnings produced by GCC optimizer #define Standard_OutOfRange_Raise_if(CONDITION, MESSAGE) \ -- 2.39.5