From 2d9e4e1a7312541387a17b93d7242e5ed8e8d61e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Fri, 31 Jul 2009 10:49:43 +0200 Subject: [PATCH] null pointers: detect when there are possible null pointer dereferencing when looping through a linked list both in inner and outer loops at the same time --- src/checkother.cpp | 69 ++++++++++++++++++++++++++++++++++++++++++++++ test/testother.cpp | 5 +--- 2 files changed, 70 insertions(+), 4 deletions(-) diff --git a/src/checkother.cpp b/src/checkother.cpp index 248c0eae9..930aecb0b 100644 --- a/src/checkother.cpp +++ b/src/checkother.cpp @@ -1011,6 +1011,75 @@ void CheckOther::nullPointer() } } + // looping through items in a linked list in a inner loop.. + for (const Token *tok1 = _tokenizer->tokens(); tok1; tok1 = tok1->next()) + { + // search for a "for" token.. + if (!Token::simpleMatch(tok1, "for (")) + continue; + + if (!Token::simpleMatch(tok1->next()->link(), ") {")) + continue; + + // is there any dereferencing occuring in the for statement.. + unsigned int parlevel2 = 1; + for (const Token *tok2 = tok1->tokAt(2); tok2; tok2 = tok2->next()) + { + // Parantheses.. + if (tok2->str() == "(") + ++parlevel2; + else if (tok2->str() == ")") + { + if (parlevel2 <= 1) + break; + --parlevel2; + } + + // Dereferencing a variable inside the "for" parantheses.. + else if (Token::Match(tok2, "%var% . %var%")) + { + const unsigned int varid(tok2->varId()); + if (varid == 0) + continue; + + // Check usage of dereferenced variable in the loop.. + unsigned int indentlevel3 = 0; + for (const Token *tok3 = tok1->next()->link(); tok3; tok3 = tok3->next()) + { + if (tok3->str() == "{") + ++indentlevel3; + else if (tok3->str() == "}") + { + if (indentlevel3 <= 1) + break; + --indentlevel3; + } + else if (Token::Match(tok3, "while ( %varid% &&|)", varid)) + { + // Make sure there is a "break" to prevent segmentation faults.. + unsigned int indentlevel4 = indentlevel3; + for (const Token *tok4 = tok3; tok4; tok4 = tok4->next()) + { + if (tok4->str() == "{") + ++indentlevel4; + else if (tok4->str() == "}") + { + if (indentlevel4 <= 1) + { + nullPointerError(tok1); + break; + } + --indentlevel4; + } + else if (tok4->str() == "break") + break; + } + } + } + } + } + } + // Dereferencing a struct pointer and then checking if it's NULL.. for (const Token *tok1 = _tokenizer->tokens(); tok1; tok1 = tok1->next()) { diff --git a/test/testother.cpp b/test/testother.cpp index e969e2662..1a7eeb068 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -445,10 +445,7 @@ private: " tok = tok->next();\n" " }\n" "}\n"); - // Actual result: - ASSERT_EQUALS("", errout.str()); - // Expected (todo) result: - TODO_ASSERT_EQUALS("[test.cpp:3]: (error) Possible null pointer dereference\n", errout.str()); + ASSERT_EQUALS("[test.cpp:3]: (error) Possible null pointer dereference\n", errout.str()); } void nullpointer2()