diff --git a/src/checkother.cpp b/src/checkother.cpp index c444f04fb..4e4808424 100644 --- a/src/checkother.cpp +++ b/src/checkother.cpp @@ -1106,12 +1106,54 @@ void CheckOther::nullPointerByDeRefAndChec() } } +void CheckOther::nullPointerConditionalAssignment() +{ + for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) + { + // 1. Initialize.. + if (!tok->Match(tok, "; %var% = 0 ;")) + continue; + + const unsigned int varid(tok->next()->varId()); + if (!varid) + continue; + + for (const Token *tok2 = tok; tok2; tok2 = tok2->next()) + { + if (tok2->str() == "{" || tok2->str() == "}") + break; + + if (Token::simpleMatch(tok2, "if (")) + { + const Token *tok3 = tok2; + tok3 = tok3->next()->link(); + if (!tok3) + break; + if (tok3->next()->str() == "{") + { + tok2 = tok3->next()->link(); + if (!tok2) + break; + } + continue; + } + + if (Token::Match(tok2, "else !!if")) + break; + + if (Token::Match(tok2, "%varid% . %var% (", varid)) + nullPointerError(tok2, tok->next()->str()); + } + } +} + void CheckOther::nullPointer() { nullPointerAfterLoop(); nullPointerLinkedList(); nullPointerStructByDeRefAndChec(); nullPointerByDeRefAndChec(); + nullPointerConditionalAssignment(); } void CheckOther::checkZeroDivision() diff --git a/src/checkother.h b/src/checkother.h index e95deead0..98300aaf6 100644 --- a/src/checkother.h +++ b/src/checkother.h @@ -228,6 +228,14 @@ private: * Dereferencing a pointer and then checking if it's NULL.. */ void nullPointerByDeRefAndChec(); + + /** + * Does one part of the check for nullPointer(). + * 1. initialize pointer to 0 + * 2. conditionally assign pointer + * 3. dereference pointer + */ + void nullPointerConditionalAssignment(); }; /// @} //--------------------------------------------------------------------------- diff --git a/test/testother.cpp b/test/testother.cpp index 3f5aad336..91b14ea77 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -65,7 +65,8 @@ private: TEST_CASE(nullpointer2); TEST_CASE(nullpointer3); // dereferencing struct and then checking if it's null TEST_CASE(nullpointer4); - TEST_CASE(nullpointer5); // References should not be checked + TEST_CASE(nullpointer5); // References should not be checked + TEST_CASE(nullpointer6); TEST_CASE(oldStylePointerCast); @@ -885,6 +886,21 @@ private: ASSERT_EQUALS("", errout.str()); } + void nullpointer6() + { + // errors.. + checkNullPointer("static void foo()\n" + "{\n" + " Foo *p = 0;\n" + " if (a == 1)\n" + " p = new FooBar;\n" + " else if (a == 2)\n" + " p = new FooCar;\n" + " p->abcd();\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:8]: (error) Possible null pointer dereference: p\n", errout.str()); + } + void checkOldStylePointerCast(const char code[]) { // Tokenize..