From a4d26cf522b966056e47e47a004b7e4d668e3a2d Mon Sep 17 00:00:00 2001 From: Alex Trotsenko Date: Fri, 8 Apr 2016 16:55:39 +0300 Subject: QWindowsPipeWriter: ensure validity of the write buffer QWindowsPipeWriter uses asynchronous API to perform writing. Once a cycle has been started, the write buffer must remain valid until the write operation is completed. To avoid data corruption and possibly undefined behavior, this patch makes QWindowsPipeWriter::write() take a QByteArray, which it keeps alive for the duration of the write cycle. Autotest-by: Thomas Hartmann Task-number: QTBUG-52401 Change-Id: Ia35faee735c4e684267daa1f6bd689512b670cd2 Reviewed-by: Joerg Bornemann --- src/network/socket/qlocalsocket.h | 2 +- src/network/socket/qlocalsocket_p.h | 3 +-- src/network/socket/qlocalsocket_win.cpp | 24 +++++++++--------------- 3 files changed, 11 insertions(+), 18 deletions(-) (limited to 'src/network/socket') diff --git a/src/network/socket/qlocalsocket.h b/src/network/socket/qlocalsocket.h index 09828c8b0d..4b39a7c562 100644 --- a/src/network/socket/qlocalsocket.h +++ b/src/network/socket/qlocalsocket.h @@ -124,7 +124,7 @@ private: Q_PRIVATE_SLOT(d_func(), void _q_stateChanged(QAbstractSocket::SocketState)) Q_PRIVATE_SLOT(d_func(), void _q_error(QAbstractSocket::SocketError)) #elif defined(Q_OS_WIN) - Q_PRIVATE_SLOT(d_func(), void _q_bytesWritten(qint64)) + Q_PRIVATE_SLOT(d_func(), void _q_canWrite()) Q_PRIVATE_SLOT(d_func(), void _q_pipeClosed()) Q_PRIVATE_SLOT(d_func(), void _q_winError(ulong, const QString &)) #else diff --git a/src/network/socket/qlocalsocket_p.h b/src/network/socket/qlocalsocket_p.h index a594605ae0..5e9a07be82 100644 --- a/src/network/socket/qlocalsocket_p.h +++ b/src/network/socket/qlocalsocket_p.h @@ -124,8 +124,7 @@ public: ~QLocalSocketPrivate(); void destroyPipeHandles(); void setErrorString(const QString &function); - void startNextWrite(); - void _q_bytesWritten(qint64 bytes); + void _q_canWrite(); void _q_pipeClosed(); void _q_winError(ulong windowsError, const QString &function); HANDLE handle; diff --git a/src/network/socket/qlocalsocket_win.cpp b/src/network/socket/qlocalsocket_win.cpp index 4507c98835..99c8c77ed8 100644 --- a/src/network/socket/qlocalsocket_win.cpp +++ b/src/network/socket/qlocalsocket_win.cpp @@ -212,11 +212,12 @@ qint64 QLocalSocket::writeData(const char *data, qint64 len) memcpy(dest, data, len); if (!d->pipeWriter) { d->pipeWriter = new QWindowsPipeWriter(d->handle, this); - QObjectPrivate::connect(d->pipeWriter, &QWindowsPipeWriter::bytesWritten, - d, &QLocalSocketPrivate::_q_bytesWritten); + connect(d->pipeWriter, &QWindowsPipeWriter::bytesWritten, + this, &QLocalSocket::bytesWritten); + QObjectPrivate::connect(d->pipeWriter, &QWindowsPipeWriter::canWrite, + d, &QLocalSocketPrivate::_q_canWrite); } - if (!d->pipeWriter->isWriteOperationActive()) - d->startNextWrite(); + d->_q_canWrite(); return len; } @@ -269,7 +270,7 @@ qint64 QLocalSocket::bytesAvailable() const qint64 QLocalSocket::bytesToWrite() const { Q_D(const QLocalSocket); - return d->writeBuffer.size(); + return d->writeBuffer.size() + (d->pipeWriter ? d->pipeWriter->bytesToWrite() : 0); } bool QLocalSocket::canReadLine() const @@ -352,7 +353,7 @@ bool QLocalSocket::setSocketDescriptor(qintptr socketDescriptor, return true; } -void QLocalSocketPrivate::startNextWrite() +void QLocalSocketPrivate::_q_canWrite() { Q_Q(QLocalSocket); if (writeBuffer.isEmpty()) { @@ -360,18 +361,11 @@ void QLocalSocketPrivate::startNextWrite() q->close(); } else { Q_ASSERT(pipeWriter); - pipeWriter->write(writeBuffer.readPointer(), writeBuffer.nextDataBlockSize()); + if (!pipeWriter->isWriteOperationActive()) + pipeWriter->write(writeBuffer.read()); } } -void QLocalSocketPrivate::_q_bytesWritten(qint64 bytes) -{ - Q_Q(QLocalSocket); - writeBuffer.free(bytes); - startNextWrite(); - emit q->bytesWritten(bytes); -} - qintptr QLocalSocket::socketDescriptor() const { Q_D(const QLocalSocket); -- cgit v1.2.3