summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOlivier Goffart <ogoffart@trolltech.com>2009-12-01 19:58:44 (GMT)
committerOlivier Goffart <ogoffart@trolltech.com>2009-12-01 19:58:44 (GMT)
commit480b395bd652a4ac6e3f262bd99a045dff95c4ac (patch)
treefc149cdab904c5ba8bb59b67a3192d2002c71133
parent537bff8c020c8fd2c150b2821d1cc035ee96f84f (diff)
downloadQt-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.h6
-rw-r--r--tests/auto/qvector/tst_qvector.cpp14
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"