diff --git a/lib/checkleakautovar.cpp b/lib/checkleakautovar.cpp index 83f7227091c..0ff4bcd8931 100644 --- a/lib/checkleakautovar.cpp +++ b/lib/checkleakautovar.cpp @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -191,11 +192,20 @@ static bool isVarUsedInTree(const Token *tok, nonneg int varid) { if (!tok) return false; - if (tok->varId() == varid) - return true; - if (tok->str() == "(" && Token::simpleMatch(tok->astOperand1(), "sizeof")) - return false; - return isVarUsedInTree(tok->astOperand1(), varid) || isVarUsedInTree(tok->astOperand2(), varid); + std::deque nodes{ tok }; + while (!nodes.empty()) { + const Token* node = nodes.front(); + if (node->varId() == varid) + return true; + if (node->str() != "(" || !Token::simpleMatch(node->astOperand1(), "sizeof")) { + if (node->astOperand1()) + nodes.emplace_back(node->astOperand1()); + if (node->astOperand2()) + nodes.emplace_back(node->astOperand2()); + } + nodes.pop_front(); + } + return false; } static bool isPointerReleased(const Token *startToken, const Token *endToken, nonneg int varid) diff --git a/lib/fwdanalysis.cpp b/lib/fwdanalysis.cpp index 11434e5356d..64a896733d2 100644 --- a/lib/fwdanalysis.cpp +++ b/lib/fwdanalysis.cpp @@ -26,6 +26,7 @@ #include "token.h" #include "vfvalue.h" +#include #include #include #include @@ -478,9 +479,18 @@ bool FwdAnalysis::hasOperand(const Token *tok, const Token *lhs) const { if (!tok) return false; - if (isSameExpression(false, tok, lhs, mSettings, false, false, nullptr)) - return true; - return hasOperand(tok->astOperand1(), lhs) || hasOperand(tok->astOperand2(), lhs); + std::deque nodes{ tok }; + while (!nodes.empty()) { + const Token* node = nodes.front(); + if (isSameExpression(false, node, lhs, mSettings, false, false, nullptr)) + return true; + if (node->astOperand1()) + nodes.emplace_back(node->astOperand1()); + if (node->astOperand2()) + nodes.emplace_back(node->astOperand2()); + nodes.pop_front(); + } + return false; } const Token *FwdAnalysis::reassign(const Token *expr, const Token *startToken, const Token *endToken) diff --git a/test/cli/performance_test.py b/test/cli/performance_test.py index 90daf9b58cc..fe3408a2e61 100644 --- a/test/cli/performance_test.py +++ b/test/cli/performance_test.py @@ -146,6 +146,30 @@ def test_slow_exprid(tmpdir): my_env["DISABLE_VALUEFLOW"] = "1" cppcheck([filename], env=my_env) +@pytest.mark.skipif(sys.platform == 'darwin', reason='GitHub macOS runners are too slow') +@pytest.mark.timeout(30) +def test_stack_overflow_AST(tmpdir): + # 14435 + filename = os.path.join(tmpdir, 'hang.cpp') + with open(filename, 'wt') as f: + f.write(""" +#define ROW 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, +#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 +#define ROW4096 ROW512 ROW512 ROW512 ROW512 ROW512 ROW512 ROW512 ROW512 +#define ROW32768 ROW4096 ROW4096 ROW4096 ROW4096 ROW4096 ROW4096 ROW4096 ROW4096 +void f(std::vector& v) { + v = { + ROW32768 0 + }; +} + """) + + my_env = os.environ.copy() + my_env["DISABLE_VALUEFLOW"] = "1" + cppcheck([filename], env=my_env) + @pytest.mark.timeout(10) def test_slow_initlist_varchanged(tmpdir):