Skip to content

Commit

Permalink
Fix 12315: FP containerOutOfBounds when size of container is defined …
Browse files Browse the repository at this point in the history
…by constexpr (#6412)
  • Loading branch information
pfultz2 authored May 18, 2024
1 parent da124d1 commit 337dfc9
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 9 deletions.
30 changes: 21 additions & 9 deletions lib/valueflow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2996,7 +2996,7 @@ struct ValueFlowAnalyzer : Analyzer {
return isThisModified(tok);

// bailout: global non-const variables
if (isGlobal() && !dependsOnThis() && Token::Match(tok, "%name% (") &&
if (isGlobal() && !dependsOnThis() && Token::Match(tok, "%name% (") && !tok->variable() &&
!Token::simpleMatch(tok->linkAt(1), ") {")) {
return isGlobalModified(tok);
}
Expand Down Expand Up @@ -5938,7 +5938,7 @@ static void valueFlowForwardAssign(Token* const tok,
}

// Static variable initialisation?
if (vars.size() == 1 && vars.front()->isStatic() && init)
if (vars.size() == 1 && vars.front()->isStatic() && !vars.front()->isConst() && init)
lowerToPossible(values);

// is volatile
Expand Down Expand Up @@ -6057,13 +6057,25 @@ static std::list<ValueFlow::Value> truncateValues(std::list<ValueFlow::Value> va

static bool isVariableInit(const Token *tok)
{
return (tok->str() == "(" || tok->str() == "{") &&
(tok->isBinaryOp() || (tok->astOperand1() && tok->link() == tok->next())) &&
tok->astOperand1()->variable() &&
tok->astOperand1()->variable()->nameToken() == tok->astOperand1() &&
tok->astOperand1()->variable()->valueType() &&
tok->astOperand1()->variable()->valueType()->type >= ValueType::Type::VOID &&
!Token::simpleMatch(tok->astOperand2(), ",");
if (!tok)
return false;
if (!Token::Match(tok->previous(), "%var% (|{"))
return false;
if (!tok->isBinaryOp() && !(tok->astOperand1() && tok->link() == tok->next()))
return false;
if (Token::simpleMatch(tok->astOperand2(), ","))
return false;
const Variable* var = tok->astOperand1()->variable();
if (!var)
return false;
if (var->nameToken() != tok->astOperand1())
return false;
const ValueType* vt = var->valueType();
if (!vt)
return false;
if (vt->type < ValueType::Type::VOID)
return false;
return true;
}

// Return true if two associative containers intersect
Expand Down
21 changes: 21 additions & 0 deletions test/testvalueflow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2818,6 +2818,27 @@ class TestValueFlow : public TestFixture {
"}\n";
ASSERT_EQUALS(true, testValueOfX(code, 4U, 3));
ASSERT_EQUALS(false, testValueOfXKnown(code, 4U, 3));

code = "void f() {\n"
" constexpr int x(123);\n"
" constexpr int y(x*x);\n"
" return x;\n"
"}";
ASSERT_EQUALS(true, testValueOfXKnown(code, 4U, 123));

code = "void f() {\n"
" static const int x(123);\n"
" static const int y(x*x);\n"
" return x;\n"
"}";
ASSERT_EQUALS(true, testValueOfXKnown(code, 4U, 123));

code = "void f() {\n"
" static int x(123);\n"
" static int y(x*x);\n"
" return x;\n"
"}";
ASSERT_EQUALS(true, testValueOfX(code, 4U, 123));
}

void valueFlowAfterSwap()
Expand Down

0 comments on commit 337dfc9

Please sign in to comment.