Commit 9cdb0ec2 authored by Ulf Hermann's avatar Ulf Hermann

QmlProfiler: Don't trust in externally provided timestamps

We might get timestamps that are outside the trace time, negative
timestamps, ranges that go backwards, and other insane things.

In order to deal with this, we clamp all negative timestamps to 0, and
treat the specified trace time as minimum range, that can be overridden
by events.

Change-Id: Iba661f2a4346077871fc62a46759e169b2aad49d
Reviewed-by: default avatarMilian Wolff <milian.wolff@kdab.com>
parent 8fa07c81
...@@ -92,18 +92,23 @@ bool QmlProfilerTraceTime::isRestrictedToRange() const ...@@ -92,18 +92,23 @@ bool QmlProfilerTraceTime::isRestrictedToRange() const
void QmlProfilerTraceTime::clear() void QmlProfilerTraceTime::clear()
{ {
restrictToRange(-1, -1); restrictToRange(-1, -1);
setTime(-1, -1); m_startTime = -1;
m_endTime = -1;
} }
void QmlProfilerTraceTime::setTime(qint64 startTime, qint64 endTime) void QmlProfilerTraceTime::update(qint64 time)
{ {
QTC_ASSERT(startTime <= endTime, endTime = startTime); QTC_ASSERT(time >= 0, return);
m_startTime = startTime; if (m_startTime > time || m_startTime == -1)
m_endTime = endTime; m_startTime = time;
if (m_endTime < time || m_endTime == -1)
m_endTime = time;
QTC_ASSERT(m_endTime >= m_startTime, m_startTime = m_endTime);
} }
void QmlProfilerTraceTime::decreaseStartTime(qint64 time) void QmlProfilerTraceTime::decreaseStartTime(qint64 time)
{ {
QTC_ASSERT(time >= 0, return);
if (m_startTime > time || m_startTime == -1) { if (m_startTime > time || m_startTime == -1) {
m_startTime = time; m_startTime = time;
if (m_endTime == -1) if (m_endTime == -1)
...@@ -115,6 +120,7 @@ void QmlProfilerTraceTime::decreaseStartTime(qint64 time) ...@@ -115,6 +120,7 @@ void QmlProfilerTraceTime::decreaseStartTime(qint64 time)
void QmlProfilerTraceTime::increaseEndTime(qint64 time) void QmlProfilerTraceTime::increaseEndTime(qint64 time)
{ {
QTC_ASSERT(time >= 0, return);
if (m_endTime < time || m_endTime == -1) { if (m_endTime < time || m_endTime == -1) {
m_endTime = time; m_endTime = time;
if (m_startTime == -1) if (m_startTime == -1)
...@@ -244,6 +250,7 @@ void QmlProfilerModelManager::addEvents(const QVector<QmlEvent> &events) ...@@ -244,6 +250,7 @@ void QmlProfilerModelManager::addEvents(const QVector<QmlEvent> &events)
{ {
for (const QmlEvent &event : events) { for (const QmlEvent &event : events) {
d->eventStream << event; d->eventStream << event;
d->traceTime->update(event.timestamp());
d->dispatch(event, d->eventTypes[event.typeIndex()]); d->dispatch(event, d->eventTypes[event.typeIndex()]);
} }
} }
...@@ -251,6 +258,7 @@ void QmlProfilerModelManager::addEvents(const QVector<QmlEvent> &events) ...@@ -251,6 +258,7 @@ void QmlProfilerModelManager::addEvents(const QVector<QmlEvent> &events)
void QmlProfilerModelManager::addEvent(const QmlEvent &event) void QmlProfilerModelManager::addEvent(const QmlEvent &event)
{ {
d->eventStream << event; d->eventStream << event;
d->traceTime->update(event.timestamp());
QTC_ASSERT(event.typeIndex() < d->eventTypes.size(), QTC_ASSERT(event.typeIndex() < d->eventTypes.size(),
d->eventTypes.resize(event.typeIndex() + 1)); d->eventTypes.resize(event.typeIndex() + 1));
d->dispatch(event, d->eventTypes.at(event.typeIndex())); d->dispatch(event, d->eventTypes.at(event.typeIndex()));
...@@ -606,7 +614,10 @@ void QmlProfilerModelManager::load(const QString &filename) ...@@ -606,7 +614,10 @@ void QmlProfilerModelManager::load(const QString &filename)
this, &QmlProfilerModelManager::addEvents); this, &QmlProfilerModelManager::addEvents);
connect(reader, &QmlProfilerFileReader::success, this, [this, reader]() { connect(reader, &QmlProfilerFileReader::success, this, [this, reader]() {
d->traceTime->setTime(reader->traceStart(), reader->traceEnd()); if (reader->traceStart() >= 0)
d->traceTime->decreaseStartTime(reader->traceStart());
if (reader->traceEnd() >= 0)
d->traceTime->increaseEndTime(reader->traceEnd());
setRecordedFeatures(reader->loadedFeatures()); setRecordedFeatures(reader->loadedFeatures());
delete reader; delete reader;
acquiringDone(); acquiringDone();
......
...@@ -58,7 +58,7 @@ public: ...@@ -58,7 +58,7 @@ public:
void clear(); void clear();
void setTime(qint64 startTime, qint64 endTime); void update(qint64 time);
void decreaseStartTime(qint64 time); void decreaseStartTime(qint64 time);
void increaseEndTime(qint64 time); void increaseEndTime(qint64 time);
void restrictToRange(qint64 startTime, qint64 endTime); void restrictToRange(qint64 startTime, qint64 endTime);
......
...@@ -247,7 +247,7 @@ void QmlProfilerTraceClient::setRequestedFeatures(quint64 features) ...@@ -247,7 +247,7 @@ void QmlProfilerTraceClient::setRequestedFeatures(quint64 features)
const QmlDebug::QDebugContextInfo &context) const QmlDebug::QDebugContextInfo &context)
{ {
d->updateFeatures(ProfileDebugMessages); d->updateFeatures(ProfileDebugMessages);
d->currentEvent.event.setTimestamp(context.timestamp); d->currentEvent.event.setTimestamp(context.timestamp > 0 ? context.timestamp : 0);
d->currentEvent.event.setTypeIndex(-1); d->currentEvent.event.setTypeIndex(-1);
d->currentEvent.event.setString(text); d->currentEvent.event.setString(text);
d->currentEvent.type = QmlEventType(DebugMessage, MaximumRangeType, type, d->currentEvent.type = QmlEventType(DebugMessage, MaximumRangeType, type,
......
...@@ -257,6 +257,8 @@ void QmlProfilerFileReader::loadQzt(QIODevice *device) ...@@ -257,6 +257,8 @@ void QmlProfilerFileReader::loadQzt(QIODevice *device)
return; return;
} }
m_loadedFeatures |= (1ULL << m_eventTypes[event.typeIndex()].feature()); m_loadedFeatures |= (1ULL << m_eventTypes[event.typeIndex()].feature());
if (event.timestamp() < 0)
event.setTimestamp(0);
} else if (bufferStream.status() == QDataStream::ReadPastEnd) { } else if (bufferStream.status() == QDataStream::ReadPastEnd) {
break; // Apparently EOF is a character so we end up here after the last event. break; // Apparently EOF is a character so we end up here after the last event.
} else if (bufferStream.status() == QDataStream::ReadCorruptData) { } else if (bufferStream.status() == QDataStream::ReadCorruptData) {
...@@ -506,15 +508,16 @@ void QmlProfilerFileReader::loadEvents(QXmlStreamReader &stream) ...@@ -506,15 +508,16 @@ void QmlProfilerFileReader::loadEvents(QXmlStreamReader &stream)
continue; continue;
} }
event.setTimestamp(attributes.value(_("startTime")).toLongLong()); const qint64 timestamp = attributes.value(_("startTime")).toLongLong();
event.setTimestamp(timestamp > 0 ? timestamp : 0);
event.setTypeIndex(attributes.value(_("eventIndex")).toInt()); event.setTypeIndex(attributes.value(_("eventIndex")).toInt());
if (attributes.hasAttribute(_("duration"))) { if (attributes.hasAttribute(_("duration"))) {
event.setRangeStage(RangeStart); event.setRangeStage(RangeStart);
QmlEvent rangeEnd(event); QmlEvent rangeEnd(event);
rangeEnd.setRangeStage(RangeEnd); rangeEnd.setRangeStage(RangeEnd);
rangeEnd.setTimestamp(event.timestamp() const qint64 duration = attributes.value(_("duration")).toLongLong();
+ attributes.value(_("duration")).toLongLong()); rangeEnd.setTimestamp(event.timestamp() + (duration > 0 ? duration : 0));
events.addRange(event, rangeEnd); events.addRange(event, rangeEnd);
} else { } else {
// attributes for special events // attributes for special events
......
...@@ -44,7 +44,7 @@ QDataStream &operator>>(QDataStream &stream, QmlTypedEvent &event) ...@@ -44,7 +44,7 @@ QDataStream &operator>>(QDataStream &stream, QmlTypedEvent &event)
subtype = -1; subtype = -1;
} }
event.event.setTimestamp(time); event.event.setTimestamp(time > 0 ? time : 0);
event.event.setTypeIndex(-1); event.event.setTypeIndex(-1);
event.serverTypeId = 0; event.serverTypeId = 0;
......
...@@ -38,7 +38,8 @@ PixmapCacheModelTest::PixmapCacheModelTest(QObject *parent) : QObject(parent), ...@@ -38,7 +38,8 @@ PixmapCacheModelTest::PixmapCacheModelTest(QObject *parent) : QObject(parent),
void PixmapCacheModelTest::initTestCase() void PixmapCacheModelTest::initTestCase()
{ {
manager.startAcquiring(); manager.startAcquiring();
manager.traceTime()->setTime(1, 300); manager.traceTime()->decreaseStartTime(1);
manager.traceTime()->increaseEndTime(300);
for (int i = 0; i < MaximumPixmapEventType; ++i) { for (int i = 0; i < MaximumPixmapEventType; ++i) {
eventTypeIndices[i] = manager.numLoadedEventTypes(); eventTypeIndices[i] = manager.numLoadedEventTypes();
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment