forked from qt-creator/qt-creator
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>
This commit is contained in:
@@ -53,16 +53,22 @@ public:
|
|||||||
: m_accumulating(false), m_aborted(false), m_lockDepth(0)
|
: 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;
|
bool found;
|
||||||
*ret = value(name.toUtf8(), &found);
|
*ret = value(name.toUtf8(), &found);
|
||||||
if (found)
|
if (found)
|
||||||
return true;
|
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;
|
MacroExpander *expander = p ? p() : 0;
|
||||||
return expander && expander->resolveMacro(name, ret);
|
return expander && expander->d->resolveMacro(name, ret, seen);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (found)
|
if (found)
|
||||||
@@ -75,7 +81,7 @@ public:
|
|||||||
if (found)
|
if (found)
|
||||||
return true;
|
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)
|
QString value(const QByteArray &variable, bool *found)
|
||||||
@@ -243,7 +249,8 @@ MacroExpander::~MacroExpander()
|
|||||||
*/
|
*/
|
||||||
bool MacroExpander::resolveMacro(const QString &name, QString *ret) const
|
bool MacroExpander::resolveMacro(const QString &name, QString *ret) const
|
||||||
{
|
{
|
||||||
return d->resolveMacro(name, ret);
|
QSet<AbstractMacroExpander*> seen;
|
||||||
|
return d->resolveMacro(name, ret, seen);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@@ -31,6 +31,7 @@
|
|||||||
|
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
|
#include <QSet>
|
||||||
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
|
||||||
@@ -153,7 +154,8 @@ bool AbstractMacroExpander::expandNestedMacros(const QString &str, int *pos, QSt
|
|||||||
*pos = i;
|
*pos = i;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (resolveMacro(varName, ret)) {
|
QSet<AbstractMacroExpander*> seen;
|
||||||
|
if (resolveMacro(varName, ret, seen)) {
|
||||||
*pos = i;
|
*pos = i;
|
||||||
if (!pattern.isEmpty() && currArg == &replace) {
|
if (!pattern.isEmpty() && currArg == &replace) {
|
||||||
const QRegularExpression regexp(pattern);
|
const QRegularExpression regexp(pattern);
|
||||||
|
@@ -65,7 +65,7 @@ public:
|
|||||||
//! \param name The name of the expando
|
//! \param name The name of the expando
|
||||||
//! \param ret Replacement string on output
|
//! \param ret Replacement string on output
|
||||||
//! \return True if the expando was found
|
//! \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:
|
private:
|
||||||
bool expandNestedMacros(const QString &str, int *pos, QString *ret);
|
bool expandNestedMacros(const QString &str, int *pos, QString *ret);
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user