Fix 12033: false negative: uninitialized data passed as const data to function (#5747)
This commit is contained in:
parent
2af3b7bf44
commit
77157a678a
|
@ -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())
|
||||||
|
|
|
@ -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()))
|
||||||
|
|
|
@ -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"
|
||||||
|
|
Loading…
Reference in New Issue