Details
-
Bug
-
Resolution: Done
-
P2: Important
-
5.5.0, 5.5.1
-
None
Description
If toUpper is called on a temporary QString and the QString contains a character which expands to two or more letters (for example the german ligature ß (szett) expands to SS) the result is wrong.
The problematic code
template <typename Traits, typename T> Q_NEVER_INLINE static QString detachAndConvertCase(T &str, QStringIterator it) { QString s = qMove(str); // will copy if T is const QString QChar *pp = s.begin() + it.index(); // will detach if necessary uint uc = it.nextUnchecked(); forever { const QUnicodeTables::Properties *prop = qGetProp(uc); signed short caseDiff = Traits::caseDiff(prop); if (Q_UNLIKELY(Traits::caseSpecial(prop))) { // slow path const ushort *specialCase = specialCaseMap + caseDiff; ushort length = *specialCase++; int pos = pp - s.constBegin(); s.replace(pos, 1, reinterpret_cast<const QChar *>(specialCase), length); pp = const_cast<QChar *>(s.constBegin()) + pos + length; } else if (QChar::requiresSurrogates(uc)) { *pp++ = QChar::highSurrogate(uc + caseDiff); *pp++ = QChar::lowSurrogate(uc + caseDiff); } else { *pp++ = QChar(uc + caseDiff); } if (!it.hasNext()) return s; uc = it.nextUnchecked(); } }
With C++ 11 and a temporary QString
QString detachAndConvertCase(T &str, QStringIterator it) gets calls as
QString detachAndConvertCase(QString &str, QStringIterator it), if not C++11 or not a temporary QString
QString detachAndConvertCase(const QString &str, QStringIterator it) gets calls.
The iterator it points to str but it should point to s.
Luckily with a const str the it always points to the next character, but with a moved QString it falls behind if the "slow path" is chosen.
As a result QString( "ß_demo" ).toUpper() becomes "SSSSSSS" instead of "SS_DEMO"
Reproducible with
- qmake and Xcode7
- QtCreator with installed Xcode7
- tried MSVC2015 but it fails to link
Attachments
For Gerrit Dashboard: QTBUG-49181 | ||||||
---|---|---|---|---|---|---|
# | Subject | Branch | Project | Status | CR | V |
139733,6 | QString: Fix in-place toUpper/Lower when there's size expansion | 5.6 | qt/qtbase | Status: MERGED | +2 | 0 |