Fix crash when there are too many nested scopes. Bail out after 1000 nested scopes. The crash was in gcc and was seen with daca@home.

This commit is contained in:
Daniel Marjamäki 2019-11-02 18:23:10 +01:00
parent 29778fdddb
commit 28182084f2
2 changed files with 9 additions and 7 deletions

View File

@ -1493,9 +1493,11 @@ static bool isUnchanged(const Token *startToken, const Token *endToken, const st
return true; return true;
} }
struct FwdAnalysis::Result FwdAnalysis::checkRecursive(const Token *expr, const Token *startToken, const Token *endToken, const std::set<int> &exprVarIds, bool local, bool inInnerClass) struct FwdAnalysis::Result FwdAnalysis::checkRecursive(const Token *expr, const Token *startToken, const Token *endToken, const std::set<int> &exprVarIds, bool local, bool inInnerClass, int depth)
{ {
// Parse the given tokens // Parse the given tokens
if (++depth > 1000)
return Result(Result::Type::BAILOUT);
for (const Token* tok = startToken; precedes(tok, endToken); tok = tok->next()) { for (const Token* tok = startToken; precedes(tok, endToken); tok = tok->next()) {
if (Token::simpleMatch(tok, "try {")) { if (Token::simpleMatch(tok, "try {")) {
@ -1512,7 +1514,7 @@ struct FwdAnalysis::Result FwdAnalysis::checkRecursive(const Token *expr, const
if (!inInnerClass && tok->str() == "{" && tok->scope()->isClassOrStruct()) { if (!inInnerClass && tok->str() == "{" && tok->scope()->isClassOrStruct()) {
// skip returns from local class definition // skip returns from local class definition
FwdAnalysis::Result result = checkRecursive(expr, tok, tok->link(), exprVarIds, local, true); FwdAnalysis::Result result = checkRecursive(expr, tok, tok->link(), exprVarIds, local, true, depth);
if (result.type != Result::Type::NONE) if (result.type != Result::Type::NONE)
return result; return result;
tok=tok->link(); tok=tok->link();
@ -1524,7 +1526,7 @@ struct FwdAnalysis::Result FwdAnalysis::checkRecursive(const Token *expr, const
if (const Token *lambdaEndToken = findLambdaEndToken(tok)) { if (const Token *lambdaEndToken = findLambdaEndToken(tok)) {
tok = lambdaEndToken; tok = lambdaEndToken;
const Result lambdaResult = checkRecursive(expr, lambdaEndToken->link()->next(), lambdaEndToken, exprVarIds, local, inInnerClass); const Result lambdaResult = checkRecursive(expr, lambdaEndToken->link()->next(), lambdaEndToken, exprVarIds, local, inInnerClass, depth);
if (lambdaResult.type == Result::Type::READ || lambdaResult.type == Result::Type::BAILOUT) if (lambdaResult.type == Result::Type::READ || lambdaResult.type == Result::Type::BAILOUT)
return lambdaResult; return lambdaResult;
} }
@ -1577,7 +1579,7 @@ struct FwdAnalysis::Result FwdAnalysis::checkRecursive(const Token *expr, const
} }
// check loop body again.. // check loop body again..
const struct FwdAnalysis::Result &result = checkRecursive(expr, tok->link(), tok, exprVarIds, local, inInnerClass); const struct FwdAnalysis::Result &result = checkRecursive(expr, tok->link(), tok, exprVarIds, local, inInnerClass, depth);
if (result.type == Result::Type::BAILOUT || result.type == Result::Type::READ) if (result.type == Result::Type::BAILOUT || result.type == Result::Type::READ)
return result; return result;
} }
@ -1680,14 +1682,14 @@ struct FwdAnalysis::Result FwdAnalysis::checkRecursive(const Token *expr, const
if (tok->str() == ")" && Token::simpleMatch(tok->link()->previous(), "switch (")) if (tok->str() == ")" && Token::simpleMatch(tok->link()->previous(), "switch ("))
// TODO: parse switch // TODO: parse switch
return Result(Result::Type::BAILOUT); return Result(Result::Type::BAILOUT);
const Result &result1 = checkRecursive(expr, tok->tokAt(2), tok->linkAt(1), exprVarIds, local, inInnerClass); const Result &result1 = checkRecursive(expr, tok->tokAt(2), tok->linkAt(1), exprVarIds, local, inInnerClass, depth);
if (result1.type == Result::Type::READ || result1.type == Result::Type::BAILOUT) if (result1.type == Result::Type::READ || result1.type == Result::Type::BAILOUT)
return result1; return result1;
if (mWhat == What::ValueFlow && result1.type == Result::Type::WRITE) if (mWhat == What::ValueFlow && result1.type == Result::Type::WRITE)
mValueFlowKnown = false; mValueFlowKnown = false;
if (Token::simpleMatch(tok->linkAt(1), "} else {")) { if (Token::simpleMatch(tok->linkAt(1), "} else {")) {
const Token *elseStart = tok->linkAt(1)->tokAt(2); const Token *elseStart = tok->linkAt(1)->tokAt(2);
const Result &result2 = checkRecursive(expr, elseStart, elseStart->link(), exprVarIds, local, inInnerClass); const Result &result2 = checkRecursive(expr, elseStart, elseStart->link(), exprVarIds, local, inInnerClass, depth);
if (mWhat == What::ValueFlow && result2.type == Result::Type::WRITE) if (mWhat == What::ValueFlow && result2.type == Result::Type::WRITE)
mValueFlowKnown = false; mValueFlowKnown = false;
if (result2.type == Result::Type::READ || result2.type == Result::Type::BAILOUT) if (result2.type == Result::Type::READ || result2.type == Result::Type::BAILOUT)

View File

@ -264,7 +264,7 @@ private:
}; };
struct Result check(const Token *expr, const Token *startToken, const Token *endToken); struct Result check(const Token *expr, const Token *startToken, const Token *endToken);
struct Result checkRecursive(const Token *expr, const Token *startToken, const Token *endToken, const std::set<int> &exprVarIds, bool local, bool inInnerClass); struct Result checkRecursive(const Token *expr, const Token *startToken, const Token *endToken, const std::set<int> &exprVarIds, bool local, bool inInnerClass, int depth=0);
// Is expression a l-value global data? // Is expression a l-value global data?
bool isGlobalData(const Token *expr) const; bool isGlobalData(const Token *expr) const;