From d7734f03746e90b3a5920bfe66f14b025639e767 Mon Sep 17 00:00:00 2001 From: Edward Welbourne <edward.welbourne@qt.io> Date: Wed, 12 Aug 2020 14:24:10 +0200 Subject: [PATCH 056/147] 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> (cherry picked from commit 7715b186c79a968950fd1c8e0993641f2f58b3be) --- src/corelib/text/qstringiterator_p.h | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/src/corelib/text/qstringiterator_p.h b/src/corelib/text/qstringiterator_p.h index b31c7673c2..731a241407 100644 --- a/src/corelib/text/qstringiterator_p.h +++ b/src/corelib/text/qstringiterator_p.h @@ -123,16 +123,20 @@ public: { 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; + } } inline uint peekNextUnchecked() const { 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 pos->unicode(); } @@ -158,8 +162,10 @@ public: Q_ASSERT_X(hasNext(), Q_FUNC_INFO, "iterator hasn't a next item"); 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 cur.unicode(); } @@ -199,16 +205,20 @@ public: { 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; + } } inline uint peekPreviousUnchecked() const { 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 pos[-1].unicode(); } @@ -233,8 +243,10 @@ public: Q_ASSERT_X(hasPrevious(), Q_FUNC_INFO, "iterator hasn't a previous item"); 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 cur.unicode(); } -- 2.40.1