diff options
| author | Ivan Solovev <ivan.solovev@qt.io> | 2025-03-31 16:52:20 +0200 |
|---|---|---|
| committer | Ivan Solovev <ivan.solovev@qt.io> | 2025-04-04 22:04:45 +0200 |
| commit | b6b725aef59390f403a1a39f49d1318c48f13c07 (patch) | |
| tree | 61bdd1c02b22c75e0cc9dc3bc94b2515357d4af3 /src/corelib/serialization/qxmlstream.cpp | |
| parent | 35dd681f2ba00e7196e59309d76f920ad8807205 (diff) | |
QXmlStreamReader: fix addData() unnecessary conversion to UTF-8
The addData(QASV) overload was unconditionally converting UTF-16 and
Latin1 data to UTF-8.
However, if we already started reading the XML document, and we know
that its encoding is UTF-16 or Latin1, then we know for sure that the
new data has to be added as-is.
Amends 6bc227a06a0d1392d220aa79ddb1cdc145d4f76e.
[ChangeLog][QtCore][QXmlStreamReader] Fixed a bug when
addData(QAnyStringView) was incorrectly recoding UTF-16 and Latin1
data to UTF-8, thus potentially mangling it.
Fixes: QTBUG-135129
Pick-to: 6.9 6.8 6.5
Change-Id: Ie1171a5e5596b72a6f160031a4c5a9df3baae4fd
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/corelib/serialization/qxmlstream.cpp')
| -rw-r--r-- | src/corelib/serialization/qxmlstream.cpp | 23 |
1 files changed, 23 insertions, 0 deletions
diff --git a/src/corelib/serialization/qxmlstream.cpp b/src/corelib/serialization/qxmlstream.cpp index 58fc076c216..c7527e29634 100644 --- a/src/corelib/serialization/qxmlstream.cpp +++ b/src/corelib/serialization/qxmlstream.cpp @@ -551,6 +551,15 @@ QIODevice *QXmlStreamReader::device() const \sa readNext(), clear() */ +static bool isDecoderForEncoding(const QStringDecoder &dec, QStringDecoder::Encoding enc) +{ + if (!dec.isValid()) + return false; + + const QAnyStringView nameView{dec.name()}; + return !nameView.empty() && nameView == QStringDecoder::nameForEncoding(enc); +} + /*! Adds more \a data for the reader to read. This function does nothing if the reader has a device(). @@ -565,11 +574,25 @@ void QXmlStreamReader::addData(QAnyStringView data) Q_D(QXmlStreamReader); data.visit([this, d](auto data) { if constexpr (std::is_same_v<decltype(data), QStringView>) { + if (d->lockEncoding && isDecoderForEncoding(d->decoder, QStringDecoder::Utf16)) { + // We already expect the data in the proper encoding, no need + // to recode the data. + addDataImpl(QByteArray{reinterpret_cast<const char *>(data.utf16()), + data.size() * 2}); + return; + } + // keep the pre-existing behavior d->lockEncoding = true; if (!d->decoder.isValid()) d->decoder = QStringDecoder(QStringDecoder::Utf8); addDataImpl(data.toUtf8()); } else if constexpr (std::is_same_v<decltype(data), QLatin1StringView>) { + if (d->lockEncoding && isDecoderForEncoding(d->decoder, QStringDecoder::Latin1)) { + // We already expect the data in the proper encoding, no need + // to recode the data. + addDataImpl(QByteArray{data.data(), data.size()}); + return; + } // Conversion to a QString is required, to avoid breaking // pre-existing (before porting to QAnyStringView) behavior. d->lockEncoding = true; |
