Fix issue 9293: false negative: uninitvar
This commit is contained in:
parent
dc201d110d
commit
55a78f482b
|
@ -1338,28 +1338,31 @@ void CheckUninitVar::valueFlowUninit()
|
||||||
tok = tok->linkAt(1);
|
tok = tok->linkAt(1);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!tok->variable())
|
if (!tok->variable() && !tok->isUnaryOp("*"))
|
||||||
continue;
|
continue;
|
||||||
auto v = std::find_if(tok->values().begin(), tok->values().end(), std::mem_fn(&ValueFlow::Value::isUninitValue));
|
auto v = std::find_if(tok->values().begin(), tok->values().end(), std::mem_fn(&ValueFlow::Value::isUninitValue));
|
||||||
if (v == tok->values().end())
|
if (v == tok->values().end())
|
||||||
continue;
|
continue;
|
||||||
if (v->isInconclusive())
|
if (v->isInconclusive())
|
||||||
continue;
|
continue;
|
||||||
if (!isVariableUsage(tok, tok->variable()->isPointer(), tok->variable()->isArray() ? ARRAY : NO_ALLOC))
|
|
||||||
continue;
|
|
||||||
if (v->indirect > 1 || v->indirect < 0)
|
if (v->indirect > 1 || v->indirect < 0)
|
||||||
continue;
|
continue;
|
||||||
|
bool uninitderef = false;
|
||||||
|
if (tok->variable()) {
|
||||||
|
if (!isVariableUsage(tok, tok->variable()->isPointer(), tok->variable()->isArray() ? ARRAY : NO_ALLOC))
|
||||||
|
continue;
|
||||||
bool unknown;
|
bool unknown;
|
||||||
const bool deref = CheckNullPointer::isPointerDeRef(tok, unknown, mSettings);
|
const bool deref = CheckNullPointer::isPointerDeRef(tok, unknown, mSettings);
|
||||||
if (v->indirect == 1 && !deref)
|
if (v->indirect == 1 && !deref)
|
||||||
continue;
|
continue;
|
||||||
const bool uninitderef = deref && v->indirect == 0;
|
uninitderef = deref && v->indirect == 0;
|
||||||
const bool isleaf = isLeafDot(tok) || uninitderef;
|
const bool isleaf = isLeafDot(tok) || uninitderef;
|
||||||
if (Token::Match(tok->astParent(), ". %var%") && !isleaf)
|
if (Token::Match(tok->astParent(), ". %var%") && !isleaf)
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
if (!Token::Match(tok->astParent(), ". %name% (") && !uninitderef && isVariableChanged(tok, v->indirect, mSettings, mTokenizer->isCPP()))
|
if (!Token::Match(tok->astParent(), ". %name% (") && !uninitderef && isVariableChanged(tok, v->indirect, mSettings, mTokenizer->isCPP()))
|
||||||
continue;
|
continue;
|
||||||
uninitvarError(tok, tok->str(), v->errorPath);
|
uninitvarError(tok, tok->expressionString(), v->errorPath);
|
||||||
const Token * nextTok = tok;
|
const Token * nextTok = tok;
|
||||||
while (Token::simpleMatch(nextTok->astParent(), "."))
|
while (Token::simpleMatch(nextTok->astParent(), "."))
|
||||||
nextTok = nextTok->astParent();
|
nextTok = nextTok->astParent();
|
||||||
|
|
|
@ -4307,6 +4307,32 @@ private:
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS("[test.cpp:8]: (error) Uninitialized variable: pcdata\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:8]: (error) Uninitialized variable: pcdata\n", errout.str());
|
||||||
|
|
||||||
|
// # 9293
|
||||||
|
valueFlowUninit("struct S {\n"
|
||||||
|
" int x;\n"
|
||||||
|
" int y;\n"
|
||||||
|
"};\n"
|
||||||
|
"\n"
|
||||||
|
"void f() {\n"
|
||||||
|
" struct S s1;\n"
|
||||||
|
" int * x = &s1.x;\n"
|
||||||
|
" struct S s2 = {*x, 0}; \n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("[test.cpp:8] -> [test.cpp:9]: (error) Uninitialized variable: *x\n", errout.str());
|
||||||
|
|
||||||
|
valueFlowUninit("struct S {\n"
|
||||||
|
" int x;\n"
|
||||||
|
" int y;\n"
|
||||||
|
"};\n"
|
||||||
|
"\n"
|
||||||
|
"void f() {\n"
|
||||||
|
" struct S s1;\n"
|
||||||
|
" struct S s2;\n"
|
||||||
|
" int * x = &s1.x;\n"
|
||||||
|
" s2.x = *x; \n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("[test.cpp:9] -> [test.cpp:10]: (error) Uninitialized variable: *x\n", errout.str());
|
||||||
|
|
||||||
valueFlowUninit("void f(bool * x) {\n"
|
valueFlowUninit("void f(bool * x) {\n"
|
||||||
" *x = false;\n"
|
" *x = false;\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
|
|
Loading…
Reference in New Issue