diff options
author | Tobias Hunger <tobias.hunger@qt.io> | 2017-06-07 16:50:04 +0200 |
---|---|---|
committer | Tobias Hunger <tobias.hunger@qt.io> | 2017-06-20 12:53:38 +0000 |
commit | 4e96f2ce22e1a01b08b196e9b940034d50b87460 (patch) | |
tree | 96affc46818e609fdcaf2243e259a533c540f0fe | |
parent | ba8e7d11562f7d2c811fd3a211fc7c429cddf3c3 (diff) | |
download | qt-creator-4e96f2ce22e1a01b08b196e9b940034d50b87460.tar.gz |
MacroExpander: Prevent loop with subproviders
Prevent a loop where a subprovider of a macroexpander creates
the macroexpander itself.
Change-Id: Id2f3e29651aeb22c818091d8c785a6ea01545463
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
-rw-r--r-- | src/libs/utils/macroexpander.cpp | 17 | ||||
-rw-r--r-- | src/libs/utils/stringutils.cpp | 4 | ||||
-rw-r--r-- | src/libs/utils/stringutils.h | 2 |
3 files changed, 16 insertions, 7 deletions
diff --git a/src/libs/utils/macroexpander.cpp b/src/libs/utils/macroexpander.cpp index 6aa965a942..755f2e0a89 100644 --- a/src/libs/utils/macroexpander.cpp +++ b/src/libs/utils/macroexpander.cpp @@ -53,16 +53,22 @@ public: : m_accumulating(false), m_aborted(false), m_lockDepth(0) {} - bool resolveMacro(const QString &name, QString *ret) + bool resolveMacro(const QString &name, QString *ret, QSet<AbstractMacroExpander *> &seen) { + // Prevent loops: + const int count = seen.count(); + seen.insert(this); + if (seen.count() == count) + return false; + bool found; *ret = value(name.toUtf8(), &found); if (found) return true; - found = Utils::anyOf(m_subProviders, [name, ret] (const MacroExpanderProvider &p) -> bool { + found = Utils::anyOf(m_subProviders, [name, ret, &seen] (const MacroExpanderProvider &p) -> bool { MacroExpander *expander = p ? p() : 0; - return expander && expander->resolveMacro(name, ret); + return expander && expander->d->resolveMacro(name, ret, seen); }); if (found) @@ -75,7 +81,7 @@ public: if (found) return true; - return this == globalMacroExpander()->d ? false : globalMacroExpander()->d->resolveMacro(name, ret); + return this == globalMacroExpander()->d ? false : globalMacroExpander()->d->resolveMacro(name, ret, seen); } QString value(const QByteArray &variable, bool *found) @@ -243,7 +249,8 @@ MacroExpander::~MacroExpander() */ bool MacroExpander::resolveMacro(const QString &name, QString *ret) const { - return d->resolveMacro(name, ret); + QSet<AbstractMacroExpander*> seen; + return d->resolveMacro(name, ret, seen); } /*! diff --git a/src/libs/utils/stringutils.cpp b/src/libs/utils/stringutils.cpp index 85813004de..04df87fb5f 100644 --- a/src/libs/utils/stringutils.cpp +++ b/src/libs/utils/stringutils.cpp @@ -31,6 +31,7 @@ #include <QDir> #include <QRegularExpression> +#include <QSet> #include <limits.h> @@ -153,7 +154,8 @@ bool AbstractMacroExpander::expandNestedMacros(const QString &str, int *pos, QSt *pos = i; return true; } - if (resolveMacro(varName, ret)) { + QSet<AbstractMacroExpander*> seen; + if (resolveMacro(varName, ret, seen)) { *pos = i; if (!pattern.isEmpty() && currArg == &replace) { const QRegularExpression regexp(pattern); diff --git a/src/libs/utils/stringutils.h b/src/libs/utils/stringutils.h index 8e0c78f028..20f6063710 100644 --- a/src/libs/utils/stringutils.h +++ b/src/libs/utils/stringutils.h @@ -65,7 +65,7 @@ public: //! \param name The name of the expando //! \param ret Replacement string on output //! \return True if the expando was found - virtual bool resolveMacro(const QString &name, QString *ret) = 0; + virtual bool resolveMacro(const QString &name, QString *ret, QSet<AbstractMacroExpander *> &seen) = 0; private: bool expandNestedMacros(const QString &str, int *pos, QString *ret); }; |