Skip to content

Commit db31440

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

File tree

3 files changed

+64
-4
lines changed

3 files changed

+64
-4
lines changed

lib/token.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1437,12 +1437,16 @@ void Token::astParent(Token* tok)
14371437
// Clear children to avoid nodes referenced twice
14381438
if (this->astParent()) {
14391439
Token* parent = this->astParent();
1440+
parent->mImpl->mAstChildren.remove(this);
14401441
if (parent->astOperand1() == this)
14411442
parent->mImpl->mAstOperand1 = nullptr;
14421443
if (parent->astOperand2() == this)
14431444
parent->mImpl->mAstOperand2 = nullptr;
14441445
}
14451446
mImpl->mAstParent = tok;
1447+
if(tok) {
1448+
tok->mImpl->mAstChildren.push_back(this);
1449+
}
14461450
}
14471451

14481452
void Token::astOperand1(Token *tok)
@@ -1451,7 +1455,9 @@ void Token::astOperand1(Token *tok)
14511455
mImpl->mAstOperand1->astParent(nullptr);
14521456
// goto parent operator
14531457
if (tok) {
1454-
tok = tok->astTop();
1458+
while (tok->mImpl->mAstParent) {
1459+
tok = tok->mImpl->mAstParent;
1460+
}
14551461
tok->astParent(this);
14561462
}
14571463
mImpl->mAstOperand1 = tok;
@@ -1463,7 +1469,9 @@ void Token::astOperand2(Token *tok)
14631469
mImpl->mAstOperand2->astParent(nullptr);
14641470
// goto parent operator
14651471
if (tok) {
1466-
tok = tok->astTop();
1472+
while (tok->mImpl->mAstParent) {
1473+
tok = tok->mImpl->mAstParent;
1474+
}
14671475
tok->astParent(this);
14681476
}
14691477
mImpl->mAstOperand2 = tok;

lib/token.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,8 @@ class CPPCHECKLIB Token {
117117
Token* mAstOperand1{};
118118
Token* mAstOperand2{};
119119
Token* mAstParent{};
120+
Token* mAstTop{};
121+
std::list<Token *> mAstChildren;
120122

121123
// symbol database information
122124
const Scope* mScope{};
@@ -400,6 +402,9 @@ class CPPCHECKLIB Token {
400402
mTokType == eBoolean || mTokType == eLiteral || mTokType == eEnumerator);
401403
setFlag(fIsLiteral, memoizedIsLiteral);
402404
}
405+
bool isTopSet() const {
406+
return mImpl->mAstTop != nullptr;
407+
}
403408
bool isKeyword() const {
404409
return mTokType == eKeyword;
405410
}
@@ -1557,6 +1562,11 @@ class CPPCHECKLIB Token {
15571562
* @throws InternalError thrown on cyclic dependency
15581563
*/
15591564
void astParent(Token* tok);
1565+
void astTop(Token * tok) {
1566+
if (tok) {
1567+
mImpl->mAstTop = tok;
1568+
}
1569+
}
15601570

15611571
Token * astOperand1() {
15621572
return mImpl->mAstOperand1;
@@ -1576,6 +1586,12 @@ class CPPCHECKLIB Token {
15761586
const Token * astParent() const {
15771587
return mImpl->mAstParent;
15781588
}
1589+
std::list<Token *> astChildren() {
1590+
return mImpl->mAstChildren;
1591+
}
1592+
const std::list<Token *> astChildren() const {
1593+
return mImpl->mAstChildren;
1594+
}
15791595
Token * astSibling() {
15801596
if (!astParent())
15811597
return nullptr;
@@ -1597,13 +1613,19 @@ class CPPCHECKLIB Token {
15971613

15981614
}
15991615
RET_NONNULL Token *astTop() {
1616+
if (mImpl->mAstTop) {
1617+
return mImpl->mAstTop;
1618+
}
16001619
Token *ret = this;
16011620
while (ret->mImpl->mAstParent)
16021621
ret = ret->mImpl->mAstParent;
16031622
return ret;
16041623
}
16051624

16061625
RET_NONNULL const Token *astTop() const {
1626+
if (mImpl->mAstTop) {
1627+
return mImpl->mAstTop;
1628+
}
16071629
const Token *ret = this;
16081630
while (ret->mImpl->mAstParent)
16091631
ret = ret->mImpl->mAstParent;

lib/tokenlist.cpp

Lines changed: 32 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,31 @@ 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->astChildren()).size() > 0) && (!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+
std::list<Token *> l = (*it)->astChildren();
1880+
for (auto it_c = l.begin(); it_c != l.end(); ++it_c) {
1881+
back_list.push_back(*it_c);
1882+
(*it_c)->astTop(top);
1883+
}
1884+
++it;
1885+
if (it == current_list.end() && back_list.size() > 0) {
1886+
current_list = back_list;
1887+
it = current_list.begin();
1888+
back_list.clear();
1889+
}
1890+
}
1891+
}
1892+
}
18631893
}
18641894

18651895
namespace {

0 commit comments

Comments
 (0)