From a41ef743f42b76a0d3f58a195b0998fa31f34da0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Thu, 11 Apr 2024 22:48:57 +0200 Subject: [PATCH] Fixed #12504 (dumpfile: usage of relative paths is inconsistent) (#6275) --- Makefile | 2 +- lib/cppcheck.cpp | 66 +++++++++++++++++++++++-------------------- lib/cppcheck.h | 7 +++++ lib/tokenize.cpp | 3 +- oss-fuzz/Makefile | 2 +- test/testcppcheck.cpp | 17 +++++++++++ test/testtokenize.cpp | 30 ++++++++++++++++---- 7 files changed, 88 insertions(+), 39 deletions(-) diff --git a/Makefile b/Makefile index b4396864969..8836add7519 100644 --- a/Makefile +++ b/Makefile @@ -462,7 +462,7 @@ validateRules: $(libcppdir)/valueflow.o: lib/valueflow.cpp lib/addoninfo.h lib/analyzer.h lib/astutils.h lib/calculate.h lib/check.h lib/checkuninitvar.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/findtoken.h lib/forwardanalyzer.h lib/infer.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/programmemory.h lib/reverseanalyzer.h lib/settings.h lib/smallvector.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/valueptr.h lib/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/valueflow.cpp -$(libcppdir)/tokenize.o: lib/tokenize.cpp externals/simplecpp/simplecpp.h lib/addoninfo.h lib/check.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/library.h lib/mathlib.h lib/platform.h lib/preprocessor.h lib/settings.h lib/sourcelocation.h lib/standards.h lib/summaries.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/vfvalue.h +$(libcppdir)/tokenize.o: lib/tokenize.cpp externals/simplecpp/simplecpp.h lib/addoninfo.h lib/check.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.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/summaries.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/vfvalue.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $(libcppdir)/tokenize.cpp $(libcppdir)/symboldatabase.o: lib/symboldatabase.cpp lib/addoninfo.h lib/astutils.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/keywords.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/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h lib/vfvalue.h diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp index 1d736a6b989..db1df11cd54 100644 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -716,36 +716,7 @@ unsigned int CppCheck::checkFile(const std::string& filename, const std::string std::string dumpProlog; if (mSettings.dump || !mSettings.addons.empty()) { - dumpProlog += " \n"; - for (unsigned int i = 0; i < files.size(); ++i) { - dumpProlog += " \n"; - } - for (const simplecpp::Token *tok = tokens1.cfront(); tok; tok = tok->next) { - dumpProlog += " location.fileIndex); - dumpProlog += "\" "; - - dumpProlog += "linenr=\""; - dumpProlog += std::to_string(tok->location.line); - dumpProlog += "\" "; - - dumpProlog +="column=\""; - dumpProlog += std::to_string(tok->location.col); - dumpProlog += "\" "; - - dumpProlog += "str=\""; - dumpProlog += ErrorLogger::toxml(tok->str()); - dumpProlog += "\""; - - dumpProlog += "/>\n"; - } - dumpProlog += " \n"; + dumpProlog += getDumpFileContentsRawTokens(files, tokens1); } // Parse comments and then remove them @@ -1905,3 +1876,38 @@ bool CppCheck::isPremiumCodingStandardId(const std::string& id) const { return true; return false; } + +std::string CppCheck::getDumpFileContentsRawTokens(const std::vector& files, const simplecpp::TokenList& tokens1) const { + std::string dumpProlog; + dumpProlog += " \n"; + for (unsigned int i = 0; i < files.size(); ++i) { + dumpProlog += " \n"; + } + for (const simplecpp::Token *tok = tokens1.cfront(); tok; tok = tok->next) { + dumpProlog += " location.fileIndex); + dumpProlog += "\" "; + + dumpProlog += "linenr=\""; + dumpProlog += std::to_string(tok->location.line); + dumpProlog += "\" "; + + dumpProlog +="column=\""; + dumpProlog += std::to_string(tok->location.col); + dumpProlog += "\" "; + + dumpProlog += "str=\""; + dumpProlog += ErrorLogger::toxml(tok->str()); + dumpProlog += "\""; + + dumpProlog += "/>\n"; + } + dumpProlog += " \n"; + return dumpProlog; +} diff --git a/lib/cppcheck.h b/lib/cppcheck.h index ef68a9c4342..bf8b7c9b464 100644 --- a/lib/cppcheck.h +++ b/lib/cppcheck.h @@ -44,6 +44,8 @@ enum class SHOWTIME_MODES; struct FileSettings; class CheckUnusedFunctions; +namespace simplecpp { class TokenList; } + /// @addtogroup Core /// @{ @@ -151,6 +153,11 @@ class CPPCHECKLIB CppCheck : ErrorLogger { std::string getAddonMessage(const std::string& id, const std::string& text) const; + /** + * @brief Get dumpfile contents, this is only public for testing purposes + */ + std::string getDumpFileContentsRawTokens(const std::vector& files, const simplecpp::TokenList& tokens1) const; + private: #ifdef HAVE_RULES /** Are there "simple" rules */ diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 71220142b01..005bc6146fa 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -24,6 +24,7 @@ #include "errortypes.h" #include "library.h" #include "mathlib.h" +#include "path.h" #include "platform.h" #include "preprocessor.h" #include "settings.h" @@ -5916,7 +5917,7 @@ void Tokenizer::dump(std::ostream &out) const for (const Directive &dir : mDirectives) { outs += " #include #include @@ -56,6 +58,7 @@ class TestCppcheck : public TestFixture { TEST_CASE(suppress_error_library); TEST_CASE(unique_errors); TEST_CASE(isPremiumCodingStandardId); + TEST_CASE(getDumpFileContentsRawTokens); } void getErrorMessages() const { @@ -206,6 +209,20 @@ class TestCppcheck : public TestFixture { ASSERT_EQUALS(true, cppcheck.isPremiumCodingStandardId("premium-autosar-0-0-0")); } + void getDumpFileContentsRawTokens() const { + ErrorLogger2 errorLogger; + CppCheck cppcheck(errorLogger, false, {}); + cppcheck.settings() = settingsBuilder().build(); + cppcheck.settings().relativePaths = true; + cppcheck.settings().basePaths.emplace_back("/some/path"); + std::vector files{"/some/path/test.cpp"}; + simplecpp::TokenList tokens1(files); + const std::string expected = " \n" + " \n" + " \n"; + ASSERT_EQUALS(expected, cppcheck.getDumpFileContentsRawTokens(files, tokens1)); + } + // TODO: test suppressions // TODO: test all with FS }; diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index eb2ca30f1c2..1f153ebad02 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -453,6 +453,7 @@ class TestTokenizer : public TestFixture { TEST_CASE(testDirectiveIncludeTypes); TEST_CASE(testDirectiveIncludeLocations); TEST_CASE(testDirectiveIncludeComments); + TEST_CASE(testDirectiveRelativePath); } #define tokenizeAndStringify(...) tokenizeAndStringify_(__FILE__, __LINE__, __VA_ARGS__) @@ -502,15 +503,18 @@ class TestTokenizer : public TestFixture { } void directiveDump(const char filedata[], std::ostream& ostr) { - Preprocessor preprocessor(settingsDefault, *this); + directiveDump(filedata, "test.c", settingsDefault, ostr); + } + + void directiveDump(const char filedata[], const char filename[], const Settings& settings, std::ostream& ostr) { + Preprocessor preprocessor(settings, *this); std::istringstream istr(filedata); simplecpp::OutputList outputList; - std::vector files; - simplecpp::TokenList tokens1(istr, files, "test.c", &outputList); + std::vector files{filename}; + const simplecpp::TokenList tokens1(istr, files, filename, &outputList); std::list directives = preprocessor.createDirectives(tokens1); - const Settings s = settingsBuilder().severity(Severity::information).build(); - Tokenizer tokenizer(s, *this); + Tokenizer tokenizer(settings, *this); tokenizer.setDirectives(std::move(directives)); tokenizer.dump(ostr); @@ -7954,7 +7958,6 @@ class TestTokenizer : public TestFixture { "#warning some warning message\n" "#error some error message\n"; const char dumpdata[] = " \n" - " \n" " \n" " \n" @@ -8020,6 +8023,21 @@ class TestTokenizer : public TestFixture { directiveDump(filedata, ostr); ASSERT_EQUALS(dumpdata, ostr.str()); } + + void testDirectiveRelativePath() { + const char filedata[] = "#define macro 1\n"; + const char dumpdata[] = " \n" + " \n" + " \n" + " \n" + " \n"; + std::ostringstream ostr; + Settings s(settingsDefault); + s.relativePaths = true; + s.basePaths.emplace_back("/some/path"); + directiveDump(filedata, "/some/path/test.c", s, ostr); + ASSERT_EQUALS(dumpdata, ostr.str()); + } }; REGISTER_TEST(TestTokenizer)