diff options
author | Marco Bubke <[email protected]> | 2018-02-08 15:12:00 +0100 |
---|---|---|
committer | Marco Bubke <[email protected]> | 2018-02-22 10:23:51 +0000 |
commit | 1a4c51d15f927984f62fea0a322919846e978906 (patch) | |
tree | 33cd5b0318d4f4b78b50a8397836ebcdced91c04 | |
parent | 6922f549d58e777020586c9572a4bcee49a7b778 (diff) |
Clang: Prevent segmentation fault in WriteMessageBlock
There could be already messages send before the backend is available. In
that case we now record that messages and send them if the socket is set.
Task-number: QTCREATORBUG-19761
Change-Id: I7c8d6fdb4fcc043bcdbb9e9aeb5752f89c24fdab
Reviewed-by: Ivan Donchevskii <[email protected]>
-rw-r--r-- | src/libs/clangsupport/baseserverproxy.cpp | 6 | ||||
-rw-r--r-- | src/libs/clangsupport/baseserverproxy.h | 2 | ||||
-rw-r--r-- | src/libs/clangsupport/clangcodemodelconnectionclient.cpp | 4 | ||||
-rw-r--r-- | src/libs/clangsupport/clangcodemodelconnectionclient.h | 2 | ||||
-rw-r--r-- | src/libs/clangsupport/connectionclient.cpp | 2 | ||||
-rw-r--r-- | src/libs/clangsupport/connectionclient.h | 2 | ||||
-rw-r--r-- | src/libs/clangsupport/readmessageblock.cpp | 2 | ||||
-rw-r--r-- | src/libs/clangsupport/readmessageblock.h | 2 | ||||
-rw-r--r-- | src/libs/clangsupport/writemessageblock.cpp | 27 | ||||
-rw-r--r-- | src/libs/clangsupport/writemessageblock.h | 6 | ||||
-rw-r--r-- | src/plugins/clangpchmanager/pchmanagerconnectionclient.cpp | 4 | ||||
-rw-r--r-- | src/plugins/clangpchmanager/pchmanagerconnectionclient.h | 2 | ||||
-rw-r--r-- | src/plugins/clangrefactoring/refactoringconnectionclient.cpp | 4 | ||||
-rw-r--r-- | src/plugins/clangrefactoring/refactoringconnectionclient.h | 2 | ||||
-rw-r--r-- | tests/unit/unittest/readandwritemessageblock-test.cpp | 58 |
15 files changed, 99 insertions, 26 deletions
diff --git a/src/libs/clangsupport/baseserverproxy.cpp b/src/libs/clangsupport/baseserverproxy.cpp index 2c9f3071fd0..6f563ffd9de 100644 --- a/src/libs/clangsupport/baseserverproxy.cpp +++ b/src/libs/clangsupport/baseserverproxy.cpp @@ -45,10 +45,10 @@ void BaseServerProxy::readMessages() m_client->dispatch(message); } -void BaseServerProxy::resetCounter() +void BaseServerProxy::resetState() { - m_writeMessageBlock.resetCounter(); - m_readMessageBlock.resetCounter(); + m_writeMessageBlock.resetState(); + m_readMessageBlock.resetState(); } void BaseServerProxy::setIoDevice(QIODevice *ioDevice) diff --git a/src/libs/clangsupport/baseserverproxy.h b/src/libs/clangsupport/baseserverproxy.h index 2211f9da256..eee427b3a62 100644 --- a/src/libs/clangsupport/baseserverproxy.h +++ b/src/libs/clangsupport/baseserverproxy.h @@ -41,7 +41,7 @@ public: void readMessages(); - void resetCounter(); + void resetState(); void setIoDevice(QIODevice *ioDevice); diff --git a/src/libs/clangsupport/clangcodemodelconnectionclient.cpp b/src/libs/clangsupport/clangcodemodelconnectionclient.cpp index 1bfa5678839..1938d063537 100644 --- a/src/libs/clangsupport/clangcodemodelconnectionclient.cpp +++ b/src/libs/clangsupport/clangcodemodelconnectionclient.cpp @@ -69,9 +69,9 @@ void ClangCodeModelConnectionClient::sendEndCommand() m_serverProxy.end(); } -void ClangCodeModelConnectionClient::resetCounter() +void ClangCodeModelConnectionClient::resetState() { - m_serverProxy.resetCounter(); + m_serverProxy.resetState(); } QString ClangCodeModelConnectionClient::outputName() const diff --git a/src/libs/clangsupport/clangcodemodelconnectionclient.h b/src/libs/clangsupport/clangcodemodelconnectionclient.h index ac7afa678a7..c1618b06d95 100644 --- a/src/libs/clangsupport/clangcodemodelconnectionclient.h +++ b/src/libs/clangsupport/clangcodemodelconnectionclient.h @@ -39,7 +39,7 @@ public: protected: void sendEndCommand() override; - void resetCounter() override; + void resetState() override; QString outputName() const override; void newConnectedServer(QIODevice *ioDevice) override; diff --git a/src/libs/clangsupport/connectionclient.cpp b/src/libs/clangsupport/connectionclient.cpp index 2a3ec8af30e..bdbedab5c07 100644 --- a/src/libs/clangsupport/connectionclient.cpp +++ b/src/libs/clangsupport/connectionclient.cpp @@ -267,7 +267,7 @@ void ConnectionClient::finishProcess(QProcessUniquePointer &&process) terminateProcess(process.get()); killProcess(process.get()); - resetCounter(); + resetState(); } else { finishConnection(); } diff --git a/src/libs/clangsupport/connectionclient.h b/src/libs/clangsupport/connectionclient.h index 45797bd8922..13636ab8bfe 100644 --- a/src/libs/clangsupport/connectionclient.h +++ b/src/libs/clangsupport/connectionclient.h @@ -89,7 +89,7 @@ protected: LinePrefixer &stdOutPrefixer(); virtual void sendEndCommand() = 0; - virtual void resetCounter() = 0; + virtual void resetState() = 0; virtual QString outputName() const = 0; QString connectionName() const; diff --git a/src/libs/clangsupport/readmessageblock.cpp b/src/libs/clangsupport/readmessageblock.cpp index 9c93934eaf6..e08406c1338 100644 --- a/src/libs/clangsupport/readmessageblock.cpp +++ b/src/libs/clangsupport/readmessageblock.cpp @@ -92,7 +92,7 @@ std::vector<MessageEnvelop> ReadMessageBlock::readAll() Q_UNREACHABLE(); } -void ReadMessageBlock::resetCounter() +void ReadMessageBlock::resetState() { m_messageCounter = 0; } diff --git a/src/libs/clangsupport/readmessageblock.h b/src/libs/clangsupport/readmessageblock.h index 6e838e0b485..391d89b751d 100644 --- a/src/libs/clangsupport/readmessageblock.h +++ b/src/libs/clangsupport/readmessageblock.h @@ -46,7 +46,7 @@ public: MessageEnvelop read(); std::vector<MessageEnvelop> readAll(); - void resetCounter(); + void resetState(); void setIoDevice(QIODevice *ioDevice); diff --git a/src/libs/clangsupport/writemessageblock.cpp b/src/libs/clangsupport/writemessageblock.cpp index fe5ef43a375..999c63e9b1f 100644 --- a/src/libs/clangsupport/writemessageblock.cpp +++ b/src/libs/clangsupport/writemessageblock.cpp @@ -42,9 +42,9 @@ WriteMessageBlock::WriteMessageBlock(QIODevice *ioDevice) void WriteMessageBlock::write(const MessageEnvelop &message) { - QByteArray block; - QDataStream out(&block, QIODevice::WriteOnly); + QDataStream out(&m_block, QIODevice::WriteOnly | QIODevice::Append); + int startOffset = m_block.size(); const qint32 dummyBockSize = 0; out << dummyBockSize; @@ -52,14 +52,12 @@ void WriteMessageBlock::write(const MessageEnvelop &message) out << message; - out.device()->seek(0); - out << qint32(block.size() - sizeof(qint32)); + out.device()->seek(startOffset); + out << qint32(m_block.size() - startOffset - sizeof(qint32)); ++m_messageCounter; - const qint64 bytesWritten = m_ioDevice->write(block); - if (bytesWritten == -1) - qWarning() << "Failed to write data:" << m_ioDevice->errorString(); + flushBlock(); } qint64 WriteMessageBlock::counter() const @@ -67,14 +65,27 @@ qint64 WriteMessageBlock::counter() const return m_messageCounter; } -void WriteMessageBlock::resetCounter() +void WriteMessageBlock::resetState() { + m_block.clear(); m_messageCounter = 0; } void WriteMessageBlock::setIoDevice(QIODevice *ioDevice) { m_ioDevice = ioDevice; + + flushBlock(); +} + +void WriteMessageBlock::flushBlock() +{ + if (m_ioDevice) { + const qint64 bytesWritten = m_ioDevice->write(m_block); + m_block.clear(); + if (bytesWritten == -1) + qWarning() << "Failed to write data:" << m_ioDevice->errorString(); + } } } // namespace ClangBackEnd diff --git a/src/libs/clangsupport/writemessageblock.h b/src/libs/clangsupport/writemessageblock.h index d7b4aca204c..b75f0ce2944 100644 --- a/src/libs/clangsupport/writemessageblock.h +++ b/src/libs/clangsupport/writemessageblock.h @@ -25,6 +25,7 @@ #pragma once +#include <QByteArray> #include <QtGlobal> QT_BEGIN_NAMESPACE @@ -46,11 +47,14 @@ public: qint64 counter() const; - void resetCounter(); + void resetState(); void setIoDevice(QIODevice *ioDevice); + void flushBlock(); + private: + QByteArray m_block; qint64 m_messageCounter; QIODevice *m_ioDevice; }; diff --git a/src/plugins/clangpchmanager/pchmanagerconnectionclient.cpp b/src/plugins/clangpchmanager/pchmanagerconnectionclient.cpp index 41c17b04549..8528583201f 100644 --- a/src/plugins/clangpchmanager/pchmanagerconnectionclient.cpp +++ b/src/plugins/clangpchmanager/pchmanagerconnectionclient.cpp @@ -72,9 +72,9 @@ void ClangPchManager::PchManagerConnectionClient::sendEndCommand() m_serverProxy.end(); } -void PchManagerConnectionClient::resetCounter() +void PchManagerConnectionClient::resetState() { - m_serverProxy.resetCounter(); + m_serverProxy.resetState(); } QString PchManagerConnectionClient::outputName() const diff --git a/src/plugins/clangpchmanager/pchmanagerconnectionclient.h b/src/plugins/clangpchmanager/pchmanagerconnectionclient.h index 1566b08f47c..672b6ef7cff 100644 --- a/src/plugins/clangpchmanager/pchmanagerconnectionclient.h +++ b/src/plugins/clangpchmanager/pchmanagerconnectionclient.h @@ -40,7 +40,7 @@ public: protected: void sendEndCommand() override; - void resetCounter() override; + void resetState() override; QString outputName() const override; void newConnectedServer(QIODevice *ioDevice) override; diff --git a/src/plugins/clangrefactoring/refactoringconnectionclient.cpp b/src/plugins/clangrefactoring/refactoringconnectionclient.cpp index aacbb9810fc..865c9d53d13 100644 --- a/src/plugins/clangrefactoring/refactoringconnectionclient.cpp +++ b/src/plugins/clangrefactoring/refactoringconnectionclient.cpp @@ -71,9 +71,9 @@ void RefactoringConnectionClient::sendEndCommand() m_serverProxy.end(); } -void RefactoringConnectionClient::resetCounter() +void RefactoringConnectionClient::resetState() { - m_serverProxy.resetCounter(); + m_serverProxy.resetState(); } QString RefactoringConnectionClient::outputName() const diff --git a/src/plugins/clangrefactoring/refactoringconnectionclient.h b/src/plugins/clangrefactoring/refactoringconnectionclient.h index 55c9270ecca..16734f7ed97 100644 --- a/src/plugins/clangrefactoring/refactoringconnectionclient.h +++ b/src/plugins/clangrefactoring/refactoringconnectionclient.h @@ -42,7 +42,7 @@ public: protected: void sendEndCommand() override; - void resetCounter() override; + void resetState() override; QString outputName() const override; void newConnectedServer(QIODevice *ioDevice) override; diff --git a/tests/unit/unittest/readandwritemessageblock-test.cpp b/tests/unit/unittest/readandwritemessageblock-test.cpp index 656ef60e9ec..35c09bf0653 100644 --- a/tests/unit/unittest/readandwritemessageblock-test.cpp +++ b/tests/unit/unittest/readandwritemessageblock-test.cpp @@ -122,6 +122,64 @@ TEST_F(ReadAndWriteMessageBlock, ReadThreeMessagesAndTestCount) ASSERT_THAT(readMessageBlock.readAll(), SizeIs(3)); } +TEST_F(ReadAndWriteMessageBlock, WriteMessagesToWriteBlockWithoutIoDeviceAndNoMessagesAreSent) +{ + ClangBackEnd::WriteMessageBlock writeMessageBlock; + + writeMessageBlock.write(ClangBackEnd::EndMessage()); + writeMessageBlock.write(ClangBackEnd::EndMessage()); + buffer.seek(0); + + ASSERT_THAT(readMessageBlock.readAll(), IsEmpty()); +} + +TEST_F(ReadAndWriteMessageBlock, WriteMessagesToWriteBlockWithoutIoDeviceAndSetIoDeviceToNullPointerLater) +{ + ClangBackEnd::WriteMessageBlock writeMessageBlock; + writeMessageBlock.write(ClangBackEnd::EndMessage()); + writeMessageBlock.write(ClangBackEnd::EndMessage()); + + writeMessageBlock.setIoDevice(nullptr); + buffer.seek(0); + + ASSERT_THAT(readMessageBlock.readAll(), IsEmpty()); +} + +TEST_F(ReadAndWriteMessageBlock, WriteMessagesToWriteBlockWithoutIoDeviceAndSetIoDeviceLater) +{ + ClangBackEnd::WriteMessageBlock writeMessageBlock; + writeMessageBlock.write(ClangBackEnd::EndMessage()); + writeMessageBlock.write(ClangBackEnd::EndMessage()); + + writeMessageBlock.setIoDevice(&buffer); + buffer.seek(0); + + ASSERT_THAT(readMessageBlock.readAll(), SizeIs(2)); +} + +TEST_F(ReadAndWriteMessageBlock, ResetStateResetsCounter) +{ + writeMessageBlock.write(ClangBackEnd::EndMessage()); + writeMessageBlock.write(ClangBackEnd::EndMessage()); + buffer.seek(0); + + writeMessageBlock.resetState(); + + ASSERT_THAT(writeMessageBlock.counter(), 0); +} + +TEST_F(ReadAndWriteMessageBlock, ResetStateResetsWritingBlock) +{ + ClangBackEnd::WriteMessageBlock writeMessageBlock; + writeMessageBlock.write(ClangBackEnd::EndMessage()); + + writeMessageBlock.resetState(); + + writeMessageBlock.setIoDevice(&buffer); + buffer.seek(0); + ASSERT_THAT(readMessageBlock.readAll(), IsEmpty()); +} + TEST_F(ReadAndWriteMessageBlock, CompareEndMessage) { CompareMessage(ClangBackEnd::EndMessage()); |