Skip to content

Commit e190ffa

Browse files
committed
Fix #12861 Hang in valueFlowCondition() with huge array
1 parent 4617bc2 commit e190ffa

File tree

4 files changed

+36
-9
lines changed

4 files changed

+36
-9
lines changed

lib/forwardanalyzer.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -610,7 +610,7 @@ namespace {
610610
// In the middle of a loop structure so bail
611611
return Break(Analyzer::Terminate::Bail);
612612
} else if (tok->str() == ";" && tok->astParent()) {
613-
Token* top = tok->astTop();
613+
Token* top = tok->astFinalTop();
614614
if (Token::Match(top->previous(), "for|while (") && Token::simpleMatch(top->link(), ") {")) {
615615
Token* endCond = top->link();
616616
Token* endBlock = endCond->linkAt(1);

lib/reverseanalyzer.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ namespace {
295295
if (!condTok)
296296
break;
297297
Analyzer::Action condAction = analyzeRecursive(condTok);
298-
const bool inLoop = Token::Match(condTok->astTop()->previous(), "for|while (");
298+
const bool inLoop = Token::Match(condTok->astFinalTop()->previous(), "for|while (");
299299
// Evaluate condition of for and while loops first
300300
if (inLoop) {
301301
if (Token::findmatch(tok->link(), "goto|break", tok))

lib/token.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ struct TokenImpl {
8888
Token* mAstOperand1{};
8989
Token* mAstOperand2{};
9090
Token* mAstParent{};
91+
Token* mAstTop{};
9192

9293
// symbol database information
9394
const Scope* mScope{};
@@ -1545,6 +1546,32 @@ class CPPCHECKLIB Token {
15451546
return ret;
15461547
}
15471548

1549+
RET_NONNULL Token *astFinalTop() {
1550+
Token *ret = this;
1551+
if (mImpl->mAstTop) {
1552+
return mImpl->mAstTop;
1553+
}
1554+
while (ret->mImpl->mAstParent)
1555+
ret = ret->mImpl->mAstParent;
1556+
if (mImpl->mAstParent) {
1557+
mImpl->mAstTop = ret;
1558+
}
1559+
return ret;
1560+
}
1561+
1562+
RET_NONNULL const Token *astFinalTop() const {
1563+
const Token *ret = this;
1564+
if (ret->mImpl->mAstTop) {
1565+
return ret->mImpl->mAstTop;
1566+
}
1567+
while (ret->mImpl->mAstParent)
1568+
ret = ret->mImpl->mAstParent;
1569+
if (mImpl->mAstParent) {
1570+
mImpl->mAstTop = const_cast<Token *>(ret);
1571+
}
1572+
return ret;
1573+
}
1574+
15481575
std::pair<const Token *, const Token *> findExpressionStartEndTokens() const;
15491576

15501577
/**

lib/valueflow.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4598,7 +4598,7 @@ struct ConditionHandler {
45984598
if (Token::Match(tok, ":|;|,"))
45994599
continue;
46004600

4601-
const Token* top = tok->astTop();
4601+
const Token* top = tok->astFinalTop();
46024602

46034603
if (!Token::Match(top->previous(), "if|while|for (") && !Token::Match(tok->astParent(), "&&|%oror%|?|!"))
46044604
continue;
@@ -4632,7 +4632,7 @@ struct ConditionHandler {
46324632
if (tok->hasKnownIntValue())
46334633
return;
46344634

4635-
Token* top = tok->astTop();
4635+
Token* top = tok->astFinalTop();
46364636

46374637
if (Token::Match(top, "%assign%"))
46384638
return;
@@ -4851,7 +4851,7 @@ struct ConditionHandler {
48514851
}
48524852
}
48534853

4854-
Token* top = condTok->astTop();
4854+
Token* top = condTok->astFinalTop();
48554855

48564856
if (top->previous()->isExpandedMacro()) {
48574857
for (std::list<ValueFlow::Value>* values : {&thenValues, &elseValues}) {
@@ -5413,7 +5413,7 @@ static void valueFlowForLoopSimplify(Token* const bodyStart,
54135413
}
54145414

54155415
if (Token::Match(tok2, "%oror%|&&")) {
5416-
const ProgramMemory programMemory(getProgramMemory(tok2->astTop(), expr, ValueFlow::Value(value), settings));
5416+
const ProgramMemory programMemory(getProgramMemory(tok2->astFinalTop(), expr, ValueFlow::Value(value), settings));
54175417
if ((tok2->str() == "&&" && !conditionIsTrue(tok2->astOperand1(), programMemory, settings)) ||
54185418
(tok2->str() == "||" && !conditionIsFalse(tok2->astOperand1(), programMemory, settings))) {
54195419
// Skip second expression..
@@ -5438,11 +5438,11 @@ static void valueFlowForLoopSimplify(Token* const bodyStart,
54385438

54395439
if ((tok2->str() == "&&" &&
54405440
conditionIsFalse(tok2->astOperand1(),
5441-
getProgramMemory(tok2->astTop(), expr, ValueFlow::Value(value), settings),
5441+
getProgramMemory(tok2->astFinalTop(), expr, ValueFlow::Value(value), settings),
54425442
settings)) ||
54435443
(tok2->str() == "||" &&
54445444
conditionIsTrue(tok2->astOperand1(),
5445-
getProgramMemory(tok2->astTop(), expr, ValueFlow::Value(value), settings),
5445+
getProgramMemory(tok2->astFinalTop(), expr, ValueFlow::Value(value), settings),
54465446
settings)))
54475447
break;
54485448

@@ -6797,7 +6797,7 @@ static void valueFlowContainerSize(const TokenList& tokenlist,
67976797
!Token::Match(nameToken, "%name% ("))
67986798
continue;
67996799
}
6800-
if (Token::Match(nameToken->astTop()->previous(), "for|while"))
6800+
if (Token::Match(nameToken->astFinalTop()->previous(), "for|while"))
68016801
known = !isVariableChanged(var, settings);
68026802
std::vector<ValueFlow::Value> values{ValueFlow::Value{size}};
68036803
values.back().valueType = ValueFlow::Value::ValueType::CONTAINER_SIZE;

0 commit comments

Comments
 (0)