From e120ad442d7ebff0b9862e8af9ebf9717b5ac92e Mon Sep 17 00:00:00 2001 From: Marko Pellikka Date: Thu, 22 Aug 2013 17:45:47 -0700 Subject: [PATCH] QString::reserve fix to avoid truncation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In case of implicit memory sharing, QString::reserve caused data truncation if given size was smaller than size of data. Task-number: QTBUG-29664 Change-Id: If2da5ad051385635ebb829c18b5ebaa349f08e8a Reviewed-by: Olivier Goffart Reviewed-by: Jędrzej Nowacki --- src/corelib/tools/qstring.h | 4 ++-- tests/auto/corelib/tools/qstring/tst_qstring.cpp | 12 ++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h index 701082c7e6..2eaed65148 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/tools/qstring.h @@ -934,8 +934,8 @@ inline QString::~QString() { if (!d->ref.deref()) Data::deallocate(d); } inline void QString::reserve(int asize) { - if (d->ref.isShared() || uint(asize) + 1u > d->alloc) - reallocData(uint(asize) + 1u); + if (d->ref.isShared() || uint(asize) >= d->alloc) + reallocData(qMax(asize, d->size) + 1u); if (!d->capacityReserved) { // cannot set unconditionally, since d could be the shared_null/shared_empty (which is const) diff --git a/tests/auto/corelib/tools/qstring/tst_qstring.cpp b/tests/auto/corelib/tools/qstring/tst_qstring.cpp index 0148ba6d03..48874781c0 100644 --- a/tests/auto/corelib/tools/qstring/tst_qstring.cpp +++ b/tests/auto/corelib/tools/qstring/tst_qstring.cpp @@ -5240,6 +5240,18 @@ void tst_QString::resizeAfterReserve() s += "hello world"; s.resize(0); QVERIFY(s.capacity() == 100); + + // reserve() can't be used to truncate data + s.fill('x', 100); + s.reserve(50); + QVERIFY(s.capacity() == 100); + QVERIFY(s.size() == 100); + + // even with increased ref count truncation isn't allowed + QString t = s; + s.reserve(50); + QVERIFY(s.capacity() == 100); + QVERIFY(s.size() == 100); } void tst_QString::resizeWithNegative() const