summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/io/qbuffer.cpp6
-rw-r--r--tests/auto/corelib/io/qbuffer/tst_qbuffer.cpp24
2 files changed, 28 insertions, 2 deletions
diff --git a/src/corelib/io/qbuffer.cpp b/src/corelib/io/qbuffer.cpp
index 8bf51709bc..1b34eed876 100644
--- a/src/corelib/io/qbuffer.cpp
+++ b/src/corelib/io/qbuffer.cpp
@@ -366,7 +366,9 @@ qint64 QBuffer::size() const
bool QBuffer::seek(qint64 pos)
{
Q_D(QBuffer);
- if (pos > d->buf->size() && isWritable()) {
+ const auto oldBufSize = d->buf->size();
+ constexpr qint64 MaxSeekPos = (std::numeric_limits<decltype(oldBufSize)>::max)();
+ if (pos <= MaxSeekPos && pos > oldBufSize && isWritable()) {
if (seek(d->buf->size())) {
const qint64 gapSize = pos - d->buf->size();
if (write(QByteArray(gapSize, 0)) != gapSize) {
@@ -377,7 +379,7 @@ bool QBuffer::seek(qint64 pos)
return false;
}
} else if (pos > d->buf->size() || pos < 0) {
- qWarning("QBuffer::seek: Invalid pos: %d", int(pos));
+ qWarning("QBuffer::seek: Invalid pos: %lld", pos);
return false;
}
return QIODevice::seek(pos);
diff --git a/tests/auto/corelib/io/qbuffer/tst_qbuffer.cpp b/tests/auto/corelib/io/qbuffer/tst_qbuffer.cpp
index fb756d9e63..a4f26e2c6f 100644
--- a/tests/auto/corelib/io/qbuffer/tst_qbuffer.cpp
+++ b/tests/auto/corelib/io/qbuffer/tst_qbuffer.cpp
@@ -46,6 +46,7 @@ private slots:
void writeBlock_data();
void writeBlock();
void seek();
+ void invalidSeeks();
void seekTest_data();
void seekTest();
void read_rawdata();
@@ -291,6 +292,29 @@ void tst_QBuffer::seek()
QCOMPARE(buffer.size(), pos);
}
+void tst_QBuffer::invalidSeeks()
+{
+ if constexpr (sizeof(qsizetype) == sizeof(qint64)) {
+ // sizeof(qsizetype) == sizeof(qint64), so +1 would overflow
+ QSKIP("This is a 32-bit-only test.");
+ } else {
+ QBuffer buffer;
+ buffer.open(QIODevice::WriteOnly);
+ QCOMPARE(buffer.buffer().size(), qsizetype(0));
+ QCOMPARE(buffer.pos(), qint64(0));
+ constexpr qint64 MaxQByteArrayCapacity = (std::numeric_limits<qsizetype>::max)();
+ // this should fail fast, not after trying to allocate nearly 2 GiB of data,
+ // potentially crashing in the process:
+ QVERIFY(!buffer.seek(2 * MaxQByteArrayCapacity - 1));
+ QCOMPARE(buffer.buffer().size(), qsizetype(0));
+ QCOMPARE(buffer.pos(), qint64(0));
+ // ditto:
+ QVERIFY(!buffer.seek(MaxQByteArrayCapacity + 1));
+ QCOMPARE(buffer.buffer().size(), qsizetype(0));
+ QCOMPARE(buffer.pos(), qint64(0));
+ }
+}
+
void tst_QBuffer::seekTest_data()
{
writeBlock_data();