From c0b608059a9354404a70387380486ed66872c262 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Fri, 27 Mar 2009 17:19:34 +0100 Subject: [PATCH] possible null pointer dereference after a while-loop --- src/checkother.cpp | 59 ++++++++++++++++++++++++++++++++++++++++++++++ src/checkother.h | 6 +++++ test/testother.cpp | 37 +++++++++++++++++++++++++++++ 3 files changed, 102 insertions(+) diff --git a/src/checkother.cpp b/src/checkother.cpp index afda33446..e1fe09b72 100644 --- a/src/checkother.cpp +++ b/src/checkother.cpp @@ -908,6 +908,60 @@ void CheckOther::returnPointerToStackData() } + +void CheckOther::nullPointer() +{ + // Locate insufficient null-pointer handling after loop + for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) + { + if (! Token::Match(tok, "while ( %var% )")) + continue; + + const unsigned int varid(tok->tokAt(2)->varId()); + if (varid == 0) + continue; + + // Locate the end of the while loop.. + const Token *tok2 = tok->tokAt(4); + int indentlevel = 0; + while (tok2) + { + if (tok2->str() == "{") + ++indentlevel; + else if (tok2->str() == "}") + { + if (indentlevel <= 1) + break; + --indentlevel; + } + else if (indentlevel == 0 && tok2->str() == ";") + break; + tok2 = tok2->next(); + } + + // Goto next token + tok2 = tok2 ? tok2->next() : 0; + + // Check if the variable is dereferenced.. + while (tok2) + { + if (tok2->str() == "{" || tok2->str() == "}") + break; + + if (tok2->varId() == varid) + { + if (tok2->next()->str() == "." || Token::Match(tok2->next(), "= %varid% .", varid)) + nullPointerError(tok2); + break; + } + + tok2 = tok2->next(); + } + } +} + + + void CheckOther::cstyleCastError(const Token *tok) { reportError(tok, "style", "cstyleCast", "C-style pointer casting"); @@ -992,3 +1046,8 @@ void CheckOther::returnLocalVariable(const Token *tok) { reportError(tok, "error", "returnLocalVariable", "Returning pointer to local array variable"); } + +void CheckOther::nullPointerError(const Token *tok) +{ + reportError(tok, "error", "nullPointer", "Possible null pointer dereference"); +} diff --git a/src/checkother.h b/src/checkother.h index a2ddbc90f..f17dd1163 100644 --- a/src/checkother.h +++ b/src/checkother.h @@ -70,6 +70,7 @@ public: checkOther.strPlusChar(); checkOther.returnPointerToStackData(); checkOther.InvalidFunctionUsage(); + checkOther.nullPointer(); } // Casting @@ -108,6 +109,9 @@ public: /** Returning pointer to local data */ void returnPointerToStackData(); + /** possible null pointer dereference */ + void nullPointer(); + protected: void CheckVariableScope_LookupVar(const Token *tok1, const char varname[]); @@ -135,6 +139,7 @@ private: void conditionAlwaysTrueFalse(const Token *tok, const std::string &truefalse); void strPlusChar(const Token *tok); void returnLocalVariable(const Token *tok); + void nullPointerError(const Token *tok); void getErrorMessages() { @@ -155,6 +160,7 @@ private: conditionAlwaysTrueFalse(0, "true/false"); strPlusChar(0); returnLocalVariable(0); + nullPointerError(0); } }; diff --git a/test/testother.cpp b/test/testother.cpp index 93f4499c8..4d9fbd63e 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -53,6 +53,8 @@ private: TEST_CASE(varScope1); TEST_CASE(varScope2); + + TEST_CASE(nullpointer1); } void check(const char code[]) @@ -71,6 +73,9 @@ private: checkOther.WarningRedundantCode(); } + + + void delete1() { check("void foo()\n" @@ -326,6 +331,38 @@ private: "}\n"); ASSERT_EQUALS(std::string(""), errout.str()); } + + + + + void checkNullPointer(const char code[]) + { + // Tokenize.. + Tokenizer tokenizer; + std::istringstream istr(code); + tokenizer.tokenize(istr, "test.cpp"); + tokenizer.setVarId(); + + // Clear the error buffer.. + errout.str(""); + + // Check for redundant code.. + Settings settings; + settings._checkCodingStyle = true; + CheckOther checkOther(&tokenizer, &settings, this); + checkOther.nullPointer(); + } + + + void nullpointer1() + { + checkNullPointer("int foo(const Token *tok)\n" + "{\n" + " while (tok);\n" + " tok = tok->next();\n" + "}\n"); + ASSERT_EQUALS(std::string("[test.cpp:4]: (error) Possible null pointer dereference\n"), errout.str()); + } }; REGISTER_TEST(TestOther)