--- /dev/null
+diff --git a/src/corelib/serialization/qxmlstream.cpp b/src/corelib/serialization/qxmlstream.cpp
+index 6aaa65f9a6b..3175517a356 100644
+--- a/src/corelib/serialization/qxmlstream.cpp
++++ b/src/corelib/serialization/qxmlstream.cpp
+@@ -1296,7 +1296,9 @@ inline qsizetype QXmlStreamReaderPrivate::fastScanContentCharList()
+ return n;
+ }
+
+-inline qsizetype QXmlStreamReaderPrivate::fastScanName(Value *val)
++// Fast scan an XML attribute name (e.g. "xml:lang").
++inline QXmlStreamReaderPrivate::FastScanNameResult
++QXmlStreamReaderPrivate::fastScanName(Value *val)
+ {
+ qsizetype n = 0;
+ uint c;
+@@ -1304,7 +1306,8 @@ inline qsizetype QXmlStreamReaderPrivate::fastScanName(Value *val)
+ if (n >= 4096) {
+ // This is too long to be a sensible name, and
+ // can exhaust memory, or the range of decltype(*prefix)
+- return 0;
++ raiseNamePrefixTooLongError();
++ return {};
+ }
+ switch (c) {
+ case '\n':
+@@ -1338,18 +1341,18 @@ inline qsizetype QXmlStreamReaderPrivate::fastScanName(Value *val)
+ putChar(':');
+ --n;
+ }
+- return n;
++ return FastScanNameResult(n);
+ case ':':
+ if (val) {
+ if (val->prefix == 0) {
+ val->prefix = qint16(n + 2);
+ } else { // only one colon allowed according to the namespace spec.
+ putChar(c);
+- return n;
++ return FastScanNameResult(n);
+ }
+ } else {
+ putChar(c);
+- return n;
++ return FastScanNameResult(n);
+ }
+ Q_FALLTHROUGH();
+ default:
+@@ -1363,7 +1366,7 @@ inline qsizetype QXmlStreamReaderPrivate::fastScanName(Value *val)
+ qsizetype pos = textBuffer.size() - n;
+ putString(textBuffer, pos);
+ textBuffer.resize(pos);
+- return 0;
++ return FastScanNameResult(0);
+ }
+
+ enum NameChar { NameBeginning, NameNotBeginning, NotName };
+@@ -1841,6 +1844,14 @@ void QXmlStreamReaderPrivate::raiseWellFormedError(const QString &message)
+ raiseError(QXmlStreamReader::NotWellFormedError, message);
+ }
+
++void QXmlStreamReaderPrivate::raiseNamePrefixTooLongError()
++{
++ // TODO: add a ImplementationLimitsExceededError and use it instead
++ raiseError(QXmlStreamReader::NotWellFormedError,
++ QXmlStream::tr("Length of XML attribute name exceeds implemnetation limits (4KiB "
++ "characters)."));
++}
++
+ void QXmlStreamReaderPrivate::parseError()
+ {
+
+diff --git a/src/corelib/serialization/qxmlstream.g b/src/corelib/serialization/qxmlstream.g
+index f3152bff378..fc122e66811 100644
+--- a/src/corelib/serialization/qxmlstream.g
++++ b/src/corelib/serialization/qxmlstream.g
+@@ -1420,7 +1420,11 @@ qname ::= LETTER;
+ /.
+ case $rule_number: {
+ Value &val = sym(1);
+- val.len += fastScanName(&val);
++ if (auto res = fastScanName(&val))
++ val.len += *res;
++ else
++ return false;
++
+ if (atEnd) {
+ resume($rule_number);
+ return false;
+@@ -1431,7 +1435,11 @@ qname ::= LETTER;
+ name ::= LETTER;
+ /.
+ case $rule_number:
+- sym(1).len += fastScanName();
++ if (auto res = fastScanName())
++ sym(1).len += *res;
++ else
++ return false;
++
+ if (atEnd) {
+ resume($rule_number);
+ return false;
+diff --git a/src/corelib/serialization/qxmlstream_p.h b/src/corelib/serialization/qxmlstream_p.h
+index 1baa75c5fa4..417778090b0 100644
+--- a/src/corelib/serialization/qxmlstream_p.h
++++ b/src/corelib/serialization/qxmlstream_p.h
+@@ -38,7 +38,7 @@ public:
+
+ constexpr XmlStringRef() = default;
+ constexpr inline XmlStringRef(const QString *string, qsizetype pos, qsizetype length)
+- : m_string(string), m_pos(pos), m_size(length)
++ : m_string(string), m_pos(pos), m_size((Q_ASSERT(length >= 0), length))
+ {
+ }
+ XmlStringRef(const QString *string)
+@@ -498,7 +498,16 @@ public:
+ qsizetype fastScanLiteralContent();
+ qsizetype fastScanSpace();
+ qsizetype fastScanContentCharList();
+- qsizetype fastScanName(Value *val = nullptr);
++
++ struct FastScanNameResult {
++ FastScanNameResult() : ok(false) {}
++ explicit FastScanNameResult(qsizetype len) : addToLen(len), ok(true) { }
++ operator bool() { return ok; }
++ qsizetype operator*() { Q_ASSERT(ok); return addToLen; }
++ qsizetype addToLen;
++ bool ok;
++ };
++ FastScanNameResult fastScanName(Value *val = nullptr);
+ inline qsizetype fastScanNMTOKEN();
+
+
+@@ -507,6 +516,7 @@ public:
+
+ void raiseError(QXmlStreamReader::Error error, const QString& message = QString());
+ void raiseWellFormedError(const QString &message);
++ void raiseNamePrefixTooLongError();
+
+ QXmlStreamEntityResolver *entityResolver;
+
+diff --git a/src/corelib/serialization/qxmlstreamparser_p.h b/src/corelib/serialization/qxmlstreamparser_p.h
+index c12815c893c..ae3ebe7a8e1 100644
+--- a/src/corelib/serialization/qxmlstreamparser_p.h
++++ b/src/corelib/serialization/qxmlstreamparser_p.h
+@@ -948,7 +948,11 @@ bool QXmlStreamReaderPrivate::parse()
+
+ case 262: {
+ Value &val = sym(1);
+- val.len += fastScanName(&val);
++ if (auto res = fastScanName(&val))
++ val.len += *res;
++ else
++ return false;
++
+ if (atEnd) {
+ resume(262);
+ return false;
+@@ -956,7 +960,11 @@ bool QXmlStreamReaderPrivate::parse()
+ } break;
+
+ case 263:
+- sym(1).len += fastScanName();
++ if (auto res = fastScanName())
++ sym(1).len += *res;
++ else
++ return false;
++
+ if (atEnd) {
+ resume(263);
+ return false;
+