Fix issue 9235: new crash in astutils isVariableChanged from endless recursion (#2040)

This commit is contained in:
Paul Fultz II 2019-07-26 00:03:21 -05:00 committed by Daniel Marjamäki
parent b049fd9303
commit ee28a45db4
3 changed files with 13 additions and 7 deletions

View File

@ -968,10 +968,12 @@ bool isVariableChangedByFunctionCall(const Token *tok, const Settings *settings,
return arg && !arg->isConst() && arg->isReference(); return arg && !arg->isConst() && arg->isReference();
} }
bool isVariableChanged(const Token *start, const Token *end, const nonneg int varid, bool globalvar, const Settings *settings, bool cpp) bool isVariableChanged(const Token *start, const Token *end, const nonneg int varid, bool globalvar, const Settings *settings, bool cpp, int depth)
{ {
if (!precedes(start, end)) if (!precedes(start, end))
return false; return false;
if (depth < 0)
return true;
for (const Token *tok = start; tok != end; tok = tok->next()) { for (const Token *tok = start; tok != end; tok = tok->next()) {
if (tok->varId() != varid) { if (tok->varId() != varid) {
if (globalvar && Token::Match(tok, "%name% (")) if (globalvar && Token::Match(tok, "%name% ("))
@ -994,7 +996,7 @@ bool isVariableChanged(const Token *start, const Token *end, const nonneg int va
// Check if assigning to a non-const lvalue // Check if assigning to a non-const lvalue
const Variable * var = getLHSVariable(tok2->astParent()); const Variable * var = getLHSVariable(tok2->astParent());
if (var && var->isReference() && !var->isConst() && var->nameToken() && var->nameToken()->next() == tok2->astParent()) { if (var && var->isReference() && !var->isConst() && var->nameToken() && var->nameToken()->next() == tok2->astParent()) {
if (!var->isLocal() || isVariableChanged(var, settings, cpp)) if (!var->isLocal() || isVariableChanged(var, settings, cpp, depth - 1))
return true; return true;
} }
} }
@ -1050,7 +1052,7 @@ bool isVariableChanged(const Token *start, const Token *end, const nonneg int va
const Variable * loopVar = varTok->variable(); const Variable * loopVar = varTok->variable();
if (!loopVar) if (!loopVar)
continue; continue;
if (!loopVar->isConst() && loopVar->isReference() && isVariableChanged(loopVar, settings, cpp)) if (!loopVar->isConst() && loopVar->isReference() && isVariableChanged(loopVar, settings, cpp, depth - 1))
return true; return true;
continue; continue;
} }
@ -1058,7 +1060,7 @@ bool isVariableChanged(const Token *start, const Token *end, const nonneg int va
return false; return false;
} }
bool isVariableChanged(const Variable * var, const Settings *settings, bool cpp) bool isVariableChanged(const Variable * var, const Settings *settings, bool cpp, int depth)
{ {
if (!var) if (!var)
return false; return false;
@ -1069,7 +1071,7 @@ bool isVariableChanged(const Variable * var, const Settings *settings, bool cpp)
return false; return false;
if (Token::Match(start, "; %varid% =", var->declarationId())) if (Token::Match(start, "; %varid% =", var->declarationId()))
start = start->tokAt(2); start = start->tokAt(2);
return isVariableChanged(start->next(), var->scope()->bodyEnd, var->declarationId(), var->isGlobal(), settings, cpp); return isVariableChanged(start->next(), var->scope()->bodyEnd, var->declarationId(), var->isGlobal(), settings, cpp, depth);
} }
int numberOfArguments(const Token *start) int numberOfArguments(const Token *start)

View File

@ -133,9 +133,9 @@ bool isVariableChangedByFunctionCall(const Token *tok, nonneg int varid, const S
bool isVariableChangedByFunctionCall(const Token *tok, const Settings *settings, bool *inconclusive); bool isVariableChangedByFunctionCall(const Token *tok, const Settings *settings, bool *inconclusive);
/** Is variable changed in block of code? */ /** Is variable changed in block of code? */
bool isVariableChanged(const Token *start, const Token *end, const nonneg int varid, bool globalvar, const Settings *settings, bool cpp); bool isVariableChanged(const Token *start, const Token *end, const nonneg int varid, bool globalvar, const Settings *settings, bool cpp, int depth = 20);
bool isVariableChanged(const Variable * var, const Settings *settings, bool cpp); bool isVariableChanged(const Variable * var, const Settings *settings, bool cpp, int depth = 20);
bool isAliased(const Variable *var); bool isAliased(const Variable *var);

View File

@ -147,6 +147,10 @@ private:
" int b;\n" " int b;\n"
" if (b) { (int)((INTOF(8))result >> b); }\n" " if (b) { (int)((INTOF(8))result >> b); }\n"
"}", "if", "}"); "}", "if", "}");
// #9235
ASSERT_EQUALS(true, isVariableChanged("void f() {\n"
" int &a = a;\n"
"}\n", "= a", "}"));
} }
bool isVariableChangedByFunctionCall(const char code[], const char pattern[], bool *inconclusive) { bool isVariableChangedByFunctionCall(const char code[], const char pattern[], bool *inconclusive) {