From fa535ff3aead609e8b7b59001358d76c5c67e38a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Sun, 3 Jan 2010 13:30:20 +0100 Subject: [PATCH] Fixed #440 (NULL referencing not detected) --- lib/checkother.cpp | 50 +++++++++++++++++++++++++++++++++++++++++-- lib/executionpath.cpp | 23 ++++++++++++++++++++ test/testother.cpp | 30 ++++++++++++++++++++++++++ 3 files changed, 101 insertions(+), 2 deletions(-) diff --git a/lib/checkother.cpp b/lib/checkother.cpp index b21f86b19..b673410a1 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -1252,6 +1252,29 @@ private: return vartok->next(); } + // Template pointer variable.. + if (Token::Match(tok.previous(), "[;{}] %type% ::|<")) + { + const Token * vartok = &tok; + while (Token::Match(vartok, "%type% ::")) + vartok = vartok->tokAt(2); + if (Token::Match(vartok, "%type% < %type%")) + { + vartok = vartok->tokAt(3); + while (vartok && (vartok->str() == "*" || vartok->isName())) + vartok = vartok->next(); + if (Token::Match(vartok, "> * %var% ;|=")) + { + vartok = vartok->tokAt(2); + checks.push_back(new CheckNullpointer(owner, vartok->varId(), vartok->str())); + if (Token::simpleMatch(vartok->next(), "= 0 ;")) + setnull(checks, vartok->varId()); + return vartok->next(); + } + } + } + + if (Token::Match(&tok, "%var% (")) { // parse usage.. @@ -1554,6 +1577,25 @@ private: declare(checks, vartok, tok, false, true); return vartok->next()->link()->next(); } + + // Template pointer variable.. + if (Token::Match(tok.previous(), "[;{}] %type% ::|<")) + { + const Token * vartok = &tok; + while (Token::Match(vartok, "%type% ::")) + vartok = vartok->tokAt(2); + if (Token::Match(vartok, "%type% < %type%")) + { + vartok = vartok->tokAt(3); + while (vartok && (vartok->str() == "*" || vartok->isName())) + vartok = vartok->next(); + if (Token::Match(vartok, "> * %var% ;")) + { + declare(checks, vartok->tokAt(2), tok, true, false); + return vartok->tokAt(2); + } + } + } } if (tok.varId()) @@ -1646,6 +1688,7 @@ private: // is the variable passed as a parameter to some function? unsigned int parlevel = 0; + std::set bailouts; for (const Token *tok2 = tok.next(); tok2; tok2 = tok2->next()) { if (tok2->str() == "(") @@ -1667,13 +1710,16 @@ private: else if (tok2->varId()) { - if (Token::Match(tok2->tokAt(-2), "[(,] *")) + if (Token::Match(tok2->tokAt(-2), "[(,] *") || Token::Match(tok2->next(), ". %var%")) use_dead_pointer(foundError, checks, tok2); // it is possible that the variable is initialized here - ExecutionPath::bailOutVar(checks, tok2->varId()); + bailouts.insert(tok2->varId()); } } + + for (std::set::const_iterator it = bailouts.begin(); it != bailouts.end(); ++it) + ExecutionPath::bailOutVar(checks, *it); } // function call via function pointer diff --git a/lib/executionpath.cpp b/lib/executionpath.cpp index ac4b177a1..586027e5c 100644 --- a/lib/executionpath.cpp +++ b/lib/executionpath.cpp @@ -65,6 +65,29 @@ static const Token *checkExecutionPaths_(const Token *tok, std::liststr() == "}") return 0; + if (Token::simpleMatch(tok, "while (")) + { + // parse condition + if (checks.size() > 10 || check->parseCondition(*tok->tokAt(2), checks)) + { + ExecutionPath::bailOut(checks); + return 0; + } + + // skip "while (fgets()!=NULL)" + if (Token::simpleMatch(tok, "while ( fgets (")) + { + const Token *tok2 = tok->tokAt(3)->link(); + if (Token::simpleMatch(tok2, ") ) {")) + { + tok = tok2->tokAt(2)->link(); + if (!tok) + break; + continue; + } + } + } + // todo: handle for/while if (Token::Match(tok, "for|while|switch|do")) { diff --git a/test/testother.cpp b/test/testother.cpp index 1d37d7419..d1a827767 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -929,6 +929,13 @@ private: "}\n"); ASSERT_EQUALS("[test.cpp:4]: (error) Null pointer dereference\n", errout.str()); + checkNullPointer("static void foo(int x)\n" + "{\n" + " Foo *abc = 0;\n" + " abc->a();\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:4]: (error) Possible null pointer dereference: abc\n", errout.str()); + // no false positive.. checkNullPointer("static void foo()\n" "{\n" @@ -992,6 +999,13 @@ private: "}\n"); ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: p\n", errout.str()); + checkUninitVar("static void foo()\n" + "{\n" + " Foo *p;\n" + " p->abcd();\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: p\n", errout.str()); + checkUninitVar("static void foo()\n" "{\n" " int *p;\n" @@ -1308,6 +1322,15 @@ private: "}\n"); ASSERT_EQUALS("", errout.str()); + // while.. + checkUninitVar("int f()\n" + "{\n" + " int i;\n" + " while (fgets())\n" + " i = 1;\n" + " return i;" + "}\n"); + ASSERT_EQUALS("[test.cpp:6]: (error) Uninitialized variable: i\n", errout.str()); // member variables.. checkUninitVar("class Fred\n" @@ -1365,6 +1388,13 @@ private: "}\n"); ASSERT_EQUALS("", errout.str()); + checkUninitVar("void foo()\n" + "{\n" + " Foo *p;\n" + " x = bar(p->begin());\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: p\n", errout.str()); + // arrays.. checkUninitVar("void f()\n" "{\n"