QStringIterator: fix UB [2/2]: use std::less to compare pointers
The relational operators <, >, <=, >= do not form a total order for pointers. In particular, they are only defined for pointer pairs that point into the same array (incl. one past the array's last element). Other uses are undefined behavior. The iterators the class works on are user-supplied, so we cannot assume that they are pointing into the same array. In fact, we have a check in setPosition() that tries to catch such misuses, but similar checks are absent from the ctors, e.g. In addition, the implementation itself is checking for next-but-one and prev-but-one in an unsafe way. std::less can be used to provide a total order, so use that everywhere. Change-Id: I32fb0ef9f768d9336ae12cc0542ca18d1bf23adf Reviewed-by: Giuseppe D'Angelo <giuseppe.dangelo@kdab.com> Reviewed-by: Edward Welbourne <edward.welbourne@qt.io> (cherry picked from commit 7cf2684e6a11892975946bd57d8cf672fe6dd43e) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
7d92a8009d
commit
8922ead397
@ -25,6 +25,8 @@ class QStringIterator
|
||||
{
|
||||
QString::const_iterator i, pos, e;
|
||||
static_assert((std::is_same<QString::const_iterator, const QChar *>::value));
|
||||
static bool less(const QChar *lhs, const QChar *rhs) noexcept
|
||||
{ return std::less{}(lhs, rhs); }
|
||||
public:
|
||||
explicit QStringIterator(QStringView string, qsizetype idx = 0)
|
||||
: i(string.begin()),
|
||||
@ -59,7 +61,8 @@ public:
|
||||
|
||||
inline void setPosition(QString::const_iterator position)
|
||||
{
|
||||
Q_ASSERT_X(i <= position && position <= e, Q_FUNC_INFO, "position out of bounds");
|
||||
Q_ASSERT_X(!less(position, i) && !less(e, position),
|
||||
Q_FUNC_INFO, "position out of bounds");
|
||||
pos = position;
|
||||
}
|
||||
|
||||
@ -67,7 +70,7 @@ public:
|
||||
|
||||
inline bool hasNext() const
|
||||
{
|
||||
return pos < e;
|
||||
return less(pos, e);
|
||||
}
|
||||
|
||||
inline void advance()
|
||||
@ -95,7 +98,7 @@ public:
|
||||
Q_ASSERT_X(hasNext(), Q_FUNC_INFO, "iterator hasn't a next item");
|
||||
|
||||
if (Q_UNLIKELY(pos->isHighSurrogate())) {
|
||||
Q_ASSERT(pos + 1 < e && pos[1].isLowSurrogate());
|
||||
Q_ASSERT(less(pos + 1, e) && pos[1].isLowSurrogate());
|
||||
return QChar::surrogateToUcs4(pos[0], pos[1]);
|
||||
}
|
||||
|
||||
@ -148,7 +151,7 @@ public:
|
||||
|
||||
inline bool hasPrevious() const
|
||||
{
|
||||
return pos > i;
|
||||
return less(i, pos);
|
||||
}
|
||||
|
||||
inline void recede()
|
||||
@ -177,7 +180,7 @@ public:
|
||||
Q_ASSERT_X(hasPrevious(), Q_FUNC_INFO, "iterator hasn't a previous item");
|
||||
|
||||
if (Q_UNLIKELY(pos[-1].isLowSurrogate())) {
|
||||
Q_ASSERT(pos > i + 1 && pos[-2].isHighSurrogate());
|
||||
Q_ASSERT(less(i + 1, pos) && pos[-2].isHighSurrogate());
|
||||
return QChar::surrogateToUcs4(pos[-2], pos[-1]);
|
||||
}
|
||||
return pos[-1].unicode();
|
||||
|
Loading…
x
Reference in New Issue
Block a user