Assert validity in QStringIterator's unchecked methods

These methods should never be used on strings not known to be valid UTF-16.
Their optimizations will produce undefined behavior otherwise.

Change-Id: I03a95140dcbdd1f7189eea1be69289ce227331a5
Reviewed-by: Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
Reviewed-by: Konstantin Ritt <ritt.ks@gmail.com>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Edward Welbourne 2020-08-12 14:24:10 +02:00
parent 379799b10d
commit 7715b186c7

View File

@ -120,16 +120,20 @@ public:
{ {
Q_ASSERT_X(hasNext(), Q_FUNC_INFO, "iterator hasn't a next item"); Q_ASSERT_X(hasNext(), Q_FUNC_INFO, "iterator hasn't a next item");
if (Q_UNLIKELY((pos++)->isHighSurrogate())) if (Q_UNLIKELY((pos++)->isHighSurrogate())) {
Q_ASSERT(pos < e && pos->isLowSurrogate());
++pos; ++pos;
}
} }
inline char32_t peekNextUnchecked() const inline char32_t peekNextUnchecked() const
{ {
Q_ASSERT_X(hasNext(), Q_FUNC_INFO, "iterator hasn't a next item"); Q_ASSERT_X(hasNext(), Q_FUNC_INFO, "iterator hasn't a next item");
if (Q_UNLIKELY(pos->isHighSurrogate())) if (Q_UNLIKELY(pos->isHighSurrogate())) {
Q_ASSERT(pos + 1 < e && pos[1].isLowSurrogate());
return QChar::surrogateToUcs4(pos[0], pos[1]); return QChar::surrogateToUcs4(pos[0], pos[1]);
}
return pos->unicode(); return pos->unicode();
} }
@ -155,8 +159,10 @@ public:
Q_ASSERT_X(hasNext(), Q_FUNC_INFO, "iterator hasn't a next item"); Q_ASSERT_X(hasNext(), Q_FUNC_INFO, "iterator hasn't a next item");
const QChar cur = *pos++; const QChar cur = *pos++;
if (Q_UNLIKELY(cur.isHighSurrogate())) if (Q_UNLIKELY(cur.isHighSurrogate())) {
Q_ASSERT(pos < e && pos->isLowSurrogate());
return QChar::surrogateToUcs4(cur, *pos++); return QChar::surrogateToUcs4(cur, *pos++);
}
return cur.unicode(); return cur.unicode();
} }
@ -196,16 +202,20 @@ public:
{ {
Q_ASSERT_X(hasPrevious(), Q_FUNC_INFO, "iterator hasn't a previous item"); Q_ASSERT_X(hasPrevious(), Q_FUNC_INFO, "iterator hasn't a previous item");
if (Q_UNLIKELY((--pos)->isLowSurrogate())) if (Q_UNLIKELY((--pos)->isLowSurrogate())) {
Q_ASSERT(pos > i && pos[-1].isHighSurrogate());
--pos; --pos;
}
} }
inline char32_t peekPreviousUnchecked() const inline char32_t peekPreviousUnchecked() const
{ {
Q_ASSERT_X(hasPrevious(), Q_FUNC_INFO, "iterator hasn't a previous item"); Q_ASSERT_X(hasPrevious(), Q_FUNC_INFO, "iterator hasn't a previous item");
if (Q_UNLIKELY(pos[-1].isLowSurrogate())) if (Q_UNLIKELY(pos[-1].isLowSurrogate())) {
Q_ASSERT(pos > i + 1 && pos[-2].isHighSurrogate());
return QChar::surrogateToUcs4(pos[-2], pos[-1]); return QChar::surrogateToUcs4(pos[-2], pos[-1]);
}
return pos[-1].unicode(); return pos[-1].unicode();
} }
@ -230,8 +240,10 @@ public:
Q_ASSERT_X(hasPrevious(), Q_FUNC_INFO, "iterator hasn't a previous item"); Q_ASSERT_X(hasPrevious(), Q_FUNC_INFO, "iterator hasn't a previous item");
const QChar cur = *--pos; const QChar cur = *--pos;
if (Q_UNLIKELY(cur.isLowSurrogate())) if (Q_UNLIKELY(cur.isLowSurrogate())) {
Q_ASSERT(pos > i && pos[-1].isHighSurrogate());
return QChar::surrogateToUcs4(*--pos, cur); return QChar::surrogateToUcs4(*--pos, cur);
}
return cur.unicode(); return cur.unicode();
} }