Skip to content

Fix #13109 FP arrayIndexOutOfBounds with infinite loop and break in body #6986

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Dec 4, 2024
15 changes: 14 additions & 1 deletion lib/valueflow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3891,6 +3891,8 @@ static void valueFlowForLoopSimplify(Token* const bodyStart,
if (isVariableChanged(bodyStart, bodyEnd, expr->varId(), globalvar, settings))
return;

std::vector<std::pair<Token*, ValueFlow::Value>> valuesToSet;

for (Token *tok2 = bodyStart->next(); tok2 != bodyEnd; tok2 = tok2->next()) {
if (tok2->varId() == expr->varId()) {
const Token * parent = tok2->astParent();
Expand All @@ -3913,7 +3915,7 @@ static void valueFlowForLoopSimplify(Token* const bodyStart,

ValueFlow::Value value1(value);
value1.varId = tok2->varId();
setTokenValue(tok2, std::move(value1), settings);
valuesToSet.emplace_back(tok2, std::move(value1));
}

if (Token::Match(tok2, "%oror%|&&")) {
Expand Down Expand Up @@ -3955,6 +3957,7 @@ static void valueFlowForLoopSimplify(Token* const bodyStart,
if (Token::findmatch(tok2, "continue|break|return", tok2->linkAt(1), vartok->varId())) {
if (settings.debugwarnings)
bailout(tokenlist, errorLogger, tok2, "For loop variable bailout on conditional continue|break|return");
valuesToSet.clear();
break;
}
if (settings.debugwarnings)
Expand All @@ -3964,6 +3967,7 @@ static void valueFlowForLoopSimplify(Token* const bodyStart,
if (Token::findmatch(tok2, "continue|break|return", tok2->linkAt(2), vartok->varId())) {
if (settings.debugwarnings)
bailout(tokenlist, errorLogger, tok2, "For loop variable bailout on conditional continue|break|return");
valuesToSet.clear();
break;
}
tok2 = tok2->linkAt(2);
Expand All @@ -3977,7 +3981,16 @@ static void valueFlowForLoopSimplify(Token* const bodyStart,
tok2 = tok2->linkAt(2);
}
}
if (Token::Match(tok2, "continue|break|return")) {
if (settings.debugwarnings)
bailout(tokenlist, errorLogger, tok2, "For loop variable bailout on unconditional continue|break|return");
valuesToSet.clear();
break;
}
}

for (std::pair<Token*, ValueFlow::Value>& p : valuesToSet)
setTokenValue(p.first, std::move(p.second), settings);
}

static void valueFlowForLoopSimplifyAfter(Token* fortok, nonneg int varid, const MathLib::bigint num, const TokenList& tokenlist, ErrorLogger & errorLogger, const Settings& settings)
Expand Down
32 changes: 32 additions & 0 deletions test/testvalueflow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4575,6 +4575,38 @@ class TestValueFlow : public TestFixture {
ASSERT_EQUALS(true, values.empty());
values = tokenValues(code, "[ f . b");
ASSERT_EQUALS(true, values.empty());

code = "void f() {\n"
" const int a[10] = {};\n"
" for (int n = 0; 1; ++n) {\n"
" (void)a[n];\n"
" break;\n"
" }\n"
"}\n";
values = tokenValues(code, "n ]");
ASSERT_EQUALS(2, values.size());
auto it = values.begin();
ASSERT_EQUALS(-1, it->intvalue);
ASSERT(it->isImpossible());
++it;
ASSERT_EQUALS(0, it->intvalue);
ASSERT(it->isPossible());

code = "void f() {\n"
" const int a[10] = {};\n"
" for (int n = 0; 1; ++n) {\n"
" if (a[n] < 1)\n"
" break;\n"
" }\n"
"}\n";
values = tokenValues(code, "n ]");
ASSERT_EQUALS(2, values.size());
it = values.begin();
ASSERT_EQUALS(-1, it->intvalue);
ASSERT(it->isImpossible());
++it;
ASSERT_EQUALS(0, it->intvalue);
ASSERT(it->isPossible());
}

void valueFlowSubFunction() {
Expand Down
Loading