summaryrefslogtreecommitdiffstats
path: root/src/corelib
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2020-02-28 08:40:53 +0100
committerLars Knoll <lars.knoll@qt.io>2020-02-28 09:53:26 +0100
commit60f12c58a0aea6f2e9c688509d9f0afa87c8d76d (patch)
tree42bad03777b6446f6887cae3ba3f1d1ff3f160d8 /src/corelib
parent1ba46c9b632731d7d7e791de2b203d0d933245b9 (diff)
parenta450cce6b670dbcac84fcc4a66fc632b31ce8414 (diff)
Merge "Merge remote-tracking branch 'origin/5.15' into dev"
Diffstat (limited to 'src/corelib')
-rw-r--r--src/corelib/itemmodels/qconcatenatetablesproxymodel.cpp11
-rw-r--r--src/corelib/itemmodels/qconcatenatetablesproxymodel.h1
-rw-r--r--src/corelib/kernel/qobjectdefs_impl.h4
-rw-r--r--src/corelib/mimetypes/qmimeprovider_p.h2
-rw-r--r--src/corelib/serialization/qxmlstream.cpp36
-rw-r--r--src/corelib/serialization/qxmlstream.g14
-rw-r--r--src/corelib/serialization/qxmlstream.h2
-rw-r--r--src/corelib/serialization/qxmlstream_p.h14
-rw-r--r--src/corelib/thread/qrunnable.cpp12
-rw-r--r--src/corelib/thread/qrunnable.h2
-rw-r--r--src/corelib/thread/qthreadpool.cpp20
-rw-r--r--src/corelib/thread/qthreadpool.h4
-rw-r--r--src/corelib/time/qdatetimeparser.cpp8
-rw-r--r--src/corelib/tools/qhash.h52
14 files changed, 134 insertions, 48 deletions
diff --git a/src/corelib/itemmodels/qconcatenatetablesproxymodel.cpp b/src/corelib/itemmodels/qconcatenatetablesproxymodel.cpp
index 3afa132483..a2597faa93 100644
--- a/src/corelib/itemmodels/qconcatenatetablesproxymodel.cpp
+++ b/src/corelib/itemmodels/qconcatenatetablesproxymodel.cpp
@@ -448,6 +448,17 @@ QSize QConcatenateTablesProxyModel::span(const QModelIndex &index) const
}
/*!
+ Returns a list of models that were added as source models for this proxy model.
+
+ \since 5.15
+*/
+QList<QAbstractItemModel *> QConcatenateTablesProxyModel::sourceModels() const
+{
+ Q_D(const QConcatenateTablesProxyModel);
+ return d->m_models.toList();
+}
+
+/*!
Adds a source model \a sourceModel, below all previously added source models.
The ownership of \a sourceModel is not affected by this.
diff --git a/src/corelib/itemmodels/qconcatenatetablesproxymodel.h b/src/corelib/itemmodels/qconcatenatetablesproxymodel.h
index 69b3a2ba09..1fa84d5f51 100644
--- a/src/corelib/itemmodels/qconcatenatetablesproxymodel.h
+++ b/src/corelib/itemmodels/qconcatenatetablesproxymodel.h
@@ -56,6 +56,7 @@ public:
explicit QConcatenateTablesProxyModel(QObject *parent = nullptr);
~QConcatenateTablesProxyModel();
+ QList<QAbstractItemModel *> sourceModels() const;
Q_SCRIPTABLE void addSourceModel(QAbstractItemModel *sourceModel);
Q_SCRIPTABLE void removeSourceModel(QAbstractItemModel *sourceModel);
diff --git a/src/corelib/kernel/qobjectdefs_impl.h b/src/corelib/kernel/qobjectdefs_impl.h
index 31ecc8b20d..aed50d6c5a 100644
--- a/src/corelib/kernel/qobjectdefs_impl.h
+++ b/src/corelib/kernel/qobjectdefs_impl.h
@@ -285,11 +285,15 @@ namespace QtPrivate {
{
};
+ template <typename T>
+ using is_bool = std::is_same<bool, typename std::decay<T>::type>;
+
template<typename From, typename To>
struct AreArgumentsNarrowedBase<From, To, typename std::enable_if<sizeof(From) && sizeof(To)>::type>
: std::integral_constant<bool,
(std::is_floating_point<From>::value && std::is_integral<To>::value) ||
(std::is_floating_point<From>::value && std::is_floating_point<To>::value && sizeof(From) > sizeof(To)) ||
+ ((std::is_pointer<From>::value || std::is_member_pointer<From>::value) && QtPrivate::is_bool<To>::value) ||
((std::is_integral<From>::value || std::is_enum<From>::value) && std::is_floating_point<To>::value) ||
(std::is_integral<From>::value && std::is_integral<To>::value
&& (sizeof(From) > sizeof(To)
diff --git a/src/corelib/mimetypes/qmimeprovider_p.h b/src/corelib/mimetypes/qmimeprovider_p.h
index 0629df8a95..c4e712b318 100644
--- a/src/corelib/mimetypes/qmimeprovider_p.h
+++ b/src/corelib/mimetypes/qmimeprovider_p.h
@@ -140,7 +140,7 @@ public:
enum : bool { InternalDatabaseAvailable = false };
QMimeXMLProvider(QMimeDatabasePrivate *db, InternalDatabaseEnum)
: QMimeProviderBase(db, QString())
- { Q_UNREACHABLE() };
+ { Q_UNREACHABLE(); };
#endif
QMimeXMLProvider(QMimeDatabasePrivate *db, const QString &directory);
~QMimeXMLProvider();
diff --git a/src/corelib/serialization/qxmlstream.cpp b/src/corelib/serialization/qxmlstream.cpp
index 7ff87885a5..d7fb0d0d41 100644
--- a/src/corelib/serialization/qxmlstream.cpp
+++ b/src/corelib/serialization/qxmlstream.cpp
@@ -2041,6 +2041,42 @@ QStringRef QXmlStreamReader::dtdSystemId() const
return QStringRef();
}
+/*!
+ \since 5.15
+
+ Returns the maximum amount of characters a single entity is
+ allowed to expand into. If a single entity expands past the
+ given limit, the document is not considered well formed.
+
+ \sa setEntityExpansionLimit
+*/
+int QXmlStreamReader::entityExpansionLimit() const
+{
+ Q_D(const QXmlStreamReader);
+ return d->entityExpansionLimit;
+}
+
+/*!
+ \since 5.15
+
+ Sets the maximum amount of characters a single entity is
+ allowed to expand into to \a limit. If a single entity expands
+ past the given limit, the document is not considered well formed.
+
+ The limit is there to prevent DoS attacks when loading unknown
+ XML documents where recursive entity expansion could otherwise
+ exhaust all available memory.
+
+ The default value for this property is 4096 characters.
+
+ \sa entityExpansionLimit
+*/
+void QXmlStreamReader::setEntityExpansionLimit(int limit)
+{
+ Q_D(QXmlStreamReader);
+ d->entityExpansionLimit = limit;
+}
+
/*! If the tokenType() is \l StartElement, this function returns the
element's namespace declarations. Otherwise an empty vector is
returned.
diff --git a/src/corelib/serialization/qxmlstream.g b/src/corelib/serialization/qxmlstream.g
index 12ecc9bdb2..b623de9505 100644
--- a/src/corelib/serialization/qxmlstream.g
+++ b/src/corelib/serialization/qxmlstream.g
@@ -285,9 +285,19 @@ public:
QHash<QStringView, Entity> entityHash;
QHash<QStringView, Entity> parameterEntityHash;
QXmlStreamSimpleStack<Entity *>entityReferenceStack;
+ int entityExpansionLimit = 4096;
+ int entityLength = 0;
inline bool referenceEntity(Entity &entity) {
if (entity.isCurrentlyReferenced) {
- raiseWellFormedError(QXmlStream::tr("Recursive entity detected."));
+ raiseWellFormedError(QXmlStream::tr("Self-referencing entity detected."));
+ return false;
+ }
+ // entityLength represents the amount of additional characters the
+ // entity expands into (can be negative for e.g. &amp;). It's used to
+ // avoid DoS attacks through recursive entity expansions
+ entityLength += entity.value.size() - entity.name.size() - 2;
+ if (entityLength > entityExpansionLimit) {
+ raiseWellFormedError(QXmlStream::tr("Entity expands to more characters than the entity expansion limit."));
return false;
}
entity.isCurrentlyReferenced = true;
@@ -838,6 +848,8 @@ entity_done ::= ENTITY_DONE;
/.
case $rule_number:
entityReferenceStack.pop()->isCurrentlyReferenced = false;
+ if (entityReferenceStack.isEmpty())
+ entityLength = 0;
clearSym();
break;
./
diff --git a/src/corelib/serialization/qxmlstream.h b/src/corelib/serialization/qxmlstream.h
index 7d0aa64570..c8647e0465 100644
--- a/src/corelib/serialization/qxmlstream.h
+++ b/src/corelib/serialization/qxmlstream.h
@@ -426,6 +426,8 @@ public:
QStringRef dtdPublicId() const;
QStringRef dtdSystemId() const;
+ int entityExpansionLimit() const;
+ void setEntityExpansionLimit(int limit);
enum Error {
NoError,
diff --git a/src/corelib/serialization/qxmlstream_p.h b/src/corelib/serialization/qxmlstream_p.h
index 9c94e6d434..103b123b10 100644
--- a/src/corelib/serialization/qxmlstream_p.h
+++ b/src/corelib/serialization/qxmlstream_p.h
@@ -774,9 +774,19 @@ public:
QHash<QStringView, Entity> entityHash;
QHash<QStringView, Entity> parameterEntityHash;
QXmlStreamSimpleStack<Entity *>entityReferenceStack;
+ int entityExpansionLimit = 4096;
+ int entityLength = 0;
inline bool referenceEntity(Entity &entity) {
if (entity.isCurrentlyReferenced) {
- raiseWellFormedError(QXmlStream::tr("Recursive entity detected."));
+ raiseWellFormedError(QXmlStream::tr("Self-referencing entity detected."));
+ return false;
+ }
+ // entityLength represents the amount of additional characters the
+ // entity expands into (can be negative for e.g. &amp;). It's used to
+ // avoid DoS attacks through recursive entity expansions
+ entityLength += entity.value.size() - entity.name.size() - 2;
+ if (entityLength > entityExpansionLimit) {
+ raiseWellFormedError(QXmlStream::tr("Entity expands to more characters than the entity expansion limit."));
return false;
}
entity.isCurrentlyReferenced = true;
@@ -1308,6 +1318,8 @@ bool QXmlStreamReaderPrivate::parse()
case 10:
entityReferenceStack.pop()->isCurrentlyReferenced = false;
+ if (entityReferenceStack.isEmpty())
+ entityLength = 0;
clearSym();
break;
diff --git a/src/corelib/thread/qrunnable.cpp b/src/corelib/thread/qrunnable.cpp
index 5b883a05da..32f3cd657e 100644
--- a/src/corelib/thread/qrunnable.cpp
+++ b/src/corelib/thread/qrunnable.cpp
@@ -115,29 +115,29 @@ QRunnable::~QRunnable()
class FunctionRunnable : public QRunnable
{
- std::function<void()> m_functor;
+ std::function<void()> m_functionToRun;
public:
- FunctionRunnable(std::function<void()> functor) : m_functor(std::move(functor))
+ FunctionRunnable(std::function<void()> functionToRun) : m_functionToRun(std::move(functionToRun))
{
}
void run() override
{
- m_functor();
+ m_functionToRun();
}
};
/*!
\since 5.15
- Creates a QRunnable that calls \a fun in run().
+ Creates a QRunnable that calls \a functionToRun in run().
Auto-deletion is enabled by default.
\sa run(), autoDelete()
*/
-QRunnable *QRunnable::create(std::function<void()> fun)
+QRunnable *QRunnable::create(std::function<void()> functionToRun)
{
- return new FunctionRunnable(std::move(fun));
+ return new FunctionRunnable(std::move(functionToRun));
}
QT_END_NAMESPACE
diff --git a/src/corelib/thread/qrunnable.h b/src/corelib/thread/qrunnable.h
index c13aa3fa8c..26b6b991ac 100644
--- a/src/corelib/thread/qrunnable.h
+++ b/src/corelib/thread/qrunnable.h
@@ -60,7 +60,7 @@ public:
QRunnable() : ref(0) { }
virtual ~QRunnable();
- static QRunnable *create(std::function<void()> fun);
+ static QRunnable *create(std::function<void()> functionToRun);
bool autoDelete() const { return ref != -1; }
void setAutoDelete(bool _autoDelete) { ref = _autoDelete ? 0 : -1; }
diff --git a/src/corelib/thread/qthreadpool.cpp b/src/corelib/thread/qthreadpool.cpp
index d1875a69a9..a9352c3894 100644
--- a/src/corelib/thread/qthreadpool.cpp
+++ b/src/corelib/thread/qthreadpool.cpp
@@ -515,16 +515,16 @@ void QThreadPool::start(QRunnable *runnable, int priority)
\overload
\since 5.15
- Reserves a thread and uses it to run \a fun, unless this thread will
+ Reserves a thread and uses it to run \a functionToRun, unless this thread will
make the current thread count exceed maxThreadCount(). In that case,
- \a fun is added to a run queue instead. The \a priority argument can
+ \a functionToRun is added to a run queue instead. The \a priority argument can
be used to control the run queue's order of execution.
*/
-void QThreadPool::start(std::function<void()> fun, int priority)
+void QThreadPool::start(std::function<void()> functionToRun, int priority)
{
- if (!fun)
+ if (!functionToRun)
return;
- start(QRunnable::create(std::move(fun)), priority);
+ start(QRunnable::create(std::move(functionToRun)), priority);
}
/*!
@@ -561,17 +561,17 @@ bool QThreadPool::tryStart(QRunnable *runnable)
/*!
\overload
\since 5.15
- Attempts to reserve a thread to run \a fun.
+ Attempts to reserve a thread to run \a functionToRun.
If no threads are available at the time of calling, then this function
- does nothing and returns \c false. Otherwise, \a fun is run immediately
+ does nothing and returns \c false. Otherwise, \a functionToRun is run immediately
using one available thread and this function returns \c true.
*/
-bool QThreadPool::tryStart(std::function<void()> fun)
+bool QThreadPool::tryStart(std::function<void()> functionToRun)
{
- if (!fun)
+ if (!functionToRun)
return false;
- return tryStart(QRunnable::create(std::move(fun)));
+ return tryStart(QRunnable::create(std::move(functionToRun)));
}
/*! \property QThreadPool::expiryTimeout
diff --git a/src/corelib/thread/qthreadpool.h b/src/corelib/thread/qthreadpool.h
index 2eede44eca..e3691ab010 100644
--- a/src/corelib/thread/qthreadpool.h
+++ b/src/corelib/thread/qthreadpool.h
@@ -72,8 +72,8 @@ public:
void start(QRunnable *runnable, int priority = 0);
bool tryStart(QRunnable *runnable);
- void start(std::function<void()> fun, int priority = 0);
- bool tryStart(std::function<void()> fun);
+ void start(std::function<void()> functionToRun, int priority = 0);
+ bool tryStart(std::function<void()> functionToRun);
int expiryTimeout() const;
void setExpiryTimeout(int expiryTimeout);
diff --git a/src/corelib/time/qdatetimeparser.cpp b/src/corelib/time/qdatetimeparser.cpp
index 790c20004a..2a19611493 100644
--- a/src/corelib/time/qdatetimeparser.cpp
+++ b/src/corelib/time/qdatetimeparser.cpp
@@ -1539,6 +1539,14 @@ QDateTimeParser::parse(QString input, int position, const QDateTime &defaultValu
text = scan.input = input;
// Set spec *after* all checking, so validity is a property of the string:
scan.value = scan.value.toTimeSpec(spec);
+
+ /*
+ However, even with a valid string we might have ended up with an invalid datetime:
+ the non-existent hour during dst changes, for instance.
+ */
+ if (!scan.value.isValid() && scan.state == Acceptable)
+ scan.state = Intermediate;
+
return scan;
}
diff --git a/src/corelib/tools/qhash.h b/src/corelib/tools/qhash.h
index 47fa0520d9..59883e3968 100644
--- a/src/corelib/tools/qhash.h
+++ b/src/corelib/tools/qhash.h
@@ -324,7 +324,7 @@ public:
QHashData::Node *i;
public:
-#if QT_DEPRECATED_SINCE(5, 15)
+#if QT_DEPRECATED_WARNINGS_SINCE < QT_VERSION_CHECK(5, 15, 0)
typedef std::bidirectional_iterator_tag iterator_category;
#else
typedef std::forward_iterator_tag iterator_category;
@@ -354,23 +354,23 @@ public:
return r;
}
#if QT_DEPRECATED_SINCE(5, 15)
- inline QT_DEPRECATED iterator &operator--()
+ inline QT_DEPRECATED_VERSION_5_15 iterator &operator--()
{
i = QHashData::previousNode(i);
return *this;
}
- inline QT_DEPRECATED iterator operator--(int)
+ inline QT_DEPRECATED_VERSION_5_15 iterator operator--(int)
{
iterator r = *this;
i = QHashData::previousNode(i);
return r;
}
- inline QT_DEPRECATED iterator operator+(int j) const
+ inline QT_DEPRECATED_VERSION_5_15 iterator operator+(int j) const
{ iterator r = *this; if (j > 0) while (j--) ++r; else while (j++) --r; return r; }
- inline QT_DEPRECATED iterator operator-(int j) const { return operator+(-j); }
- inline QT_DEPRECATED iterator &operator+=(int j) { return *this = *this + j; }
- inline QT_DEPRECATED iterator &operator-=(int j) { return *this = *this - j; }
- friend inline QT_DEPRECATED iterator operator+(int j, iterator k) { return k + j; }
+ inline QT_DEPRECATED_VERSION_5_15 iterator operator-(int j) const { return operator+(-j); }
+ inline QT_DEPRECATED_VERSION_5_15 iterator &operator+=(int j) { return *this = *this + j; }
+ inline QT_DEPRECATED_VERSION_5_15 iterator &operator-=(int j) { return *this = *this - j; }
+ friend inline QT_DEPRECATED_VERSION_5_15 iterator operator+(int j, iterator k) { return k + j; }
#endif
inline bool operator==(const const_iterator &o) const { return i == o.i; }
@@ -387,7 +387,7 @@ public:
QHashData::Node *i;
public:
-#if QT_DEPRECATED_SINCE(5, 15)
+#if QT_DEPRECATED_WARNINGS_SINCE < QT_VERSION_CHECK(5, 15, 0)
typedef std::bidirectional_iterator_tag iterator_category;
#else
typedef std::forward_iterator_tag iterator_category;
@@ -420,23 +420,23 @@ public:
return r;
}
#if QT_DEPRECATED_SINCE(5, 15)
- inline QT_DEPRECATED const_iterator &operator--()
+ inline QT_DEPRECATED_VERSION_5_15 const_iterator &operator--()
{
i = QHashData::previousNode(i);
return *this;
}
- inline QT_DEPRECATED const_iterator operator--(int)
+ inline QT_DEPRECATED_VERSION_5_15 const_iterator operator--(int)
{
const_iterator r = *this;
i = QHashData::previousNode(i);
return r;
}
- inline QT_DEPRECATED const_iterator operator+(int j) const
+ inline QT_DEPRECATED_VERSION_5_15 const_iterator operator+(int j) const
{ const_iterator r = *this; if (j > 0) while (j--) ++r; else while (j++) --r; return r; }
- inline QT_DEPRECATED const_iterator operator-(int j) const { return operator+(-j); }
- inline QT_DEPRECATED const_iterator &operator+=(int j) { return *this = *this + j; }
- inline QT_DEPRECATED const_iterator &operator-=(int j) { return *this = *this - j; }
- friend inline QT_DEPRECATED const_iterator operator+(int j, const_iterator k)
+ inline QT_DEPRECATED_VERSION_5_15 const_iterator operator-(int j) const { return operator+(-j); }
+ inline QT_DEPRECATED_VERSION_5_15 const_iterator &operator+=(int j) { return *this = *this + j; }
+ inline QT_DEPRECATED_VERSION_5_15 const_iterator &operator-=(int j) { return *this = *this - j; }
+ friend inline QT_DEPRECATED_VERSION_5_15 const_iterator operator+(int j, const_iterator k)
{
return k + j;
}
@@ -466,12 +466,12 @@ public:
inline key_iterator &operator++() { ++i; return *this; }
inline key_iterator operator++(int) { return key_iterator(i++);}
#if QT_DEPRECATED_SINCE(5, 15)
- inline QT_DEPRECATED key_iterator &operator--()
+ inline QT_DEPRECATED_VERSION_5_15 key_iterator &operator--()
{
--i;
return *this;
}
- inline QT_DEPRECATED key_iterator operator--(int) { return key_iterator(i--); }
+ inline QT_DEPRECATED_VERSION_5_15 key_iterator operator--(int) { return key_iterator(i--); }
#endif
const_iterator base() const { return i; }
};
@@ -1302,18 +1302,18 @@ public:
return false;
}
#if QT_DEPRECATED_SINCE(5, 15)
- inline QT_DEPRECATED bool hasPrevious() const { return i != c.constBegin(); }
- inline QT_DEPRECATED Item previous()
+ inline QT_DEPRECATED_VERSION_5_15 bool hasPrevious() const { return i != c.constBegin(); }
+ inline QT_DEPRECATED_VERSION_5_15 Item previous()
{
n = --i;
return n;
}
- inline QT_DEPRECATED Item peekPrevious() const
+ inline QT_DEPRECATED_VERSION_5_15 Item peekPrevious() const
{
const_iterator p = i;
return --p;
}
- inline bool QT_DEPRECATED findPrevious(const T &t)
+ inline bool QT_DEPRECATED_VERSION_5_15 findPrevious(const T &t)
{
while (i != c.constBegin())
if (*(n = --i) == t)
@@ -1399,18 +1399,18 @@ public:
return false;
}
#if QT_DEPRECATED_SINCE(5, 15)
- inline QT_DEPRECATED bool hasPrevious() const { return const_iterator(i) != c->constBegin(); }
- inline QT_DEPRECATED Item previous()
+ inline QT_DEPRECATED_VERSION_5_15 bool hasPrevious() const { return const_iterator(i) != c->constBegin(); }
+ inline QT_DEPRECATED_VERSION_5_15 Item previous()
{
n = --i;
return n;
}
- inline QT_DEPRECATED Item peekPrevious() const
+ inline QT_DEPRECATED_VERSION_5_15 Item peekPrevious() const
{
iterator p = i;
return --p;
}
- inline QT_DEPRECATED bool findPrevious(const T &t)
+ inline QT_DEPRECATED_VERSION_5_15 bool findPrevious(const T &t)
{
while (const_iterator(i) != c->constBegin())
if (*(n = --i) == t)