From f2e52c0bdb3011a363a172e7f5b618c83615c12e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Fri, 12 Jan 2024 14:18:35 +0100 Subject: [PATCH 1/3] Fix #12344 (cmdline: better validation of premium options) --- cli/cmdlineparser.cpp | 20 ++++++++++++++++++-- test/testcmdlineparser.cpp | 31 +++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/cli/cmdlineparser.cpp b/cli/cmdlineparser.cpp index ba374586faa..448b7075d67 100644 --- a/cli/cmdlineparser.cpp +++ b/cli/cmdlineparser.cpp @@ -890,11 +890,26 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a // Special Cppcheck Premium options else if (std::strncmp(argv[i], "--premium=", 10) == 0 && isCppcheckPremium()) { + const std::string valid = " " + "autosar " + "cert-c-2016 " + "cert-c++-2016 " + "misra-c-2012 " + "misra-c-2023 " + "misra-c++-2008 " + "misra-c++-2023 " + "bughunting " + "safety "; + if (std::strcmp(argv[i], "--premium=safety") == 0) mSettings.safety = true; if (!mSettings.premiumArgs.empty()) mSettings.premiumArgs += " "; const std::string p(argv[i] + 10); + if (valid.find(" " + p + " ") == std::string::npos && !startsWith(p, "cert-c-int-precision=")) { + mLogger.printError("invalid --premium option '" + p + "'."); + return Result::Fail; + } mSettings.premiumArgs += "--" + p; if (p == "misra-c-2012" || p == "misra-c-2023") mSettings.addons.emplace("misra"); @@ -1516,10 +1531,11 @@ void CmdLineParser::printHelp() const " * cert-c++-2016 Cert C++ 2016 checking\n" " * misra-c-2012 Misra C 2012\n" " * misra-c-2023 Misra C 2023\n" - " * misra-c++-2008 Misra C++ 2008 (partial)\n" + " * misra-c++-2008 Misra C++ 2008\n" " Other:\n" " * bughunting Soundy analysis\n" - " * cert-c-int-precision=BITS Integer precision to use in Cert C analysis.\n"; + " * cert-c-int-precision=BITS Integer precision to use in Cert C analysis.\n" + " * safety Safe mode\n"; } oss << diff --git a/test/testcmdlineparser.cpp b/test/testcmdlineparser.cpp index e0d0f3de65e..e7295299f40 100644 --- a/test/testcmdlineparser.cpp +++ b/test/testcmdlineparser.cpp @@ -213,6 +213,7 @@ class TestCmdlineParser : public TestFixture { TEST_CASE(maxConfigsMissingCount); TEST_CASE(maxConfigsInvalid); TEST_CASE(maxConfigsTooSmall); + TEST_CASE(premiumOptions); TEST_CASE(premiumSafety); TEST_CASE(reportProgress1); TEST_CASE(reportProgress2); @@ -1187,6 +1188,36 @@ class TestCmdlineParser : public TestFixture { ASSERT_EQUALS("cppcheck: error: argument to '--max-configs=' must be greater than 0.\n", logger->str()); } + void premiumOptions() { + REDIRECT; + settings->cppcheckCfgProductName = "Cppcheck Premium 0.0.0"; + { + const char * const argv[] = {"cppcheck", "--premium=misra-c-2012", "file.c"}; + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); + } + { + const char * const argv[] = {"cppcheck", "--premium=misra-c++-2023", "file.c"}; + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); + } + { + const char * const argv[] = {"cppcheck", "--premium=cert-c++-2016", "file.c"}; + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); + } + // invalid options + { + const char * const argv[] = {"cppcheck", "--premium=misra", "file.c"}; + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); + ASSERT_EQUALS("cppcheck: error: invalid --premium option 'misra'.\n", logger->str()); + } + { + const char * const argv[] = {"cppcheck", "--premium=cert", "file.c"}; + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); + ASSERT_EQUALS("cppcheck: error: invalid --premium option 'cert'.\n", logger->str()); + } + settings->cppcheckCfgProductName.clear(); + settings->premiumArgs.clear(); + } + void premiumSafety() { REDIRECT; const char * const argv[] = {"cppcheck", "--premium=safety", "file.cpp"}; From 719b600c1a554ac9dea0746b64741a6c079e3222 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Fri, 12 Jan 2024 14:23:39 +0100 Subject: [PATCH 2/3] runformat --- test/testcmdlineparser.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/test/testcmdlineparser.cpp b/test/testcmdlineparser.cpp index e7295299f40..617b1a6d01a 100644 --- a/test/testcmdlineparser.cpp +++ b/test/testcmdlineparser.cpp @@ -1192,27 +1192,27 @@ class TestCmdlineParser : public TestFixture { REDIRECT; settings->cppcheckCfgProductName = "Cppcheck Premium 0.0.0"; { - const char * const argv[] = {"cppcheck", "--premium=misra-c-2012", "file.c"}; - ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); + const char * const argv[] = {"cppcheck", "--premium=misra-c-2012", "file.c"}; + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); } { - const char * const argv[] = {"cppcheck", "--premium=misra-c++-2023", "file.c"}; - ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); + const char * const argv[] = {"cppcheck", "--premium=misra-c++-2023", "file.c"}; + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); } { - const char * const argv[] = {"cppcheck", "--premium=cert-c++-2016", "file.c"}; - ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); + const char * const argv[] = {"cppcheck", "--premium=cert-c++-2016", "file.c"}; + ASSERT_EQUALS(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); } // invalid options { - const char * const argv[] = {"cppcheck", "--premium=misra", "file.c"}; - ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); - ASSERT_EQUALS("cppcheck: error: invalid --premium option 'misra'.\n", logger->str()); + const char * const argv[] = {"cppcheck", "--premium=misra", "file.c"}; + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); + ASSERT_EQUALS("cppcheck: error: invalid --premium option 'misra'.\n", logger->str()); } { - const char * const argv[] = {"cppcheck", "--premium=cert", "file.c"}; - ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); - ASSERT_EQUALS("cppcheck: error: invalid --premium option 'cert'.\n", logger->str()); + const char * const argv[] = {"cppcheck", "--premium=cert", "file.c"}; + ASSERT_EQUALS(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); + ASSERT_EQUALS("cppcheck: error: invalid --premium option 'cert'.\n", logger->str()); } settings->cppcheckCfgProductName.clear(); settings->premiumArgs.clear(); From 693c8688241142d12d6272929f5054fdbfa2c376 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Fri, 12 Jan 2024 16:32:30 +0100 Subject: [PATCH 3/3] refactor --- cli/cmdlineparser.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/cli/cmdlineparser.cpp b/cli/cmdlineparser.cpp index 448b7075d67..07362a56c2a 100644 --- a/cli/cmdlineparser.cpp +++ b/cli/cmdlineparser.cpp @@ -890,23 +890,23 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a // Special Cppcheck Premium options else if (std::strncmp(argv[i], "--premium=", 10) == 0 && isCppcheckPremium()) { - const std::string valid = " " - "autosar " - "cert-c-2016 " - "cert-c++-2016 " - "misra-c-2012 " - "misra-c-2023 " - "misra-c++-2008 " - "misra-c++-2023 " - "bughunting " - "safety "; + const std::set valid{ + "autosar", + "cert-c-2016", + "cert-c++-2016", + "misra-c-2012", + "misra-c-2023", + "misra-c++-2008", + "misra-c++-2023", + "bughunting", + "safety"}; if (std::strcmp(argv[i], "--premium=safety") == 0) mSettings.safety = true; if (!mSettings.premiumArgs.empty()) mSettings.premiumArgs += " "; const std::string p(argv[i] + 10); - if (valid.find(" " + p + " ") == std::string::npos && !startsWith(p, "cert-c-int-precision=")) { + if (!valid.count(p) && !startsWith(p, "cert-c-int-precision=")) { mLogger.printError("invalid --premium option '" + p + "'."); return Result::Fail; }