From d550ba4e9628cf67880a1c8596629ec598718b3e Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Mon, 14 Aug 2017 12:06:35 +0200 Subject: qmake: make access to raw data temporaries safe make sure the access is properly scoped and does not recurse. Change-Id: Iaa345cd2771811281b9ed6f634c70235a78c3c33 Reviewed-by: Joerg Bornemann --- qmake/library/proitems.h | 49 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) (limited to 'qmake/library/proitems.h') diff --git a/qmake/library/proitems.h b/qmake/library/proitems.h index 1d7ebed3aa..fcb6869780 100644 --- a/qmake/library/proitems.h +++ b/qmake/library/proitems.h @@ -229,6 +229,55 @@ inline bool operator!=(const QString &that, const ProString &other) QTextStream &operator<<(QTextStream &t, const ProString &str); +// This class manages read-only access to a ProString via a raw data QString +// temporary, ensuring that the latter is accessed exclusively. +class ProStringRoUser +{ +public: + ProStringRoUser(QString &rs) + { + Q_ASSERT(rs.isDetached() || rs.isEmpty()); + m_rs = &rs; + } + ProStringRoUser(const ProString &ps, QString &rs) + : ProStringRoUser(rs) + { + ps.toQString(rs); + } + // No destructor, as a RAII pattern cannot be used: references to the + // temporary string can legitimately outlive instances of this class + // (if they are held by Qt, e.g. in QRegExp). + QString &set(const ProString &ps) { return ps.toQString(*m_rs); } + QString &str() { return *m_rs; } + +protected: + QString *m_rs; +}; + +// This class manages read-write access to a ProString via a raw data QString +// temporary, ensuring that the latter is accessed exclusively, and that raw +// data does not leak outside its source's refcounting. +class ProStringRwUser : public ProStringRoUser +{ +public: + ProStringRwUser(QString &rs) + : ProStringRoUser(rs), m_ps(0) {} + ProStringRwUser(const ProString &ps, QString &rs) + : ProStringRoUser(ps, rs), m_ps(&ps) {} + QString &set(const ProString &ps) { m_ps = &ps; return ProStringRoUser::set(ps); } + ProString extract(const QString &s) const + { return s.isSharedWith(*m_rs) ? *m_ps : ProString(s).setSource(*m_ps); } + ProString extract(const QString &s, const ProStringRwUser &other) const + { + if (other.m_ps && s.isSharedWith(*other.m_rs)) + return *other.m_ps; + return extract(s); + } + +private: + const ProString *m_ps; +}; + class ProStringList : public QVector { public: ProStringList() {} -- cgit v1.2.3