summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/text/qstringbuilder.h4
-rw-r--r--tests/auto/corelib/text/qstringbuilder/qstringbuilder1/stringbuilder.cpp43
2 files changed, 45 insertions, 2 deletions
diff --git a/src/corelib/text/qstringbuilder.h b/src/corelib/text/qstringbuilder.h
index 2fbbb43b32..f5219232b1 100644
--- a/src/corelib/text/qstringbuilder.h
+++ b/src/corelib/text/qstringbuilder.h
@@ -450,7 +450,7 @@ QByteArray &appendToByteArray(QByteArray &a, const QStringBuilder<A, B> &b, char
// append 8-bit data to a byte array
qsizetype len = a.size() + QConcatenable< QStringBuilder<A, B> >::size(b);
a.detach(); // a detach() in a.data() could reset a.capacity() to a.size()
- if (len > a.capacity())
+ if (len > a.data_ptr().freeSpaceAtEnd()) // capacity() was broken when prepend()-optimization landed
a.reserve(qMax(len, 2 * a.capacity()));
char *it = a.data() + a.size();
QConcatenable< QStringBuilder<A, B> >::appendTo(b, it);
@@ -479,7 +479,7 @@ QString &operator+=(QString &a, const QStringBuilder<A, B> &b)
{
qsizetype len = a.size() + QConcatenable< QStringBuilder<A, B> >::size(b);
a.detach(); // a detach() in a.data() could reset a.capacity() to a.size()
- if (len > a.capacity())
+ if (len > a.data_ptr().freeSpaceAtEnd()) // capacity() was broken when prepend()-optimization landed
a.reserve(qMax(len, 2 * a.capacity()));
QChar *it = a.data() + a.size();
QConcatenable< QStringBuilder<A, B> >::appendTo(b, it);
diff --git a/tests/auto/corelib/text/qstringbuilder/qstringbuilder1/stringbuilder.cpp b/tests/auto/corelib/text/qstringbuilder/qstringbuilder1/stringbuilder.cpp
index 4d7e452e6f..de5277ab44 100644
--- a/tests/auto/corelib/text/qstringbuilder/qstringbuilder1/stringbuilder.cpp
+++ b/tests/auto/corelib/text/qstringbuilder/qstringbuilder1/stringbuilder.cpp
@@ -73,6 +73,36 @@ template <> QByteArray toQByteArray(char * const &p) { return p; }
template <size_t N> QByteArray toQByteArray(const char (&a)[N]) { return a; }
template <> QByteArray toQByteArray(const char &c) { return QByteArray(&c, 1); }
+template <typename String, typename Separator>
+void checkItWorksWithFreeSpaceAtBegin(const String &chunk, const Separator &separator)
+{
+ // GIVEN: a String with freeSpaceAtBegin() and less than chunk.size() freeSpaceAtEnd()
+ String str;
+
+ int prepends = 0;
+ const int max_prepends = 10;
+ while (str.data_ptr().freeSpaceAtBegin() < chunk.size() && prepends++ < max_prepends)
+ str.prepend(chunk);
+ QVERIFY(prepends < max_prepends);
+
+ int appends = 0;
+ const int max_appends = 100;
+ while (str.data_ptr().freeSpaceAtEnd() >= chunk.size() && appends++ < max_appends)
+ str.append(chunk);
+ QVERIFY(appends < max_appends);
+
+ QVERIFY(str.capacity() - str.size() >= chunk.size());
+ QVERIFY(str.data_ptr().freeSpaceAtEnd() < chunk.size());
+
+ // WHEN: adding a QStringBuilder expression which exceeds freeSpaceAtEnd()
+ str += separator P chunk;
+
+ // THEN: it doesn't crash (QTBUG-99330)
+ const String expected = chunk.repeated(prepends + appends) + separator + chunk;
+ QCOMPARE(str, expected);
+}
+
+
void runScenario()
{
// this code is latin1. TODO: replace it with the utf8 block below, once
@@ -329,6 +359,16 @@ void runScenario()
QCOMPARE(str2, str2_e);
}
+ checkItWorksWithFreeSpaceAtBegin(QString::fromUtf8(UTF8_LITERAL),
+ #ifdef QT_NO_CAST_FROM_ASCII
+ QLatin1String("1234")
+ #else
+ "1234"
+ #endif
+ );
+ if (QTest::currentTestFailed())
+ return;
+
//operator QByteArray +=
{
QByteArray ba = UTF8_LITERAL;
@@ -350,4 +390,7 @@ void runScenario()
QCOMPARE(byteArray, "multipart/mixed; boundary=\"oooooooooooooooooooooooooooooo\"");
}
+ checkItWorksWithFreeSpaceAtBegin(QByteArray(UTF8_LITERAL), "1234");
+ if (QTest::currentTestFailed())
+ return;
}