Fix 11056: FP uninitvar with known condition in loop (#4107)

* Fix 11056: FP uninitvar with known condition in loop

* Format
This commit is contained in:
Paul Fultz II 2022-05-11 23:37:48 -05:00 committed by GitHub
parent 6d3208ecb0
commit 5f9bee9b91
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 74 additions and 2 deletions

View File

@ -232,6 +232,25 @@ static bool frontIs(const std::vector<MathLib::bigint>& v, bool i)
return !i;
}
// If the scope is a non-range for loop
static bool isBasicForLoop(const Token* tok)
{
if (!tok)
return false;
if (Token::simpleMatch(tok, "}"))
return isBasicForLoop(tok->link());
if (!Token::simpleMatch(tok->previous(), ") {"))
return false;
const Token* start = tok->linkAt(-1);
if (!start)
return false;
if (!Token::simpleMatch(start->previous(), "for ("))
return false;
if (!Token::simpleMatch(start->astOperand2(), ";"))
return false;
return true;
}
void programMemoryParseCondition(ProgramMemory& pm, const Token* tok, const Token* endTok, const Settings* settings, bool then)
{
auto eval = [&](const Token* t) -> std::vector<MathLib::bigint> {
@ -343,8 +362,10 @@ static void fillProgramMemoryFromAssignments(ProgramMemory& pm, const Token* tok
if (tok2->str() == "{") {
if (indentlevel <= 0) {
// Keep progressing with anonymous/do scopes
if (!Token::Match(tok2->previous(), "do|; {"))
const Token* cond = getCondTokFromEnd(tok2->link());
// Keep progressing with anonymous/do scopes and always true branches
if (!Token::Match(tok2->previous(), "do|; {") && !conditionIsTrue(cond, state) &&
(cond || !isBasicForLoop(tok2)))
break;
} else
--indentlevel;

View File

@ -104,6 +104,7 @@ private:
TEST_CASE(valueFlowForwardTryCatch);
TEST_CASE(valueFlowForwardInconclusiveImpossible);
TEST_CASE(valueFlowForwardConst);
TEST_CASE(valueFlowForwardAfterCondition);
TEST_CASE(valueFlowFwdAnalysis);
@ -3685,6 +3686,56 @@ private:
ASSERT_EQUALS(true, testValueOfXKnown(code, 8U, 3));
}
void valueFlowForwardAfterCondition()
{
const char* code;
code = "int g();\n"
"void f() {\n"
" int x = 3;\n"
" int kk = 11;\n"
" for (;;) {\n"
" if (kk > 10) {\n"
" kk = 0;\n"
" x = g();\n"
" }\n"
" kk++;\n"
" int a = x;\n"
" }\n"
"}\n";
ASSERT_EQUALS(false, testValueOfX(code, 11U, 3));
code = "int g();\n"
"void f() {\n"
" int x = 3;\n"
" int kk = 11;\n"
" while (true) {\n"
" if (kk > 10) {\n"
" kk = 0;\n"
" x = g();\n"
" }\n"
" kk++;\n"
" int a = x;\n"
" }\n"
"}\n";
ASSERT_EQUALS(false, testValueOfX(code, 11U, 3));
code = "int g();\n"
"void f() {\n"
" int x = 3;\n"
" int kk = 11;\n"
" if (true) {\n"
" if (kk > 10) {\n"
" kk = 0;\n"
" x = g();\n"
" }\n"
" kk++;\n"
" int a = x;\n"
" }\n"
"}\n";
ASSERT_EQUALS(false, testValueOfX(code, 11U, 3));
}
void valueFlowRightShift() {
const char *code;
/* Set some temporary fixed values to simplify testing */