diff options
author | Olivier Goffart <ogoffart@trolltech.com> | 2009-12-01 19:58:44 (GMT) |
---|---|---|
committer | Olivier Goffart <ogoffart@trolltech.com> | 2009-12-01 19:58:44 (GMT) |
commit | 480b395bd652a4ac6e3f262bd99a045dff95c4ac (patch) | |
tree | fc149cdab904c5ba8bb59b67a3192d2002c71133 | |
parent | 537bff8c020c8fd2c150b2821d1cc035ee96f84f (diff) | |
download | Qt-480b395bd652a4ac6e3f262bd99a045dff95c4ac.zip Qt-480b395bd652a4ac6e3f262bd99a045dff95c4ac.tar.gz Qt-480b395bd652a4ac6e3f262bd99a045dff95c4ac.tar.bz2 |
Fix crash in QVector::reserve when reserving smaller size on a shared vector
We cannot call realloc with aalloc smaller than asize.
Also include obvious optimisation: take the qMin computation out of
the loop.
Task-number: QTBUG-6416
Reviewed-by: Thiago
-rw-r--r-- | src/corelib/tools/qvector.h | 6 | ||||
-rw-r--r-- | tests/auto/qvector/tst_qvector.cpp | 14 |
2 files changed, 18 insertions, 2 deletions
diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h index f0de98d..201e7b3 100644 --- a/src/corelib/tools/qvector.h +++ b/src/corelib/tools/qvector.h @@ -324,7 +324,7 @@ void QVector<T>::detach_helper() { realloc(d->size, d->alloc); } template <typename T> void QVector<T>::reserve(int asize) -{ if (asize > d->alloc || d->ref != 1) realloc(d->size, asize); d->capacity = 1; } +{ if (asize > d->alloc) realloc(d->size, asize); if (d->ref == 1) d->capacity = 1; } template <typename T> void QVector<T>::resize(int asize) { realloc(asize, (asize > d->alloc || (!d->capacity && asize < d->size && asize < (d->alloc >> 1))) ? @@ -441,6 +441,7 @@ void QVector<T>::free(Data *x) template <typename T> void QVector<T>::realloc(int asize, int aalloc) { + Q_ASSERT(asize <= aalloc); T *pOld; T *pNew; union { QVectorData *d; Data *p; } x; @@ -496,7 +497,8 @@ void QVector<T>::realloc(int asize, int aalloc) pOld = p->array + x.d->size; pNew = x.p->array + x.d->size; // copy objects from the old array into the new array - while (x.d->size < qMin(asize, d->size)) { + const int toMove = qMin(asize, d->size); + while (x.d->size < toMove) { new (pNew++) T(*pOld++); x.d->size++; } diff --git a/tests/auto/qvector/tst_qvector.cpp b/tests/auto/qvector/tst_qvector.cpp index 21c9270..f538f6a 100644 --- a/tests/auto/qvector/tst_qvector.cpp +++ b/tests/auto/qvector/tst_qvector.cpp @@ -56,6 +56,7 @@ public: private slots: void outOfMemory(); + void QTBUG6416_reserve(); }; int fooCtor; @@ -220,5 +221,18 @@ void tst_QVector::outOfMemory() } } +void tst_QVector::QTBUG6416_reserve() +{ + fooCtor = 0; + fooDtor = 0; + { + QVector<Foo> a; + a.resize(2); + QVector<Foo> b(a); + b.reserve(1); + } + QCOMPARE(fooCtor, fooDtor); +} + QTEST_APPLESS_MAIN(tst_QVector) #include "tst_qvector.moc" |