Merge "Merge remote-tracking branch 'origin/5.14' into 5.15"
This commit is contained in:
commit
7ed097b31f
@ -3,8 +3,9 @@ QT_FOR_CONFIG += gui
|
||||
defineTest(prependOpenGlLib) {
|
||||
path = $$QT.core.libs/$$QMAKE_PREFIX_STATICLIB$$1
|
||||
ext = .$$QMAKE_EXTENSION_STATICLIB
|
||||
!mingw|qtConfig(debug_and_release): debug_suffix = "d"
|
||||
QMAKE_LIBS_OPENGL_ES2 = $${path}$${ext} $$QMAKE_LIBS_OPENGL_ES2
|
||||
QMAKE_LIBS_OPENGL_ES2_DEBUG = $${path}d$${ext} $$QMAKE_LIBS_OPENGL_ES2_DEBUG
|
||||
QMAKE_LIBS_OPENGL_ES2_DEBUG = $${path}$${debug_suffix}$${ext} $$QMAKE_LIBS_OPENGL_ES2_DEBUG
|
||||
export(QMAKE_LIBS_OPENGL_ES2)
|
||||
export(QMAKE_LIBS_OPENGL_ES2_DEBUG)
|
||||
}
|
||||
|
37
src/3rdparty/tinycbor/tests/parser/data.cpp
vendored
37
src/3rdparty/tinycbor/tests/parser/data.cpp
vendored
@ -338,7 +338,7 @@ void addValidationColumns()
|
||||
QTest::addColumn<CborError>("expectedError");
|
||||
}
|
||||
|
||||
void addValidationData()
|
||||
void addValidationData(size_t minInvalid = ~size_t(0))
|
||||
{
|
||||
// illegal numbers are future extension points
|
||||
QTest::newRow("illegal-number-in-unsigned-1") << raw("\x81\x1c") << 0 << CborErrorIllegalNumber;
|
||||
@ -488,26 +488,35 @@ void addValidationData()
|
||||
QTest::newRow("map-break-after-value-tag2") << raw("\x81\xbf\0\xd8\x20\xff") << 0 << CborErrorUnexpectedBreak;
|
||||
|
||||
// check for pointer additions wrapping over the limit of the address space
|
||||
CborError tooLargeOn32bit = (sizeof(void *) == 4) ? CborErrorDataTooLarge : CborErrorUnexpectedEOF;
|
||||
auto wraparoundError = [minInvalid](uint64_t encodedSize) {
|
||||
if (encodedSize > minInvalid)
|
||||
return CborErrorDataTooLarge;
|
||||
return CborErrorUnexpectedEOF;
|
||||
};
|
||||
constexpr uint64_t FourGB = UINT32_MAX + UINT64_C(1);
|
||||
// on 32-bit systems, this is a -1
|
||||
QTest::newRow("bytearray-wraparound1") << raw("\x81\x5a\xff\xff\xff\xff") << 0 << CborErrorUnexpectedEOF;
|
||||
QTest::newRow("string-wraparound1") << raw("\x81\x7a\xff\xff\xff\xff") << 0 << CborErrorUnexpectedEOF;
|
||||
QTest::newRow("bytearray-wraparound1") << raw("\x81\x5a\xff\xff\xff\xff") << 0 << wraparoundError(UINT32_MAX);
|
||||
QTest::newRow("string-wraparound1") << raw("\x81\x7a\xff\xff\xff\xff") << 0 << wraparoundError(UINT32_MAX);
|
||||
// on 32-bit systems, a 4GB addition could be dropped
|
||||
QTest::newRow("bytearray-wraparound2") << raw("\x81\x5b\0\0\0\1\0\0\0\0") << 0 << tooLargeOn32bit;
|
||||
QTest::newRow("string-wraparound2") << raw("\x81\x7b\0\0\0\1\0\0\0\0") << 0 << tooLargeOn32bit;
|
||||
QTest::newRow("bytearray-wraparound2") << raw("\x81\x5b\0\0\0\1\0\0\0\0") << 0 << wraparoundError(FourGB);
|
||||
QTest::newRow("string-wraparound2") << raw("\x81\x7b\0\0\0\1\0\0\0\0") << 0 << wraparoundError(FourGB);
|
||||
// on 64-bit systems, this could be a -1
|
||||
QTest::newRow("bytearray-wraparound3") << raw("\x81\x5b\xff\xff\xff\xff\xff\xff\xff\xff") << 0 << tooLargeOn32bit;
|
||||
QTest::newRow("string-wraparound3") << raw("\x81\x7b\xff\xff\xff\xff\xff\xff\xff\xff") << 0 << tooLargeOn32bit;
|
||||
QTest::newRow("bytearray-wraparound3") << raw("\x81\x5b\xff\xff\xff\xff\xff\xff\xff\xff") << 0
|
||||
<< wraparoundError(UINT64_MAX);
|
||||
QTest::newRow("string-wraparound3") << raw("\x81\x7b\xff\xff\xff\xff\xff\xff\xff\xff") << 0
|
||||
<< wraparoundError(UINT64_MAX);
|
||||
|
||||
// ditto on chunks
|
||||
QTest::newRow("bytearray-chunk-wraparound1") << raw("\x81\x5f\x5a\xff\xff\xff\xff") << 0 << CborErrorUnexpectedEOF;
|
||||
QTest::newRow("string-chunk-wraparound1") << raw("\x81\x7f\x7a\xff\xff\xff\xff") << 0 << CborErrorUnexpectedEOF;
|
||||
QTest::newRow("bytearray-chunk-wraparound1") << raw("\x81\x5f\x5a\xff\xff\xff\xff") << 0 << wraparoundError(UINT32_MAX);
|
||||
QTest::newRow("string-chunk-wraparound1") << raw("\x81\x7f\x7a\xff\xff\xff\xff") << 0 << wraparoundError(UINT32_MAX);
|
||||
// on 32-bit systems, a 4GB addition could be dropped
|
||||
QTest::newRow("bytearray-chunk-wraparound2") << raw("\x81\x5f\x5b\0\0\0\1\0\0\0\0") << 0 << tooLargeOn32bit;
|
||||
QTest::newRow("string-chunk-wraparound2") << raw("\x81\x7f\x7b\0\0\0\1\0\0\0\0") << 0 << tooLargeOn32bit;
|
||||
QTest::newRow("bytearray-chunk-wraparound2") << raw("\x81\x5f\x5b\0\0\0\1\0\0\0\0") << 0 << wraparoundError(FourGB);
|
||||
QTest::newRow("string-chunk-wraparound2") << raw("\x81\x7f\x7b\0\0\0\1\0\0\0\0") << 0 << wraparoundError(FourGB);
|
||||
// on 64-bit systems, this could be a -1
|
||||
QTest::newRow("bytearray-chunk-wraparound3") << raw("\x81\x5f\x5b\xff\xff\xff\xff\xff\xff\xff\xff") << 0 << tooLargeOn32bit;
|
||||
QTest::newRow("string-chunk-wraparound3") << raw("\x81\x7f\x7b\xff\xff\xff\xff\xff\xff\xff\xff") << 0 << tooLargeOn32bit;
|
||||
QTest::newRow("bytearray-chunk-wraparound3") << raw("\x81\x5f\x5b\xff\xff\xff\xff\xff\xff\xff\xff") << 0
|
||||
<< wraparoundError(UINT64_MAX);
|
||||
QTest::newRow("string-chunk-wraparound3") << raw("\x81\x7f\x7b\xff\xff\xff\xff\xff\xff\xff\xff") << 0
|
||||
<< wraparoundError(UINT64_MAX);
|
||||
|
||||
QTest::newRow("eof-after-array") << raw("\x81") << 0 << CborErrorUnexpectedEOF;
|
||||
QTest::newRow("eof-after-array2") << raw("\x81\x78\x20") << 0 << CborErrorUnexpectedEOF;
|
||||
|
@ -1,6 +1,6 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2018 Intel Corporation.
|
||||
** Copyright (C) 2020 Intel Corporation.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtCore module of the Qt Toolkit.
|
||||
@ -42,6 +42,7 @@
|
||||
#define CBOR_NO_ENCODER_API
|
||||
#include <private/qcborcommon_p.h>
|
||||
|
||||
#include <private/qbytearray_p.h>
|
||||
#include <private/qnumeric_p.h>
|
||||
#include <private/qutfcodec_p.h>
|
||||
#include <qdebug.h>
|
||||
@ -1055,6 +1056,10 @@ bool QCborStreamReader::next(int maxRecursion)
|
||||
} else if (isString() || isByteArray()) {
|
||||
auto r = _readByteArray_helper();
|
||||
while (r.status == Ok) {
|
||||
if (isString() && r.data.size() > MaxStringSize) {
|
||||
d->handleError(CborErrorDataTooLarge);
|
||||
break;
|
||||
}
|
||||
if (isString() && !QUtf8::isValidUtf8(r.data, r.data.size()).isValidUtf8) {
|
||||
d->handleError(CborErrorInvalidUtf8TextString);
|
||||
break;
|
||||
@ -1337,15 +1342,23 @@ QCborStreamReader::StringResult<QString> QCborStreamReader::_readString_helper()
|
||||
result.status = r.status;
|
||||
|
||||
if (r.status == Ok) {
|
||||
QTextCodec::ConverterState cs;
|
||||
result.data = QUtf8::convertToUnicode(r.data, r.data.size(), &cs);
|
||||
if (cs.invalidChars == 0 && cs.remainingChars == 0)
|
||||
return result;
|
||||
// See QUtf8::convertToUnicode() a detailed explanation of why this
|
||||
// conversion uses the same number of words or less.
|
||||
CborError err = CborNoError;
|
||||
if (r.data.size() > MaxStringSize) {
|
||||
err = CborErrorDataTooLarge;
|
||||
} else {
|
||||
QTextCodec::ConverterState cs;
|
||||
result.data = QUtf8::convertToUnicode(r.data, r.data.size(), &cs);
|
||||
if (cs.invalidChars != 0 || cs.remainingChars != 0)
|
||||
err = CborErrorInvalidUtf8TextString;
|
||||
}
|
||||
|
||||
d->handleError(CborErrorInvalidUtf8TextString);
|
||||
result.data.clear();
|
||||
result.status = Error;
|
||||
return result;
|
||||
if (err) {
|
||||
d->handleError(err);
|
||||
result.data.clear();
|
||||
result.status = Error;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -1373,6 +1386,10 @@ QCborStreamReader::StringResult<QByteArray> QCborStreamReader::_readByteArray_he
|
||||
qsizetype len = _currentStringChunkSize();
|
||||
if (len < 0)
|
||||
return result;
|
||||
if (len > MaxByteArraySize) {
|
||||
d->handleError(CborErrorDataTooLarge);
|
||||
return result;
|
||||
}
|
||||
|
||||
result.data.resize(len);
|
||||
auto r = readStringChunk(result.data.data(), len);
|
||||
|
@ -1,6 +1,6 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2018 Intel Corporation.
|
||||
** Copyright (C) 2020 Intel Corporation.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtCore module of the Qt Toolkit.
|
||||
@ -53,6 +53,7 @@
|
||||
|
||||
#include <qendian.h>
|
||||
#include <qlocale.h>
|
||||
#include <private/qbytearray_p.h>
|
||||
#include <private/qnumeric_p.h>
|
||||
#include <private/qsimd_p.h>
|
||||
|
||||
@ -1553,6 +1554,8 @@ void QCborContainerPrivate::decodeStringFromCbor(QCborStreamReader &reader)
|
||||
// and calculate the final size
|
||||
if (add_overflow(offset, increment, &newSize))
|
||||
return -1;
|
||||
if (newSize > MaxByteArraySize)
|
||||
return -1;
|
||||
|
||||
// since usedData <= data.size(), this can't overflow
|
||||
usedData += increment;
|
||||
@ -1627,13 +1630,6 @@ void QCborContainerPrivate::decodeStringFromCbor(QCborStreamReader &reader)
|
||||
setErrorInReader(reader, { QCborError::DataTooLarge });
|
||||
}
|
||||
|
||||
if (r.status == QCborStreamReader::Error) {
|
||||
// There can only be errors if there was data to be read.
|
||||
Q_ASSERT(e.flags & Element::HasByteData);
|
||||
data.truncate(e.value);
|
||||
return;
|
||||
}
|
||||
|
||||
// update size
|
||||
if (e.flags & Element::HasByteData) {
|
||||
auto b = new (dataPtr() + e.value) ByteData;
|
||||
@ -1645,6 +1641,21 @@ void QCborContainerPrivate::decodeStringFromCbor(QCborStreamReader &reader)
|
||||
Q_ASSERT(e.type == QCborValue::String);
|
||||
e.flags |= Element::StringIsAscii;
|
||||
}
|
||||
|
||||
// check that this UTF-8 text string can be loaded onto a QString
|
||||
if (e.type == QCborValue::String) {
|
||||
if (Q_UNLIKELY(b->len > MaxStringSize)) {
|
||||
setErrorInReader(reader, { QCborError::DataTooLarge });
|
||||
r.status = QCborStreamReader::Error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (r.status == QCborStreamReader::Error) {
|
||||
// There can only be errors if there was data to be read.
|
||||
Q_ASSERT(e.flags & Element::HasByteData);
|
||||
data.truncate(e.value);
|
||||
return;
|
||||
}
|
||||
|
||||
elements.append(e);
|
||||
|
@ -56,10 +56,9 @@
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
enum {
|
||||
// Define as enum to force inlining. Don't expose MaxAllocSize in a public header.
|
||||
MaxByteArraySize = MaxAllocSize - sizeof(std::remove_pointer<QByteArray::DataPtr>::type)
|
||||
};
|
||||
// -1 because of the terminating NUL
|
||||
constexpr qsizetype MaxByteArraySize = MaxAllocSize - sizeof(std::remove_pointer<QByteArray::DataPtr>::type) - 1;
|
||||
constexpr qsizetype MaxStringSize = (MaxAllocSize - sizeof(std::remove_pointer<QByteArray::DataPtr>::type)) / 2 - 1;
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
|
@ -288,6 +288,12 @@ QAbstractItemModelTester::FailureReportingMode QAbstractItemModelTester::failure
|
||||
return d->failureReportingMode;
|
||||
}
|
||||
|
||||
bool QAbstractItemModelTester::verify(bool statement, const char *statementStr, const char *description, const char *file, int line)
|
||||
{
|
||||
Q_D(QAbstractItemModelTester);
|
||||
return d->verify(statement, statementStr, description, file, line);
|
||||
}
|
||||
|
||||
QAbstractItemModelTesterPrivate::QAbstractItemModelTesterPrivate(QAbstractItemModel *model, QAbstractItemModelTester::FailureReportingMode failureReportingMode)
|
||||
: model(model),
|
||||
failureReportingMode(failureReportingMode),
|
||||
|
@ -1844,10 +1844,16 @@ void QAbstractItemView::mouseMoveEvent(QMouseEvent *event)
|
||||
|| edit(index, NoEditTriggers, event))
|
||||
return;
|
||||
|
||||
if (d->selectionMode != SingleSelection)
|
||||
topLeft = d->pressedPosition - d->offset();
|
||||
else
|
||||
if (d->selectionMode != SingleSelection) {
|
||||
// Use the current selection start index if it is valid as this will be based on the
|
||||
// start of the selection and not the last item being pressed which can be different
|
||||
// when in extended selection
|
||||
topLeft = d->currentSelectionStartIndex.isValid()
|
||||
? visualRect(d->currentSelectionStartIndex).center()
|
||||
: d->pressedPosition - d->offset();
|
||||
} else {
|
||||
topLeft = bottomRight;
|
||||
}
|
||||
|
||||
d->checkMouseMove(index);
|
||||
|
||||
|
@ -505,7 +505,7 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event)
|
||||
QGuiApplicationPrivate::platformTheme()->themeHint(QPlatformTheme::ContextMenuOnMouseRelease).toBool() ?
|
||||
QEvent::MouseButtonRelease : QEvent::MouseButtonPress;
|
||||
if (QApplicationPrivate::inPopupMode()) {
|
||||
QWidget *activePopupWidget = QApplication::activePopupWidget();
|
||||
QPointer<QWidget> activePopupWidget = QApplication::activePopupWidget();
|
||||
QPoint mapped = event->pos();
|
||||
if (activePopupWidget != m_widget)
|
||||
mapped = activePopupWidget->mapFromGlobal(event->globalPos());
|
||||
@ -565,9 +565,11 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event)
|
||||
#endif
|
||||
if ((event->type() != QEvent::MouseButtonPress)
|
||||
|| !(event->flags().testFlag(Qt::MouseEventCreatedDoubleClick))) {
|
||||
|
||||
// if the widget that was pressed is gone, then deliver move events without buttons
|
||||
const auto buttons = event->type() == QEvent::MouseMove && qt_button_down == nullptr
|
||||
? Qt::NoButton : event->buttons();
|
||||
QMouseEvent e(event->type(), widgetPos, event->windowPos(), event->screenPos(),
|
||||
event->button(), event->buttons(), event->modifiers(), event->source());
|
||||
event->button(), buttons, event->modifiers(), event->source());
|
||||
e.setTimestamp(event->timestamp());
|
||||
QApplicationPrivate::sendMouseEvent(receiver, &e, receiver, receiver->window(), &qt_button_down, qt_last_mouse_receiver);
|
||||
qt_last_mouse_receiver = receiver;
|
||||
|
134
tests/auto/corelib/serialization/cborlargedatavalidation.cpp
Normal file
134
tests/auto/corelib/serialization/cborlargedatavalidation.cpp
Normal file
@ -0,0 +1,134 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 Intel Corporation.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtCore module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include <QtTest/QtTest>
|
||||
#include <cbor.h>
|
||||
|
||||
namespace {
|
||||
// A QIODevice that supplies a fixed header followed by a large sequence of
|
||||
// null bytes up until a pre-determined size.
|
||||
class LargeIODevice final : public QIODevice
|
||||
{
|
||||
public:
|
||||
qint64 realSize;
|
||||
QByteArray start;
|
||||
|
||||
LargeIODevice(const QByteArray &start, qint64 size, QObject *parent = nullptr)
|
||||
: QIODevice(parent), realSize(size), start(start)
|
||||
{}
|
||||
|
||||
qint64 size() const override { return realSize; }
|
||||
bool isSequential() const override { return false; }
|
||||
|
||||
protected:
|
||||
qint64 readData(char *data, qint64 maxlen) override;
|
||||
qint64 writeData(const char *, qint64) override { return -1; }
|
||||
};
|
||||
};
|
||||
|
||||
qint64 LargeIODevice::readData(char *data, qint64 maxlen)
|
||||
{
|
||||
qint64 p = pos();
|
||||
if (maxlen > realSize - p)
|
||||
maxlen = realSize - p;
|
||||
memset(data, '\0', maxlen);
|
||||
|
||||
qint64 fromstart = start.size() - p;
|
||||
if (fromstart > maxlen)
|
||||
fromstart = maxlen;
|
||||
else if (fromstart < 0)
|
||||
fromstart = 0;
|
||||
if (fromstart)
|
||||
memcpy(data, start.constData() + p, fromstart);
|
||||
return maxlen;
|
||||
}
|
||||
|
||||
void addValidationLargeData(qsizetype minInvalid, qsizetype maxInvalid)
|
||||
{
|
||||
char toolong[2 + sizeof(qsizetype)] = { char(0x81) };
|
||||
for (qsizetype v = maxInvalid; v >= minInvalid; --v) {
|
||||
// 0x5a for 32-bit, 0x5b for 64-bit
|
||||
toolong[1] = sizeof(v) > 4 ? 0x5b : 0x5a;
|
||||
qToBigEndian(v, toolong + 2);
|
||||
|
||||
QTest::addRow("bytearray-too-big-for-qbytearray-%llx", v)
|
||||
<< QByteArray(toolong, sizeof(toolong)) << 0 << CborErrorDataTooLarge;
|
||||
toolong[1] |= 0x20;
|
||||
|
||||
// QCborStreamReader::readString copies to a QByteArray first
|
||||
QTest::addRow("string-too-big-for-qbytearray-%llx", v)
|
||||
<< QByteArray(toolong, sizeof(toolong)) << 0 << CborErrorDataTooLarge;
|
||||
}
|
||||
}
|
||||
|
||||
void addValidationHugeDevice(qsizetype byteArrayInvalid, qsizetype stringInvalid)
|
||||
{
|
||||
qRegisterMetaType<QSharedPointer<QIODevice>>();
|
||||
QTest::addColumn<QSharedPointer<QIODevice>>("device");
|
||||
QTest::addColumn<CborError>("expectedError");
|
||||
|
||||
char buf[1 + sizeof(quint64)];
|
||||
auto device = [&buf](QCborStreamReader::Type t, quint64 size) {
|
||||
buf[0] = quint8(t) | 0x1b;
|
||||
qToBigEndian(size, buf + 1);
|
||||
size += sizeof(buf);
|
||||
QSharedPointer<QIODevice> p =
|
||||
QSharedPointer<LargeIODevice>::create(QByteArray(buf, sizeof(buf)), size);
|
||||
return p;
|
||||
};
|
||||
|
||||
// do the exact limits
|
||||
QTest::newRow("bytearray-just-too-big")
|
||||
<< device(QCborStreamReader::ByteArray, byteArrayInvalid) << CborErrorDataTooLarge;
|
||||
QTest::newRow("string-just-too-big")
|
||||
<< device(QCborStreamReader::String, stringInvalid) << CborErrorDataTooLarge;
|
||||
|
||||
auto addSize = [=](const char *sizename, qint64 size) {
|
||||
if (byteArrayInvalid < size)
|
||||
QTest::addRow("bytearray-%s", sizename)
|
||||
<< device(QCborStreamReader::ByteArray, size) << CborErrorDataTooLarge;
|
||||
if (stringInvalid < size)
|
||||
QTest::addRow("string-%s", sizename)
|
||||
<< device(QCborStreamReader::String, size) << CborErrorDataTooLarge;
|
||||
};
|
||||
addSize("1GB", quint64(1) << 30);
|
||||
addSize("2GB", quint64(1) << 31);
|
||||
addSize("4GB", quint64(1) << 32);
|
||||
addSize("max", std::numeric_limits<qint64>::max() - sizeof(buf));
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
QT = core testlib
|
||||
QT = core-private testlib
|
||||
TARGET = tst_qcborstreamreader
|
||||
CONFIG += testcase
|
||||
SOURCES += \
|
||||
|
@ -1,6 +1,6 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2018 Intel Corporation.
|
||||
** Copyright (C) 2020 Intel Corporation.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtCore module of the Qt Toolkit.
|
||||
@ -40,6 +40,8 @@
|
||||
#include <QtCore/qcborstream.h>
|
||||
#include <QtTest>
|
||||
|
||||
#include <QtCore/private/qbytearray_p.h>
|
||||
|
||||
class tst_QCborStreamReader : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
@ -73,6 +75,8 @@ private Q_SLOTS:
|
||||
void next();
|
||||
void validation_data();
|
||||
void validation();
|
||||
void hugeDeviceValidation_data();
|
||||
void hugeDeviceValidation();
|
||||
void recursionLimit_data();
|
||||
void recursionLimit();
|
||||
|
||||
@ -902,16 +906,26 @@ void tst_QCborStreamReader::next()
|
||||
QVERIFY(doit("\xbf\x9f\1\xff\x9f" + data + "\xff\xff"));
|
||||
}
|
||||
|
||||
#include "../cborlargedatavalidation.cpp"
|
||||
|
||||
void tst_QCborStreamReader::validation_data()
|
||||
{
|
||||
// Add QCborStreamReader-specific limitations due to use of QByteArray and
|
||||
// QString, which are allocated by QArrayData::allocate().
|
||||
const qsizetype MaxInvalid = std::numeric_limits<QByteArray::size_type>::max();
|
||||
const qsizetype MinInvalid = MaxByteArraySize + 1;
|
||||
|
||||
addValidationColumns();
|
||||
addValidationData();
|
||||
addValidationData(MinInvalid);
|
||||
addValidationLargeData(MinInvalid, MaxInvalid);
|
||||
}
|
||||
|
||||
void tst_QCborStreamReader::validation()
|
||||
{
|
||||
QFETCH_GLOBAL(bool, useDevice);
|
||||
QFETCH(QByteArray, data);
|
||||
QFETCH(CborError, expectedError);
|
||||
QCborError error = { QCborError::Code(expectedError) };
|
||||
|
||||
QBuffer buffer(&data);
|
||||
QCborStreamReader reader(data);
|
||||
@ -920,12 +934,39 @@ void tst_QCborStreamReader::validation()
|
||||
reader.setDevice(&buffer);
|
||||
}
|
||||
parse(reader, data);
|
||||
QVERIFY(reader.lastError() != QCborError::NoError);
|
||||
QCOMPARE(reader.lastError(), error);
|
||||
|
||||
// next() should fail
|
||||
reader.reset();
|
||||
QVERIFY(!reader.next());
|
||||
QVERIFY(reader.lastError() != QCborError::NoError);
|
||||
QCOMPARE(reader.lastError(), error);
|
||||
}
|
||||
|
||||
void tst_QCborStreamReader::hugeDeviceValidation_data()
|
||||
{
|
||||
addValidationHugeDevice(MaxByteArraySize + 1, MaxStringSize + 1);
|
||||
}
|
||||
|
||||
void tst_QCborStreamReader::hugeDeviceValidation()
|
||||
{
|
||||
QFETCH_GLOBAL(bool, useDevice);
|
||||
if (!useDevice)
|
||||
return;
|
||||
|
||||
QFETCH(QSharedPointer<QIODevice>, device);
|
||||
QFETCH(CborError, expectedError);
|
||||
QCborError error = { QCborError::Code(expectedError) };
|
||||
|
||||
device->open(QIODevice::ReadOnly | QIODevice::Unbuffered);
|
||||
QCborStreamReader reader(device.data());
|
||||
|
||||
QVERIFY(parseOne(reader).isEmpty());
|
||||
QCOMPARE(reader.lastError(), error);
|
||||
|
||||
// next() should fail
|
||||
reader.reset();
|
||||
QVERIFY(!reader.next());
|
||||
QCOMPARE(reader.lastError(), error);
|
||||
}
|
||||
|
||||
static const int Recursions = 3;
|
||||
|
@ -1,4 +1,4 @@
|
||||
QT = core testlib
|
||||
QT = core-private testlib
|
||||
TARGET = tst_qcborvalue
|
||||
CONFIG += testcase
|
||||
SOURCES += \
|
||||
|
@ -1,6 +1,6 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2018 Intel Corporation.
|
||||
** Copyright (C) 2020 Intel Corporation.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtCore module of the Qt Toolkit.
|
||||
@ -40,6 +40,8 @@
|
||||
#include <QtCore/qcborvalue.h>
|
||||
#include <QtTest>
|
||||
|
||||
#include <QtCore/private/qbytearray_p.h>
|
||||
|
||||
Q_DECLARE_METATYPE(QCborKnownTags)
|
||||
Q_DECLARE_METATYPE(QCborValue)
|
||||
Q_DECLARE_METATYPE(QCborValue::EncodingOptions)
|
||||
@ -102,6 +104,8 @@ private slots:
|
||||
void fromCborStreamReaderIODevice();
|
||||
void validation_data();
|
||||
void validation();
|
||||
void hugeDeviceValidation_data();
|
||||
void hugeDeviceValidation();
|
||||
void recursionLimit_data();
|
||||
void recursionLimit();
|
||||
void toDiagnosticNotation_data();
|
||||
@ -1689,39 +1693,75 @@ void tst_QCborValue::fromCborStreamReaderIODevice()
|
||||
fromCbor_common(doCheck);
|
||||
}
|
||||
|
||||
#include "../cborlargedatavalidation.cpp"
|
||||
|
||||
void tst_QCborValue::validation_data()
|
||||
{
|
||||
// Add QCborStreamReader-specific limitations due to use of QByteArray and
|
||||
// QString, which are allocated by QArrayData::allocate().
|
||||
const qsizetype MaxInvalid = std::numeric_limits<QByteArray::size_type>::max();
|
||||
const qsizetype MinInvalid = MaxByteArraySize + 1;
|
||||
addValidationColumns();
|
||||
addValidationData();
|
||||
addValidationData(MinInvalid);
|
||||
addValidationLargeData(MinInvalid, MaxInvalid);
|
||||
|
||||
// These tests say we have arrays and maps with very large item counts.
|
||||
// They are meant to ensure we don't pre-allocate a lot of memory
|
||||
// unnecessarily and possibly crash the application. The actual number of
|
||||
// elements in the stream is only 2, so we should get an unexpected EOF
|
||||
// error. QCborValue internally uses 16 bytes per element, so we get to
|
||||
// 2 GB at 2^27 elements.
|
||||
QTest::addRow("very-large-array-no-overflow") << raw("\x9a\x07\xff\xff\xff" "\0\0");
|
||||
QTest::addRow("very-large-array-overflow1") << raw("\x9a\x40\0\0\0" "\0\0");
|
||||
// error. QCborValue internally uses 16 bytes per element, so we get to 2
|
||||
// GB at 2^27 elements (32-bit) or, theoretically, 2^63 bytes at 2^59
|
||||
// elements (64-bit).
|
||||
if (sizeof(QVector<int>::size_type) == sizeof(int)) {
|
||||
// 32-bit sizes (Qt 5 and 32-bit platforms)
|
||||
QTest::addRow("very-large-array-no-overflow") << raw("\x9a\x07\xff\xff\xff" "\0\0") << 0 << CborErrorUnexpectedEOF;
|
||||
QTest::addRow("very-large-array-overflow1") << raw("\x9a\x40\0\0\0" "\0\0") << 0 << CborErrorUnexpectedEOF;
|
||||
|
||||
// this makes sure we don't accidentally clip to 32-bit: sending 2^32+2 elements
|
||||
QTest::addRow("very-large-array-overflow2") << raw("\x9b\0\0\0\1""\0\0\0\2" "\0\0");
|
||||
// this makes sure we don't accidentally clip to 32-bit: sending 2^32+2 elements
|
||||
QTest::addRow("very-large-array-overflow2") << raw("\x9b\0\0\0\1""\0\0\0\2" "\0\0") << 0 << CborErrorDataTooLarge;
|
||||
} else {
|
||||
// 64-bit Qt 6
|
||||
QTest::addRow("very-large-array-no-overflow") << raw("\x9b\x07\xff\xff\xff" "\xff\xff\xff\xff" "\0\0");
|
||||
QTest::addRow("very-large-array-overflow") << raw("\x9b\x40\0\0\0" "\0\0\0\0" "\0\0");
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QCborValue::validation()
|
||||
{
|
||||
QFETCH(QByteArray, data);
|
||||
QFETCH(CborError, expectedError);
|
||||
QCborError error = { QCborError::Code(expectedError) };
|
||||
|
||||
QCborParserError error;
|
||||
QCborValue decoded = QCborValue::fromCbor(data, &error);
|
||||
QVERIFY(error.error != QCborError{});
|
||||
QCborParserError parserError;
|
||||
QCborValue decoded = QCborValue::fromCbor(data, &parserError);
|
||||
QCOMPARE(parserError.error, error);
|
||||
|
||||
if (data.startsWith('\x81')) {
|
||||
// decode without the array prefix
|
||||
decoded = QCborValue::fromCbor(data.mid(1), &error);
|
||||
QVERIFY(error.error != QCborError{});
|
||||
char *ptr = const_cast<char *>(data.constData());
|
||||
QByteArray mid = QByteArray::fromRawData(ptr + 1, data.size() - 1);
|
||||
decoded = QCborValue::fromCbor(mid, &parserError);
|
||||
QCOMPARE(parserError.error, error);
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QCborValue::hugeDeviceValidation_data()
|
||||
{
|
||||
addValidationHugeDevice(MaxByteArraySize + 1, MaxStringSize + 1);
|
||||
}
|
||||
|
||||
void tst_QCborValue::hugeDeviceValidation()
|
||||
{
|
||||
QFETCH(QSharedPointer<QIODevice>, device);
|
||||
QFETCH(CborError, expectedError);
|
||||
QCborError error = { QCborError::Code(expectedError) };
|
||||
|
||||
device->open(QIODevice::ReadOnly | QIODevice::Unbuffered);
|
||||
QCborStreamReader reader(device.data());
|
||||
QCborValue decoded = QCborValue::fromCbor(reader);
|
||||
QCOMPARE(reader.lastError(), error);
|
||||
}
|
||||
|
||||
void tst_QCborValue::recursionLimit_data()
|
||||
{
|
||||
constexpr int RecursionAttempts = 4096;
|
||||
|
@ -149,6 +149,7 @@ private slots:
|
||||
void currentFollowsIndexWidget();
|
||||
void checkFocusAfterActivationChanges_data();
|
||||
void checkFocusAfterActivationChanges();
|
||||
void dragSelectAfterNewPress();
|
||||
private:
|
||||
static QAbstractItemView *viewFromString(const QByteArray &viewType, QWidget *parent = nullptr)
|
||||
{
|
||||
@ -2453,5 +2454,62 @@ void tst_QAbstractItemView::checkFocusAfterActivationChanges()
|
||||
QVERIFY(view->hasFocus());
|
||||
}
|
||||
|
||||
void tst_QAbstractItemView::dragSelectAfterNewPress()
|
||||
{
|
||||
QStandardItemModel model;
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
QStandardItem *item = new QStandardItem(QString::number(i));
|
||||
model.setItem(i, 0, item);
|
||||
}
|
||||
|
||||
QListView view;
|
||||
view.setFixedSize(160, 650); // Minimum width for windows with frame on Windows 8
|
||||
view.setSelectionMode(QListView::ExtendedSelection);
|
||||
view.setModel(&model);
|
||||
centerOnScreen(&view);
|
||||
moveCursorAway(&view);
|
||||
view.show();
|
||||
QVERIFY(QTest::qWaitForWindowExposed(&view));
|
||||
|
||||
QModelIndex index0 = model.index(0, 0);
|
||||
QModelIndex index2 = model.index(2, 0);
|
||||
|
||||
view.setCurrentIndex(index0);
|
||||
QCOMPARE(view.currentIndex(), index0);
|
||||
|
||||
// Select item 0 using a single click
|
||||
QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::NoModifier,
|
||||
view.visualRect(index0).center());
|
||||
QCOMPARE(view.currentIndex(), index0);
|
||||
|
||||
// Press to select item 2
|
||||
QTest::mousePress(view.viewport(), Qt::LeftButton, Qt::ShiftModifier,
|
||||
view.visualRect(index2).center());
|
||||
QCOMPARE(view.currentIndex(), index2);
|
||||
|
||||
// Verify that the selection worked OK
|
||||
QModelIndexList selected = view.selectionModel()->selectedIndexes();
|
||||
QCOMPARE(selected.count(), 3);
|
||||
for (int i = 0; i < 2; ++i)
|
||||
QVERIFY(selected.contains(model.index(i, 0)));
|
||||
|
||||
QModelIndex index5 = model.index(5, 0);
|
||||
const QPoint releasePos = view.visualRect(index5).center();
|
||||
// The mouse move event has to be created manually because the QTest framework does not
|
||||
// contain a function for mouse moves with buttons pressed
|
||||
QMouseEvent moveEvent2(QEvent::MouseMove, releasePos, Qt::NoButton, Qt::LeftButton,
|
||||
Qt::ShiftModifier);
|
||||
const bool moveEventReceived = qApp->notify(view.viewport(), &moveEvent2);
|
||||
QVERIFY(moveEventReceived);
|
||||
QTest::mouseRelease(view.viewport(), Qt::LeftButton, Qt::ShiftModifier, releasePos);
|
||||
QCOMPARE(view.currentIndex(), index5);
|
||||
|
||||
// Verify that the selection worked OK
|
||||
selected = view.selectionModel()->selectedIndexes();
|
||||
QCOMPARE(selected.count(), 6);
|
||||
for (int i = 0; i < 5; ++i)
|
||||
QVERIFY(selected.contains(model.index(i, 0)));
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_QAbstractItemView)
|
||||
#include "tst_qabstractitemview.moc"
|
||||
|
Loading…
Reference in New Issue
Block a user