From 84f002880192b41be76f57f1bdca0770d002ae76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Tue, 12 Mar 2024 10:22:20 +0100 Subject: [PATCH] Fix #12462 (False positive: uninitialized data passed by const address, not used in subfunction) (#6115) --- lib/astutils.cpp | 17 +++++++++++++---- test/testuninitvar.cpp | 31 +++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 4 deletions(-) diff --git a/lib/astutils.cpp b/lib/astutils.cpp index 7ec19bedaf1..e5c31c01f72 100644 --- a/lib/astutils.cpp +++ b/lib/astutils.cpp @@ -3282,10 +3282,19 @@ static ExprUsage getFunctionUsage(const Token* tok, int indirect, const Settings for (const Variable* arg : args) { if (!arg) continue; - if (arg->isReference()) - return ExprUsage::PassedByReference; - if (arg->isPointer() && indirect == 1) - return ExprUsage::PassedByReference; + if (arg->isReference() || (arg->isPointer() && indirect == 1)) { + if (!ftok->function()->hasBody()) + return ExprUsage::PassedByReference; + for (const Token* bodytok = ftok->function()->functionScope->bodyStart; bodytok != ftok->function()->functionScope->bodyEnd; bodytok = bodytok->next()) { + if (bodytok->variable() == arg) { + if (arg->isReference()) + return ExprUsage::PassedByReference; + if (Token::Match(bodytok->astParent(), "%comp%|!")) + return ExprUsage::NotUsed; + return ExprUsage::PassedByReference; + } + } + } } if (!args.empty() && indirect == 0 && !addressOf) return ExprUsage::Used; diff --git a/test/testuninitvar.cpp b/test/testuninitvar.cpp index bccf0746b5e..2555e29fcf0 100644 --- a/test/testuninitvar.cpp +++ b/test/testuninitvar.cpp @@ -64,6 +64,7 @@ class TestUninitVar : public TestFixture { TEST_CASE(uninitvar2_value); // value flow TEST_CASE(valueFlowUninit2_value); TEST_CASE(valueFlowUninit_uninitvar2); + TEST_CASE(valueFlowUninit_functioncall); TEST_CASE(uninitStructMember); // struct members TEST_CASE(uninitvar2_while); TEST_CASE(uninitvar2_4494); // #4494 @@ -4319,6 +4320,36 @@ class TestUninitVar : public TestFixture { ASSERT_EQUALS("", errout.str()); } + void valueFlowUninit_functioncall() { + + // #12462 - pointer data is not read + valueFlowUninit("struct myst { int a; };\n" + "void bar(const void* p) {}\n" + "void foo() {\n" + " struct myst item;\n" + " bar(&item);\n" + "}", "test.c"); + ASSERT_EQUALS("", errout.str()); + + valueFlowUninit("struct myst { int a; };\n" + "void bar(const void* p) { a = (p != 0); }\n" + "void foo() {\n" + " struct myst item;\n" + " bar(&item);\n" + " a = item.a;\n" // <- item.a is not initialized + "}", "test.c"); + ASSERT_EQUALS("[test.c:6]: (error) Uninitialized variable: item.a\n", errout.str()); + + valueFlowUninit("struct myst { int a; };\n" + "void bar(struct myst* p) { p->a = 0; }\n" + "void foo() {\n" + " struct myst item;\n" + " bar(&item);\n" + " a = item.a;\n" + "}", "test.c"); + ASSERT_EQUALS("", errout.str()); + } + void uninitStructMember() { // struct members checkUninitVar("struct AB { int a; int b; };\n" "void f(void) {\n"