From 16ce0f1dbf2872114955b9522818cb137e953c11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Mon, 17 May 2021 09:22:19 +0200 Subject: [PATCH] Uninitialized variables; Clarify warnings, bailout for binary & to avoid FPs --- lib/checkuninitvar.cpp | 12 ++++++++---- test/testuninitvar.cpp | 16 +++++++++------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/lib/checkuninitvar.cpp b/lib/checkuninitvar.cpp index 1025ebced..0372041b9 100644 --- a/lib/checkuninitvar.cpp +++ b/lib/checkuninitvar.cpp @@ -802,10 +802,10 @@ bool CheckUninitVar::checkIfForWhileHead(const Token *startparentheses, const Va continue; } - if (isVariableUsage(tok, var.isPointer(), alloc)) { + if (const Token *errorToken = isVariableUsage(tok, var.isPointer(), alloc)) { if (suppressErrors) continue; - uninitvarError(tok, tok->str(), alloc); + uninitvarError(errorToken, errorToken->expressionString(), alloc); } return true; } @@ -920,8 +920,8 @@ const Token* CheckUninitVar::checkLoopBodyRecursive(const Token *start, const Va return nullptr; } } else { - if (isVariableUsage(tok, var.isPointer(), alloc)) - return tok; + if (const Token *errorToken = isVariableUsage(tok, var.isPointer(), alloc)) + return errorToken; else if (tok->strAt(1) == "=") { bool varIsUsedInRhs = false; visitAstNodes(tok->next()->astOperand2(), [&](const Token * t) { @@ -1069,6 +1069,10 @@ const Token* CheckUninitVar::isVariableUsage(const Token *vartok, bool pointer, if (derefValue && derefValue->astParent() && derefValue->astParent()->isUnaryOp("&")) return nullptr; + // BAILOUT for binary & + if (Token::simpleMatch(valueExpr->astParent(), "&") && astIsRhs(valueExpr) && Token::Match(valueExpr->astParent()->tokAt(-3), "( %name% ) &")) + return nullptr; + // safe operations if (isVoidCast(valueExpr->astParent())) return nullptr; diff --git a/test/testuninitvar.cpp b/test/testuninitvar.cpp index f3352717a..619573a03 100644 --- a/test/testuninitvar.cpp +++ b/test/testuninitvar.cpp @@ -1698,7 +1698,7 @@ private: " char *p = (char*)malloc(64);\n" " if (p[0]) { }\n" "}"); - ASSERT_EQUALS("[test.cpp:3]: (error) Memory is allocated but not initialized: p\n", errout.str()); + ASSERT_EQUALS("[test.cpp:3]: (error) Memory is allocated but not initialized: p[0]\n", errout.str()); checkUninitVar("char f() {\n" " char *p = (char*)malloc(64);\n" @@ -1787,9 +1787,11 @@ private: checkUninitVar("void f()\n" "{\n" " char *s = (char*)malloc(100);\n" - " if (!s) {}\n" - "};"); - ASSERT_EQUALS("", errout.str()); + " if (!s)\n" + " return;\n" + " char c = *s;\n" + "}"); + TODO_ASSERT_EQUALS("[test.cpp:6]: (error) Memory is allocated but not initialized: s\n", "", errout.str()); // #3708 - false positive when using ptr typedef checkUninitVar("void f() {\n" @@ -2748,7 +2750,7 @@ private: " int done;\n" " dostuff(1, (AuPointer) &done);\n" // <- It is not conclusive if the "&" is a binary or unary operator. Bailout. "}"); - // FP ASSERT_EQUALS("", errout.str()); + ASSERT_EQUALS("", errout.str()); checkUninitVar("void f() {\n" // #4778 - cast address of uninitialized variable " long a;\n" @@ -3324,7 +3326,7 @@ private: " ab.a = (addr)&x;\n" " dostuff(&ab,0);\n" "}\n", "test.c"); - // FP ASSERT_EQUALS("", errout.str()); + ASSERT_EQUALS("", errout.str()); checkUninitVar("struct Element {\n" " static void f() { }\n" @@ -3939,7 +3941,7 @@ private: " while(*p && *p == '_')\n" " p++;\n" "}"); - ASSERT_EQUALS("[test.cpp:3]: (error) Memory is allocated but not initialized: p\n", errout.str()); + ASSERT_EQUALS("[test.cpp:3]: (error) Memory is allocated but not initialized: *p\n", errout.str()); // #6646 - init in for loop checkUninitVar("void f() {\n" // No FP