From 797e9aeaf51aae192edec30ddbcd40ae53f115f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Tue, 3 Nov 2009 17:03:53 +0100 Subject: [PATCH] Fixed #890 (false positive: Uninitialized variable when pointer takes the address to array) --- lib/checkother.cpp | 32 +++++++++++++++++++++++++------- test/testother.cpp | 14 ++++++++++++++ 2 files changed, 39 insertions(+), 7 deletions(-) diff --git a/lib/checkother.cpp b/lib/checkother.cpp index 1ab3f6eaf..47af286cb 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -1180,7 +1180,7 @@ void CheckOther::nullPointer() nullPointerConditionalAssignment(); } -static const Token *uninitvar_checkscope(const Token *tok, const unsigned int varid, bool &init, const bool pointer, const bool array) +static const Token *uninitvar_checkscope(const Token * const tokens, const Token *tok, const unsigned int varid, bool &init, const bool pointer, const bool array) { /* limit the checking in conditional code.. * int x; @@ -1238,7 +1238,7 @@ static const Token *uninitvar_checkscope(const Token *tok, const unsigned int va // Recursively check into the if .. bool init2 = false; - const Token *tokerr = uninitvar_checkscope(tok->next(), varid, init2, pointer, array); + const Token *tokerr = uninitvar_checkscope(tokens, tok->next(), varid, init2, pointer, array); if (!limit && tokerr) return tokerr; @@ -1263,7 +1263,7 @@ static const Token *uninitvar_checkscope(const Token *tok, const unsigned int va // there is no "if".. init2 = false; - tokerr = uninitvar_checkscope(tok->next(), varid, init2, pointer, array); + tokerr = uninitvar_checkscope(tokens, tok->next(), varid, init2, pointer, array); if (!limit && tokerr) return tokerr; @@ -1302,15 +1302,22 @@ static const Token *uninitvar_checkscope(const Token *tok, const unsigned int va return tok->tokAt(2); if (Token::Match(tok, "strcpy|strcat|strncpy|strncat|memcpy ( %any% , %varid% [,)]", varid)) return tok->tokAt(4); + if (Token::Match(tok, "strcat|strncat ( %varid% ,", varid)) + return tok->tokAt(3); + if (Token::Match(tok, "asm ( )")) + { + init = true; + return 0; + } // is the variable passed as a parameter to some function? unsigned int parlevel = 0; for (const Token *tok2 = tok->next(); tok2; tok2 = tok2->next()) { - if (tok2->str() == "{") + if (tok2->str() == "(") ++parlevel; - else if (tok2->str() == "}") + else if (tok2->str() == ")") { if (parlevel <= 1) break; @@ -1332,7 +1339,18 @@ static const Token *uninitvar_checkscope(const Token *tok, const unsigned int va return tok; if (Token::simpleMatch(tok->previous(), "=")) - return tok; + { + if (!Token::Match(tok->tokAt(-3), "[;{}] %var% =")) + return tok; + + const unsigned int varid2 = tok->tokAt(-2)->varId(); + if (varid2) + { + const Token *tok2 = Token::findmatch(tokens, "%varid%", varid2); + if (tok2 && !Token::simpleMatch(tok2->previous(), "*")) + return tok; + } + } if (pointer && Token::simpleMatch(tok->next(), ".")) return tok; @@ -1391,7 +1409,7 @@ void CheckOther::uninitvar() // check if variable is accessed uninitialized.. bool init = false; - const Token *tokerr = uninitvar_checkscope(tok->next(), tok->varId(), init, pointer, array); + const Token *tokerr = uninitvar_checkscope(_tokenizer->tokens(), tok->next(), tok->varId(), init, pointer, array); if (tokerr) uninitvarError(tokerr, tok->str()); } diff --git a/test/testother.cpp b/test/testother.cpp index c83f7c206..9b99c025d 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -980,6 +980,13 @@ private: "}\n"); ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: x\n", errout.str()); + checkUninitVar("void a()\n" + "{\n" + " int x[10];\n" + " int *y = x;\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); + checkUninitVar("int a()\n" "{\n" " int ret;\n" @@ -1077,6 +1084,13 @@ private: " strcpy(s2, s);\n" "};\n"); ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: s\n", errout.str()); + + checkUninitVar("void f()\n" + "{\n" + " char s[20];\n" + " strcat(s, \"abc\");\n" + "};\n"); + ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: s\n", errout.str()); }