Check for cycles in AST when adding nodes to prevent hangs from cyclic ASTs (#3329)
This commit is contained in:
parent
3b9c399f72
commit
5825a35566
|
@ -1340,18 +1340,29 @@ std::string Token::stringifyList(bool varid) const
|
|||
return stringifyList(varid, false, true, true, true, nullptr, nullptr);
|
||||
}
|
||||
|
||||
static Token* checkAstCycle(Token* tok)
|
||||
{
|
||||
std::set<const Token*> visited;
|
||||
visitAstNodes(tok, [&](const Token* child) {
|
||||
if (!visited.insert(child).second)
|
||||
throw InternalError(child, "Internal error. AST cyclic dependency.");
|
||||
return ChildrenToVisit::op1_and_op2;
|
||||
});
|
||||
while (tok->astParent()) {
|
||||
if (!visited.insert(tok->astParent()).second) // #6838/#6726/#8352 avoid hang on garbage code
|
||||
throw InternalError(tok, "Internal error. AST cyclic dependency.");
|
||||
tok = tok->astParent();
|
||||
}
|
||||
return tok;
|
||||
}
|
||||
|
||||
void Token::astOperand1(Token *tok)
|
||||
{
|
||||
if (mImpl->mAstOperand1)
|
||||
mImpl->mAstOperand1->mImpl->mAstParent = nullptr;
|
||||
// goto parent operator
|
||||
if (tok) {
|
||||
std::set<Token*> visitedParents;
|
||||
while (tok->mImpl->mAstParent) {
|
||||
if (!visitedParents.insert(tok->mImpl->mAstParent).second) // #6838/#6726/#8352 avoid hang on garbage code
|
||||
throw InternalError(this, "Internal error. Token::astOperand1() cyclic dependency.");
|
||||
tok = tok->mImpl->mAstParent;
|
||||
}
|
||||
tok = checkAstCycle(tok);
|
||||
tok->mImpl->mAstParent = this;
|
||||
}
|
||||
mImpl->mAstOperand1 = tok;
|
||||
|
@ -1363,13 +1374,7 @@ void Token::astOperand2(Token *tok)
|
|||
mImpl->mAstOperand2->mImpl->mAstParent = nullptr;
|
||||
// goto parent operator
|
||||
if (tok) {
|
||||
std::set<Token*> visitedParents;
|
||||
while (tok->mImpl->mAstParent) {
|
||||
//std::cout << tok << " -> " << tok->mAstParent ;
|
||||
if (!visitedParents.insert(tok->mImpl->mAstParent).second) // #6838/#6726 avoid hang on garbage code
|
||||
throw InternalError(this, "Internal error. Token::astOperand2() cyclic dependency.");
|
||||
tok = tok->mImpl->mAstParent;
|
||||
}
|
||||
tok = checkAstCycle(tok);
|
||||
tok->mImpl->mAstParent = this;
|
||||
}
|
||||
mImpl->mAstOperand2 = tok;
|
||||
|
|
Loading…
Reference in New Issue