2009-10-19 20:57:11 +02:00
|
|
|
/*
|
|
|
|
* Cppcheck - A tool for static C/C++ code analysis
|
2022-02-05 11:45:17 +01:00
|
|
|
* Copyright (C) 2007-2022 Cppcheck team.
|
2009-10-19 20:57:11 +02:00
|
|
|
*
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
#ifndef checkexceptionsafetyH
|
|
|
|
#define checkexceptionsafetyH
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
#include "check.h"
|
2017-05-27 04:33:47 +02:00
|
|
|
#include "config.h"
|
2020-05-23 07:16:49 +02:00
|
|
|
#include "errortypes.h"
|
2017-05-27 04:33:47 +02:00
|
|
|
#include "tokenize.h"
|
2009-10-19 20:57:11 +02:00
|
|
|
|
2017-05-27 04:33:47 +02:00
|
|
|
#include <string>
|
|
|
|
|
|
|
|
class Settings;
|
2020-05-23 07:16:49 +02:00
|
|
|
class ErrorLogger;
|
2021-12-15 19:47:27 +01:00
|
|
|
class Token;
|
2017-05-27 04:33:47 +02:00
|
|
|
|
CWE mapping of unsafeClassCanLeak, zerodivcond, invalidPointerCast, redundantCopy, redundantAssignment, comparisonFunctionIsAlwaysTrueOrFalse, checkCastIntToCharAndBack, cstyleCast, passedByValue, clarifyCondition, exceptThrowInDestructor, exceptDeallocThrow, exceptRethrowCopy, catchExceptionByValue, fflushOnInputStream, seekOnAppendedFile, publicAllocationError
CWE mapping of unsafeClassCanLeak, zerodivcond, invalidPointerCast, redundantCopy, redundantAssignment, comparisonFunctionIsAlwaysTrueOrFalse, checkCastIntToCharAndBack, cstyleCast, passedByValue, clarifyCondition, exceptThrowInDestructor, exceptDeallocThrow, exceptRethrowCopy, catchExceptionByValue, fflushOnInputStream, seekOnAppendedFile, publicAllocationError
2016-04-12 19:29:40 +02:00
|
|
|
// CWE ID used:
|
|
|
|
static const struct CWE CWE398(398U); // Indicator of Poor Code Quality
|
2016-08-24 12:43:45 +02:00
|
|
|
static const struct CWE CWE703(703U); // Improper Check or Handling of Exceptional Conditions
|
2021-05-31 10:39:24 +02:00
|
|
|
static const struct CWE CWE480(480U); // Use of Incorrect Operator
|
CWE mapping of unsafeClassCanLeak, zerodivcond, invalidPointerCast, redundantCopy, redundantAssignment, comparisonFunctionIsAlwaysTrueOrFalse, checkCastIntToCharAndBack, cstyleCast, passedByValue, clarifyCondition, exceptThrowInDestructor, exceptDeallocThrow, exceptRethrowCopy, catchExceptionByValue, fflushOnInputStream, seekOnAppendedFile, publicAllocationError
CWE mapping of unsafeClassCanLeak, zerodivcond, invalidPointerCast, redundantCopy, redundantAssignment, comparisonFunctionIsAlwaysTrueOrFalse, checkCastIntToCharAndBack, cstyleCast, passedByValue, clarifyCondition, exceptThrowInDestructor, exceptDeallocThrow, exceptRethrowCopy, catchExceptionByValue, fflushOnInputStream, seekOnAppendedFile, publicAllocationError
2016-04-12 19:29:40 +02:00
|
|
|
|
|
|
|
|
2009-10-19 20:57:11 +02:00
|
|
|
/// @addtogroup Checks
|
|
|
|
/// @{
|
|
|
|
|
|
|
|
|
2010-03-13 21:12:18 +01:00
|
|
|
/**
|
2010-03-13 22:16:06 +01:00
|
|
|
* @brief %Check exception safety (exceptions shouldn't cause leaks nor corrupt data)
|
2010-03-13 21:12:18 +01:00
|
|
|
*
|
|
|
|
* The problem with these checks is that Cppcheck can't determine what the valid
|
|
|
|
* values are for variables. But in some cases (dead pointers) it can be determined
|
|
|
|
* that certain variable values are corrupt.
|
|
|
|
*/
|
|
|
|
|
2012-06-10 14:19:09 +02:00
|
|
|
class CPPCHECKLIB CheckExceptionSafety : public Check {
|
2009-10-19 20:57:11 +02:00
|
|
|
public:
|
|
|
|
/** This constructor is used when registering the CheckClass */
|
2021-08-07 20:51:18 +02:00
|
|
|
CheckExceptionSafety() : Check(myName()) {}
|
2009-10-19 20:57:11 +02:00
|
|
|
|
2010-03-17 22:16:18 +01:00
|
|
|
/** This constructor is used when running checks. */
|
2009-10-19 20:57:11 +02:00
|
|
|
CheckExceptionSafety(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
|
2021-08-07 20:51:18 +02:00
|
|
|
: Check(myName(), tokenizer, settings, errorLogger) {}
|
2009-10-19 20:57:11 +02:00
|
|
|
|
2019-03-16 07:19:48 +01:00
|
|
|
void runChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) OVERRIDE {
|
2012-09-10 19:02:32 +02:00
|
|
|
if (tokenizer->isC())
|
|
|
|
return;
|
|
|
|
|
2009-10-19 20:57:11 +02:00
|
|
|
CheckExceptionSafety checkExceptionSafety(tokenizer, settings, errorLogger);
|
|
|
|
checkExceptionSafety.destructors();
|
2009-11-08 09:54:08 +01:00
|
|
|
checkExceptionSafety.deallocThrow();
|
2011-02-05 10:11:09 +01:00
|
|
|
checkExceptionSafety.checkRethrowCopy();
|
2012-02-02 16:17:42 +01:00
|
|
|
checkExceptionSafety.checkCatchExceptionByValue();
|
2014-04-10 16:17:10 +02:00
|
|
|
checkExceptionSafety.nothrowThrows();
|
2014-04-20 08:58:36 +02:00
|
|
|
checkExceptionSafety.unhandledExceptionSpecification();
|
2021-05-31 10:39:24 +02:00
|
|
|
checkExceptionSafety.rethrowNoCurrentException();
|
2009-10-19 20:57:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/** Don't throw exceptions in destructors */
|
|
|
|
void destructors();
|
|
|
|
|
2010-12-31 13:58:17 +01:00
|
|
|
/** deallocating memory and then throw (dead pointer) */
|
2009-11-08 09:54:08 +01:00
|
|
|
void deallocThrow();
|
|
|
|
|
2011-02-05 10:11:09 +01:00
|
|
|
/** Don't rethrow a copy of the caught exception; use a bare throw instead */
|
|
|
|
void checkRethrowCopy();
|
|
|
|
|
2012-02-02 16:17:42 +01:00
|
|
|
/** @brief %Check for exceptions that are caught by value instead of by reference */
|
|
|
|
void checkCatchExceptionByValue();
|
|
|
|
|
2014-04-20 20:40:55 +02:00
|
|
|
/** @brief %Check for functions that throw that shouldn't */
|
2014-04-10 16:17:10 +02:00
|
|
|
void nothrowThrows();
|
|
|
|
|
2014-04-20 08:58:36 +02:00
|
|
|
/** @brief %Check for unhandled exception specification */
|
|
|
|
void unhandledExceptionSpecification();
|
|
|
|
|
2021-05-31 10:39:24 +02:00
|
|
|
/** @brief %Check for rethrow not from catch scope */
|
|
|
|
void rethrowNoCurrentException();
|
|
|
|
|
2009-10-19 20:57:11 +02:00
|
|
|
private:
|
|
|
|
/** Don't throw exceptions in destructors */
|
2021-06-02 07:00:10 +02:00
|
|
|
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);
|
2014-04-20 08:58:36 +02:00
|
|
|
/** Missing exception specification */
|
2021-06-02 07:00:10 +02:00
|
|
|
void unhandledExceptionSpecificationError(const Token * const tok1, const Token * const tok2, const std::string & funcname);
|
2021-05-31 10:39:24 +02:00
|
|
|
/** Rethrow without currently handled exception */
|
|
|
|
void rethrowNoCurrentExceptionError(const Token *tok);
|
|
|
|
|
2010-03-13 21:12:18 +01:00
|
|
|
/** Generate all possible errors (for --errorlist) */
|
2019-01-12 07:37:42 +01:00
|
|
|
void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const OVERRIDE {
|
2016-05-07 16:30:54 +02:00
|
|
|
CheckExceptionSafety c(nullptr, settings, errorLogger);
|
|
|
|
c.destructorsError(nullptr, "Class");
|
|
|
|
c.deallocThrowError(nullptr, "p");
|
|
|
|
c.rethrowCopyError(nullptr, "varname");
|
|
|
|
c.catchExceptionByValueError(nullptr);
|
|
|
|
c.noexceptThrowError(nullptr);
|
2017-08-09 20:00:26 +02:00
|
|
|
c.unhandledExceptionSpecificationError(nullptr, nullptr, "funcname");
|
2021-05-31 10:39:24 +02:00
|
|
|
c.rethrowNoCurrentExceptionError(nullptr);
|
2009-10-19 20:57:11 +02:00
|
|
|
}
|
|
|
|
|
2010-03-13 21:12:18 +01:00
|
|
|
/** Short description of class (for --doc) */
|
2014-11-20 14:20:09 +01:00
|
|
|
static std::string myName() {
|
2009-10-19 20:57:11 +02:00
|
|
|
return "Exception Safety";
|
|
|
|
}
|
|
|
|
|
2010-03-13 21:12:18 +01:00
|
|
|
/** wiki formatted description of the class (for --doc) */
|
2019-01-12 07:37:42 +01:00
|
|
|
std::string classInfo() const OVERRIDE {
|
2009-10-19 20:57:11 +02:00
|
|
|
return "Checking exception safety\n"
|
2014-09-30 14:56:12 +02:00
|
|
|
"- Throwing exceptions in destructors\n"
|
|
|
|
"- Throwing exception during invalid state\n"
|
|
|
|
"- Throwing a copy of a caught exception instead of rethrowing the original exception\n"
|
|
|
|
"- Exception caught by value instead of by reference\n"
|
2015-01-09 20:18:09 +01:00
|
|
|
"- Throwing exception in noexcept, nothrow(), __attribute__((nothrow)) or __declspec(nothrow) function\n"
|
2021-05-31 10:39:24 +02:00
|
|
|
"- Unhandled exception specification when calling function foo()\n"
|
|
|
|
"- Rethrow without currently handled exception\n";
|
2009-10-19 20:57:11 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
/// @}
|
|
|
|
//---------------------------------------------------------------------------
|
2013-09-04 20:59:49 +02:00
|
|
|
#endif // checkexceptionsafetyH
|