Commit 5219f770 authored by Daniel Vrátil's avatar Daniel Vrátil 🤖

DataStream: throw exception if device is null

During Connection destruction it can happen that the socket is
deleted, but the actual handler is still running and tries to
write to that socket (in which case it passes a nullptr to
DataStream). This is caused by the issue described in #376822.

To prevent the crash in this case (until the root cause is fixed)
the DataStream throws an exception if its used without a valid
device. This will effectively cause execution to leave the Handler
and return.

BUG: 376385
FIXED-IN: 5.4.3
parent 3557b70d
......@@ -59,6 +59,8 @@ void DataStream::setWaitTimeout(int timeout)
void DataStream::waitForData(quint32 size)
{
checkDevice();
while (mDev->bytesAvailable() < size) {
if (!mDev->waitForReadyRead(mWaitTimeout)) {
throw ProtocolException("Timeout while waiting for data");
......@@ -68,7 +70,7 @@ void DataStream::waitForData(quint32 size)
void DataStream::writeRawData(const char *data, int len)
{
Q_ASSERT(mDev);
checkDevice();
int ret = mDev->write(data, len);
if (ret != len) {
......@@ -87,6 +89,7 @@ void DataStream::writeBytes(const char *bytes, int len)
int DataStream::readRawData(char *buffer, int len)
{
Q_ASSERT(mDev);
checkDevice();
return mDev->read(buffer, len);
}
......@@ -75,10 +75,15 @@ public:
void waitForData(quint32 size);
private:
Q_DISABLE_COPY(DataStream)
inline void checkDevice() const
{
if (Q_UNLIKELY(!mDev)) {
throw ProtocolException("Device does not exist");
}
}
QIODevice *mDev;
int mWaitTimeout;
};
......@@ -87,7 +92,7 @@ template<typename T>
inline typename std::enable_if<std::is_integral<T>::value, DataStream>::type
&DataStream::operator<<(T val)
{
Q_ASSERT(mDev);
checkDevice();
if (mDev->write((char *)&val, sizeof(T)) != sizeof(T)) {
throw Akonadi::ProtocolException("Failed to write data to stream");
}
......@@ -103,7 +108,6 @@ inline typename std::enable_if<std::is_enum<T>::value, DataStream>::type
inline DataStream &DataStream::operator<<(const QString &str)
{
Q_ASSERT(mDev);
if (str.isNull()) {
*this << (quint32) 0xffffffff;
} else {
......@@ -114,7 +118,6 @@ inline DataStream &DataStream::operator<<(const QString &str)
inline DataStream &DataStream::operator<<(const QByteArray &data)
{
Q_ASSERT(mDev);
if (data.isNull()) {
*this << (quint32) 0xffffffff;
} else {
......@@ -143,7 +146,8 @@ template<typename T>
inline typename std::enable_if<std::is_integral<T>::value, DataStream>::type
&DataStream::operator>>(T &val)
{
Q_ASSERT(mDev);
checkDevice();
waitForData(sizeof(T));
if (mDev->read((char *)&val, sizeof(T)) != sizeof(T)) {
......
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