From 2e49aaf484ad69700e39de72a6abfb79fc836c27 Mon Sep 17 00:00:00 2001 From: Roberto Raggi <roberto.raggi@nokia.com> Date: Mon, 13 Jul 2009 18:00:22 +0200 Subject: [PATCH] Fixed possible crashes when resolving namespace and class bindings. --- src/libs/cplusplus/CppBindings.cpp | 51 ++++++++++++++++++++++-------- src/libs/cplusplus/CppBindings.h | 12 +++---- 2 files changed, 43 insertions(+), 20 deletions(-) diff --git a/src/libs/cplusplus/CppBindings.cpp b/src/libs/cplusplus/CppBindings.cpp index ba5c37754ee..06d16a281ae 100644 --- a/src/libs/cplusplus/CppBindings.cpp +++ b/src/libs/cplusplus/CppBindings.cpp @@ -113,8 +113,13 @@ NamespaceBinding *NamespaceBinding::globalNamespaceBinding() return it; } -Binding *NamespaceBinding::findClassOrNamespaceBinding(Identifier *id) +Binding *NamespaceBinding::findClassOrNamespaceBinding(Identifier *id, QSet<Binding *> *processed) { + if (processed->contains(this)) + return 0; + + processed->insert(this); + if (id->isEqualTo(identifier())) return const_cast<NamespaceBinding *>(this); @@ -129,21 +134,26 @@ Binding *NamespaceBinding::findClassOrNamespaceBinding(Identifier *id) } foreach (NamespaceBinding *u, usings) { - if (Binding *b = u->findClassOrNamespaceBinding(id)) + if (Binding *b = u->findClassOrNamespaceBinding(id, processed)) return b; } if (parent) - return parent->findClassOrNamespaceBinding(id); + return parent->findClassOrNamespaceBinding(id, processed); return 0; } -ClassBinding *NamespaceBinding::findClassBinding(Name *name) +ClassBinding *NamespaceBinding::findClassBinding(Name *name, QSet<Binding *> *processed) { if (! name) return 0; + if (processed->contains(this)) + return 0; + + processed->insert(this); + Identifier *id = name->identifier(); foreach (ClassBinding *classBinding, classBindings) { @@ -152,7 +162,12 @@ ClassBinding *NamespaceBinding::findClassBinding(Name *name) } if (parent) - return parent->findClassBinding(name); + return parent->findClassBinding(name, processed); + + foreach (NamespaceBinding *u, usings) { + if (ClassBinding *classBinding = u->findClassBinding(name, processed)) + return classBinding; + } return 0; } @@ -384,7 +399,7 @@ QByteArray ClassBinding::qualifiedId() const return s; } -Binding *ClassBinding::findClassOrNamespaceBinding(Identifier *id) +Binding *ClassBinding::findClassOrNamespaceBinding(Identifier *id, QSet<Binding *> *processed) { if (id->isEqualTo(identifier())) return this; @@ -397,21 +412,26 @@ Binding *ClassBinding::findClassOrNamespaceBinding(Identifier *id) foreach (ClassBinding *baseClassBinding, baseClassBindings) { if (! baseClassBinding) continue; - else if (Binding *b = baseClassBinding->findClassOrNamespaceBinding(id)) + else if (Binding *b = baseClassBinding->findClassOrNamespaceBinding(id, processed)) return b; } if (parent) - return parent->findClassOrNamespaceBinding(id); + return parent->findClassOrNamespaceBinding(id, processed); return 0; } -ClassBinding *ClassBinding::findClassBinding(Name *name) +ClassBinding *ClassBinding::findClassBinding(Name *name, QSet<Binding *> *processed) { if (! name) return 0; + if (processed->contains(this)) + return 0; + + processed->insert(this); + if (const QualifiedNameId *q = name->asQualifiedNameId()) { Binding *currentBinding = this; @@ -420,7 +440,7 @@ ClassBinding *ClassBinding::findClassBinding(Name *name) if (! id) return 0; - Binding *classOrNamespaceBinding = currentBinding->findClassOrNamespaceBinding(id); + Binding *classOrNamespaceBinding = currentBinding->findClassOrNamespaceBinding(id, processed); if (! classOrNamespaceBinding) return 0; @@ -429,7 +449,7 @@ ClassBinding *ClassBinding::findClassBinding(Name *name) } if (currentBinding) - return currentBinding->findClassBinding(q->unqualifiedNameId()); + return currentBinding->findClassBinding(q->unqualifiedNameId(), processed); return 0; } @@ -446,7 +466,7 @@ ClassBinding *ClassBinding::findClassBinding(Name *name) } if (parent) - return parent->findClassBinding(name); + return parent->findClassBinding(name, processed); } return 0; @@ -637,6 +657,7 @@ NamespaceBinding *Binder::switchNamespaceBinding(NamespaceBinding *binding) ClassBinding *Binder::findOrCreateClassBinding(Class *classSymbol) { + // ### FINISH ME ClassBinding *binding = 0; if (classBinding) @@ -650,13 +671,15 @@ ClassBinding *Binder::findOrCreateClassBinding(Class *classSymbol) ClassBinding *Binder::findClassBinding(Name *name) { + QSet<Binding *> processed; + if (classBinding) { - if (ClassBinding *k = classBinding->findClassBinding(name)) + if (ClassBinding *k = classBinding->findClassBinding(name, &processed)) return k; } if (namespaceBinding) - return namespaceBinding->findClassBinding(name); + return namespaceBinding->findClassBinding(name, &processed); return 0; } diff --git a/src/libs/cplusplus/CppBindings.h b/src/libs/cplusplus/CppBindings.h index be5933e2c20..d3c4fa2198f 100644 --- a/src/libs/cplusplus/CppBindings.h +++ b/src/libs/cplusplus/CppBindings.h @@ -84,8 +84,8 @@ public: virtual NamespaceBinding *asNamespaceBinding() { return 0; } virtual ClassBinding *asClassBinding() { return 0; } - virtual ClassBinding *findClassBinding(Name *name) = 0; - virtual Binding *findClassOrNamespaceBinding(Identifier *id) = 0; + virtual ClassBinding *findClassBinding(Name *name, QSet<Binding *> *processed) = 0; + virtual Binding *findClassOrNamespaceBinding(Identifier *id, QSet<Binding *> *processed) = 0; }; class CPLUSPLUS_EXPORT NamespaceBinding: public Binding @@ -116,8 +116,8 @@ public: Name *name, bool lookAtParent = true); - virtual ClassBinding *findClassBinding(Name *name); - virtual Binding *findClassOrNamespaceBinding(Identifier *id); + virtual ClassBinding *findClassBinding(Name *name, QSet<Binding *> *processed); + virtual Binding *findClassOrNamespaceBinding(Identifier *id, QSet<Binding *> *processed); /// Helpers. virtual QByteArray qualifiedId() const; @@ -171,8 +171,8 @@ public: Identifier *identifier() const; virtual QByteArray qualifiedId() const; - virtual ClassBinding *findClassBinding(Name *name); - virtual Binding *findClassOrNamespaceBinding(Identifier *id); + virtual ClassBinding *findClassBinding(Name *name, QSet<Binding *> *processed); + virtual Binding *findClassOrNamespaceBinding(Identifier *id, QSet<Binding *> *processed); void dump(); -- GitLab