From ea81ce933ea989806335ceef148dcd717abb2aff Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Tue, 25 Jan 2022 12:13:49 +0100 Subject: [PATCH 1/2] Fix #10754 FP invalidFunctionArg with resize() (#3737) --- lib/checkfunctions.cpp | 2 +- test/testfunctions.cpp | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/lib/checkfunctions.cpp b/lib/checkfunctions.cpp index 87f200bdb..4ac614610 100644 --- a/lib/checkfunctions.cpp +++ b/lib/checkfunctions.cpp @@ -154,7 +154,7 @@ void CheckFunctions::invalidFunctionArgError(const Token *tok, const std::string errmsg << " The value is 0 or 1 (boolean) but the valid values are '" << validstr << "'."; if (invalidValue) reportError(getErrorPath(tok, invalidValue, "Invalid argument"), - invalidValue->errorSeverity() ? Severity::error : Severity::warning, + invalidValue->errorSeverity() && invalidValue->isKnown() ? Severity::error : Severity::warning, "invalidFunctionArg", errmsg.str(), CWE628, diff --git a/test/testfunctions.cpp b/test/testfunctions.cpp index bc94487a4..05e16b6f8 100644 --- a/test/testfunctions.cpp +++ b/test/testfunctions.cpp @@ -464,6 +464,44 @@ private: check("void f() { strtol(a,b,10); }"); ASSERT_EQUALS("", errout.str()); + + check("void f(std::vector& v) {\n" // #10754 + " int N = -1;\n" + " for (long i = 0; i < g(); i++)\n" + " N = h(N);\n" + " v.resize(N);\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:5]: (warning) Invalid v.resize() argument nr 1. The value is -1 but the valid values are '0:'.\n", errout.str()); + + check("void f(std::vector& v, int N) {\n" + " if (N < -1)\n" + " return;\n" + " v.resize(N);\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:4]: (warning) Either the condition 'N<-1' is redundant or v.resize() argument nr 1 can have invalid value. The value is -1 but the valid values are '0:'.\n", + errout.str()); + + check("void f(std::vector& v, int N) {\n" + " if (N == -1) {}\n" + " v.resize(N);\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (warning) Either the condition 'N==-1' is redundant or v.resize() argument nr 1 can have invalid value. The value is -1 but the valid values are '0:'.\n", + errout.str()); + + check("void f(std::vector& v, int N, bool b) {\n" + " if (b)\n" + " N = -1;\n" + " v.resize(N);\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:4]: (warning) Invalid v.resize() argument nr 1. The value is -1 but the valid values are '0:'.\n", + errout.str()); + + check("void f(std::vector& v) {\n" + " int N = -1;\n" + " v.resize(N);\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:3]: (error) Invalid v.resize() argument nr 1. The value is -1 but the valid values are '0:'.\n", + errout.str()); } void invalidFunctionUsageStrings() { From f49cfcd23c0831f66a59865c3bbb3675e43d4358 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Tue, 25 Jan 2022 12:14:20 +0100 Subject: [PATCH 2/2] Fix #10200 False positive: uninitStructMember (#3741) --- lib/checkuninitvar.cpp | 2 ++ test/testuninitvar.cpp | 49 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/lib/checkuninitvar.cpp b/lib/checkuninitvar.cpp index d0bf9661b..c6645bf5a 100644 --- a/lib/checkuninitvar.cpp +++ b/lib/checkuninitvar.cpp @@ -196,6 +196,8 @@ void CheckUninitVar::checkScope(const Scope* scope, const std::set void CheckUninitVar::checkStruct(const Token *tok, const Variable &structvar) { const Token *typeToken = structvar.typeStartToken(); + while (Token::Match(typeToken, "%name% ::")) + typeToken = typeToken->tokAt(2); const SymbolDatabase * symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope *scope2 : symbolDatabase->classAndStructScopes) { if (scope2->className == typeToken->str() && scope2->numConstructors == 0U) { diff --git a/test/testuninitvar.cpp b/test/testuninitvar.cpp index 735efe7a7..8e0d12066 100644 --- a/test/testuninitvar.cpp +++ b/test/testuninitvar.cpp @@ -6052,6 +6052,55 @@ private: " if ((&a)->bar) ;\n" "}"); ASSERT_EQUALS("", errout.str()); + + valueFlowUninit("struct A {\n" // #10200 + " struct B {\n" + " int i;\n" + " };\n" + " int j;\n" + "};\n" + "void f(std::vector& x) {\n" + " A::B b;\n" + " b.i = 123;\n" + " x.push_back(b);\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); + + valueFlowUninit("struct A {\n" + " struct B {\n" + " int i;\n" + " };\n" + " int j;\n" + "};\n" + "void f(std::vector& x) {\n" + " A::B b;\n" + " x.push_back(b);\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:9]: (error) Uninitialized variable: b\n", errout.str()); + + valueFlowUninit("struct A {\n" + " struct B {\n" + " int i;\n" + " };\n" + " int j;\n" + "};\n" + "void f(std::vector&x) {\n" + " A a;\n" + " a.j = 123;\n" + " x.push_back(a);\n" + "}\n"); + + valueFlowUninit("struct A {\n" + " struct B {\n" + " int i;\n" + " };\n" + " int j;\n" + "};\n" + "void f(std::vector& x) {\n" + " A a;\n" + " x.push_back(a);\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:9]: (error) Uninitialized variable: a\n", errout.str()); } void ctu_(const char* file, int line, const char code[]) {