diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2018-01-25 11:30:04 +0100 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2018-01-29 10:09:55 +0000 |
commit | d35f2ee49a094d8462c0aa92735fca4993cc04e4 (patch) | |
tree | c53a78b1019f189e77a806d8f9f6fcca056b4d23 | |
parent | a24a2af95e22cce759da46bf9a2e8a2687d3611d (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.cpp | 42 | ||||
-rw-r--r-- | app/perfheader.h | 9 |
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; }; |