diff --git a/lib/checkexceptionsafety.cpp b/lib/checkexceptionsafety.cpp index 365878d9f..ef2e9b69c 100644 --- a/lib/checkexceptionsafety.cpp +++ b/lib/checkexceptionsafety.cpp @@ -72,7 +72,13 @@ void CheckExceptionSafety::destructors() } } - +void CheckExceptionSafety::destructorsError(const Token * const tok, const std::string &className) { + reportError(tok, Severity::warning, "exceptThrowInDestructor", + "Class " + className + " is not safe, destructor throws exception\n" + "The class " + className + " is not safe because its destructor " + "throws an exception. If " + className + " is used and an exception " + "is thrown that is caught in an outer scope the program will terminate.", CWE398, Certainty::normal); +} void CheckExceptionSafety::deallocThrow() @@ -136,6 +142,11 @@ void CheckExceptionSafety::deallocThrow() } } +void CheckExceptionSafety::deallocThrowError(const Token * const tok, const std::string &varname) { + reportError(tok, Severity::warning, "exceptDeallocThrow", "Exception thrown in invalid state, '" + + varname + "' points at deallocated memory.", CWE398, Certainty::normal); +} + //--------------------------------------------------------------------------- // catch(const exception & err) // { @@ -173,6 +184,13 @@ void CheckExceptionSafety::checkRethrowCopy() } } +void CheckExceptionSafety::rethrowCopyError(const Token * const tok, const std::string &varname) { + reportError(tok, Severity::style, "exceptRethrowCopy", + "Throwing a copy of the caught exception instead of rethrowing the original exception.\n" + "Rethrowing an exception with 'throw " + varname + ";' creates an unnecessary copy of '" + varname + "'. " + "To rethrow the caught exception without unnecessary copying or slicing, use a bare 'throw;'.", CWE398, Certainty::normal); +} + //--------------------------------------------------------------------------- // try {} catch (std::exception err) {} <- Should be "std::exception& err" //--------------------------------------------------------------------------- @@ -195,6 +213,13 @@ void CheckExceptionSafety::checkCatchExceptionByValue() } } +void CheckExceptionSafety::catchExceptionByValueError(const Token *tok) { + reportError(tok, Severity::style, + "catchExceptionByValue", "Exception should be caught by reference.\n" + "The exception is caught by value. It could be caught " + "as a (const) reference which is usually recommended in C++.", CWE398, Certainty::normal); +} + static const Token * functionThrowsRecursive(const Function * function, std::set & recursive) { @@ -273,6 +298,10 @@ void CheckExceptionSafety::nothrowThrows() } } +void CheckExceptionSafety::noexceptThrowError(const Token * const tok) { + reportError(tok, Severity::error, "throwInNoexceptFunction", "Exception thrown in function declared not to throw exceptions.", CWE398, Certainty::normal); +} + //-------------------------------------------------------------------------- // void func() { functionWithExceptionSpecification(); } //-------------------------------------------------------------------------- @@ -305,6 +334,15 @@ void CheckExceptionSafety::unhandledExceptionSpecification() } } +void CheckExceptionSafety::unhandledExceptionSpecificationError(const Token * const tok1, const Token * const tok2, const std::string & funcname) { + const std::string str1(tok1 ? tok1->str() : "foo"); + const std::list locationList = { tok1, tok2 }; + reportError(locationList, Severity::style, "unhandledExceptionSpecification", + "Unhandled exception specification when calling function " + str1 + "().\n" + "Unhandled exception specification when calling function " + str1 + "(). " + "Either use a try/catch around the function call, or add a exception specification for " + funcname + "() also.", CWE703, Certainty::inconclusive); +} + //-------------------------------------------------------------------------- // 7.6.18.4 If no exception is presently being handled, evaluating a throw-expression with no operand calls std​::​​terminate(). //-------------------------------------------------------------------------- diff --git a/lib/checkexceptionsafety.h b/lib/checkexceptionsafety.h index f316e4683..a169ae83f 100644 --- a/lib/checkexceptionsafety.h +++ b/lib/checkexceptionsafety.h @@ -99,47 +99,13 @@ public: private: /** Don't throw exceptions in destructors */ - void destructorsError(const Token * const tok, const std::string &className) { - reportError(tok, Severity::warning, "exceptThrowInDestructor", - "Class " + className + " is not safe, destructor throws exception\n" - "The class " + className + " is not safe because its destructor " - "throws an exception. If " + className + " is used and an exception " - "is thrown that is caught in an outer scope the program will terminate.", CWE398, Certainty::normal); - } - - void deallocThrowError(const Token * const tok, const std::string &varname) { - reportError(tok, Severity::warning, "exceptDeallocThrow", "Exception thrown in invalid state, '" + - varname + "' points at deallocated memory.", CWE398, Certainty::normal); - } - - void rethrowCopyError(const Token * const tok, const std::string &varname) { - reportError(tok, Severity::style, "exceptRethrowCopy", - "Throwing a copy of the caught exception instead of rethrowing the original exception.\n" - "Rethrowing an exception with 'throw " + varname + ";' creates an unnecessary copy of '" + varname + "'. " - "To rethrow the caught exception without unnecessary copying or slicing, use a bare 'throw;'.", CWE398, Certainty::normal); - } - - void catchExceptionByValueError(const Token *tok) { - reportError(tok, Severity::style, - "catchExceptionByValue", "Exception should be caught by reference.\n" - "The exception is caught by value. It could be caught " - "as a (const) reference which is usually recommended in C++.", CWE398, Certainty::normal); - } - - void noexceptThrowError(const Token * const tok) { - reportError(tok, Severity::error, "throwInNoexceptFunction", "Exception thrown in function declared not to throw exceptions.", CWE398, Certainty::normal); - } - + void destructorsError(const Token * const tok, const std::string &className); + void deallocThrowError(const Token * const tok, const std::string &varname); + void rethrowCopyError(const Token * const tok, const std::string &varname); + void catchExceptionByValueError(const Token *tok); + void noexceptThrowError(const Token * const tok); /** Missing exception specification */ - void unhandledExceptionSpecificationError(const Token * const tok1, const Token * const tok2, const std::string & funcname) { - const std::string str1(tok1 ? tok1->str() : "foo"); - const std::list locationList = { tok1, tok2 }; - reportError(locationList, Severity::style, "unhandledExceptionSpecification", - "Unhandled exception specification when calling function " + str1 + "().\n" - "Unhandled exception specification when calling function " + str1 + "(). " - "Either use a try/catch around the function call, or add a exception specification for " + funcname + "() also.", CWE703, Certainty::inconclusive); - } - + void unhandledExceptionSpecificationError(const Token * const tok1, const Token * const tok2, const std::string & funcname); /** Rethrow without currently handled exception */ void rethrowNoCurrentExceptionError(const Token *tok);