From a93ef00409c84de7919c2cbefd4341718faedd8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludvig=20Gunne=20Lindstr=C3=B6m?= Date: Thu, 24 Jul 2025 11:22:29 +0200 Subject: [PATCH 1/5] forbid mixing --xml... and --output-format --- cli/cmdlineparser.cpp | 23 +++++++++++++++++++++++ cli/cmdlineparser.h | 2 ++ 2 files changed, 25 insertions(+) diff --git a/cli/cmdlineparser.cpp b/cli/cmdlineparser.cpp index ff4a37b629c..57eaf11449d 100644 --- a/cli/cmdlineparser.cpp +++ b/cli/cmdlineparser.cpp @@ -315,6 +315,9 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a { mSettings.exename = Path::getCurrentExecutablePath(argv[0]); + bool xmlOptionProvided = false; + bool outputFormatOptionProvided = false; + // default to --check-level=normal from CLI for now mSettings.setCheckLevel(Settings::CheckLevel::normal); @@ -1001,6 +1004,10 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a mSettings.outputFile = Path::simplifyPath(argv[i] + 14); else if (std::strncmp(argv[i], "--output-format=", 16) == 0) { + if (xmlOptionProvided) { + outputFormatOptionMixingError(); + return Result::Fail; + } const std::string format = argv[i] + 16; // plist can not be handled here because it requires additional data if (format == "text") @@ -1014,6 +1021,7 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a return Result::Fail; } mSettings.plistOutput = ""; + outputFormatOptionProvided = true; } @@ -1486,11 +1494,20 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a // Write results in results.xml else if (std::strcmp(argv[i], "--xml") == 0) { + if (outputFormatOptionProvided) { + outputFormatOptionMixingError(); + return Result::Fail; + } mSettings.outputFormat = Settings::OutputFormat::xml; + xmlOptionProvided = true; } // Define the XML file version (and enable XML output) else if (std::strncmp(argv[i], "--xml-version=", 14) == 0) { + if (outputFormatOptionProvided) { + outputFormatOptionMixingError(); + return Result::Fail; + } int tmp; if (!parseNumberArg(argv[i], 14, tmp)) return Result::Fail; @@ -1503,6 +1520,7 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a mSettings.xml_version = tmp; // Enable also XML if version is set mSettings.outputFormat = Settings::OutputFormat::xml; + xmlOptionProvided = true; } else { @@ -2149,3 +2167,8 @@ std::list CmdLineParser::filterFiles(const std::vector Date: Thu, 24 Jul 2025 11:45:16 +0200 Subject: [PATCH 2/5] add --output-format arguments xml2 & xml3 --- cli/cmdlineparser.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/cli/cmdlineparser.cpp b/cli/cmdlineparser.cpp index 57eaf11449d..8915fb4599d 100644 --- a/cli/cmdlineparser.cpp +++ b/cli/cmdlineparser.cpp @@ -1016,8 +1016,14 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a mSettings.outputFormat = Settings::OutputFormat::sarif; else if (format == "xml") mSettings.outputFormat = Settings::OutputFormat::xml; - else { - mLogger.printError("argument to '--output-format=' must be 'text', 'sarif' or 'xml'."); + else if (format == "xml2") { + mSettings.outputFormat = Settings::OutputFormat::xml; + mSettings.xml_version = 2; + } else if (format == "xml3") { + mSettings.outputFormat = Settings::OutputFormat::xml; + mSettings.xml_version = 3; + } else { + mLogger.printError("argument to '--output-format=' must be 'text', 'sarif', 'xml' (deprecated), 'xml2' or 'xml3'."); return Result::Fail; } mSettings.plistOutput = ""; @@ -1832,7 +1838,9 @@ void CmdLineParser::printHelp() const " Specify the output format. The available formats are:\n" " * text\n" " * sarif\n" - " * xml\n" + " * xml (deprecated)\n" + " * xml2\n" + " * xml3\n" " --platform=, --platform=\n" " Specifies platform specific types and sizes. The\n" " available builtin platforms are:\n" From 1e29668494b6669a59eaf41fd64e543c1553b8b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludvig=20Gunne=20Lindstr=C3=B6m?= Date: Thu, 24 Jul 2025 11:55:25 +0200 Subject: [PATCH 3/5] add/update cmdlineparser tests --- test/testcmdlineparser.cpp | 40 +++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/test/testcmdlineparser.cpp b/test/testcmdlineparser.cpp index 746b7b7d8fd..7c4470c8304 100644 --- a/test/testcmdlineparser.cpp +++ b/test/testcmdlineparser.cpp @@ -227,10 +227,13 @@ class TestCmdlineParser : public TestFixture { TEST_CASE(outputFormatText); TEST_CASE(outputFormatSarif); TEST_CASE(outputFormatXml); + TEST_CASE(outputFormatXml2); + TEST_CASE(outputFormatXml3); TEST_CASE(outputFormatOther); TEST_CASE(outputFormatImplicitPlist); TEST_CASE(outputFormatImplicitXml); TEST_CASE(outputFormatOverridePlist); + TEST_CASE(outputFormatMixed); TEST_CASE(premiumOptions1); TEST_CASE(premiumOptions2); TEST_CASE(premiumOptions3); @@ -1381,11 +1384,27 @@ class TestCmdlineParser : public TestFixture { ASSERT_EQUALS_ENUM(Settings::OutputFormat::xml, settings->outputFormat); } + void outputFormatXml2() { + REDIRECT; + const char * const argv[] = {"cppcheck", "--output-format=xml2", "file.cpp"}; + ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parseFromArgs(argv)); + ASSERT_EQUALS_ENUM(Settings::OutputFormat::xml, settings->outputFormat); + ASSERT_EQUALS(2, settings->xml_version); + } + + void outputFormatXml3() { + REDIRECT; + const char * const argv[] = {"cppcheck", "--output-format=xml3", "file.cpp"}; + ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parseFromArgs(argv)); + ASSERT_EQUALS_ENUM(Settings::OutputFormat::xml, settings->outputFormat); + ASSERT_EQUALS(3, settings->xml_version); + } + void outputFormatOther() { REDIRECT; const char * const argv[] = {"cppcheck", "--output-format=plist", "file.cpp"}; ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parseFromArgs(argv)); - ASSERT_EQUALS("cppcheck: error: argument to '--output-format=' must be 'text', 'sarif' or 'xml'.\n", logger->str()); + ASSERT_EQUALS("cppcheck: error: argument to '--output-format=' must be 'text', 'sarif', 'xml' (deprecated), 'xml2' or 'xml3'.\n", logger->str()); } void outputFormatImplicitPlist() { @@ -1411,6 +1430,25 @@ class TestCmdlineParser : public TestFixture { ASSERT_EQUALS("", settings->plistOutput); } + void outputFormatMixed() { + REDIRECT; + { + const char * const argv[] = {"cppcheck", "--xml", "--output-format=xml", "file.cpp"}; + ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parseFromArgs(argv)); + ASSERT_EQUALS("cppcheck: error: '--output-format' and '--xml...' may not be used in conjunction.\n", logger->str()); + } + { + const char * const argv[] = {"cppcheck", "--output-format=xml", "--xml", "file.cpp"}; + ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parseFromArgs(argv)); + ASSERT_EQUALS("cppcheck: error: '--output-format' and '--xml...' may not be used in conjunction.\n", logger->str()); + } + { + const char * const argv[] = {"cppcheck", "--xml-version=2", "--output-format=xml", "file.cpp"}; + ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parseFromArgs(argv)); + ASSERT_EQUALS("cppcheck: error: '--output-format' and '--xml...' may not be used in conjunction.\n", logger->str()); + } + } + void premiumOptions1() { REDIRECT; asPremium(); From 99843e6eb67b42dbabd983b37811b633ddfd661a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludvig=20Gunne=20Lindstr=C3=B6m?= Date: Tue, 5 Aug 2025 13:56:41 +0200 Subject: [PATCH 4/5] rename xmlX -> xmlvX --- cli/cmdlineparser.cpp | 10 +++++----- test/testcmdlineparser.cpp | 14 +++++++------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/cli/cmdlineparser.cpp b/cli/cmdlineparser.cpp index 8915fb4599d..608e1844716 100644 --- a/cli/cmdlineparser.cpp +++ b/cli/cmdlineparser.cpp @@ -1016,14 +1016,14 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a mSettings.outputFormat = Settings::OutputFormat::sarif; else if (format == "xml") mSettings.outputFormat = Settings::OutputFormat::xml; - else if (format == "xml2") { + else if (format == "xmlv2") { mSettings.outputFormat = Settings::OutputFormat::xml; mSettings.xml_version = 2; - } else if (format == "xml3") { + } else if (format == "xmlv3") { mSettings.outputFormat = Settings::OutputFormat::xml; mSettings.xml_version = 3; } else { - mLogger.printError("argument to '--output-format=' must be 'text', 'sarif', 'xml' (deprecated), 'xml2' or 'xml3'."); + mLogger.printError("argument to '--output-format=' must be 'text', 'sarif', 'xml' (deprecated), 'xmlv2' or 'xmlv3'."); return Result::Fail; } mSettings.plistOutput = ""; @@ -1839,8 +1839,8 @@ void CmdLineParser::printHelp() const " * text\n" " * sarif\n" " * xml (deprecated)\n" - " * xml2\n" - " * xml3\n" + " * xmlv2\n" + " * xmlv3\n" " --platform=, --platform=\n" " Specifies platform specific types and sizes. The\n" " available builtin platforms are:\n" diff --git a/test/testcmdlineparser.cpp b/test/testcmdlineparser.cpp index 7c4470c8304..6ed577f67af 100644 --- a/test/testcmdlineparser.cpp +++ b/test/testcmdlineparser.cpp @@ -227,8 +227,8 @@ class TestCmdlineParser : public TestFixture { TEST_CASE(outputFormatText); TEST_CASE(outputFormatSarif); TEST_CASE(outputFormatXml); - TEST_CASE(outputFormatXml2); - TEST_CASE(outputFormatXml3); + TEST_CASE(outputFormatXmlv2); + TEST_CASE(outputFormatXmlv3); TEST_CASE(outputFormatOther); TEST_CASE(outputFormatImplicitPlist); TEST_CASE(outputFormatImplicitXml); @@ -1384,17 +1384,17 @@ class TestCmdlineParser : public TestFixture { ASSERT_EQUALS_ENUM(Settings::OutputFormat::xml, settings->outputFormat); } - void outputFormatXml2() { + void outputFormatXmlv2() { REDIRECT; - const char * const argv[] = {"cppcheck", "--output-format=xml2", "file.cpp"}; + const char * const argv[] = {"cppcheck", "--output-format=xmlv2", "file.cpp"}; ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parseFromArgs(argv)); ASSERT_EQUALS_ENUM(Settings::OutputFormat::xml, settings->outputFormat); ASSERT_EQUALS(2, settings->xml_version); } - void outputFormatXml3() { + void outputFormatXmlv3() { REDIRECT; - const char * const argv[] = {"cppcheck", "--output-format=xml3", "file.cpp"}; + const char * const argv[] = {"cppcheck", "--output-format=xmlv3", "file.cpp"}; ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parseFromArgs(argv)); ASSERT_EQUALS_ENUM(Settings::OutputFormat::xml, settings->outputFormat); ASSERT_EQUALS(3, settings->xml_version); @@ -1404,7 +1404,7 @@ class TestCmdlineParser : public TestFixture { REDIRECT; const char * const argv[] = {"cppcheck", "--output-format=plist", "file.cpp"}; ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parseFromArgs(argv)); - ASSERT_EQUALS("cppcheck: error: argument to '--output-format=' must be 'text', 'sarif', 'xml' (deprecated), 'xml2' or 'xml3'.\n", logger->str()); + ASSERT_EQUALS("cppcheck: error: argument to '--output-format=' must be 'text', 'sarif', 'xml' (deprecated), 'xmlv2' or 'xmlv3'.\n", logger->str()); } void outputFormatImplicitPlist() { From c5cd0e76d49eaf3a96b1ad144be7d56a05ada438 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludvig=20Gunne=20Lindstr=C3=B6m?= Date: Tue, 5 Aug 2025 14:09:02 +0200 Subject: [PATCH 5/5] split tests --- test/testcmdlineparser.cpp | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/test/testcmdlineparser.cpp b/test/testcmdlineparser.cpp index 6ed577f67af..1e811586345 100644 --- a/test/testcmdlineparser.cpp +++ b/test/testcmdlineparser.cpp @@ -233,7 +233,9 @@ class TestCmdlineParser : public TestFixture { TEST_CASE(outputFormatImplicitPlist); TEST_CASE(outputFormatImplicitXml); TEST_CASE(outputFormatOverridePlist); - TEST_CASE(outputFormatMixed); + TEST_CASE(outputFormatMixed1); + TEST_CASE(outputFormatMixed2); + TEST_CASE(outputFormatMixed3); TEST_CASE(premiumOptions1); TEST_CASE(premiumOptions2); TEST_CASE(premiumOptions3); @@ -1430,23 +1432,25 @@ class TestCmdlineParser : public TestFixture { ASSERT_EQUALS("", settings->plistOutput); } - void outputFormatMixed() { + void outputFormatMixed1() { REDIRECT; - { - const char * const argv[] = {"cppcheck", "--xml", "--output-format=xml", "file.cpp"}; - ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parseFromArgs(argv)); - ASSERT_EQUALS("cppcheck: error: '--output-format' and '--xml...' may not be used in conjunction.\n", logger->str()); - } - { - const char * const argv[] = {"cppcheck", "--output-format=xml", "--xml", "file.cpp"}; - ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parseFromArgs(argv)); - ASSERT_EQUALS("cppcheck: error: '--output-format' and '--xml...' may not be used in conjunction.\n", logger->str()); - } - { - const char * const argv[] = {"cppcheck", "--xml-version=2", "--output-format=xml", "file.cpp"}; - ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parseFromArgs(argv)); - ASSERT_EQUALS("cppcheck: error: '--output-format' and '--xml...' may not be used in conjunction.\n", logger->str()); - } + const char * const argv[] = {"cppcheck", "--xml", "--output-format=xml", "file.cpp"}; + ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parseFromArgs(argv)); + ASSERT_EQUALS("cppcheck: error: '--output-format' and '--xml...' may not be used in conjunction.\n", logger->str()); + } + + void outputFormatMixed2() { + REDIRECT; + const char * const argv[] = {"cppcheck", "--output-format=xml", "--xml", "file.cpp"}; + ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parseFromArgs(argv)); + ASSERT_EQUALS("cppcheck: error: '--output-format' and '--xml...' may not be used in conjunction.\n", logger->str()); + } + + void outputFormatMixed3() { + REDIRECT; + const char * const argv[] = {"cppcheck", "--xml-version=2", "--output-format=xml", "file.cpp"}; + ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parseFromArgs(argv)); + ASSERT_EQUALS("cppcheck: error: '--output-format' and '--xml...' may not be used in conjunction.\n", logger->str()); } void premiumOptions1() {