summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2018-01-25 11:30:04 +0100
committerUlf Hermann <ulf.hermann@qt.io>2018-01-29 10:09:55 +0000
commitd35f2ee49a094d8462c0aa92735fca4993cc04e4 (patch)
treec53a78b1019f189e77a806d8f9f6fcca056b4d23
parenta24a2af95e22cce759da46bf9a2e8a2687d3611d (diff)
Deduce the perf header sizes from the actual data
The magic constants will only work as long as the header doesn't grow. Change-Id: Ib931363b440da83646bbb57e8b3ea574b303a52f Reviewed-by: Milian Wolff <milian.wolff@kdab.com>
-rw-r--r--app/perfheader.cpp42
-rw-r--r--app/perfheader.h9
2 files changed, 41 insertions, 10 deletions
diff --git a/app/perfheader.cpp b/app/perfheader.cpp
index d08d6c3..369b611 100644
--- a/app/perfheader.cpp
+++ b/app/perfheader.cpp
@@ -36,14 +36,13 @@ void PerfHeader::read()
QDataStream stream(m_source);
if (m_size == 0) {
- const auto expectedSize = static_cast<qint64>(sizeof(m_magic) + sizeof(m_size));
- if (!m_source->isSequential() && m_source->size() < expectedSize) {
+ if (!m_source->isSequential() && m_source->size() < pipeHeaderFixedLength()) {
qWarning() << "File is too small for perf header.";
emit error();
return;
}
- if (m_source->bytesAvailable() < expectedSize)
+ if (m_source->bytesAvailable() < pipeHeaderFixedLength())
return;
stream >> m_magic;
@@ -59,15 +58,21 @@ void PerfHeader::read()
stream >> m_size;
}
- if (m_size == s_perfHeaderSize) {
- if (!m_source->isSequential() && m_source->size() < static_cast<qint64>(m_size)) {
+ if (m_size < pipeHeaderFixedLength()) {
+ qWarning() << "Header claims to be smaller than magic + size:" << m_size;
+ emit error();
+ return;
+ } else if (m_size > pipeHeaderFixedLength()) {
+ // read extended header information only available in perf.data files,
+ // not in piped perf streams
+
+ if (!m_source->isSequential() && m_source->size() < fileHeaderFixedLength()) {
qWarning() << "File is too small for perf header.";
emit error();
return;
}
- if (m_source->bytesAvailable()
- < m_size - static_cast<qint64>(sizeof(m_magic) + sizeof(m_size)))
+ if (m_source->bytesAvailable() < fileHeaderFixedLength() - pipeHeaderFixedLength())
return;
// file header
@@ -96,6 +101,16 @@ void PerfHeader::read()
emit error();
return;
}
+
+ if (m_size > fileHeaderFixedLength()) {
+ if (m_size > std::numeric_limits<int>::max()) {
+ qWarning() << "Excessively large perf file header:" << m_size;
+ emit error();
+ return;
+ }
+ qWarning() << "Header not completely read.";
+ stream.skipRawData(static_cast<int>(m_size) - fileHeaderFixedLength());
+ }
} else {
// pipe header, anything to do here?
}
@@ -105,6 +120,19 @@ void PerfHeader::read()
emit finished();
}
+quint16 PerfHeader::pipeHeaderFixedLength()
+{
+ return sizeof(m_magic) + sizeof(m_size);
+}
+
+quint16 PerfHeader::fileHeaderFixedLength()
+{
+ return pipeHeaderFixedLength()
+ + sizeof(m_attrSize)
+ + 3 * PerfFileSection::fixedLength() // m_attrs, m_data, m_eventTypes
+ + sizeof(m_features);
+}
+
QDataStream::ByteOrder PerfHeader::byteOrder() const
{
// magic is read in QDataStream's default big endian mode
diff --git a/app/perfheader.h b/app/perfheader.h
index 47d7a5f..32e41b4 100644
--- a/app/perfheader.h
+++ b/app/perfheader.h
@@ -69,7 +69,9 @@ public:
qint64 featureOffset() const { return m_data.offset + m_data.size; }
qint64 dataOffset() const { return m_data.offset; }
qint64 dataSize() const { return m_data.size; }
- bool isPipe() const { return m_size == s_pipeHeaderSize; }
+ bool isPipe() const { return m_size == pipeHeaderFixedLength(); }
+
+ qint64 size() const { return m_size; }
public slots:
void read();
@@ -79,6 +81,9 @@ signals:
void error();
private:
+ static quint16 fileHeaderFixedLength();
+ static quint16 pipeHeaderFixedLength();
+
QIODevice *m_source;
qint64 m_magic;
@@ -93,6 +98,4 @@ private:
static const qint64 s_magicSame = 0x32454c4946524550LL;
static const qint64 s_magicSwitched = 0x50455246494c4532LL;
- static const qint64 s_pipeHeaderSize = 16LL;
- static const qint64 s_perfHeaderSize = 104LL;
};