diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2017-11-14 13:15:29 +0100 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2017-11-15 10:12:08 +0000 |
commit | 141dbed197c1ab28c22f7378dc19d76576fce5e8 (patch) | |
tree | 0ba42cc9aefe0e149ea9655912b648fd7a30bfc2 | |
parent | e41b16ea55b739bfaf7b2802bc38bb8d9a3c5cff (diff) |
Read the contentSize of a stack sample only if section size > 0
Otherwise we crash on any samples in kernel space.
Change-Id: Id194302c7ba2e0fcc2f7d79d56eed6e1d1796308
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
-rw-r--r-- | app/perfdata.cpp | 15 | ||||
-rw-r--r-- | tests/auto/perfdata/contentsize.data | bin | 0 -> 40688 bytes | |||
-rw-r--r-- | tests/auto/perfdata/perfdata.qrc | 1 | ||||
-rw-r--r-- | tests/auto/perfdata/tst_perfdata.cpp | 33 |
4 files changed, 42 insertions, 7 deletions
diff --git a/app/perfdata.cpp b/app/perfdata.cpp index 1305d21..20253c4 100644 --- a/app/perfdata.cpp +++ b/app/perfdata.cpp @@ -554,17 +554,18 @@ QDataStream &operator>>(QDataStream &stream, PerfRecordSample &record) } while (sectionSize > intMax); stream.skipRawData(static_cast<int>(sectionSize)); sectionSize = 0; + stream.skipRawData(sizeof(quint64)); // skip contentSize } else if (sectionSize > 0) { record.m_userStack.resize(static_cast<int>(sectionSize)); stream.readRawData(record.m_userStack.data(), record.m_userStack.size()); - } - quint64 contentSize; - stream >> contentSize; - if (contentSize > sectionSize) - qWarning() << "Truncated stack snapshot" << contentSize << sectionSize; - else - record.m_userStack.resize(static_cast<int>(contentSize)); + quint64 contentSize; + stream >> contentSize; + if (contentSize > sectionSize) + qWarning() << "Truncated stack snapshot" << contentSize << sectionSize; + else + record.m_userStack.resize(static_cast<int>(contentSize)); + } } if (sampleType & PerfEventAttributes::SAMPLE_WEIGHT) diff --git a/tests/auto/perfdata/contentsize.data b/tests/auto/perfdata/contentsize.data Binary files differnew file mode 100644 index 0000000..0c1db67 --- /dev/null +++ b/tests/auto/perfdata/contentsize.data diff --git a/tests/auto/perfdata/perfdata.qrc b/tests/auto/perfdata/perfdata.qrc index 1b5d91a..8df083c 100644 --- a/tests/auto/perfdata/perfdata.qrc +++ b/tests/auto/perfdata/perfdata.qrc @@ -1,5 +1,6 @@ <RCC> <qresource prefix="/"> <file>probe.data.stream</file> + <file>contentsize.data</file> </qresource> </RCC> diff --git a/tests/auto/perfdata/tst_perfdata.cpp b/tests/auto/perfdata/tst_perfdata.cpp index 820dae9..08ef47d 100644 --- a/tests/auto/perfdata/tst_perfdata.cpp +++ b/tests/auto/perfdata/tst_perfdata.cpp @@ -31,6 +31,7 @@ class TestPerfData : public QObject Q_OBJECT private slots: void testTraceDataHeaderEvent(); + void testContentSize(); }; void TestPerfData::testTraceDataHeaderEvent() @@ -48,6 +49,7 @@ void TestPerfData::testTraceDataHeaderEvent() QSignalSpy spy(&data, SIGNAL(finished())); connect(&header, &PerfHeader::finished, &data, &PerfData::read); + header.read(); QCOMPARE(spy.count(), 1); @@ -64,6 +66,37 @@ void TestPerfData::testTraceDataHeaderEvent() QCOMPARE(stats.maxTime, 13780586522722ull); } +void TestPerfData::testContentSize() +{ + QString file(":/contentsize.data"); + + QBuffer output; + QFile input(file); + + QVERIFY(input.open(QIODevice::ReadOnly)); + QVERIFY(output.open(QIODevice::WriteOnly)); + + // Don't try to load any system files. They are not the same as the ones we use to report. + PerfUnwind unwind(&output, ":/", QString(), QString(), QString(), true); + PerfHeader header(&input); + PerfAttributes attributes; + PerfData data(&input, &unwind, &header, &attributes); + + QSignalSpy spy(&data, SIGNAL(finished())); + connect(&header, &PerfHeader::finished, &data, &PerfData::read); + + header.read(); + QCOMPARE(spy.count(), 1); + + unwind.finalize(); + + QObject::connect(&data, &PerfData::error, []() { + QFAIL("PerfData reported an error"); + }); + + QCOMPARE(unwind.stats().numSamples, 69u); +} + QTEST_GUILESS_MAIN(TestPerfData) #include "tst_perfdata.moc" |