diff --git a/lib/executionpath.cpp b/lib/executionpath.cpp index be4721773..b4529fe42 100644 --- a/lib/executionpath.cpp +++ b/lib/executionpath.cpp @@ -265,6 +265,17 @@ void ExecutionPath::checkScope(const Token *tok, std::list &che if (tok3->varId()) ExecutionPath::bailOutVar(checks, tok3->varId()); } + + // it is not certain that a for/while will be executed: + for (std::list::iterator it = checks.begin(); it != checks.end();) + { + if ((*it)->numberOfIf > 0) + checks.erase(it++); + else + ++it; + } + + // parse loop bodies check->parseLoopBody(tok2->next(), checks); } diff --git a/test/testnullpointer.cpp b/test/testnullpointer.cpp index a355ac3c2..90a3811a3 100644 --- a/test/testnullpointer.cpp +++ b/test/testnullpointer.cpp @@ -39,7 +39,8 @@ private: TEST_CASE(structDerefAndCheck); // dereferencing struct and then checking if it's null TEST_CASE(pointerDerefAndCheck); TEST_CASE(nullpointer5); // References should not be checked - TEST_CASE(nullpointer6); + TEST_CASE(nullpointerExecutionPaths); + TEST_CASE(nullpointerExecutionPathsLoop); TEST_CASE(nullpointer7); TEST_CASE(nullpointer8); TEST_CASE(nullpointer9); @@ -410,7 +411,7 @@ private: } // Execution paths.. - void nullpointer6() + void nullpointerExecutionPaths() { // errors.. check("static void foo()\n" @@ -634,6 +635,41 @@ private: } + // Ticket #2350 + void nullpointerExecutionPathsLoop() + { + // No false positive: + check("void foo() {\n" + " int n;\n" + " int *argv32;\n" + " if (x) {\n" + " n = 0;\n" + " argv32 = 0;\n" + " }\n" + "\n" + " for (int i = 0; i < n; i++) {\n" + " argv32[i] = 0;\n" + " }\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); + + // No false negative: + check("void foo() {\n" + " int n;\n" + " int *argv32;\n" + " if (x) {\n" + " n = 10;\n" + " argv32 = 0;\n" + " }\n" + "\n" + " for (int i = 0; i < n; i++) {\n" + " argv32[i] = 0;\n" + " }\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); + TODO_ASSERT_EQUALS("error", errout.str()); + } + void nullpointer7() { check("void foo()\n"