diff options
Diffstat (limited to 'src/corelib/io/qurlidna.cpp')
-rw-r--r-- | src/corelib/io/qurlidna.cpp | 36 |
1 files changed, 20 insertions, 16 deletions
diff --git a/src/corelib/io/qurlidna.cpp b/src/corelib/io/qurlidna.cpp index fac1703da8..5fa4b5f7a1 100644 --- a/src/corelib/io/qurlidna.cpp +++ b/src/corelib/io/qurlidna.cpp @@ -1468,11 +1468,12 @@ static void mapToLowerCase(QString *str, int from) int l = 1; while (l < 4 && entry->mapping[l]) ++l; - if (l > 1) { + if (l > 1 || uc > 0xffff) { if (uc <= 0xffff) str->replace(i, 1, reinterpret_cast<const QChar *>(&entry->mapping[0]), l); else - str->replace(i-1, 2, reinterpret_cast<const QChar *>(&entry->mapping[0]), l); + str->replace(--i, 2, reinterpret_cast<const QChar *>(&entry->mapping[0]), l); + i += l - 1; d = 0; } else { if (!d) @@ -1501,18 +1502,20 @@ static bool isMappedToNothing(uint uc) } -static void stripProhibitedOutput(QString *str, int from) +static bool containsProhibitedOuptut(const QString *str, int from) { - ushort *out = (ushort *)str->data() + from; - const ushort *in = out; + const ushort *in = reinterpret_cast<const ushort *>(str->begin() + from); const ushort *end = (ushort *)str->data() + str->size(); - while (in < end) { + for ( ; in < end; ++in) { uint uc = *in; if (QChar(uc).isHighSurrogate() && in < end - 1) { ushort low = *(in + 1); if (QChar(low).isLowSurrogate()) { ++in; uc = QChar::surrogateToUcs4(uc, low); + } else { + // unpaired surrogates are prohibited + return true; } } if (uc <= 0xFFFF) { @@ -1537,7 +1540,7 @@ static void stripProhibitedOutput(QString *str, int from) || (uc >= 0xFDD0 && uc <= 0xFDEF) || uc == 0xFEFF || (uc >= 0xFFF9 && uc <= 0xFFFF))) { - *out++ = *in; + continue; } } else { if (!((uc >= 0x1D173 && uc <= 0x1D17A) @@ -1561,14 +1564,12 @@ static void stripProhibitedOutput(QString *str, int from) || (uc >= 0xFFFFE && uc <= 0xFFFFF) || (uc >= 0x100000 && uc <= 0x10FFFD) || (uc >= 0x10FFFE && uc <= 0x10FFFF))) { - *out++ = QChar::highSurrogate(uc); - *out++ = QChar::lowSurrogate(uc); + continue; } } - ++in; + return true; } - if (in != out) - str->truncate(out - str->utf16()); + return false; } static bool isBidirectionalRorAL(uint uc) @@ -2028,7 +2029,7 @@ Q_AUTOTEST_EXPORT void qt_nameprep(QString *source, int from) for ( ; out < e; ++out) { register ushort uc = out->unicode(); - if (uc > 0x80) { + if (uc >= 0x80) { break; } else if (uc >= 'A' && uc <= 'Z') { *out = QChar(uc | 0x20); @@ -2065,8 +2066,8 @@ Q_AUTOTEST_EXPORT void qt_nameprep(QString *source, int from) if (uc <= 0xFFFF) { *out++ = *in; } else { - *out++ = QChar::highSurrogate(uc); - *out++ = QChar::lowSurrogate(uc); + *out++ = in[-1]; + *out++ = in[0]; } } } @@ -2083,7 +2084,10 @@ Q_AUTOTEST_EXPORT void qt_nameprep(QString *source, int from) firstNonAscii > from ? firstNonAscii - 1 : from); // Strip prohibited output - stripProhibitedOutput(source, firstNonAscii); + if (containsProhibitedOuptut(source, firstNonAscii)) { + source->resize(from); + return; + } // Check for valid bidirectional characters bool containsLCat = false; |