summaryrefslogtreecommitdiffstats
path: root/tests/auto/corelib/io
diff options
context:
space:
mode:
authorMarc Mutz <marc.mutz@qt.io>2022-03-31 12:02:11 +0200
committerMarc Mutz <marc.mutz@qt.io>2022-04-04 08:17:09 +0200
commit61157c8354484f607282719bbd836cb7220de109 (patch)
treec8109398c7bc17c095b22a681c3e76ca4deff22c /tests/auto/corelib/io
parent30873cc720346bd91ee7fc9d45ff0faceb56f011 (diff)
QBuffer: fix writing more than two GiB of data
In Qt 6, QByteArray can hold more than two GiB of data on 64-bit platforms, so QBuffer should be able to handle writes of more than two GiB, too. But the implementation didn't check for overflow and held sizes in int variables, so it happily reported success but wrote data only mod INT_MAX. Fix by carefully avoiding overflow and using size variables of proper type. [ChangeLog][QtCore][QBuffer] Fixed silent data truncation when writing more than two GiB at once on 64-bit platforms. Pick-to: 6.3 6.2 Fixes: QTBUG-102171 Change-Id: Ib666f9f7db24495b4ed64191a48b35edc410f7e9 Reviewed-by: hjk <hjk@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'tests/auto/corelib/io')
-rw-r--r--tests/auto/corelib/io/qbuffer/tst_qbuffer.cpp53
1 files changed, 53 insertions, 0 deletions
diff --git a/tests/auto/corelib/io/qbuffer/tst_qbuffer.cpp b/tests/auto/corelib/io/qbuffer/tst_qbuffer.cpp
index 7a68da8192..fb756d9e63 100644
--- a/tests/auto/corelib/io/qbuffer/tst_qbuffer.cpp
+++ b/tests/auto/corelib/io/qbuffer/tst_qbuffer.cpp
@@ -31,6 +31,9 @@
#include <QBuffer>
#include <QByteArray>
+#include <QElapsedTimer>
+
+#include <string>
class tst_QBuffer : public QObject
{
@@ -58,6 +61,7 @@ private slots:
void readLineBoundaries();
void getAndUngetChar();
void writeAfterQByteArrayResize();
+ void writeOfMoreThan2GiB();
void read_null();
protected slots:
@@ -599,6 +603,55 @@ void tst_QBuffer::writeAfterQByteArrayResize()
QCOMPARE(buffer.buffer().size(), 1000);
}
+void tst_QBuffer::writeOfMoreThan2GiB()
+{
+ if constexpr (sizeof(void*) == 4)
+ QSKIP("This is a 64-bit-only test");
+
+ [[maybe_unused]] constexpr size_t GiB = 1024 * 1024 * 1024;
+
+#ifndef QT_NO_EXCEPTIONS
+
+ try {
+ //
+ // GIVEN: an empty QBuffer open for writing
+ //
+ QBuffer buffer;
+ QVERIFY(buffer.open(QIODevice::WriteOnly));
+
+ //
+ // WHEN: writing more than 2GiB in a singe chunk:
+ //
+ QElapsedTimer timer;
+ timer.start();
+
+ const std::string input(2 * GiB + 1, 42);
+
+ qDebug("created dataset in %lld ms", timer.restart());
+
+ const auto inputSize = qint64(input.size());
+
+ QCOMPARE(buffer.write(input.data(), inputSize), inputSize);
+
+ qDebug("performed write in %lld ms", timer.restart());
+
+ //
+ // THEN: the buffer contains the written data
+ //
+ QCOMPARE(buffer.buffer().size(), inputSize);
+ QVERIFY(buffer.buffer() == QByteArrayView{input});
+
+ qDebug("verified result in %lld ms", timer.elapsed());
+
+ } catch (const std::bad_alloc &) {
+ QSKIP("Cannot allocate enough memory for this test");
+ }
+
+#else
+ QSKIP("This test requires exceptions enabled.");
+#endif // QT_NO_EXCEPTIONS
+}
+
void tst_QBuffer::read_null()
{
QByteArray buffer;