From 1d2065de1b255e3e3c91ef38c527e4644525079a Mon Sep 17 00:00:00 2001 From: firewave Date: Mon, 7 Apr 2025 14:40:29 +0200 Subject: [PATCH 1/3] added script to detect missing `--errorlist` entries and test coverage --- tools/errorid.sh | 29 +++++++++++++++++++++++++++++ tools/readme.md | 5 +++++ 2 files changed, 34 insertions(+) create mode 100755 tools/errorid.sh diff --git a/tools/errorid.sh b/tools/errorid.sh new file mode 100755 index 00000000000..3de53630ec7 --- /dev/null +++ b/tools/errorid.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +#set -x + +SCRIPT_DIR="$(dirname "$(realpath "$0")")" + +# TODO: exclude testinternal.cpp +echo 'no --errorlist entry:' +grep -h -o -P '\[[a-zA-Z0-9_]+\]\\n\"' $SCRIPT_DIR/../test/*.cpp | tr -d '[]\"' | sed 's/\\n$//' | sort -u | \ +while read -r id; do + if [ ${#id} -lt 4 ]; then + continue + fi + $SCRIPT_DIR/../cppcheck --errorlist | grep "id=\"$id\"" > /dev/null + if [ $? -ne 0 ]; then + echo $id + fi +done + +echo '' + +echo 'no test coverage:' +$SCRIPT_DIR/../cppcheck --errorlist | grep -h -o -P 'id=\"[a-zA-Z0-9_]*\"' | sed 's/\id=//' | tr -d '\"' | sort -u | \ +while read -r id; do + grep -h -o -P "\[$id\]\\\\n\"" $SCRIPT_DIR/../test/*.cpp > /dev/null + if [ $? -ne 0 ]; then + echo $id + fi +done \ No newline at end of file diff --git a/tools/readme.md b/tools/readme.md index 436f3322b1d..70d6cc75c3e 100644 --- a/tools/readme.md +++ b/tools/readme.md @@ -78,3 +78,8 @@ Script to compare result of working Cppcheck from your branch with main branch. This tool lets you comfortably look at Cppcheck analysis results for daca packages. It automatically downloads the package, extracts it and jumps to the corresponding source code for a Cppcheck message. + +### * tools/errorid.sh + +Script to compare the error IDs in the expected `testrunner` output (without executing it) with the `--errorlist` output. +It will report missing test coverage for an ID and missing IDs in the `--errorlist` output. From bad038c4f6b03a438759dedd7edded510144cee7 Mon Sep 17 00:00:00 2001 From: firewave Date: Mon, 7 Apr 2025 14:48:00 +0200 Subject: [PATCH 2/3] added some missing `--errorlist` entries --- Makefile | 2 +- lib/checkbufferoverrun.cpp | 3 +++ lib/checkclass.cpp | 1 + lib/checkfunctions.cpp | 2 ++ lib/checknullpointer.cpp | 4 ++++ lib/checkother.cpp | 4 ++++ lib/checkstl.cpp | 11 ++++++++++- lib/checktype.cpp | 2 ++ lib/checkuninitvar.cpp | 2 +- lib/checkunusedfunctions.cpp | 9 +++------ lib/checkunusedfunctions.h | 5 +++++ lib/cppcheck.cpp | 2 ++ lib/symboldatabase.cpp | 7 +++++++ lib/symboldatabase.h | 2 ++ oss-fuzz/Makefile | 2 +- 15 files changed, 48 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index 4d7b43b7b29..6b88b7445c6 100644 --- a/Makefile +++ b/Makefile @@ -563,7 +563,7 @@ $(libcppdir)/clangimport.o: lib/clangimport.cpp lib/addoninfo.h lib/checkers.h l $(libcppdir)/color.o: lib/color.cpp lib/color.h lib/config.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/color.cpp -$(libcppdir)/cppcheck.o: lib/cppcheck.cpp externals/picojson/picojson.h externals/simplecpp/simplecpp.h externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/analyzerinfo.h lib/check.h lib/checkers.h lib/checkunusedfunctions.h lib/clangimport.h lib/color.h lib/config.h lib/cppcheck.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/json.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/preprocessor.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/version.h lib/vfvalue.h lib/xml.h +$(libcppdir)/cppcheck.o: lib/cppcheck.cpp externals/picojson/picojson.h externals/simplecpp/simplecpp.h externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/analyzerinfo.h lib/check.h lib/checkers.h lib/checkunusedfunctions.h lib/clangimport.h lib/color.h lib/config.h lib/cppcheck.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/filesettings.h lib/json.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/preprocessor.h lib/settings.h lib/sourcelocation.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/version.h lib/vfvalue.h lib/xml.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/cppcheck.cpp $(libcppdir)/ctu.o: lib/ctu.cpp externals/tinyxml2/tinyxml2.h lib/addoninfo.h lib/astutils.h lib/check.h lib/checkers.h lib/config.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/smallvector.h lib/sourcelocation.h lib/standards.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h lib/xml.h diff --git a/lib/checkbufferoverrun.cpp b/lib/checkbufferoverrun.cpp index e79f8d05c6f..ed0ad16510a 100644 --- a/lib/checkbufferoverrun.cpp +++ b/lib/checkbufferoverrun.cpp @@ -1235,4 +1235,7 @@ void CheckBufferOverrun::getErrorMessages(ErrorLogger *errorLogger, const Settin c.argumentSizeError(nullptr, "function", 1, "buffer", nullptr, nullptr); c.negativeMemoryAllocationSizeError(nullptr, nullptr); c.negativeArraySizeError(nullptr); + c.terminateStrncpyError(nullptr, "var_name"); + // TODO: ctuArrayIndex + // TODO: ctuPointerArith } diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index 3c461c0ab44..7877c1bd576 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -3819,4 +3819,5 @@ void CheckClass::getErrorMessages(ErrorLogger *errorLogger, const Settings *sett c.virtualFunctionCallInConstructorError(nullptr, std::list(), "f"); c.thisUseAfterFree(nullptr, nullptr, nullptr); c.unsafeClassRefMemberError(nullptr, "UnsafeClass::var"); + // TODO: ctuOneDefinitionRuleViolation } diff --git a/lib/checkfunctions.cpp b/lib/checkfunctions.cpp index 26ff9736f43..8884a03fc48 100644 --- a/lib/checkfunctions.cpp +++ b/lib/checkfunctions.cpp @@ -865,6 +865,7 @@ void CheckFunctions::getErrorMessages(ErrorLogger *errorLogger, const Settings * c.invalidFunctionArgBoolError(nullptr, "func_name", 1); c.invalidFunctionArgStrError(nullptr, "func_name", 1); c.ignoredReturnValueError(nullptr, "malloc"); + c.ignoredReturnErrorCode(nullptr, "func_name"); c.mathfunctionCallWarning(nullptr); c.mathfunctionCallWarning(nullptr, "1 - erf(x)", "erfc(x)"); c.memsetZeroBytesError(nullptr); @@ -873,4 +874,5 @@ void CheckFunctions::getErrorMessages(ErrorLogger *errorLogger, const Settings * c.missingReturnError(nullptr); c.copyElisionError(nullptr); c.useStandardLibraryError(nullptr, "memcpy"); + // TODO: allocaCalled, Called } diff --git a/lib/checknullpointer.cpp b/lib/checknullpointer.cpp index 3ad0a381d06..1c4221eddd7 100644 --- a/lib/checknullpointer.cpp +++ b/lib/checknullpointer.cpp @@ -719,5 +719,9 @@ void CheckNullPointer::getErrorMessages(ErrorLogger *errorLogger, const Settings CheckNullPointer c(nullptr, settings, errorLogger); c.nullPointerError(nullptr, "pointer", nullptr, false); c.pointerArithmeticError(nullptr, nullptr, false); + // TODO: nullPointerArithmeticOutOfMemory c.redundantConditionWarning(nullptr, nullptr, nullptr, false); + // TODO: ctunullpointer + // TODO: ctunullpointerOutOfMemory + // TODO: ctunullpointerOutOfResources } diff --git a/lib/checkother.cpp b/lib/checkother.cpp index 2bf8439cdf6..a705bd4a181 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -4580,6 +4580,8 @@ void CheckOther::getErrorMessages(ErrorLogger *errorLogger, const Settings *sett c.intToPointerCastError(nullptr, "decimal"); c.suspiciousFloatingPointCastError(nullptr); c.passedByValueError(nullptr, false); + // TODO: iterateByValue + // TODO: passedByValueCallback c.constVariableError(nullptr, nullptr); c.constStatementError(nullptr, "type", false); c.signedCharArrayIndexError(nullptr); @@ -4623,8 +4625,10 @@ void CheckOther::getErrorMessages(ErrorLogger *errorLogger, const Settings *sett c.knownArgumentError(nullptr, nullptr, nullptr, "x", false); c.knownPointerToBoolError(nullptr, nullptr); c.comparePointersError(nullptr, nullptr, nullptr); + // TODO: subtractPointers c.redundantAssignmentError(nullptr, nullptr, "var", false); c.redundantInitializationError(nullptr, nullptr, "var", false); + c.redundantContinueError(nullptr); const std::vector nullvec; c.funcArgOrderDifferent("function", nullptr, nullptr, nullvec, nullvec); diff --git a/lib/checkstl.cpp b/lib/checkstl.cpp index bdade21bd48..23b63dd2919 100644 --- a/lib/checkstl.cpp +++ b/lib/checkstl.cpp @@ -2345,7 +2345,8 @@ void CheckStl::uselessCallsSubstrError(const Token *tok, SubstrErrorType type) void CheckStl::uselessCallsConstructorError(const Token *tok) { - const std::string msg = "Inefficient constructor call: container '" + tok->str() + "' is assigned a partial copy of itself. Use erase() or resize() instead."; + const std::string container = tok ? tok->str() : ""; + const std::string msg = "Inefficient constructor call: container '" + container + "' is assigned a partial copy of itself. Use erase() or resize() instead."; reportError(tok, Severity::performance, "uselessCallsConstructor", msg, CWE398, Certainty::normal); } @@ -3451,6 +3452,7 @@ void CheckStl::getErrorMessages(ErrorLogger* errorLogger, const Settings* settin c.iteratorsError(nullptr, nullptr, "container"); c.invalidContainerLoopError(nullptr, nullptr, ErrorPath{}); c.invalidContainerError(nullptr, nullptr, nullptr, ErrorPath{}); + c.invalidContainerReferenceError(nullptr, nullptr, ErrorPath{}); c.mismatchingContainerIteratorError(nullptr, nullptr, nullptr); c.mismatchingContainersError(nullptr, nullptr); c.mismatchingContainerExpressionError(nullptr, nullptr); @@ -3465,6 +3467,10 @@ void CheckStl::getErrorMessages(ErrorLogger* errorLogger, const Settings* settin c.string_c_strError(nullptr); c.string_c_strReturn(nullptr); c.string_c_strParam(nullptr, 0); + c.string_c_strConstructor(nullptr); + c.string_c_strAssignment(nullptr); + c.string_c_strConcat(nullptr); + c.string_c_strStream(nullptr); c.string_c_strThrowError(nullptr); c.sizeError(nullptr); c.missingComparisonError(nullptr, nullptr); @@ -3472,12 +3478,15 @@ void CheckStl::getErrorMessages(ErrorLogger* errorLogger, const Settings* settin c.uselessCallsReturnValueError(nullptr, "str", "find"); c.uselessCallsSwapError(nullptr, "str"); c.uselessCallsSubstrError(nullptr, SubstrErrorType::COPY); + c.uselessCallsConstructorError(nullptr); c.uselessCallsEmptyError(nullptr); c.uselessCallsRemoveError(nullptr, "remove"); c.dereferenceInvalidIteratorError(nullptr, "i"); + // TODO: derefInvalidIteratorRedundantCheck c.eraseIteratorOutOfBoundsError(nullptr, nullptr); c.useStlAlgorithmError(nullptr, ""); c.knownEmptyContainerError(nullptr, ""); c.globalLockGuardError(nullptr); c.localMutexError(nullptr); + c.outOfBoundsIndexExpressionError(nullptr, nullptr); } diff --git a/lib/checktype.cpp b/lib/checktype.cpp index 3498e161aae..4cc60003876 100644 --- a/lib/checktype.cpp +++ b/lib/checktype.cpp @@ -540,7 +540,9 @@ void CheckType::getErrorMessages(ErrorLogger *errorLogger, const Settings *setti c.tooBigBitwiseShiftError(nullptr, 32, ValueFlow::Value(64)); c.tooBigSignedBitwiseShiftError(nullptr, 31, ValueFlow::Value(31)); c.integerOverflowError(nullptr, ValueFlow::Value(1LL<<32)); + // TODO: integerOverflowCond c.signConversionError(nullptr, nullptr, false); + // TODO: signConversionCond c.longCastAssignError(nullptr); c.longCastReturnError(nullptr); ValueFlow::Value f; diff --git a/lib/checkuninitvar.cpp b/lib/checkuninitvar.cpp index f9fba3b5c08..494ef45e4ae 100644 --- a/lib/checkuninitvar.cpp +++ b/lib/checkuninitvar.cpp @@ -1813,7 +1813,7 @@ void CheckUninitVar::getErrorMessages(ErrorLogger* errorLogger, const Settings* ValueFlow::Value v{}; - c.uninitvarError(nullptr, v); + c.uninitvarError(nullptr, v); // TODO: does not produce any output c.uninitdataError(nullptr, "varname"); c.uninitStructMemberError(nullptr, "a.b"); } diff --git a/lib/checkunusedfunctions.cpp b/lib/checkunusedfunctions.cpp index 5798d7d5ca3..55547b8e2d3 100644 --- a/lib/checkunusedfunctions.cpp +++ b/lib/checkunusedfunctions.cpp @@ -341,12 +341,9 @@ static bool isOperatorFunction(const std::string & funcName) return std::find(additionalOperators.cbegin(), additionalOperators.cend(), funcName.substr(operatorPrefix.length())) != additionalOperators.cend(); } -static void staticFunctionError(ErrorLogger& errorLogger, - const std::string &filename, - nonneg int fileIndex, - nonneg int lineNumber, - nonneg int column, - const std::string &funcname) +void CheckUnusedFunctions::staticFunctionError(ErrorLogger& errorLogger, + const std::string &filename, nonneg int fileIndex, nonneg int lineNumber, nonneg int column, + const std::string &funcname) { std::list locationList; if (!filename.empty()) { diff --git a/lib/checkunusedfunctions.h b/lib/checkunusedfunctions.h index b835b505ebd..b3b0bd4429c 100644 --- a/lib/checkunusedfunctions.h +++ b/lib/checkunusedfunctions.h @@ -58,6 +58,7 @@ class CPPCHECKLIB CheckUnusedFunctions { static void getErrorMessages(ErrorLogger &errorLogger) { unusedFunctionError(errorLogger, "", 0, 0, 0, "funcName"); + staticFunctionError(errorLogger, "", 0, 0, 0, "funcName"); } // Return true if an error is reported. @@ -70,6 +71,10 @@ class CPPCHECKLIB CheckUnusedFunctions { const std::string &filename, nonneg int fileIndex, nonneg int lineNumber, nonneg int column, const std::string &funcname); + static void staticFunctionError(ErrorLogger& errorLogger, + const std::string &filename, nonneg int fileIndex, nonneg int lineNumber, nonneg int column, + const std::string &funcname); + struct CPPCHECKLIB FunctionUsage { std::string filename; nonneg int lineNumber{}; diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp index 4c30f31a7a7..f9882049723 100644 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -35,6 +35,7 @@ #include "settings.h" #include "standards.h" #include "suppressions.h" +#include "symboldatabase.h" #include "timer.h" #include "token.h" #include "tokenize.h" @@ -1929,6 +1930,7 @@ void CppCheck::getErrorMessages(ErrorLogger &errorlogger) CheckUnusedFunctions::getErrorMessages(errorlogger); Preprocessor::getErrorMessages(errorlogger, s); Tokenizer::getErrorMessages(errorlogger, s); + SymbolDatabase::getErrorMessages(errorlogger); } void CppCheck::analyseClangTidy(const FileSettings &fileSettings) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 9ec965e3f46..186a74724ab 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -8390,3 +8390,10 @@ ValueType::MatchResult ValueType::matchParameter(const ValueType *call, const Va } return res; } + +void SymbolDatabase::getErrorMessages(ErrorLogger& /*errorLogger*/) +{ + // TODO + //SymbolDatabase symdb; + //symdb.returnImplicitIntError(nullptr); +} diff --git a/lib/symboldatabase.h b/lib/symboldatabase.h index 6d16fddbe84..fbfd2a93c95 100644 --- a/lib/symboldatabase.h +++ b/lib/symboldatabase.h @@ -1418,6 +1418,8 @@ class CPPCHECKLIB SymbolDatabase { /* returns the opening { if tok points to enum */ static const Token* isEnumDefinition(const Token* tok); + static void getErrorMessages(ErrorLogger &errorLogger); + private: friend class Scope; friend class Function; diff --git a/oss-fuzz/Makefile b/oss-fuzz/Makefile index 69a7147e895..20277ba3bf1 100644 --- a/oss-fuzz/Makefile +++ b/oss-fuzz/Makefile @@ -252,7 +252,7 @@ $(libcppdir)/clangimport.o: ../lib/clangimport.cpp ../lib/addoninfo.h ../lib/che $(libcppdir)/color.o: ../lib/color.cpp ../lib/color.h ../lib/config.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/color.cpp -$(libcppdir)/cppcheck.o: ../lib/cppcheck.cpp ../externals/picojson/picojson.h ../externals/simplecpp/simplecpp.h ../externals/tinyxml2/tinyxml2.h ../lib/addoninfo.h ../lib/analyzerinfo.h ../lib/check.h ../lib/checkers.h ../lib/checkunusedfunctions.h ../lib/clangimport.h ../lib/color.h ../lib/config.h ../lib/cppcheck.h ../lib/ctu.h ../lib/errorlogger.h ../lib/errortypes.h ../lib/filesettings.h ../lib/json.h ../lib/library.h ../lib/mathlib.h ../lib/path.h ../lib/platform.h ../lib/preprocessor.h ../lib/settings.h ../lib/standards.h ../lib/suppressions.h ../lib/templatesimplifier.h ../lib/timer.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/valueflow.h ../lib/version.h ../lib/vfvalue.h ../lib/xml.h +$(libcppdir)/cppcheck.o: ../lib/cppcheck.cpp ../externals/picojson/picojson.h ../externals/simplecpp/simplecpp.h ../externals/tinyxml2/tinyxml2.h ../lib/addoninfo.h ../lib/analyzerinfo.h ../lib/check.h ../lib/checkers.h ../lib/checkunusedfunctions.h ../lib/clangimport.h ../lib/color.h ../lib/config.h ../lib/cppcheck.h ../lib/ctu.h ../lib/errorlogger.h ../lib/errortypes.h ../lib/filesettings.h ../lib/json.h ../lib/library.h ../lib/mathlib.h ../lib/path.h ../lib/platform.h ../lib/preprocessor.h ../lib/settings.h ../lib/sourcelocation.h ../lib/standards.h ../lib/suppressions.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/timer.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/valueflow.h ../lib/version.h ../lib/vfvalue.h ../lib/xml.h $(CXX) ${LIB_FUZZING_ENGINE} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/cppcheck.cpp $(libcppdir)/ctu.o: ../lib/ctu.cpp ../externals/tinyxml2/tinyxml2.h ../lib/addoninfo.h ../lib/astutils.h ../lib/check.h ../lib/checkers.h ../lib/config.h ../lib/ctu.h ../lib/errorlogger.h ../lib/errortypes.h ../lib/library.h ../lib/mathlib.h ../lib/path.h ../lib/platform.h ../lib/settings.h ../lib/smallvector.h ../lib/sourcelocation.h ../lib/standards.h ../lib/symboldatabase.h ../lib/templatesimplifier.h ../lib/token.h ../lib/tokenize.h ../lib/tokenlist.h ../lib/utils.h ../lib/vfvalue.h ../lib/xml.h From 4f6a9831eee73965c9f875138664981f1ecd22df Mon Sep 17 00:00:00 2001 From: firewave Date: Tue, 3 Jun 2025 12:31:45 +0200 Subject: [PATCH 3/3] tools/errorid.sh: suppressed ShellCheck warnings --- tools/errorid.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/errorid.sh b/tools/errorid.sh index 3de53630ec7..ffef62fea42 100755 --- a/tools/errorid.sh +++ b/tools/errorid.sh @@ -12,6 +12,7 @@ while read -r id; do continue fi $SCRIPT_DIR/../cppcheck --errorlist | grep "id=\"$id\"" > /dev/null + # shellcheck disable=SC2181 if [ $? -ne 0 ]; then echo $id fi @@ -23,6 +24,7 @@ echo 'no test coverage:' $SCRIPT_DIR/../cppcheck --errorlist | grep -h -o -P 'id=\"[a-zA-Z0-9_]*\"' | sed 's/\id=//' | tr -d '\"' | sort -u | \ while read -r id; do grep -h -o -P "\[$id\]\\\\n\"" $SCRIPT_DIR/../test/*.cpp > /dev/null + # shellcheck disable=SC2181 if [ $? -ne 0 ]; then echo $id fi