From 112b1573c566e26e3c6f77904fe216230b1121b4 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Wed, 18 May 2022 13:52:44 +0200 Subject: [PATCH] Fix #11078 FN constructing string from nullptr / #11079 FN unread variables (#4112) * Fix #11078 FN constructing string from nullptr / #11079 FN unread variables * Format --- lib/checknullpointer.cpp | 8 ++++---- lib/checkunusedvar.cpp | 4 +++- test/testnullpointer.cpp | 9 +++++++++ test/testunusedvar.cpp | 23 +++++++++++++++++++++++ 4 files changed, 39 insertions(+), 5 deletions(-) diff --git a/lib/checknullpointer.cpp b/lib/checknullpointer.cpp index 62ff03ba0..56d256b0b 100644 --- a/lib/checknullpointer.cpp +++ b/lib/checknullpointer.cpp @@ -215,9 +215,9 @@ bool CheckNullPointer::isPointerDeRef(const Token *tok, bool &unknown, const Set return true; // std::string dereferences nullpointers - if (Token::Match(parent->tokAt(-3), "std :: string|wstring (") && tok->strAt(1) == ")") + if (Token::Match(parent->tokAt(-3), "std :: string|wstring (|{ %name% )|}")) return true; - if (Token::Match(parent->previous(), "%name% (") && tok->strAt(1) == ")") { + if (Token::Match(parent->previous(), "%name% (|{ %name% )|}")) { const Variable* var = tok->tokAt(-2)->variable(); if (var && !var->isPointer() && !var->isArray() && var->isStlStringType()) return true; @@ -350,8 +350,8 @@ void CheckNullPointer::nullConstantDereference() else if (Token::Match(tok, "0 [") && (tok->previous()->str() != "&" || !Token::Match(tok->next()->link()->next(), "[.(]"))) nullPointerError(tok); - else if (Token::Match(tok->previous(), "!!. %name% (") && (tok->previous()->str() != "::" || tok->strAt(-2) == "std")) { - if (Token::Match(tok->tokAt(2), "0|NULL|nullptr )") && tok->varId()) { // constructor call + else if (Token::Match(tok->previous(), "!!. %name% (|{") && (tok->previous()->str() != "::" || tok->strAt(-2) == "std")) { + if (Token::Match(tok->tokAt(2), "0|NULL|nullptr )|}") && tok->varId()) { // constructor call const Variable *var = tok->variable(); if (var && !var->isPointer() && !var->isArray() && var->isStlStringType()) nullPointerError(tok); diff --git a/lib/checkunusedvar.cpp b/lib/checkunusedvar.cpp index 9a4db1f99..36455a0ad 100644 --- a/lib/checkunusedvar.cpp +++ b/lib/checkunusedvar.cpp @@ -1198,6 +1198,8 @@ void CheckUnusedVar::checkFunctionVariableUsage() if (tok->str() == "=" && isRaiiClass(tok->valueType(), mTokenizer->isCPP(), false)) continue; + const bool isPointer = tok->valueType() && tok->valueType()->pointer; + if (tok->isName()) { if (isRaiiClass(tok->valueType(), mTokenizer->isCPP(), false)) continue; @@ -1213,7 +1215,7 @@ void CheckUnusedVar::checkFunctionVariableUsage() continue; } // Do not warn about assignment with NULL - if (isNullOperand(tok->astOperand2())) + if (isPointer && isNullOperand(tok->astOperand2())) continue; if (!tok->astOperand1()) diff --git a/test/testnullpointer.cpp b/test/testnullpointer.cpp index c01f1a4a7..f2705009d 100644 --- a/test/testnullpointer.cpp +++ b/test/testnullpointer.cpp @@ -3588,6 +3588,15 @@ private: " return s;\n" "}\n", /*inconclusive*/ true); ASSERT_EQUALS("", errout.str()); + + check("void f() {\n" // #11078 + " const char* p = nullptr;\n" + " std::string s1{ p };\n" + " std::string s2{ nullptr };\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:3]: (error) Null pointer dereference: p\n" + "[test.cpp:4]: (error) Null pointer dereference\n", + errout.str()); } void nullpointerStdStream() { diff --git a/test/testunusedvar.cpp b/test/testunusedvar.cpp index 53ac45bd3..666e85bc2 100644 --- a/test/testunusedvar.cpp +++ b/test/testunusedvar.cpp @@ -5961,6 +5961,29 @@ private: " p = (Foo *)NULL;\n" "}"); ASSERT_EQUALS("", errout.str()); + + functionVariableUsage("void f() {\n" // #11079 + " std::string s1{ nullptr };\n" + " std::string s2{ NULL };\n" + " std::string s4(nullptr);\n" + " std::string s5(NULL);\n" + "}\n" + "struct A { A(void*) {} };\n" + "static void g() {\n" + " A a1{ nullptr };\n" + " A a2{ NULL };\n" + " A a4(nullptr);\n" + " A a5(NULL);\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:2]: (style) Variable 's1' is assigned a value that is never used.\n" + "[test.cpp:3]: (style) Variable 's2' is assigned a value that is never used.\n" + "[test.cpp:4]: (style) Variable 's4' is assigned a value that is never used.\n" + "[test.cpp:5]: (style) Variable 's5' is assigned a value that is never used.\n" + "[test.cpp:9]: (style) Variable 'a1' is assigned a value that is never used.\n" + "[test.cpp:10]: (style) Variable 'a2' is assigned a value that is never used.\n" + "[test.cpp:11]: (style) Variable 'a4' is assigned a value that is never used.\n" + "[test.cpp:12]: (style) Variable 'a5' is assigned a value that is never used.\n", + errout.str()); } void localvarUnusedGoto() {