From b61dbac6ff78b08318049e77f57965c9005bdde3 Mon Sep 17 00:00:00 2001 From: Leandro Melo <leandro.melo@nokia.com> Date: Thu, 5 Aug 2010 11:41:21 +0200 Subject: [PATCH] Fix potential endless recursion in C++ hover handler. To catch cases of invalid code like this: struct A : B {}; struct B : A {}; Reviewed-by: Roberto Raggi --- src/plugins/cppeditor/cpphoverhandler.cpp | 47 ++++++++++++++--------- 1 file changed, 28 insertions(+), 19 deletions(-) diff --git a/src/plugins/cppeditor/cpphoverhandler.cpp b/src/plugins/cppeditor/cpphoverhandler.cpp index 6efc3ae1b17..d90162e6088 100644 --- a/src/plugins/cppeditor/cpphoverhandler.cpp +++ b/src/plugins/cppeditor/cpphoverhandler.cpp @@ -49,6 +49,7 @@ #include <cplusplus/LookupContext.h> #include <cplusplus/LookupItem.h> +#include <QtCore/QSet> #include <QtCore/QDir> #include <QtCore/QFileInfo> #include <QtCore/QtAlgorithms> @@ -82,24 +83,30 @@ namespace { } } - void buildClassHierarchyHelper(Symbol *symbol, + void buildClassHierarchyHelper(ClassOrNamespace *classSymbol, const LookupContext &context, const Overview &overview, - QList<QStringList> *hierarchy) { - if (ClassOrNamespace *classSymbol = context.lookupType(symbol)) { - const QList<ClassOrNamespace *> &bases = classSymbol->usings(); - foreach (ClassOrNamespace *baseClass, bases) { - const QList<Symbol *> &symbols = baseClass->symbols(); - foreach (Symbol *baseSymbol, symbols) { - if (baseSymbol->isClass()) { - const QString &qualifiedName = overview.prettyName( - LookupContext::fullyQualifiedName(baseSymbol)); - if (!qualifiedName.isEmpty()) { - hierarchy->back().append(qualifiedName); - buildClassHierarchyHelper(baseSymbol, context, overview, hierarchy); - hierarchy->append(hierarchy->back()); - hierarchy->back().removeLast(); - } + QList<QStringList> *hierarchy, + QSet<ClassOrNamespace *> *visited) { + visited->insert(classSymbol); + const QList<ClassOrNamespace *> &bases = classSymbol->usings(); + foreach (ClassOrNamespace *baseClass, bases) { + const QList<Symbol *> &symbols = baseClass->symbols(); + foreach (Symbol *baseSymbol, symbols) { + if (baseSymbol->isClass() && ( + classSymbol = context.lookupType(baseSymbol)) && + !visited->contains(classSymbol)) { + const QString &qualifiedName = overview.prettyName( + LookupContext::fullyQualifiedName(baseSymbol)); + if (!qualifiedName.isEmpty()) { + hierarchy->back().append(qualifiedName); + buildClassHierarchyHelper(classSymbol, + context, + overview, + hierarchy, + visited); + hierarchy->append(hierarchy->back()); + hierarchy->back().removeLast(); } } } @@ -110,10 +117,12 @@ namespace { const LookupContext &context, const Overview &overview, QList<QStringList> *hierarchy) { - if (hierarchy->isEmpty()) + if (ClassOrNamespace *classSymbol = context.lookupType(symbol)) { hierarchy->append(QStringList()); - buildClassHierarchyHelper(symbol, context, overview, hierarchy); - hierarchy->removeLast(); + QSet<ClassOrNamespace *> visited; + buildClassHierarchyHelper(classSymbol, context, overview, hierarchy, &visited); + hierarchy->removeLast(); + } } struct ClassHierarchyComp -- GitLab