mirror of https://github.com/qt/qtbase.git
Change source identifier type in ProString
The strings remember in which file they were created/assigned. However, this used a non-counting reference to a ProFile, which could become dangling. If a subsequent ProFile re-used the exact same address, a string's source would be mis-identified, which would be fatal in conjunction with discard_from(). Since we actually need only a unique id for comparison, let's use an integer for that. Task-number: QTBUG-62434 Started-by: Simon Hausmann <simon.hausmann@qt.io> Change-Id: I395153afaf7c835d0119690ee7f4b915e6f90d4a Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
This commit is contained in:
parent
e6fad35155
commit
190aa94be7
|
@ -477,9 +477,10 @@ bool ProStringList::contains(const char *str, Qt::CaseSensitivity cs) const
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ProFile::ProFile(const QString &fileName)
|
ProFile::ProFile(int id, const QString &fileName)
|
||||||
: m_refCount(1),
|
: m_refCount(1),
|
||||||
m_fileName(fileName),
|
m_fileName(fileName),
|
||||||
|
m_id(id),
|
||||||
m_ok(true),
|
m_ok(true),
|
||||||
m_hostBuild(false)
|
m_hostBuild(false)
|
||||||
{
|
{
|
||||||
|
@ -496,7 +497,7 @@ ProString ProFile::getStr(const ushort *&tPtr)
|
||||||
{
|
{
|
||||||
uint len = *tPtr++;
|
uint len = *tPtr++;
|
||||||
ProString ret(items(), tPtr - tokPtr(), len);
|
ProString ret(items(), tPtr - tokPtr(), len);
|
||||||
ret.setSource(this);
|
ret.setSource(m_id);
|
||||||
tPtr += len;
|
tPtr += len;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,8 +73,8 @@ public:
|
||||||
void setValue(const QString &str);
|
void setValue(const QString &str);
|
||||||
void clear() { m_string.clear(); m_length = 0; }
|
void clear() { m_string.clear(); m_length = 0; }
|
||||||
ProString &setSource(const ProString &other) { m_file = other.m_file; return *this; }
|
ProString &setSource(const ProString &other) { m_file = other.m_file; return *this; }
|
||||||
ProString &setSource(const ProFile *pro) { m_file = pro; return *this; }
|
ProString &setSource(int id) { m_file = id; return *this; }
|
||||||
const ProFile *sourceFile() const { return m_file; }
|
int sourceFile() const { return m_file; }
|
||||||
|
|
||||||
ProString &prepend(const ProString &other);
|
ProString &prepend(const ProString &other);
|
||||||
ProString &append(const ProString &other, bool *pending = 0);
|
ProString &append(const ProString &other, bool *pending = 0);
|
||||||
|
@ -163,7 +163,7 @@ private:
|
||||||
|
|
||||||
QString m_string;
|
QString m_string;
|
||||||
int m_offset, m_length;
|
int m_offset, m_length;
|
||||||
const ProFile *m_file;
|
int m_file;
|
||||||
mutable uint m_hash;
|
mutable uint m_hash;
|
||||||
QChar *prepareExtend(int extraLen, int thisTarget, int extraTarget);
|
QChar *prepareExtend(int extraLen, int thisTarget, int extraTarget);
|
||||||
uint updatedHash() const;
|
uint updatedHash() const;
|
||||||
|
@ -340,9 +340,10 @@ enum ProToken {
|
||||||
class QMAKE_EXPORT ProFile
|
class QMAKE_EXPORT ProFile
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit ProFile(const QString &fileName);
|
ProFile(int id, const QString &fileName);
|
||||||
~ProFile();
|
~ProFile();
|
||||||
|
|
||||||
|
int id() const { return m_id; }
|
||||||
QString fileName() const { return m_fileName; }
|
QString fileName() const { return m_fileName; }
|
||||||
QString directoryName() const { return m_directoryName; }
|
QString directoryName() const { return m_directoryName; }
|
||||||
const QString &items() const { return m_proitems; }
|
const QString &items() const { return m_proitems; }
|
||||||
|
@ -367,6 +368,7 @@ private:
|
||||||
QString m_proitems;
|
QString m_proitems;
|
||||||
QString m_fileName;
|
QString m_fileName;
|
||||||
QString m_directoryName;
|
QString m_directoryName;
|
||||||
|
int m_id;
|
||||||
bool m_ok;
|
bool m_ok;
|
||||||
bool m_hostBuild;
|
bool m_hostBuild;
|
||||||
};
|
};
|
||||||
|
|
|
@ -713,9 +713,9 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinExpand(
|
||||||
after = args[3];
|
after = args[3];
|
||||||
const ProStringList &var = values(map(args.at(0)));
|
const ProStringList &var = values(map(args.at(0)));
|
||||||
if (!var.isEmpty()) {
|
if (!var.isEmpty()) {
|
||||||
const ProFile *src = currentProFile();
|
int src = currentFileId();
|
||||||
for (const ProString &v : var)
|
for (const ProString &v : var)
|
||||||
if (const ProFile *s = v.sourceFile()) {
|
if (int s = v.sourceFile()) {
|
||||||
src = s;
|
src = s;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1064,7 +1064,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinExpand(
|
||||||
dirs.append(fname + QLatin1Char('/'));
|
dirs.append(fname + QLatin1Char('/'));
|
||||||
}
|
}
|
||||||
if (regex.exactMatch(qdir[i]))
|
if (regex.exactMatch(qdir[i]))
|
||||||
ret += ProString(fname).setSource(currentProFile());
|
ret += ProString(fname).setSource(currentFileId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1331,7 +1331,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
|
||||||
return ReturnFalse;
|
return ReturnFalse;
|
||||||
}
|
}
|
||||||
QString fn = resolvePath(args.at(0).toQString(m_tmp1));
|
QString fn = resolvePath(args.at(0).toQString(m_tmp1));
|
||||||
ProFile *pro = m_parser->parsedProFile(fn, QMakeParser::ParseOnlyCached);
|
int pro = m_parser->idForFileName(fn);
|
||||||
if (!pro)
|
if (!pro)
|
||||||
return ReturnFalse;
|
return ReturnFalse;
|
||||||
ProValueMap &vmap = m_valuemapStack.first();
|
ProValueMap &vmap = m_valuemapStack.first();
|
||||||
|
@ -1351,18 +1351,17 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
|
||||||
++vit;
|
++vit;
|
||||||
}
|
}
|
||||||
for (auto fit = m_functionDefs.testFunctions.begin(); fit != m_functionDefs.testFunctions.end(); ) {
|
for (auto fit = m_functionDefs.testFunctions.begin(); fit != m_functionDefs.testFunctions.end(); ) {
|
||||||
if (fit->pro() == pro)
|
if (fit->pro()->id() == pro)
|
||||||
fit = m_functionDefs.testFunctions.erase(fit);
|
fit = m_functionDefs.testFunctions.erase(fit);
|
||||||
else
|
else
|
||||||
++fit;
|
++fit;
|
||||||
}
|
}
|
||||||
for (auto fit = m_functionDefs.replaceFunctions.begin(); fit != m_functionDefs.replaceFunctions.end(); ) {
|
for (auto fit = m_functionDefs.replaceFunctions.begin(); fit != m_functionDefs.replaceFunctions.end(); ) {
|
||||||
if (fit->pro() == pro)
|
if (fit->pro()->id() == pro)
|
||||||
fit = m_functionDefs.replaceFunctions.erase(fit);
|
fit = m_functionDefs.replaceFunctions.erase(fit);
|
||||||
else
|
else
|
||||||
++fit;
|
++fit;
|
||||||
}
|
}
|
||||||
pro->deref();
|
|
||||||
ProStringList &iif = m_valuemapStack.first()[ProKey("QMAKE_INTERNAL_INCLUDED_FILES")];
|
ProStringList &iif = m_valuemapStack.first()[ProKey("QMAKE_INTERNAL_INCLUDED_FILES")];
|
||||||
int idx = iif.indexOf(ProString(fn));
|
int idx = iif.indexOf(ProString(fn));
|
||||||
if (idx >= 0)
|
if (idx >= 0)
|
||||||
|
|
|
@ -271,13 +271,13 @@ void QMakeEvaluator::skipHashStr(const ushort *&tokPtr)
|
||||||
|
|
||||||
// FIXME: this should not build new strings for direct sections.
|
// FIXME: this should not build new strings for direct sections.
|
||||||
// Note that the E_SPRINTF and E_LIST implementations rely on the deep copy.
|
// Note that the E_SPRINTF and E_LIST implementations rely on the deep copy.
|
||||||
ProStringList QMakeEvaluator::split_value_list(const QStringRef &vals, const ProFile *source)
|
ProStringList QMakeEvaluator::split_value_list(const QStringRef &vals, int source)
|
||||||
{
|
{
|
||||||
QString build;
|
QString build;
|
||||||
ProStringList ret;
|
ProStringList ret;
|
||||||
|
|
||||||
if (!source)
|
if (!source)
|
||||||
source = currentProFile();
|
source = currentFileId();
|
||||||
|
|
||||||
const QChar *vals_data = vals.data();
|
const QChar *vals_data = vals.data();
|
||||||
const int vals_len = vals.length();
|
const int vals_len = vals.length();
|
||||||
|
@ -1299,7 +1299,7 @@ void QMakeEvaluator::setupProject()
|
||||||
{
|
{
|
||||||
setTemplate();
|
setTemplate();
|
||||||
ProValueMap &vars = m_valuemapStack.top();
|
ProValueMap &vars = m_valuemapStack.top();
|
||||||
ProFile *proFile = currentProFile();
|
int proFile = currentFileId();
|
||||||
vars[ProKey("TARGET")] << ProString(QFileInfo(currentFileName()).baseName()).setSource(proFile);
|
vars[ProKey("TARGET")] << ProString(QFileInfo(currentFileName()).baseName()).setSource(proFile);
|
||||||
vars[ProKey("_PRO_FILE_")] << ProString(currentFileName()).setSource(proFile);
|
vars[ProKey("_PRO_FILE_")] << ProString(currentFileName()).setSource(proFile);
|
||||||
vars[ProKey("_PRO_FILE_PWD_")] << ProString(currentDirectory()).setSource(proFile);
|
vars[ProKey("_PRO_FILE_PWD_")] << ProString(currentDirectory()).setSource(proFile);
|
||||||
|
@ -1593,6 +1593,14 @@ ProFile *QMakeEvaluator::currentProFile() const
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int QMakeEvaluator::currentFileId() const
|
||||||
|
{
|
||||||
|
ProFile *pro = currentProFile();
|
||||||
|
if (pro)
|
||||||
|
return pro->id();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
QString QMakeEvaluator::currentFileName() const
|
QString QMakeEvaluator::currentFileName() const
|
||||||
{
|
{
|
||||||
ProFile *pro = currentProFile();
|
ProFile *pro = currentProFile();
|
||||||
|
|
|
@ -176,12 +176,13 @@ public:
|
||||||
|
|
||||||
void setTemplate();
|
void setTemplate();
|
||||||
|
|
||||||
ProStringList split_value_list(const QStringRef &vals, const ProFile *source = 0);
|
ProStringList split_value_list(const QStringRef &vals, int source = 0);
|
||||||
VisitReturn expandVariableReferences(const ushort *&tokPtr, int sizeHint, ProStringList *ret, bool joined);
|
VisitReturn expandVariableReferences(const ushort *&tokPtr, int sizeHint, ProStringList *ret, bool joined);
|
||||||
|
|
||||||
QString currentFileName() const;
|
QString currentFileName() const;
|
||||||
QString currentDirectory() const;
|
QString currentDirectory() const;
|
||||||
ProFile *currentProFile() const;
|
ProFile *currentProFile() const;
|
||||||
|
int currentFileId() const;
|
||||||
QString resolvePath(const QString &fileName) const
|
QString resolvePath(const QString &fileName) const
|
||||||
{ return QMakeInternal::IoUtils::resolvePath(currentDirectory(), fileName); }
|
{ return QMakeInternal::IoUtils::resolvePath(currentDirectory(), fileName); }
|
||||||
|
|
||||||
|
|
|
@ -167,7 +167,7 @@ QMakeParser::QMakeParser(ProFileCache *cache, QMakeVfs *vfs, QMakeParserHandler
|
||||||
ProFile *QMakeParser::parsedProFile(const QString &fileName, ParseFlags flags)
|
ProFile *QMakeParser::parsedProFile(const QString &fileName, ParseFlags flags)
|
||||||
{
|
{
|
||||||
ProFile *pro;
|
ProFile *pro;
|
||||||
if ((flags & (ParseUseCache|ParseOnlyCached)) && m_cache) {
|
if ((flags & ParseUseCache) && m_cache) {
|
||||||
ProFileCache::Entry *ent;
|
ProFileCache::Entry *ent;
|
||||||
#ifdef PROPARSER_THREAD_SAFE
|
#ifdef PROPARSER_THREAD_SAFE
|
||||||
QMutexLocker locker(&m_cache->mutex);
|
QMutexLocker locker(&m_cache->mutex);
|
||||||
|
@ -189,13 +189,13 @@ ProFile *QMakeParser::parsedProFile(const QString &fileName, ParseFlags flags)
|
||||||
#endif
|
#endif
|
||||||
if ((pro = ent->pro))
|
if ((pro = ent->pro))
|
||||||
pro->ref();
|
pro->ref();
|
||||||
} else if (!(flags & ParseOnlyCached)) {
|
} else {
|
||||||
ent = &m_cache->parsed_files[fileName];
|
ent = &m_cache->parsed_files[fileName];
|
||||||
#ifdef PROPARSER_THREAD_SAFE
|
#ifdef PROPARSER_THREAD_SAFE
|
||||||
ent->locker = new ProFileCache::Entry::Locker;
|
ent->locker = new ProFileCache::Entry::Locker;
|
||||||
locker.unlock();
|
locker.unlock();
|
||||||
#endif
|
#endif
|
||||||
pro = new ProFile(fileName);
|
pro = new ProFile(idForFileName(fileName), fileName);
|
||||||
if (!read(pro, flags)) {
|
if (!read(pro, flags)) {
|
||||||
delete pro;
|
delete pro;
|
||||||
pro = 0;
|
pro = 0;
|
||||||
|
@ -214,17 +214,13 @@ ProFile *QMakeParser::parsedProFile(const QString &fileName, ParseFlags flags)
|
||||||
ent->locker = 0;
|
ent->locker = 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
} else {
|
|
||||||
pro = 0;
|
|
||||||
}
|
}
|
||||||
} else if (!(flags & ParseOnlyCached)) {
|
} else {
|
||||||
pro = new ProFile(fileName);
|
pro = new ProFile(idForFileName(fileName), fileName);
|
||||||
if (!read(pro, flags)) {
|
if (!read(pro, flags)) {
|
||||||
delete pro;
|
delete pro;
|
||||||
pro = 0;
|
pro = 0;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
pro = 0;
|
|
||||||
}
|
}
|
||||||
return pro;
|
return pro;
|
||||||
}
|
}
|
||||||
|
@ -232,11 +228,22 @@ ProFile *QMakeParser::parsedProFile(const QString &fileName, ParseFlags flags)
|
||||||
ProFile *QMakeParser::parsedProBlock(
|
ProFile *QMakeParser::parsedProBlock(
|
||||||
const QStringRef &contents, const QString &name, int line, SubGrammar grammar)
|
const QStringRef &contents, const QString &name, int line, SubGrammar grammar)
|
||||||
{
|
{
|
||||||
ProFile *pro = new ProFile(name);
|
ProFile *pro = new ProFile(0, name);
|
||||||
read(pro, contents, line, grammar);
|
read(pro, contents, line, grammar);
|
||||||
return pro;
|
return pro;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int QMakeParser::idForFileName(const QString &fileName)
|
||||||
|
{
|
||||||
|
#ifdef PROPARSER_THREAD_SAFE
|
||||||
|
QMutexLocker lck(&fileIdMutex);
|
||||||
|
#endif
|
||||||
|
int &place = fileIdMap[fileName];
|
||||||
|
if (!place)
|
||||||
|
place = ++fileIdCounter;
|
||||||
|
return place;
|
||||||
|
}
|
||||||
|
|
||||||
void QMakeParser::discardFileFromCache(const QString &fileName)
|
void QMakeParser::discardFileFromCache(const QString &fileName)
|
||||||
{
|
{
|
||||||
if (m_cache)
|
if (m_cache)
|
||||||
|
|
|
@ -78,7 +78,6 @@ public:
|
||||||
enum ParseFlag {
|
enum ParseFlag {
|
||||||
ParseDefault = 0,
|
ParseDefault = 0,
|
||||||
ParseUseCache = 1,
|
ParseUseCache = 1,
|
||||||
ParseOnlyCached = 2,
|
|
||||||
ParseReportMissing = 4
|
ParseReportMissing = 4
|
||||||
};
|
};
|
||||||
Q_DECLARE_FLAGS(ParseFlags, ParseFlag)
|
Q_DECLARE_FLAGS(ParseFlags, ParseFlag)
|
||||||
|
@ -91,6 +90,8 @@ public:
|
||||||
ProFile *parsedProBlock(const QStringRef &contents, const QString &name, int line = 0,
|
ProFile *parsedProBlock(const QStringRef &contents, const QString &name, int line = 0,
|
||||||
SubGrammar grammar = FullGrammar);
|
SubGrammar grammar = FullGrammar);
|
||||||
|
|
||||||
|
int idForFileName(const QString &fileName);
|
||||||
|
|
||||||
void discardFileFromCache(const QString &fileName);
|
void discardFileFromCache(const QString &fileName);
|
||||||
|
|
||||||
#ifdef PROPARSER_DEBUG
|
#ifdef PROPARSER_DEBUG
|
||||||
|
@ -181,6 +182,12 @@ private:
|
||||||
|
|
||||||
QString m_tmp; // Temporary for efficient toQString
|
QString m_tmp; // Temporary for efficient toQString
|
||||||
|
|
||||||
|
QHash<QString, int> fileIdMap;
|
||||||
|
#ifdef PROEVALUATOR_THREAD_SAFE
|
||||||
|
QMutex fileIdMutex;
|
||||||
|
#endif
|
||||||
|
int fileIdCounter = 0;
|
||||||
|
|
||||||
ProFileCache *m_cache;
|
ProFileCache *m_cache;
|
||||||
QMakeParserHandler *m_handler;
|
QMakeParserHandler *m_handler;
|
||||||
QMakeVfs *m_vfs;
|
QMakeVfs *m_vfs;
|
||||||
|
|
Loading…
Reference in New Issue