Fix UB (invalid pointer comparison) in QList, QVector, QVLA

QList, QVector and QVarLengthArray check the validity of iterators
passed to member functions using isValidIterator(), which checks that
the underlying pointers are in the range [begin, end]. This check is
well-defined when the outcome is positive, ie. when the iterator is
valid. But if the iterator is not valid, and does not happen to point
into [end, begin + capacity], the comparison, which uses normal
operator<, invokes UB.

Fix by using std::less<T*>, which defines a total ordering.

Change-Id: I1e5757789b4b9779f5e3e298e7f2b2dd0b27576c
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Marc Mutz 2017-12-14 14:14:50 +01:00 committed by Eric Lemanissier
parent 55d640483c
commit 8e5a2f63c3
3 changed files with 6 additions and 3 deletions

View File

@ -413,7 +413,8 @@ private:
bool isValidIterator(const iterator &i) const Q_DECL_NOTHROW
{
return (constBegin().i <= i.i) && (i.i <= constEnd().i);
const std::less<const Node *> less = {};
return !less(i.i, cbegin().i) && !less(cend().i, i.i);
}
private:

View File

@ -254,7 +254,8 @@ private:
bool isValidIterator(const const_iterator &i) const
{
return (i <= constEnd()) && (constBegin() <= i);
const std::less<const T*> less = {};
return !less(cend(), i) && !less(i, cbegin());
}
};

View File

@ -306,7 +306,8 @@ private:
void destruct(T *from, T *to);
bool isValidIterator(const iterator &i) const
{
return (i <= d->end()) && (d->begin() <= i);
const std::less<const T*> less = {};
return !less(d->end(), i) && !less(i, d->begin());
}
class AlignmentDummy { Data header; T array[1]; };
};