diff options
author | Edward Welbourne <edward.welbourne@qt.io> | 2016-07-15 20:47:57 +0200 |
---|---|---|
committer | Edward Welbourne <edward.welbourne@qt.io> | 2016-07-15 20:47:57 +0200 |
commit | 82ea53ad24c92b345ac2b542a174887f5de5723a (patch) | |
tree | 7d326274b52bbedac481be522a20732f77457073 /src/corelib | |
parent | e46e112eb10850801218bd810ecaeb8fd29f4c34 (diff) | |
parent | 178ab885626bcd67507fde7f67f65c1872ac3be3 (diff) |
Merge remote-tracking branch 'origin/5.6' into 5.7
Conflicts:
qmake/library/qmakeevaluator.cpp
One side changed the iterator to use ranged-for, the other changed its
body; they only conflicted because the latter had to add braces around
the body, intruding on the for-line. Trivial resolution.
Change-Id: Ib487bc3bd6e3c5225db15f94b9a8f6caaa33456b
Diffstat (limited to 'src/corelib')
-rw-r--r-- | src/corelib/io/qlockfile_unix.cpp | 6 | ||||
-rw-r--r-- | src/corelib/tools/qstring.cpp | 85 | ||||
-rw-r--r-- | src/corelib/tools/qstringbuilder.h | 2 | ||||
-rw-r--r-- | src/corelib/tools/qtimezoneprivate_mac.mm | 1 |
4 files changed, 62 insertions, 32 deletions
diff --git a/src/corelib/io/qlockfile_unix.cpp b/src/corelib/io/qlockfile_unix.cpp index e1bd769e77..0895f9a3fc 100644 --- a/src/corelib/io/qlockfile_unix.cpp +++ b/src/corelib/io/qlockfile_unix.cpp @@ -71,12 +71,12 @@ #elif defined(Q_OS_HAIKU) # include <kernel/OS.h> #elif defined(Q_OS_BSD4) && !defined(Q_OS_IOS) -# if !defined(Q_OS_NETBSD) -# include <sys/user.h> -# endif # include <sys/cdefs.h> # include <sys/param.h> # include <sys/sysctl.h> +# if !defined(Q_OS_NETBSD) +# include <sys/user.h> +# endif #endif QT_BEGIN_NAMESPACE diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index 68d12d85af..cef91efb14 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -2411,26 +2411,40 @@ QString &QString::replace(const QString &before, const QString &after, Qt::CaseS return replace(before.constData(), before.size(), after.constData(), after.size(), cs); } +namespace { // helpers for replace and its helper: +QChar *textCopy(const QChar *start, int len) +{ + const size_t size = len * sizeof(QChar); + QChar *const copy = static_cast<QChar *>(::malloc(size)); + Q_CHECK_PTR(copy); + ::memcpy(copy, start, size); + return copy; +} + +bool pointsIntoRange(const QChar *ptr, const ushort *base, int len) +{ + const QChar *const start = reinterpret_cast<const QChar *>(base); + return start <= ptr && ptr < start + len; +} +} // end namespace + /*! \internal */ void QString::replace_helper(uint *indices, int nIndices, int blen, const QChar *after, int alen) { - // copy *after in case it lies inside our own d->data() area - // (which we could possibly invalidate via a realloc or corrupt via memcpy operations.) - QChar *afterBuffer = const_cast<QChar *>(after); - if (after >= reinterpret_cast<QChar *>(d->data()) && after < reinterpret_cast<QChar *>(d->data()) + d->size) { - afterBuffer = static_cast<QChar *>(::malloc(alen*sizeof(QChar))); - Q_CHECK_PTR(afterBuffer); - ::memcpy(afterBuffer, after, alen*sizeof(QChar)); - } + // Copy after if it lies inside our own d->data() area (which we could + // possibly invalidate via a realloc or modify by replacement). + QChar *afterBuffer = 0; + if (pointsIntoRange(after, d->data(), d->size)) // Use copy in place of vulnerable original: + after = afterBuffer = textCopy(after, alen); QT_TRY { if (blen == alen) { // replace in place detach(); for (int i = 0; i < nIndices; ++i) - memcpy(d->data() + indices[i], afterBuffer, alen * sizeof(QChar)); + memcpy(d->data() + indices[i], after, alen * sizeof(QChar)); } else if (alen < blen) { // replace from front detach(); @@ -2446,7 +2460,7 @@ void QString::replace_helper(uint *indices, int nIndices, int blen, const QChar to += msize; } if (alen) { - memcpy(d->data() + to, afterBuffer, alen*sizeof(QChar)); + memcpy(d->data() + to, after, alen * sizeof(QChar)); to += alen; } movestart = indices[i] + blen; @@ -2469,17 +2483,15 @@ void QString::replace_helper(uint *indices, int nIndices, int blen, const QChar int moveto = insertstart + alen; memmove(d->data() + moveto, d->data() + movestart, (moveend - movestart)*sizeof(QChar)); - memcpy(d->data() + insertstart, afterBuffer, alen*sizeof(QChar)); + memcpy(d->data() + insertstart, after, alen * sizeof(QChar)); moveend = movestart-blen; } } } QT_CATCH(const std::bad_alloc &) { - if (afterBuffer != after) - ::free(afterBuffer); + ::free(afterBuffer); QT_RETHROW; } - if (afterBuffer != after) - ::free(afterBuffer); + ::free(afterBuffer); } /*! @@ -2508,31 +2520,48 @@ QString &QString::replace(const QChar *before, int blen, return *this; QStringMatcher matcher(before, blen, cs); + QChar *beforeBuffer = 0, *afterBuffer = 0; int index = 0; while (1) { uint indices[1024]; uint pos = 0; - while (pos < 1023) { + while (pos < 1024) { index = matcher.indexIn(*this, index); if (index == -1) break; indices[pos++] = index; - index += blen; - // avoid infinite loop - if (!blen) + if (blen) // Step over before: + index += blen; + else // Only count one instance of empty between any two characters: index++; } - if (!pos) + if (!pos) // Nothing to replace break; + if (Q_UNLIKELY(index != -1)) { + /* + We're about to change data, that before and after might point + into, and we'll need that data for our next batch of indices. + */ + if (!afterBuffer && pointsIntoRange(after, d->data(), d->size)) + after = afterBuffer = textCopy(after, alen); + + if (!beforeBuffer && pointsIntoRange(before, d->data(), d->size)) { + beforeBuffer = textCopy(before, blen); + matcher = QStringMatcher(beforeBuffer, blen, cs); + } + } + replace_helper(indices, pos, blen, after, alen); - if (index == -1) + if (Q_LIKELY(index == -1)) // Nothing left to replace break; - // index has to be adjusted in case we get back into the loop above. + // The call to replace_helper just moved what index points at: index += pos*(alen-blen); } + ::free(afterBuffer); + ::free(beforeBuffer); return *this; } @@ -2563,26 +2592,26 @@ QString& QString::replace(QChar ch, const QString &after, Qt::CaseSensitivity cs uint indices[1024]; uint pos = 0; if (cs == Qt::CaseSensitive) { - while (pos < 1023 && index < d->size) { + while (pos < 1024 && index < d->size) { if (d->data()[index] == cc) indices[pos++] = index; index++; } } else { - while (pos < 1023 && index < d->size) { + while (pos < 1024 && index < d->size) { if (QChar::toCaseFolded(d->data()[index]) == cc) indices[pos++] = index; index++; } } - if (!pos) + if (!pos) // Nothing to replace break; replace_helper(indices, pos, 1, after.constData(), after.d->size); - if (index == -1) + if (Q_LIKELY(index == -1)) // Nothing left to replace break; - // index has to be adjusted in case we get back into the loop above. + // The call to replace_helper just moved what index points at: index += pos*(after.d->size - 1); } return *this; @@ -5008,7 +5037,7 @@ void QString::truncate(int pos) Removes \a n characters from the end of the string. If \a n is greater than or equal to size(), the result is an - empty string. + empty string; if \a n is negative, it is equivalent to passing zero. Example: \snippet qstring/main.cpp 15 diff --git a/src/corelib/tools/qstringbuilder.h b/src/corelib/tools/qstringbuilder.h index 8ce98cbd71..b2832b5fbe 100644 --- a/src/corelib/tools/qstringbuilder.h +++ b/src/corelib/tools/qstringbuilder.h @@ -82,7 +82,7 @@ struct QStringBuilderCommon T toLower() const { return resolved().toLower(); } protected: - const T resolved() const { return *static_cast<const Builder*>(this); } + T resolved() const { return *static_cast<const Builder*>(this); } }; template<typename Builder, typename T> diff --git a/src/corelib/tools/qtimezoneprivate_mac.mm b/src/corelib/tools/qtimezoneprivate_mac.mm index a21a8fd56f..77c04ac20c 100644 --- a/src/corelib/tools/qtimezoneprivate_mac.mm +++ b/src/corelib/tools/qtimezoneprivate_mac.mm @@ -59,6 +59,7 @@ QT_BEGIN_NAMESPACE // Create the system default time zone QMacTimeZonePrivate::QMacTimeZonePrivate() + : m_nstz(0) { init(systemTimeZoneId()); } |