Fix #11649 Hang in setTokenValue() on huge array (#5010)

* Fix #11649 Hang in setTokenValue() on huge array

* Fix function call
This commit is contained in:
chrchr-github 2023-04-25 21:02:49 +02:00 committed by GitHub
parent 023e79b6c2
commit 4fdcb0c784
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 16 additions and 7 deletions

View File

@ -604,6 +604,7 @@ static ValueFlow::Value truncateImplicitConversion(Token* parent, const ValueFlo
static void setTokenValue(Token* tok, static void setTokenValue(Token* tok,
ValueFlow::Value value, ValueFlow::Value value,
const Settings* settings, const Settings* settings,
bool isInitList = false,
SourceLocation loc = SourceLocation::current()) SourceLocation loc = SourceLocation::current())
{ {
// Skip setting values that are too big since its ambiguous // Skip setting values that are too big since its ambiguous
@ -627,7 +628,7 @@ static void setTokenValue(Token* tok,
if (!parent) if (!parent)
return; return;
if (Token::simpleMatch(parent, ",") && astIsRHS(tok)) { if (!isInitList && Token::simpleMatch(parent, ",") && astIsRHS(tok)) {
const Token* callParent = findParent(parent, [](const Token* p) { const Token* callParent = findParent(parent, [](const Token* p) {
return !Token::simpleMatch(p, ","); return !Token::simpleMatch(p, ",");
}); });
@ -1137,7 +1138,7 @@ size_t ValueFlow::getSizeOf(const ValueType &vt, const Settings *settings)
static bool getMinMaxValues(const ValueType* vt, const cppcheck::Platform& platform, MathLib::bigint& minValue, MathLib::bigint& maxValue); static bool getMinMaxValues(const ValueType* vt, const cppcheck::Platform& platform, MathLib::bigint& minValue, MathLib::bigint& maxValue);
// Handle various constants.. // Handle various constants..
static Token * valueFlowSetConstantValue(Token *tok, const Settings *settings, bool cpp) static Token * valueFlowSetConstantValue(Token *tok, const Settings *settings, bool cpp, bool isInitList = false)
{ {
if ((tok->isNumber() && MathLib::isInt(tok->str())) || (tok->tokType() == Token::eChar)) { if ((tok->isNumber() && MathLib::isInt(tok->str())) || (tok->tokType() == Token::eChar)) {
try { try {
@ -1151,7 +1152,7 @@ static Token * valueFlowSetConstantValue(Token *tok, const Settings *settings, b
ValueFlow::Value value(signedValue); ValueFlow::Value value(signedValue);
if (!tok->isTemplateArg()) if (!tok->isTemplateArg())
value.setKnown(); value.setKnown();
setTokenValue(tok, std::move(value), settings); setTokenValue(tok, std::move(value), settings, isInitList);
} catch (const std::exception & /*e*/) { } catch (const std::exception & /*e*/) {
// Bad character literal // Bad character literal
} }
@ -1161,17 +1162,17 @@ static Token * valueFlowSetConstantValue(Token *tok, const Settings *settings, b
value.floatValue = MathLib::toDoubleNumber(tok->str()); value.floatValue = MathLib::toDoubleNumber(tok->str());
if (!tok->isTemplateArg()) if (!tok->isTemplateArg())
value.setKnown(); value.setKnown();
setTokenValue(tok, std::move(value), settings); setTokenValue(tok, std::move(value), settings, isInitList);
} else if (tok->enumerator() && tok->enumerator()->value_known) { } else if (tok->enumerator() && tok->enumerator()->value_known) {
ValueFlow::Value value(tok->enumerator()->value); ValueFlow::Value value(tok->enumerator()->value);
if (!tok->isTemplateArg()) if (!tok->isTemplateArg())
value.setKnown(); value.setKnown();
setTokenValue(tok, std::move(value), settings); setTokenValue(tok, std::move(value), settings, isInitList);
} else if (tok->str() == "NULL" || (cpp && tok->str() == "nullptr")) { } else if (tok->str() == "NULL" || (cpp && tok->str() == "nullptr")) {
ValueFlow::Value value(0); ValueFlow::Value value(0);
if (!tok->isTemplateArg()) if (!tok->isTemplateArg())
value.setKnown(); value.setKnown();
setTokenValue(tok, std::move(value), settings); setTokenValue(tok, std::move(value), settings, isInitList);
} else if (Token::simpleMatch(tok, "sizeof (")) { } else if (Token::simpleMatch(tok, "sizeof (")) {
if (tok->next()->astOperand2() && !tok->next()->astOperand2()->isLiteral() && tok->next()->astOperand2()->valueType() && if (tok->next()->astOperand2() && !tok->next()->astOperand2()->isLiteral() && tok->next()->astOperand2()->valueType() &&
(tok->next()->astOperand2()->valueType()->pointer == 0 || // <- TODO this is a bailout, abort when there are array->pointer conversions (tok->next()->astOperand2()->valueType()->pointer == 0 || // <- TODO this is a bailout, abort when there are array->pointer conversions
@ -1339,8 +1340,16 @@ static Token * valueFlowSetConstantValue(Token *tok, const Settings *settings, b
static void valueFlowNumber(TokenList *tokenlist, const Settings* settings) static void valueFlowNumber(TokenList *tokenlist, const Settings* settings)
{ {
bool isInitList = false;
const Token* endInit{};
for (Token *tok = tokenlist->front(); tok;) { for (Token *tok = tokenlist->front(); tok;) {
tok = valueFlowSetConstantValue(tok, settings, tokenlist->isCPP()); if (!isInitList && tok->str() == "{" && Token::simpleMatch(tok->astOperand1(), ",")) {
isInitList = true;
endInit = tok->link();
}
tok = valueFlowSetConstantValue(tok, settings, tokenlist->isCPP(), isInitList);
if (isInitList && tok == endInit)
isInitList = false;
} }
if (tokenlist->isCPP()) { if (tokenlist->isCPP()) {