Skip to content

Commit

Permalink
Fix #12462 (False positive: uninitialized data passed by const addres…
Browse files Browse the repository at this point in the history
…s, not used in subfunction)
  • Loading branch information
danmar committed Mar 11, 2024
1 parent 4d35fa9 commit d4eaea8
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 6 deletions.
21 changes: 15 additions & 6 deletions lib/astutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3271,7 +3271,7 @@ bool isConstVarExpression(const Token *tok, const std::function<bool(const Token
return false;
}

static ExprUsage getFunctionUsage(const Token* tok, int indirect, const Settings* settings)
static ExprUsage getFunctionUsage(const Token* tok, int indirect, const Settings* settings, bool cpp)
{
const bool addressOf = tok->astParent() && tok->astParent()->isUnaryOp("&");

Expand All @@ -3284,10 +3284,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;
Expand Down Expand Up @@ -3369,7 +3378,7 @@ ExprUsage getExprUsage(const Token* tok, int indirect, const Settings* settings,
(astIsLHS(tok) || Token::simpleMatch(parent, "( )")))
return ExprUsage::Used;
}
return getFunctionUsage(tok, indirect, settings);
return getFunctionUsage(tok, indirect, settings, cpp);
}

static void getLHSVariablesRecursive(std::vector<const Variable*>& vars, const Token* tok)
Expand Down
31 changes: 31 additions & 0 deletions test/testuninitvar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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"
Expand Down

0 comments on commit d4eaea8

Please sign in to comment.