diff options
-rw-r--r-- | src/corelib/io/qbuffer.cpp | 6 | ||||
-rw-r--r-- | tests/auto/corelib/io/qbuffer/tst_qbuffer.cpp | 24 |
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(); |