QmlProfiler: Don't write past end in QmlEvent

If the external data is quint16_max long, we need to stop writing at
quint16_max - 1. So we cannot rely on unsigned integer overflow to
enforce the boundary.

Also, use for (...) rather than foreach (...). This should easily offset
the extra overhead introduced by the bounds check.

Change-Id: I51d1aef1040fbaa8396ca80ec7e30b2fe7b7dd0b
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
This commit is contained in:
Ulf Hermann
2017-09-08 12:55:34 +02:00
parent 64288955f0
commit bffbae47f1
3 changed files with 24 additions and 2 deletions

View File

@@ -290,10 +290,13 @@ private:
m_dataType = static_cast<Type>(sizeof(Number) * 8); m_dataType = static_cast<Type>(sizeof(Number) * 8);
data = static_cast<Number *>(m_dataType & External ? m_data.external : &m_data); data = static_cast<Number *>(m_dataType & External ? m_data.external : &m_data);
} }
quint16 i = 0; // If you really have more than 64k items, this will wrap. Too bad. quint16 i = 0;
foreach (Number item, numbers) for (Number item : numbers) {
if (i >= m_dataLength)
break;
data[i++] = item; data[i++] = item;
} }
}
void clearPointer() void clearPointer()
{ {

View File

@@ -28,6 +28,8 @@
#include <QList> #include <QList>
#include <QQueue> #include <QQueue>
#include <cstring>
namespace QmlProfiler { namespace QmlProfiler {
namespace Internal { namespace Internal {
@@ -116,6 +118,22 @@ void QmlEventTest::testNumbers()
QCOMPARE(event.number<qint64>(5), 0LL); QCOMPARE(event.number<qint64>(5), 0LL);
} }
void QmlEventTest::testMaxSize()
{
const qint8 marker1 = 0xee;
const qint8 marker2 = 0xbb;
QmlEvent event;
QVarLengthArray<qint8> numbers(1 << 17);
std::memset(numbers.data(), 0, (1 << 17));
numbers[0] = marker1;
numbers[(1 << 16) - 2] = marker2;
event.setNumbers<QVarLengthArray<qint8>, qint8>(numbers);
const auto result = event.numbers<QVarLengthArray<qint8>, qint8>();
QCOMPARE(result.size(), (1 << 16) - 1);
QCOMPARE(result[0], marker1);
QCOMPARE(result[(1 << 16) - 2], marker2);
}
void QmlEventTest::testStreamOps() void QmlEventTest::testStreamOps()
{ {
QQueue<QmlEvent> sentEvents; QQueue<QmlEvent> sentEvents;

View File

@@ -39,6 +39,7 @@ public:
private slots: private slots:
void testCtors(); void testCtors();
void testNumbers(); void testNumbers();
void testMaxSize();
void testStreamOps(); void testStreamOps();
}; };