Fix 11250: FN: bufferAccessOutOfBounds (comma operator: int x = (3,4) ) (#4636)
* Fix 11250: FN: bufferAccessOutOfBounds (comma operator: int x = (3,4) ) * Format
This commit is contained in:
parent
e01c463ff8
commit
e2f398f81a
|
@ -98,6 +98,18 @@ const Token* findAstNode(const Token* ast, const TFunc& pred)
|
|||
return result;
|
||||
}
|
||||
|
||||
template<class TFunc>
|
||||
const Token* findParent(const Token* tok, const TFunc& pred)
|
||||
{
|
||||
if (!tok)
|
||||
return nullptr;
|
||||
const Token* parent = tok->astParent();
|
||||
while (parent && !pred(parent)) {
|
||||
parent = parent->astParent();
|
||||
}
|
||||
return parent;
|
||||
}
|
||||
|
||||
const Token* findExpression(const nonneg int exprid,
|
||||
const Token* start,
|
||||
const Token* end,
|
||||
|
|
|
@ -1160,7 +1160,7 @@ static ValueFlow::Value executeImpl(const Token* expr, ProgramMemory& pm, const
|
|||
const ValueFlow::Value* value = nullptr;
|
||||
if (!expr)
|
||||
return unknown;
|
||||
else if (expr->hasKnownIntValue() && !expr->isAssignmentOp()) {
|
||||
else if (expr->hasKnownIntValue() && !expr->isAssignmentOp() && expr->str() != ",") {
|
||||
return expr->values().front();
|
||||
} else if ((value = expr->getKnownValue(ValueFlow::Value::ValueType::FLOAT)) ||
|
||||
(value = expr->getKnownValue(ValueFlow::Value::ValueType::ITERATOR_START)) ||
|
||||
|
|
|
@ -598,6 +598,17 @@ static void setTokenValue(Token* tok,
|
|||
if (!parent)
|
||||
return;
|
||||
|
||||
if (Token::simpleMatch(parent, ",") && astIsRHS(tok)) {
|
||||
const Token* callParent = findParent(parent, [](const Token* p) {
|
||||
return !Token::simpleMatch(p, ",");
|
||||
});
|
||||
// Ensure that the comma isnt a function call
|
||||
if (!callParent || (!Token::Match(callParent->previous(), "%name%|> (") && !Token::simpleMatch(callParent, "{"))) {
|
||||
setTokenValue(parent, std::move(value), settings);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (Token::simpleMatch(parent, "=") && astIsRHS(tok) && !value.isLifetimeValue()) {
|
||||
setTokenValue(parent, value, settings);
|
||||
return;
|
||||
|
|
|
@ -71,6 +71,7 @@ private:
|
|||
|
||||
TEST_CASE(valueFlowCalculations);
|
||||
TEST_CASE(valueFlowSizeof);
|
||||
TEST_CASE(valueFlowComma);
|
||||
|
||||
TEST_CASE(valueFlowErrorPath);
|
||||
|
||||
|
@ -1365,6 +1366,31 @@ private:
|
|||
ASSERT_EQUALS(sizeof(std::int32_t) * 10 * 20, values.back().intvalue);
|
||||
}
|
||||
|
||||
void valueFlowComma()
|
||||
{
|
||||
const char* code;
|
||||
std::list<ValueFlow::Value> values;
|
||||
|
||||
code = "void f(int i) {\n"
|
||||
" int x = (i, 4);\n"
|
||||
" return x;\n"
|
||||
"}\n";
|
||||
ASSERT_EQUALS(true, testValueOfXKnown(code, 3U, 4));
|
||||
|
||||
code = "void f(int i) {\n"
|
||||
" int x = (4, i);\n"
|
||||
" return x;\n"
|
||||
"}\n";
|
||||
ASSERT_EQUALS(false, testValueOfX(code, 3U, 4));
|
||||
|
||||
code = "void f() {\n"
|
||||
" int x = g(3, 4);\n"
|
||||
" return x;\n"
|
||||
"}\n";
|
||||
values = tokenValues(code, ",");
|
||||
ASSERT_EQUALS(0U, values.size());
|
||||
}
|
||||
|
||||
void valueFlowErrorPath() {
|
||||
const char *code;
|
||||
|
||||
|
|
Loading…
Reference in New Issue