Fix 12033: false negative: uninitialized data passed as const data to function (#5747)

This commit is contained in:
Paul Fultz II 2023-12-23 03:55:39 -06:00 committed by GitHub
parent 2af3b7bf44
commit 77157a678a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 19 additions and 9 deletions

View File

@ -2651,8 +2651,11 @@ bool isVariableChanged(const Token *tok, int indirect, const Settings *settings,
const Token * ptok = tok2; const Token * ptok = tok2;
while (Token::Match(ptok->astParent(), ".|::|[")) while (Token::Match(ptok->astParent(), ".|::|["))
ptok = ptok->astParent(); ptok = ptok->astParent();
int pindirect = indirect;
if (indirect == 0 && astIsLHS(tok2) && Token::Match(ptok, ". %var%") && astIsPointer(ptok->next()))
pindirect = 1;
bool inconclusive = false; bool inconclusive = false;
bool isChanged = isVariableChangedByFunctionCall(ptok, indirect, settings, &inconclusive); bool isChanged = isVariableChangedByFunctionCall(ptok, pindirect, settings, &inconclusive);
isChanged |= inconclusive; isChanged |= inconclusive;
if (isChanged) if (isChanged)
return true; return true;
@ -3257,6 +3260,8 @@ static ExprUsage getFunctionUsage(const Token* tok, int indirect, const Settings
continue; continue;
if (arg->isReference()) if (arg->isReference())
return ExprUsage::PassedByReference; return ExprUsage::PassedByReference;
if (arg->isPointer() && indirect == 1)
return ExprUsage::PassedByReference;
} }
if (!args.empty() && indirect == 0 && !addressOf) if (!args.empty() && indirect == 0 && !addressOf)
return ExprUsage::Used; return ExprUsage::Used;
@ -3301,6 +3306,8 @@ ExprUsage getExprUsage(const Token* tok, int indirect, const Settings* settings,
parent = parent->astParent(); parent = parent->astParent();
if (Token::Match(parent, "%assign%") && (astIsRHS(tok) || astIsLHS(parent->astOperand1()))) if (Token::Match(parent, "%assign%") && (astIsRHS(tok) || astIsLHS(parent->astOperand1())))
return ExprUsage::NotUsed; return ExprUsage::NotUsed;
if (Token::Match(parent, "++|--"))
return ExprUsage::NotUsed;
if (parent->isConstOp()) if (parent->isConstOp())
return ExprUsage::NotUsed; return ExprUsage::NotUsed;
if (parent->isCast()) if (parent->isCast())

View File

@ -1642,12 +1642,7 @@ void CheckUninitVar::valueFlowUninit()
const bool isarray = tok->variable()->isArray(); const bool isarray = tok->variable()->isArray();
if (isarray && tok->variable()->isMember()) if (isarray && tok->variable()->isMember())
continue; // Todo: this is a bailout continue; // Todo: this is a bailout
const bool ispointer = astIsPointer(tok) && !isarray;
const bool deref = CheckNullPointer::isPointerDeRef(tok, unknown, mSettings); const bool deref = CheckNullPointer::isPointerDeRef(tok, unknown, mSettings);
if (ispointer && v->indirect == 1 && !deref)
continue;
if (isarray && !deref)
continue;
uninitderef = deref && v->indirect == 0; uninitderef = deref && v->indirect == 0;
const bool isleaf = isLeafDot(tok) || uninitderef; const bool isleaf = isLeafDot(tok) || uninitderef;
if (!isleaf && Token::Match(tok->astParent(), ". %name%") && (tok->astParent()->next()->varId() || tok->astParent()->next()->isEnumerator())) if (!isleaf && Token::Match(tok->astParent(), ". %name%") && (tok->astParent()->next()->varId() || tok->astParent()->next()->isEnumerator()))

View File

@ -6313,7 +6313,7 @@ private:
" f(a, b);\n" " f(a, b);\n"
" printf(\"%s\", a);\n" " printf(\"%s\", a);\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:5]: (error) Uninitialized variable: a\n", errout.str()); ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: a\n", errout.str());
valueFlowUninit("void usage(const char *);\n" // #10330 valueFlowUninit("void usage(const char *);\n" // #10330
"int main(int argc, char* argv[]) {\n" "int main(int argc, char* argv[]) {\n"
@ -6334,6 +6334,14 @@ private:
" if (pwd == NULL) {}\n" " if (pwd == NULL) {}\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:15] -> [test.cpp:17]: (warning) Uninitialized variable: pwd\n", errout.str()); ASSERT_EQUALS("[test.cpp:15] -> [test.cpp:17]: (warning) Uninitialized variable: pwd\n", errout.str());
// #12033
valueFlowUninit("void g(const char*p);\n"
"void f() {\n"
" char buf[10];\n"
" g(buf);\n"
"}\n");
ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: buf\n", errout.str());
} }
void valueFlowUninitBreak() { // Do not show duplicate warnings about the same uninitialized value void valueFlowUninitBreak() { // Do not show duplicate warnings about the same uninitialized value
@ -6385,7 +6393,7 @@ private:
" someType_t gVar;\n" " someType_t gVar;\n"
" bar(&gVar);\n" " bar(&gVar);\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:9] -> [test.cpp:5]: (warning) Uninitialized variable: p->flags\n", errout.str()); ASSERT_EQUALS("[test.cpp:9]: (error) Uninitialized variable: &gVar\n", errout.str());
valueFlowUninit("typedef struct\n" valueFlowUninit("typedef struct\n"
"{\n" "{\n"
@ -6917,7 +6925,7 @@ private:
" foo(123, &abc);\n" " foo(123, &abc);\n"
" return abc.b;\n" " return abc.b;\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:6]: (error) Uninitialized variable: abc.b\n", errout.str()); ASSERT_EQUALS("[test.cpp:5]: (error) Uninitialized variable: &abc\n", errout.str());
valueFlowUninit("struct ABC { int a; int b; int c; };\n" valueFlowUninit("struct ABC { int a; int b; int c; };\n"
"void foo() {\n" "void foo() {\n"