Skip to content

Commit 5aaa6b3

Browse files
committed
Fix #12861 Hang in valueFlowCondition() with huge array
1 parent 0fe48ba commit 5aaa6b3

File tree

3 files changed

+58
-4
lines changed

3 files changed

+58
-4
lines changed

lib/token.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1451,7 +1451,9 @@ void Token::astOperand1(Token *tok)
14511451
mImpl->mAstOperand1->astParent(nullptr);
14521452
// goto parent operator
14531453
if (tok) {
1454-
tok = tok->astTop();
1454+
while (tok->mImpl->mAstParent) {
1455+
tok = tok->mImpl->mAstParent;
1456+
}
14551457
tok->astParent(this);
14561458
}
14571459
mImpl->mAstOperand1 = tok;
@@ -1463,7 +1465,9 @@ void Token::astOperand2(Token *tok)
14631465
mImpl->mAstOperand2->astParent(nullptr);
14641466
// goto parent operator
14651467
if (tok) {
1466-
tok = tok->astTop();
1468+
while (tok->mImpl->mAstParent) {
1469+
tok = tok->mImpl->mAstParent;
1470+
}
14671471
tok->astParent(this);
14681472
}
14691473
mImpl->mAstOperand2 = tok;

lib/token.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ class CPPCHECKLIB Token {
117117
Token* mAstOperand1{};
118118
Token* mAstOperand2{};
119119
Token* mAstParent{};
120+
Token* mAstTop{};
120121

121122
// symbol database information
122123
const Scope* mScope{};
@@ -400,6 +401,9 @@ class CPPCHECKLIB Token {
400401
mTokType == eBoolean || mTokType == eLiteral || mTokType == eEnumerator);
401402
setFlag(fIsLiteral, memoizedIsLiteral);
402403
}
404+
bool isTopSet() const {
405+
return mImpl->mAstTop != nullptr;
406+
}
403407
bool isKeyword() const {
404408
return mTokType == eKeyword;
405409
}
@@ -1557,6 +1561,11 @@ class CPPCHECKLIB Token {
15571561
* @throws InternalError thrown on cyclic dependency
15581562
*/
15591563
void astParent(Token* tok);
1564+
void astTop(Token * tok) {
1565+
if (tok) {
1566+
mImpl->mAstTop = tok;
1567+
}
1568+
}
15601569

15611570
Token * astOperand1() {
15621571
return mImpl->mAstOperand1;
@@ -1597,13 +1606,19 @@ class CPPCHECKLIB Token {
15971606

15981607
}
15991608
RET_NONNULL Token *astTop() {
1609+
if (mImpl->mAstTop) {
1610+
return mImpl->mAstTop;
1611+
}
16001612
Token *ret = this;
16011613
while (ret->mImpl->mAstParent)
16021614
ret = ret->mImpl->mAstParent;
16031615
return ret;
16041616
}
16051617

16061618
RET_NONNULL const Token *astTop() const {
1619+
if (mImpl->mAstTop) {
1620+
return mImpl->mAstTop;
1621+
}
16071622
const Token *ret = this;
16081623
while (ret->mImpl->mAstParent)
16091624
ret = ret->mImpl->mAstParent;

lib/tokenlist.cpp

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1745,8 +1745,13 @@ static Token * createAstAtToken(Token *tok)
17451745
semicolon1->astOperand2(state2.op.top());
17461746
}
17471747

1748-
if (init != semicolon1)
1749-
semicolon1->astOperand1(init->astTop());
1748+
if (init != semicolon1) {
1749+
Token * top = init;
1750+
while (top->astParent()) {
1751+
top = top->astParent();
1752+
}
1753+
semicolon1->astOperand1(top);
1754+
}
17501755
tok->next()->astOperand1(tok);
17511756
tok->next()->astOperand2(semicolon1);
17521757

@@ -1860,6 +1865,36 @@ void TokenList::createAst() const
18601865
throw InternalError(tok, "Syntax Error: Infinite loop when creating AST.", InternalError::AST);
18611866
tok = nextTok;
18621867
}
1868+
for (Token *tok = mTokensFrontBack->front; tok; tok = tok ? tok->next() : nullptr) {
1869+
if ((tok->astOperand1() || tok->astOperand2()) && (!tok->isTopSet())) {
1870+
Token * top = tok;
1871+
while (top->astParent()) {
1872+
top = top->astParent();
1873+
}
1874+
std::list<Token *> current_list;
1875+
std::list<Token *> back_list;
1876+
current_list.push_back(top);
1877+
1878+
for (auto it = current_list.begin(); it != current_list.end();) {
1879+
Token * op1 = (*it)->astOperand1();
1880+
Token * op2 = (*it)->astOperand2();
1881+
if (op1) {
1882+
back_list.push_back(op1);
1883+
op1->astTop(top);
1884+
}
1885+
if (op2) {
1886+
back_list.push_back(op2);
1887+
op2->astTop(top);
1888+
}
1889+
++it;
1890+
if (it == current_list.end() && back_list.size() > 0) {
1891+
current_list = back_list;
1892+
it = current_list.begin();
1893+
back_list.clear();
1894+
}
1895+
}
1896+
}
1897+
}
18631898
}
18641899

18651900
namespace {

0 commit comments

Comments
 (0)