Skip to content

Commit 34b9c45

Browse files
authored
Fix #12861 Hang in valueFlowCondition() with huge array (danmar#7757)
I tested the fix based on 4617bc2. Use the cppcheck to check the below code which is submitted on the ticket #12861. ``` #define ROW A, A, A, A, A, A, A, A, #define ROW8 ROW ROW ROW ROW ROW ROW ROW ROW #define ROW64 ROW8 ROW8 ROW8 ROW8 ROW8 ROW8 ROW8 ROW8 #define ROW512 ROW64 ROW64 ROW64 ROW64 ROW64 ROW64 ROW64 ROW64 void f() { static const char A = 'a'; const char a[] = { ROW512 ROW512 ROW512 ROW512 }; } ``` With the fix, the overall time is 1.52582s. Without the fix, the time is 25.9674s. I also tested the testrunner for running the whole of the unit tests. There is some performance improment with the fix, but not remarkable.
1 parent 1964001 commit 34b9c45

File tree

3 files changed

+43
-0
lines changed

3 files changed

+43
-0
lines changed

lib/token.h

Lines changed: 10 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{};
@@ -1557,6 +1558,9 @@ class CPPCHECKLIB Token {
15571558
* @throws InternalError thrown on cyclic dependency
15581559
*/
15591560
void astParent(Token* tok);
1561+
void astTop(Token * tok) {
1562+
mImpl->mAstTop = tok;
1563+
}
15601564

15611565
Token * astOperand1() {
15621566
return mImpl->mAstOperand1;
@@ -1597,13 +1601,19 @@ class CPPCHECKLIB Token {
15971601

15981602
}
15991603
RET_NONNULL Token *astTop() {
1604+
if (mImpl->mAstTop) {
1605+
return mImpl->mAstTop;
1606+
}
16001607
Token *ret = this;
16011608
while (ret->mImpl->mAstParent)
16021609
ret = ret->mImpl->mAstParent;
16031610
return ret;
16041611
}
16051612

16061613
RET_NONNULL const Token *astTop() const {
1614+
if (mImpl->mAstTop) {
1615+
return mImpl->mAstTop;
1616+
}
16071617
const Token *ret = this;
16081618
while (ret->mImpl->mAstParent)
16091619
ret = ret->mImpl->mAstParent;

lib/tokenlist.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1860,6 +1860,16 @@ void TokenList::createAst() const
18601860
throw InternalError(tok, "Syntax Error: Infinite loop when creating AST.", InternalError::AST);
18611861
tok = nextTok;
18621862
}
1863+
for (Token *tok = mTokensFrontBack->front; tok; tok = tok ? tok->next() : nullptr) {
1864+
if (tok->astParent())
1865+
continue;
1866+
if (!tok->astOperand1() && !tok->astOperand2())
1867+
continue;
1868+
visitAstNodes(tok, [&](Token* child) {
1869+
child->astTop(tok);
1870+
return ChildrenToVisit::op1_and_op2;
1871+
});
1872+
}
18631873
}
18641874

18651875
namespace {

test/cli/performance_test.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ def test_slow_many_scopes(tmpdir):
221221
}""")
222222
cppcheck([filename]) # should not take more than ~1 second
223223

224+
224225
@pytest.mark.skipif(sys.platform == 'darwin', reason='GitHub macOS runners are too slow')
225226
@pytest.mark.timeout(20)
226227
def test_crash_array_in_namespace(tmpdir):
@@ -241,6 +242,28 @@ def test_crash_array_in_namespace(tmpdir):
241242
}""")
242243
cppcheck([filename]) # should not take more than ~5 seconds
243244

245+
246+
@pytest.mark.skipif(sys.platform == 'darwin', reason='GitHub macOS runners are too slow')
247+
@pytest.mark.timeout(20)
248+
def test_crash_array_in_array(tmpdir):
249+
# 12861
250+
filename = os.path.join(tmpdir, 'hang.cpp')
251+
with open(filename, 'wt') as f:
252+
f.write(r"""
253+
#define ROW A, A, A, A, A, A, A, A,
254+
#define ROW8 ROW ROW ROW ROW ROW ROW ROW ROW
255+
#define ROW64 ROW8 ROW8 ROW8 ROW8 ROW8 ROW8 ROW8 ROW8
256+
#define ROW512 ROW64 ROW64 ROW64 ROW64 ROW64 ROW64 ROW64 ROW64
257+
#define ROW4096 ROW512 ROW512 ROW512 ROW512 ROW512 ROW512 ROW512 ROW512
258+
void f() {
259+
static const char A = 'a';
260+
const char a[] = {
261+
ROW4096 ROW4096 ROW4096 ROW4096
262+
};
263+
}""")
264+
cppcheck([filename])
265+
266+
244267
@pytest.mark.timeout(5)
245268
def test_slow_bifurcate(tmpdir):
246269
# #14134

0 commit comments

Comments
 (0)