From 02e448784543df2d81135ac583c39df6237dac69 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 10 Apr 2015 23:18:23 -0700 Subject: Correct calculation of filesystem data on unusual filesystems POSIX.1 says f_blocks, f_bfree, f_bavail are calculated in terms of f_frsize, not of the regular block size f_bsize. On most systems, it's the same, which is why we didn't catch it. I don't have any filesystem to test this on to confirm. Reference: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_statvfs.h.html Task-number: QTBUG-45137 Change-Id: I27eaacb532114dd188c4ffff13d3e13016bed4e6 Reviewed-by: Dmitry Shachnev Reviewed-by: Allan Sandfeld Jensen Reviewed-by: Ivan Komissarov --- src/corelib/io/qstorageinfo_unix.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/corelib/io/qstorageinfo_unix.cpp b/src/corelib/io/qstorageinfo_unix.cpp index 2a83e87b0c..cd3c60650e 100644 --- a/src/corelib/io/qstorageinfo_unix.cpp +++ b/src/corelib/io/qstorageinfo_unix.cpp @@ -416,9 +416,9 @@ void QStorageInfoPrivate::retreiveVolumeInfo() valid = true; ready = true; - bytesTotal = statfs_buf.f_blocks * statfs_buf.f_bsize; - bytesFree = statfs_buf.f_bfree * statfs_buf.f_bsize; - bytesAvailable = statfs_buf.f_bavail * statfs_buf.f_bsize; + bytesTotal = statfs_buf.f_blocks * statfs_buf.f_frsize; + bytesFree = statfs_buf.f_bfree * statfs_buf.f_frsize; + bytesAvailable = statfs_buf.f_bavail * statfs_buf.f_frsize; #if defined(Q_OS_ANDROID) #if defined(_STATFS_F_FLAGS) readOnly = (statfs_buf.f_flags & ST_RDONLY) != 0; -- cgit v1.2.3 From 18a3b431678e3b456c33a9f7ae21d8653dd2ef85 Mon Sep 17 00:00:00 2001 From: Samuel Gaist Date: Mon, 27 Apr 2015 01:22:36 +0200 Subject: Update QProcess doc to use non-deprecated setProcessEnvironment Currently the documentation still mentions the use of the deprected setEnvironment function. This patch aims to correct that Task-number: QTBUG-45235 Change-Id: Iab35754b39f025c7493a6f061eb72e23bc4cf308 Reviewed-by: Oswald Buddenhagen --- src/corelib/io/qprocess.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp index baba9a0f9e..4d2a75c0fa 100644 --- a/src/corelib/io/qprocess.cpp +++ b/src/corelib/io/qprocess.cpp @@ -373,8 +373,8 @@ QString QProcessEnvironment::value(const QString &name, const QString &defaultVa Use with the QProcess::setEnvironment function is not recommended due to potential encoding problems under Unix, and worse performance. - \sa systemEnvironment(), QProcess::systemEnvironment(), QProcess::environment(), - QProcess::setEnvironment() + \sa systemEnvironment(), QProcess::systemEnvironment(), + QProcess::setProcessEnvironment() */ QStringList QProcessEnvironment::toStringList() const { @@ -534,7 +534,7 @@ void QProcessPrivate::Channel::clear() Certain processes need special environment settings in order to operate. You can set environment variables for your process by - calling setEnvironment(). To set a working directory, call + calling setProcessEnvironment(). To set a working directory, call setWorkingDirectory(). By default, processes are run in the current working directory of the calling process. @@ -2471,7 +2471,7 @@ QT_END_INCLUDE_NAMESPACE \note For new code, it is recommended to use QProcessEnvironment::systemEnvironment() - \sa QProcessEnvironment::systemEnvironment(), environment(), setEnvironment() + \sa QProcessEnvironment::systemEnvironment(), setProcessEnvironment() */ QStringList QProcess::systemEnvironment() { -- cgit v1.2.3 From 2cb17c1fb903434274e58692c9f0df619affdab0 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Mon, 18 May 2015 11:29:31 +0200 Subject: Improve documentation for Qt::ItemNeverHasChildren. Change-Id: Ied817314d6e72f08a81138bd817c8570d586fa30 Reviewed-by: Oswald Buddenhagen Reviewed-by: David Faure Reviewed-by: Martin Smith Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/global/qnamespace.qdoc | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc index 3f9526c788..87056b79f0 100644 --- a/src/corelib/global/qnamespace.qdoc +++ b/src/corelib/global/qnamespace.qdoc @@ -2562,6 +2562,7 @@ \value ItemIsEnabled The user can interact with the item. \value ItemIsTristate The item is checkable with three separate states. \value ItemNeverHasChildren The item never has child items. + This is used for optimization purposes only. Note that checkable items need to be given both a suitable set of flags and an initial state, indicating whether the item is checked or not. -- cgit v1.2.3 From d1ce29557cea3a4f23c400a5cb03254f6cf31dc5 Mon Sep 17 00:00:00 2001 From: David Edmundson Date: Tue, 24 Feb 2015 12:36:54 +0100 Subject: Make QStyle::itemPixmapRect handle devicePixelRatio MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Layout sizes for images should be in the form QSize layoutSize = image.size() / image.devicePixelRatio() to be in device independent pixels Change-Id: Ic149144c45c8fa5c45ac5cbe2c82c35d721549cd Reviewed-by: Morten Johan Sørvig --- src/widgets/styles/qstyle.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/widgets/styles/qstyle.cpp b/src/widgets/styles/qstyle.cpp index 6072842fc9..5c0064c7a4 100644 --- a/src/widgets/styles/qstyle.cpp +++ b/src/widgets/styles/qstyle.cpp @@ -541,17 +541,21 @@ QRect QStyle::itemPixmapRect(const QRect &rect, int alignment, const QPixmap &pi QRect result; int x, y, w, h; rect.getRect(&x, &y, &w, &h); + + const int pixmapWidth = pixmap.width()/pixmap.devicePixelRatio(); + const int pixmapHeight = pixmap.height()/pixmap.devicePixelRatio(); + if ((alignment & Qt::AlignVCenter) == Qt::AlignVCenter) - y += h/2 - pixmap.height()/2; + y += h/2 - pixmapHeight/2; else if ((alignment & Qt::AlignBottom) == Qt::AlignBottom) - y += h - pixmap.height(); + y += h - pixmapHeight; if ((alignment & Qt::AlignRight) == Qt::AlignRight) - x += w - pixmap.width(); + x += w - pixmapWidth; else if ((alignment & Qt::AlignHCenter) == Qt::AlignHCenter) - x += w/2 - pixmap.width()/2; + x += w/2 - pixmapWidth/2; else if ((alignment & Qt::AlignLeft) != Qt::AlignLeft && QApplication::isRightToLeft()) - x += w - pixmap.width(); - result = QRect(x, y, pixmap.width(), pixmap.height()); + x += w - pixmapWidth; + result = QRect(x, y, pixmapWidth, pixmapHeight); return result; } -- cgit v1.2.3 From 34014406baaeac3e9d49d5654ef57ac6540a17a8 Mon Sep 17 00:00:00 2001 From: Evgeniy Fominov Date: Mon, 16 Feb 2015 14:36:54 +0100 Subject: quote QUuid values Task-number: QTBUG-44480 Change-Id: I125ab913c867758d958a2774ad125533d6a07a83 Reviewed-by: Evgeniy Fominov Reviewed-by: Mark Brand --- src/sql/drivers/psql/qsql_psql.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/sql/drivers/psql/qsql_psql.cpp b/src/sql/drivers/psql/qsql_psql.cpp index 4268ea06f6..32f6e317d8 100644 --- a/src/sql/drivers/psql/qsql_psql.cpp +++ b/src/sql/drivers/psql/qsql_psql.cpp @@ -1320,6 +1320,9 @@ QString QPSQLDriver::formatValue(const QSqlField &field, bool trimStrings) const } break; } + case QVariant::Uuid: + r = QLatin1Char('\'') + field.value().toString() + QLatin1Char('\''); + break; default: r = QSqlDriver::formatValue(field, trimStrings); break; -- cgit v1.2.3 From d82d5b1c43b270ef6f4f0d90ce5d7d96ea0b7a97 Mon Sep 17 00:00:00 2001 From: Mikhail Lappo Date: Wed, 3 Jun 2015 10:09:42 +0300 Subject: Check for integer overflows in places where qAllocMore is used Task-number: QTBUG-41230 Change-Id: Ic2167364e326092482657f2d2b4ab6ad3e5af631 (partially cherry-picked from 880986be2357a1f80827d038d770dc2f80300201) Reviewed-by: Thiago Macieira --- src/corelib/tools/qarraydata.cpp | 16 ++++++++++++++-- src/corelib/tools/qbytearray.cpp | 7 +++++-- src/corelib/tools/qlist.cpp | 2 ++ src/corelib/tools/qstring.cpp | 5 ++++- src/corelib/tools/qtools_p.h | 6 ++++++ src/gui/text/qfragmentmap_p.h | 2 ++ 6 files changed, 33 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/corelib/tools/qarraydata.cpp b/src/corelib/tools/qarraydata.cpp index 98c484c1dd..d060ff84f2 100644 --- a/src/corelib/tools/qarraydata.cpp +++ b/src/corelib/tools/qarraydata.cpp @@ -85,8 +85,20 @@ QArrayData *QArrayData::allocate(size_t objectSize, size_t alignment, headerSize += (alignment - Q_ALIGNOF(QArrayData)); // Allocate additional space if array is growing - if (options & Grow) - capacity = qAllocMore(int(objectSize * capacity), int(headerSize)) / int(objectSize); + if (options & Grow) { + + // Guard against integer overflow when multiplying. + if (capacity > std::numeric_limits::max() / objectSize) + return 0; + + size_t alloc = objectSize * capacity; + + // Make sure qAllocMore won't overflow. + if (headerSize > size_t(MaxAllocSize) || alloc > size_t(MaxAllocSize) - headerSize) + return 0; + + capacity = qAllocMore(int(alloc), int(headerSize)) / int(objectSize); + } size_t allocSize = headerSize + objectSize * capacity; diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp index 5ec8c317e8..1e87f7b023 100644 --- a/src/corelib/tools/qbytearray.cpp +++ b/src/corelib/tools/qbytearray.cpp @@ -64,7 +64,7 @@ int qFindByteArray( int qAllocMore(int alloc, int extra) Q_DECL_NOTHROW { Q_ASSERT(alloc >= 0 && extra >= 0); - Q_ASSERT_X(uint(alloc) < QByteArray::MaxSize, "qAllocMore", "Requested size is too large!"); + Q_ASSERT_X(alloc <= MaxAllocSize - extra, "qAllocMore", "Requested size is too large!"); unsigned nalloc = qNextPowerOfTwo(alloc + extra); @@ -1495,8 +1495,11 @@ void QByteArray::reallocData(uint alloc, Data::AllocationOptions options) Data::deallocate(d); d = x; } else { - if (options & Data::Grow) + if (options & Data::Grow) { + if (alloc > uint(MaxAllocSize) - uint(sizeof(Data))) + qBadAlloc(); alloc = qAllocMore(alloc, sizeof(Data)); + } Data *x = static_cast(::realloc(d, sizeof(Data) + alloc)); Q_CHECK_PTR(x); x->alloc = alloc; diff --git a/src/corelib/tools/qlist.cpp b/src/corelib/tools/qlist.cpp index fe5e0f33b4..b91fd38a5f 100644 --- a/src/corelib/tools/qlist.cpp +++ b/src/corelib/tools/qlist.cpp @@ -55,6 +55,8 @@ const QListData::Data QListData::shared_null = { Q_REFCOUNT_INITIALIZE_STATIC, 0 static int grow(int size) { + if (size_t(size) > (MaxAllocSize - QListData::DataHeaderSize) / sizeof(void *)) + qBadAlloc(); // dear compiler: don't optimize me out. volatile int x = qAllocMore(size * sizeof(void *), QListData::DataHeaderSize) / sizeof(void *); return x; diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index 189caf8bd7..96f3c4147c 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -1656,8 +1656,11 @@ void QString::resize(int size) void QString::reallocData(uint alloc, bool grow) { - if (grow) + if (grow) { + if (alloc > (uint(MaxAllocSize) - sizeof(Data)) / sizeof(QChar)) + qBadAlloc(); alloc = qAllocMore(alloc * sizeof(QChar), sizeof(Data)) / sizeof(QChar); + } if (d->ref.isShared() || IS_RAW_DATA(d)) { Data::AllocationOptions allocOptions(d->capacityReserved ? Data::CapacityReserved : 0); diff --git a/src/corelib/tools/qtools_p.h b/src/corelib/tools/qtools_p.h index 3876d3822c..1e72db1d87 100644 --- a/src/corelib/tools/qtools_p.h +++ b/src/corelib/tools/qtools_p.h @@ -46,9 +46,15 @@ // #include "QtCore/qglobal.h" +#include QT_BEGIN_NAMESPACE +// We typically need an extra bit for qNextPowerOfTwo when determining the next allocation size. +enum { + MaxAllocSize = (1 << (std::numeric_limits::digits - 1)) - 1 +}; + // implemented in qbytearray.cpp int Q_CORE_EXPORT qAllocMore(int alloc, int extra) Q_DECL_NOTHROW; diff --git a/src/gui/text/qfragmentmap_p.h b/src/gui/text/qfragmentmap_p.h index 012d3c25ce..a19e3d9ea3 100644 --- a/src/gui/text/qfragmentmap_p.h +++ b/src/gui/text/qfragmentmap_p.h @@ -249,6 +249,8 @@ uint QFragmentMapData::createFragment() uint freePos = head->freelist; if (freePos == head->allocated) { // need to create some free space + if (freePos >= uint(MaxAllocSize) / fragmentSize) + qBadAlloc(); uint needed = qAllocMore((freePos+1)*fragmentSize, 0); Q_ASSERT(needed/fragmentSize > head->allocated); Fragment *newFragments = (Fragment *)realloc(fragments, needed); -- cgit v1.2.3 From eae0cb09f1310e755c2aff7c1112f7a6c09d7a53 Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Fri, 19 Jun 2015 15:35:34 +0200 Subject: Network: Fix up previous corruption patch This is a fix-up for cff39fba10ffc10ee4dcfdc66ff6528eb26462d3. That patch lead to some internal state issues that lead to the QTBUG-47048 or to QNetworkReply objects erroring with "Connection Closed" when the server closed the Keep-Alive connection. This patch changes the QNAM socket slot connections to be DirectConnection. We don't close the socket anymore in slots where it is anyway in a closed state afterwards. This prevents event/stack recursions. We also flush QSslSocket/QTcpSocket receive buffers when receiving a disconnect so that the developer always gets the full decrypted data from the buffers. [ChangeLog][QtNetwork] Fix HTTP issues with "Unknown Error" and "Connection Closed" [ChangeLog][QtNetwork][Sockets] Read OS/encrypted read buffers when connection closed by server. Change-Id: Ib4d6a2d0d988317e3a5356f36e8dbcee4590beed Task-number: QTBUG-47048 Reviewed-by: Kai Koehne Reviewed-by: Richard J. Moore --- src/network/access/qhttpnetworkconnection.cpp | 1 - .../access/qhttpnetworkconnectionchannel.cpp | 108 +++++++++++++-------- .../access/qhttpnetworkconnectionchannel_p.h | 1 + src/network/access/qhttpnetworkreply.cpp | 2 +- src/network/access/qhttpprotocolhandler.cpp | 1 - src/network/socket/qabstractsocket.cpp | 7 +- src/network/ssl/qsslsocket.cpp | 8 ++ src/network/ssl/qsslsocket_openssl.cpp | 7 ++ 8 files changed, 89 insertions(+), 46 deletions(-) (limited to 'src') diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp index 365ce55f2b..543c70e8b7 100644 --- a/src/network/access/qhttpnetworkconnection.cpp +++ b/src/network/access/qhttpnetworkconnection.cpp @@ -917,7 +917,6 @@ void QHttpNetworkConnectionPrivate::_q_startNextRequest() for (int i = 0; i < channelCount; ++i) { if (channels[i].resendCurrent && (channels[i].state != QHttpNetworkConnectionChannel::ClosingState)) { channels[i].resendCurrent = false; - channels[i].state = QHttpNetworkConnectionChannel::IdleState; // if this is not possible, error will be emitted and connection terminated if (!channels[i].resetUploadData()) diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp index 49c6793b1f..e2f63071e1 100644 --- a/src/network/access/qhttpnetworkconnectionchannel.cpp +++ b/src/network/access/qhttpnetworkconnectionchannel.cpp @@ -58,6 +58,11 @@ QT_BEGIN_NAMESPACE // TODO: Put channel specific stuff here so it does not polute qhttpnetworkconnection.cpp +// Because in-flight when sending a request, the server might close our connection (because the persistent HTTP +// connection times out) +// We use 3 because we can get a _q_error 3 times depending on the timing: +static const int reconnectAttemptsDefault = 3; + QHttpNetworkConnectionChannel::QHttpNetworkConnectionChannel() : socket(0) , ssl(false) @@ -69,7 +74,7 @@ QHttpNetworkConnectionChannel::QHttpNetworkConnectionChannel() , resendCurrent(false) , lastStatus(0) , pendingEncrypt(false) - , reconnectAttempts(2) + , reconnectAttempts(reconnectAttemptsDefault) , authMethod(QAuthenticatorPrivate::None) , proxyAuthMethod(QAuthenticatorPrivate::None) , authenticationCredentialsSent(false) @@ -106,19 +111,18 @@ void QHttpNetworkConnectionChannel::init() socket->setProxy(QNetworkProxy::NoProxy); #endif - // We want all signals (except the interactive ones) be connected as QueuedConnection - // because else we're falling into cases where we recurse back into the socket code - // and mess up the state. Always going to the event loop (and expecting that when reading/writing) - // is safer. + // After some back and forth in all the last years, this is now a DirectConnection because otherwise + // the state inside the *Socket classes gets messed up, also in conjunction with the socket notifiers + // which behave slightly differently on Windows vs Linux QObject::connect(socket, SIGNAL(bytesWritten(qint64)), this, SLOT(_q_bytesWritten(qint64)), - Qt::QueuedConnection); + Qt::DirectConnection); QObject::connect(socket, SIGNAL(connected()), this, SLOT(_q_connected()), - Qt::QueuedConnection); + Qt::DirectConnection); QObject::connect(socket, SIGNAL(readyRead()), this, SLOT(_q_readyRead()), - Qt::QueuedConnection); + Qt::DirectConnection); // The disconnected() and error() signals may already come // while calling connectToHost(). @@ -129,10 +133,10 @@ void QHttpNetworkConnectionChannel::init() qRegisterMetaType(); QObject::connect(socket, SIGNAL(disconnected()), this, SLOT(_q_disconnected()), - Qt::QueuedConnection); + Qt::DirectConnection); QObject::connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(_q_error(QAbstractSocket::SocketError)), - Qt::QueuedConnection); + Qt::DirectConnection); #ifndef QT_NO_NETWORKPROXY @@ -147,13 +151,13 @@ void QHttpNetworkConnectionChannel::init() // won't be a sslSocket if encrypt is false QObject::connect(sslSocket, SIGNAL(encrypted()), this, SLOT(_q_encrypted()), - Qt::QueuedConnection); + Qt::DirectConnection); QObject::connect(sslSocket, SIGNAL(sslErrors(QList)), this, SLOT(_q_sslErrors(QList)), Qt::DirectConnection); QObject::connect(sslSocket, SIGNAL(encryptedBytesWritten(qint64)), this, SLOT(_q_encryptedBytesWritten(qint64)), - Qt::QueuedConnection); + Qt::DirectConnection); if (ignoreAllSslErrors) sslSocket->ignoreSslErrors(); @@ -397,7 +401,7 @@ void QHttpNetworkConnectionChannel::allDone() // reset the reconnection attempts after we receive a complete reply. // in case of failures, each channel will attempt two reconnects before emitting error. - reconnectAttempts = 2; + reconnectAttempts = reconnectAttemptsDefault; // now the channel can be seen as free/idle again, all signal emissions for the reply have been done if (state != QHttpNetworkConnectionChannel::ClosingState) @@ -651,6 +655,15 @@ void QHttpNetworkConnectionChannel::closeAndResendCurrentRequest() QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection); } +void QHttpNetworkConnectionChannel::resendCurrentRequest() +{ + requeueCurrentlyPipelinedRequests(); + if (reply) + resendCurrent = true; + if (qobject_cast(connection)) + QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection); +} + bool QHttpNetworkConnectionChannel::isSocketBusy() const { return (state & QHttpNetworkConnectionChannel::BusyState); @@ -694,8 +707,8 @@ void QHttpNetworkConnectionChannel::_q_disconnected() return; } - // read the available data before closing - if (isSocketWaiting() || isSocketReading()) { + // read the available data before closing (also done in _q_error for other codepaths) + if ((isSocketWaiting() || isSocketReading()) && socket->bytesAvailable()) { if (reply) { state = QHttpNetworkConnectionChannel::ReadingState; _q_receiveReply(); @@ -707,7 +720,8 @@ void QHttpNetworkConnectionChannel::_q_disconnected() state = QHttpNetworkConnectionChannel::IdleState; requeueCurrentlyPipelinedRequests(); - close(); + + pendingEncrypt = false; } @@ -789,11 +803,19 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket errorCode = QNetworkReply::ConnectionRefusedError; break; case QAbstractSocket::RemoteHostClosedError: - // try to reconnect/resend before sending an error. - // while "Reading" the _q_disconnected() will handle this. - if (state != QHttpNetworkConnectionChannel::IdleState && state != QHttpNetworkConnectionChannel::ReadingState) { + // This error for SSL comes twice in a row, first from SSL layer ("The TLS/SSL connection has been closed") then from TCP layer. + // Depending on timing it can also come three times in a row (first time when we try to write into a closing QSslSocket). + // The reconnectAttempts handling catches the cases where we can re-send the request. + if (!reply && state == QHttpNetworkConnectionChannel::IdleState) { + // Not actually an error, it is normal for Keep-Alive connections to close after some time if no request + // is sent on them. No need to error the other replies below. Just bail out here. + // The _q_disconnected will handle the possibly pipelined replies + return; + } else if (state != QHttpNetworkConnectionChannel::IdleState && state != QHttpNetworkConnectionChannel::ReadingState) { + // Try to reconnect/resend before sending an error. + // While "Reading" the _q_disconnected() will handle this. if (reconnectAttempts-- > 0) { - closeAndResendCurrentRequest(); + resendCurrentRequest(); return; } else { errorCode = QNetworkReply::RemoteHostClosedError; @@ -818,24 +840,15 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket // we can ignore the readbuffersize as the data is already // in memory and we will not receive more data on the socket. reply->setReadBufferSize(0); + reply->setDownstreamLimited(false); _q_receiveReply(); -#ifndef QT_NO_SSL - if (ssl) { - // QT_NO_OPENSSL. The QSslSocket can still have encrypted bytes in the plainsocket. - // So we need to check this if the socket is a QSslSocket. When the socket is flushed - // it will force a decrypt of the encrypted data in the plainsocket. - QSslSocket *sslSocket = static_cast(socket); - qint64 beforeFlush = sslSocket->encryptedBytesAvailable(); - while (sslSocket->encryptedBytesAvailable()) { - sslSocket->flush(); - _q_receiveReply(); - qint64 afterFlush = sslSocket->encryptedBytesAvailable(); - if (afterFlush == beforeFlush) - break; - beforeFlush = afterFlush; - } + if (!reply) { + // No more reply assigned after the previous call? Then it had been finished successfully. + requeueCurrentlyPipelinedRequests(); + state = QHttpNetworkConnectionChannel::IdleState; + QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection); + return; } -#endif } errorCode = QNetworkReply::RemoteHostClosedError; @@ -846,7 +859,7 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket case QAbstractSocket::SocketTimeoutError: // try to reconnect/resend before sending an error. if (state == QHttpNetworkConnectionChannel::WritingState && (reconnectAttempts-- > 0)) { - closeAndResendCurrentRequest(); + resendCurrentRequest(); return; } errorCode = QNetworkReply::TimeoutError; @@ -860,7 +873,7 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket case QAbstractSocket::ProxyConnectionClosedError: // try to reconnect/resend before sending an error. if (reconnectAttempts-- > 0) { - closeAndResendCurrentRequest(); + resendCurrentRequest(); return; } errorCode = QNetworkReply::ProxyConnectionClosedError; @@ -868,7 +881,7 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket case QAbstractSocket::ProxyConnectionTimeoutError: // try to reconnect/resend before sending an error. if (reconnectAttempts-- > 0) { - closeAndResendCurrentRequest(); + resendCurrentRequest(); return; } errorCode = QNetworkReply::ProxyTimeoutError; @@ -916,8 +929,18 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket // send the next request QMetaObject::invokeMethod(that, "_q_startNextRequest", Qt::QueuedConnection); - if (that) //signal emission triggered event loop - close(); + if (that) { + //signal emission triggered event loop + if (!socket) + state = QHttpNetworkConnectionChannel::IdleState; + else if (socket->state() == QAbstractSocket::UnconnectedState) + state = QHttpNetworkConnectionChannel::IdleState; + else + state = QHttpNetworkConnectionChannel::ClosingState; + + // pendingEncrypt must only be true in between connected and encrypted states + pendingEncrypt = false; + } } #ifndef QT_NO_NETWORKPROXY @@ -941,7 +964,8 @@ void QHttpNetworkConnectionChannel::_q_proxyAuthenticationRequired(const QNetwor void QHttpNetworkConnectionChannel::_q_uploadDataReadyRead() { - sendRequest(); + if (reply) + sendRequest(); } #ifndef QT_NO_SSL diff --git a/src/network/access/qhttpnetworkconnectionchannel_p.h b/src/network/access/qhttpnetworkconnectionchannel_p.h index 231fe11135..a834b7d645 100644 --- a/src/network/access/qhttpnetworkconnectionchannel_p.h +++ b/src/network/access/qhttpnetworkconnectionchannel_p.h @@ -169,6 +169,7 @@ public: void handleUnexpectedEOF(); void closeAndResendCurrentRequest(); + void resendCurrentRequest(); bool isSocketBusy() const; bool isSocketWriting() const; diff --git a/src/network/access/qhttpnetworkreply.cpp b/src/network/access/qhttpnetworkreply.cpp index 55863a3c88..8b71bd8e70 100644 --- a/src/network/access/qhttpnetworkreply.cpp +++ b/src/network/access/qhttpnetworkreply.cpp @@ -191,7 +191,7 @@ QByteArray QHttpNetworkReply::readAny() return QByteArray(); // we'll take the last buffer, so schedule another read from http - if (d->downstreamLimited && d->responseData.bufferCount() == 1) + if (d->downstreamLimited && d->responseData.bufferCount() == 1 && !isFinished()) d->connection->d_func()->readMoreLater(this); return d->responseData.read(); } diff --git a/src/network/access/qhttpprotocolhandler.cpp b/src/network/access/qhttpprotocolhandler.cpp index 3357948519..380aaacf0c 100644 --- a/src/network/access/qhttpprotocolhandler.cpp +++ b/src/network/access/qhttpprotocolhandler.cpp @@ -250,7 +250,6 @@ bool QHttpProtocolHandler::sendRequest() if (!m_reply) { // heh, how should that happen! qWarning() << "QAbstractProtocolHandler::sendRequest() called without QHttpNetworkReply"; - m_channel->state = QHttpNetworkConnectionChannel::IdleState; return false; } diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp index 26667715be..0e82d4ab66 100644 --- a/src/network/socket/qabstractsocket.cpp +++ b/src/network/socket/qabstractsocket.cpp @@ -768,6 +768,7 @@ bool QAbstractSocketPrivate::canReadNotification() void QAbstractSocketPrivate::canCloseNotification() { Q_Q(QAbstractSocket); + // Note that this method is only called on Windows. Other platforms close in the canReadNotification() #if defined (QABSTRACTSOCKET_DEBUG) qDebug("QAbstractSocketPrivate::canCloseNotification()"); @@ -777,7 +778,11 @@ void QAbstractSocketPrivate::canCloseNotification() if (isBuffered) { // Try to read to the buffer, if the read fail we can close the socket. newBytes = buffer.size(); - if (!readFromSocket()) { + qint64 oldReadBufferMaxSize = readBufferMaxSize; + readBufferMaxSize = 0; // temporarily disable max read buffer, we want to empty the OS buffer + bool hadReadFromSocket = readFromSocket(); + readBufferMaxSize = oldReadBufferMaxSize; + if (!hadReadFromSocket) { q->disconnectFromHost(); return; } diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp index c1fab94fce..2b9e9230e0 100644 --- a/src/network/ssl/qsslsocket.cpp +++ b/src/network/ssl/qsslsocket.cpp @@ -2294,6 +2294,14 @@ void QSslSocketPrivate::_q_errorSlot(QAbstractSocket::SocketError error) qCDebug(lcSsl) << "\tstate =" << q->state(); qCDebug(lcSsl) << "\terrorString =" << q->errorString(); #endif + // this moves encrypted bytes from plain socket into our buffer + if (plainSocket->bytesAvailable()) { + qint64 tmpReadBufferMaxSize = readBufferMaxSize; + readBufferMaxSize = 0; // reset temporarily so the plain sockets completely drained drained + transmit(); + readBufferMaxSize = tmpReadBufferMaxSize; + } + q->setSocketError(plainSocket->error()); q->setErrorString(plainSocket->errorString()); emit q->error(error); diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp index ac4336afcc..94655feb9b 100644 --- a/src/network/ssl/qsslsocket_openssl.cpp +++ b/src/network/ssl/qsslsocket_openssl.cpp @@ -1419,6 +1419,13 @@ void QSslSocketBackendPrivate::disconnected() { if (plainSocket->bytesAvailable() <= 0) destroySslContext(); + else { + // Move all bytes into the plain buffer + qint64 tmpReadBufferMaxSize = readBufferMaxSize; + readBufferMaxSize = 0; // reset temporarily so the plain socket buffer is completely drained + transmit(); + readBufferMaxSize = tmpReadBufferMaxSize; + } //if there is still buffered data in the plain socket, don't destroy the ssl context yet. //it will be destroyed when the socket is deleted. } -- cgit v1.2.3 From 4a1e5dbade4bab55f39bd368480dcca9a11e4b38 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Thu, 9 Jul 2015 09:30:42 +0200 Subject: Better handling of invalid font tables Specifically when reading files with broken cmap tables, we could get some undeterministic results. We handle this more gracefully by verifying that the offsets are sane and bailing out early if not. This replaces the current pattern throughout the font engine for consistency. Change-Id: I507bba49c0be634afca77d1eb3d199a427451bee Reviewed-by: Simon Hausmann Reviewed-by: Thiago Macieira --- src/gui/text/qfontengine.cpp | 212 ++++++++++++++++----- src/gui/text/qfontengine_p.h | 2 +- src/gui/text/qfontengine_qpf2.cpp | 10 +- .../platforms/windows/qwindowsfontengine.cpp | 16 +- src/plugins/platforms/windows/qwindowsfontengine.h | 1 + 5 files changed, 176 insertions(+), 65 deletions(-) (limited to 'src') diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp index b360ed5c85..f973abc8e4 100644 --- a/src/gui/text/qfontengine.cpp +++ b/src/gui/text/qfontengine.cpp @@ -74,6 +74,16 @@ static inline bool qtransform_equals_no_translate(const QTransform &a, const QTr } } +template +static inline bool qSafeFromBigEndian(const uchar *source, const uchar *end, T *output) +{ + if (source + sizeof(T) > end) + return false; + + *output = qFromBigEndian(source); + return true; +} + // Harfbuzz helper functions #ifdef QT_ENABLE_HARFBUZZ_NG @@ -1044,26 +1054,38 @@ void QFontEngine::loadKerningPairs(QFixed scalingFactor) return; const uchar *table = reinterpret_cast(tab.constData()); + const uchar *end = table + tab.size(); + + quint16 version; + if (!qSafeFromBigEndian(table, end, &version)) + return; - unsigned short version = qFromBigEndian(table); if (version != 0) { // qDebug("wrong version"); return; } - unsigned short numTables = qFromBigEndian(table + 2); + quint16 numTables; + if (!qSafeFromBigEndian(table + 2, end, &numTables)) + return; + { int offset = 4; for(int i = 0; i < numTables; ++i) { - if (offset + 6 > tab.size()) { -// qDebug("offset out of bounds"); - goto end; - } const uchar *header = table + offset; - ushort version = qFromBigEndian(header); - ushort length = qFromBigEndian(header+2); - ushort coverage = qFromBigEndian(header+4); + quint16 version; + if (!qSafeFromBigEndian(header, end, &version)) + goto end; + + quint16 length; + if (!qSafeFromBigEndian(header + 2, end, &length)) + goto end; + + quint16 coverage; + if (!qSafeFromBigEndian(header + 4, end, &coverage)) + goto end; + // qDebug("subtable: version=%d, coverage=%x",version, coverage); if(version == 0 && coverage == 0x0001) { if (offset + length > tab.size()) { @@ -1072,7 +1094,10 @@ void QFontEngine::loadKerningPairs(QFixed scalingFactor) } const uchar *data = table + offset + 6; - ushort nPairs = qFromBigEndian(data); + quint16 nPairs; + if (!qSafeFromBigEndian(data, end, &nPairs)) + goto end; + if(nPairs * 6 + 8 > length - 6) { // qDebug("corrupt table!"); // corrupt table @@ -1082,8 +1107,21 @@ void QFontEngine::loadKerningPairs(QFixed scalingFactor) int off = 8; for(int i = 0; i < nPairs; ++i) { QFontEngine::KernPair p; - p.left_right = (((uint)qFromBigEndian(data+off)) << 16) + qFromBigEndian(data+off+2); - p.adjust = QFixed(((int)(short)qFromBigEndian(data+off+4))) / scalingFactor; + + quint16 tmp; + if (!qSafeFromBigEndian(data + off, end, &tmp)) + goto end; + + p.left_right = uint(tmp) << 16; + if (!qSafeFromBigEndian(data + off + 2, end, &tmp)) + goto end; + + p.left_right |= tmp; + + if (!qSafeFromBigEndian(data + off + 4, end, &tmp)) + goto end; + + p.adjust = QFixed(int(short(tmp))) / scalingFactor; kerning_pairs.append(p); off += 6; } @@ -1103,26 +1141,31 @@ int QFontEngine::glyphCount() const QByteArray maxpTable = getSfntTable(MAKE_TAG('m', 'a', 'x', 'p')); if (maxpTable.size() < 6) return 0; - return qFromBigEndian(reinterpret_cast(maxpTable.constData() + 4)); + + const uchar *source = reinterpret_cast(maxpTable.constData() + 4); + const uchar *end = source + maxpTable.size(); + + quint16 count = 0; + qSafeFromBigEndian(source, end, &count); + return count; } const uchar *QFontEngine::getCMap(const uchar *table, uint tableSize, bool *isSymbolFont, int *cmapSize) { const uchar *header = table; - if (tableSize < 4) - return 0; - const uchar *endPtr = table + tableSize; // version check - if (qFromBigEndian(header) != 0) + quint16 version; + if (!qSafeFromBigEndian(header, endPtr, &version) || version != 0) return 0; - unsigned short numTables = qFromBigEndian(header + 2); - const uchar *maps = table + 4; - if (maps + 8 * numTables > endPtr) + quint16 numTables; + if (!qSafeFromBigEndian(header + 2, endPtr, &numTables)) return 0; + const uchar *maps = table + 4; + enum { Invalid, AppleRoman, @@ -1137,8 +1180,14 @@ const uchar *QFontEngine::getCMap(const uchar *table, uint tableSize, bool *isSy int tableToUse = -1; int score = Invalid; for (int n = 0; n < numTables; ++n) { - const quint16 platformId = qFromBigEndian(maps + 8 * n); - const quint16 platformSpecificId = qFromBigEndian(maps + 8 * n + 2); + quint16 platformId; + if (!qSafeFromBigEndian(maps + 8 * n, endPtr, &platformId)) + return 0; + + quint16 platformSpecificId; + if (!qSafeFromBigEndian(maps + 8 * n + 2, endPtr, &platformSpecificId)) + return 0; + switch (platformId) { case 0: // Unicode if (score < Unicode && @@ -1192,20 +1241,30 @@ const uchar *QFontEngine::getCMap(const uchar *table, uint tableSize, bool *isSy resolveTable: *isSymbolFont = (symbolTable > -1); - unsigned int unicode_table = qFromBigEndian(maps + 8*tableToUse + 4); + quint32 unicode_table; + if (!qSafeFromBigEndian(maps + 8 * tableToUse + 4, endPtr, &unicode_table)) + return 0; - if (!unicode_table || unicode_table + 8 > tableSize) + if (!unicode_table) return 0; // get the header of the unicode table header = table + unicode_table; - unsigned short format = qFromBigEndian(header); - unsigned int length; - if(format < 8) - length = qFromBigEndian(header + 2); - else - length = qFromBigEndian(header + 4); + quint16 format; + if (!qSafeFromBigEndian(header, endPtr, &format)) + return 0; + + quint32 length; + if (format < 8) { + quint16 tmp; + if (!qSafeFromBigEndian(header + 2, endPtr, &tmp)) + return 0; + length = tmp; + } else { + if (!qSafeFromBigEndian(header + 4, endPtr, &length)) + return 0; + } if (table + unicode_table + length > endPtr) return 0; @@ -1220,7 +1279,7 @@ resolveTable: // Check that none of the latin1 range are in the unicode table bool unicodeTableHasLatin1 = false; for (int uc=0x00; uc<0x100; ++uc) { - if (getTrueTypeGlyphIndex(selectedTable, uc) != 0) { + if (getTrueTypeGlyphIndex(selectedTable, length, uc) != 0) { unicodeTableHasLatin1 = true; break; } @@ -1230,7 +1289,7 @@ resolveTable: bool unicodeTableHasSymbols = false; if (!unicodeTableHasLatin1) { for (int uc=0xf000; uc<0xf100; ++uc) { - if (getTrueTypeGlyphIndex(selectedTable, uc) != 0) { + if (getTrueTypeGlyphIndex(selectedTable, length, uc) != 0) { unicodeTableHasSymbols = true; break; } @@ -1248,12 +1307,17 @@ resolveTable: return table + unicode_table; } -quint32 QFontEngine::getTrueTypeGlyphIndex(const uchar *cmap, uint unicode) +quint32 QFontEngine::getTrueTypeGlyphIndex(const uchar *cmap, int cmapSize, uint unicode) { - unsigned short format = qFromBigEndian(cmap); + const uchar *end = cmap + cmapSize; + quint16 format; + if (!qSafeFromBigEndian(cmap, end, &format)) + return 0; + if (format == 0) { - if (unicode < 256) - return (int) *(cmap+6+unicode); + const uchar *ptr = cmap + 6 + unicode; + if (unicode < 256 && ptr < end) + return quint32(*ptr); } else if (format == 4) { /* some fonts come with invalid cmap tables, where the last segment specified end = start = rangeoffset = 0xffff, delta = 0x0001 @@ -1262,25 +1326,49 @@ quint32 QFontEngine::getTrueTypeGlyphIndex(const uchar *cmap, uint unicode) */ if(unicode >= 0xffff) return 0; - quint16 segCountX2 = qFromBigEndian(cmap + 6); + + quint16 segCountX2; + if (!qSafeFromBigEndian(cmap + 6, end, &segCountX2)) + return 0; + const unsigned char *ends = cmap + 14; + int i = 0; - for (; i < segCountX2/2 && qFromBigEndian(ends + 2*i) < unicode; i++) {} + for (; i < segCountX2/2; ++i) { + quint16 codePoint; + if (!qSafeFromBigEndian(ends + 2 * i, end, &codePoint)) + return 0; + if (codePoint >= unicode) + break; + } const unsigned char *idx = ends + segCountX2 + 2 + 2*i; - quint16 startIndex = qFromBigEndian(idx); + quint16 startIndex; + if (!qSafeFromBigEndian(idx, end, &startIndex)) + return 0; if (startIndex > unicode) return 0; idx += segCountX2; - qint16 idDelta = (qint16)qFromBigEndian(idx); + + quint16 tmp; + if (!qSafeFromBigEndian(idx, end, &tmp)) + return 0; + qint16 idDelta = qint16(tmp); + idx += segCountX2; - quint16 idRangeoffset_t = (quint16)qFromBigEndian(idx); + + quint16 idRangeoffset_t; + if (!qSafeFromBigEndian(idx, end, &idRangeoffset_t)) + return 0; quint16 glyphIndex; if (idRangeoffset_t) { - quint16 id = qFromBigEndian(idRangeoffset_t + 2*(unicode - startIndex) + idx); + quint16 id; + if (!qSafeFromBigEndian(idRangeoffset_t + 2 * (unicode - startIndex) + idx, end, &id)) + return 0; + if (id) glyphIndex = (idDelta + id) % 0x10000; else @@ -1290,13 +1378,19 @@ quint32 QFontEngine::getTrueTypeGlyphIndex(const uchar *cmap, uint unicode) } return glyphIndex; } else if (format == 6) { - quint16 tableSize = qFromBigEndian(cmap + 2); + quint16 tableSize; + if (!qSafeFromBigEndian(cmap + 2, end, &tableSize)) + return 0; - quint16 firstCode6 = qFromBigEndian(cmap + 6); + quint16 firstCode6; + if (!qSafeFromBigEndian(cmap + 6, end, &firstCode6)) + return 0; if (unicode < firstCode6) return 0; - quint16 entryCount6 = qFromBigEndian(cmap + 8); + quint16 entryCount6; + if (!qSafeFromBigEndian(cmap + 8, end, &entryCount6)) + return 0; if (entryCount6 * 2 + 10 > tableSize) return 0; @@ -1305,9 +1399,14 @@ quint32 QFontEngine::getTrueTypeGlyphIndex(const uchar *cmap, uint unicode) return 0; quint16 entryIndex6 = unicode - firstCode6; - return qFromBigEndian(cmap + 10 + (entryIndex6 * 2)); + + quint16 index = 0; + qSafeFromBigEndian(cmap + 10 + (entryIndex6 * 2), end, &index); + return index; } else if (format == 12) { - quint32 nGroups = qFromBigEndian(cmap + 12); + quint32 nGroups; + if (!qSafeFromBigEndian(cmap + 12, end, &nGroups)) + return 0; cmap += 16; // move to start of groups @@ -1315,13 +1414,24 @@ quint32 QFontEngine::getTrueTypeGlyphIndex(const uchar *cmap, uint unicode) while (left <= right) { int middle = left + ( ( right - left ) >> 1 ); - quint32 startCharCode = qFromBigEndian(cmap + 12*middle); + quint32 startCharCode; + if (!qSafeFromBigEndian(cmap + 12 * middle, end, &startCharCode)) + return 0; + if(unicode < startCharCode) right = middle - 1; else { - quint32 endCharCode = qFromBigEndian(cmap + 12*middle + 4); - if(unicode <= endCharCode) - return qFromBigEndian(cmap + 12*middle + 8) + unicode - startCharCode; + quint32 endCharCode; + if (!qSafeFromBigEndian(cmap + 12 * middle + 4, end, &endCharCode)) + return 0; + + if (unicode <= endCharCode) { + quint32 index; + if (!qSafeFromBigEndian(cmap + 12 * middle + 8, end, &index)) + return 0; + + return index + unicode - startCharCode; + } left = middle + 1; } } diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h index 9364b82bed..423b9413ed 100644 --- a/src/gui/text/qfontengine_p.h +++ b/src/gui/text/qfontengine_p.h @@ -243,7 +243,7 @@ public: QFontEngineGlyphCache *glyphCache(const void *key, GlyphFormat format, const QTransform &transform) const; static const uchar *getCMap(const uchar *table, uint tableSize, bool *isSymbolFont, int *cmapSize); - static quint32 getTrueTypeGlyphIndex(const uchar *cmap, uint unicode); + static quint32 getTrueTypeGlyphIndex(const uchar *cmap, int cmapSize, uint unicode); static QByteArray convertToPostscriptFontFamilyName(const QByteArray &fontFamily); diff --git a/src/gui/text/qfontengine_qpf2.cpp b/src/gui/text/qfontengine_qpf2.cpp index 4785902c99..4bb27c4d51 100644 --- a/src/gui/text/qfontengine_qpf2.cpp +++ b/src/gui/text/qfontengine_qpf2.cpp @@ -322,9 +322,9 @@ bool QFontEngineQPF2::getSfntTableData(uint tag, uchar *buffer, uint *length) co glyph_t QFontEngineQPF2::glyphIndex(uint ucs4) const { - glyph_t glyph = getTrueTypeGlyphIndex(cmap, ucs4); + glyph_t glyph = getTrueTypeGlyphIndex(cmap, cmapSize, ucs4); if (glyph == 0 && symbol && ucs4 < 0x100) - glyph = getTrueTypeGlyphIndex(cmap, ucs4 + 0xf000); + glyph = getTrueTypeGlyphIndex(cmap, cmapSize, ucs4 + 0xf000); if (!findGlyph(glyph)) glyph = 0; @@ -348,16 +348,16 @@ bool QFontEngineQPF2::stringToCMap(const QChar *str, int len, QGlyphLayout *glyp QStringIterator it(str, str + len); while (it.hasNext()) { const uint uc = it.next(); - glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc); + glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc); if(!glyphs->glyphs[glyph_pos] && uc < 0x100) - glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc + 0xf000); + glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc + 0xf000); ++glyph_pos; } } else { QStringIterator it(str, str + len); while (it.hasNext()) { const uint uc = it.next(); - glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc); + glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc); #if 0 && defined(DEBUG_FONTENGINE) QChar c(uc); if (!findGlyph(glyphs[glyph_pos].glyph) && !seenGlyphs.contains(c)) diff --git a/src/plugins/platforms/windows/qwindowsfontengine.cpp b/src/plugins/platforms/windows/qwindowsfontengine.cpp index e45ff5d744..afb134d014 100644 --- a/src/plugins/platforms/windows/qwindowsfontengine.cpp +++ b/src/plugins/platforms/windows/qwindowsfontengine.cpp @@ -181,9 +181,8 @@ void QWindowsFontEngine::getCMap() bool symb = false; if (ttf) { cmapTable = getSfntTable(qbswap(MAKE_TAG('c', 'm', 'a', 'p'))); - int size = 0; cmap = QFontEngine::getCMap(reinterpret_cast(cmapTable.constData()), - cmapTable.size(), &symb, &size); + cmapTable.size(), &symb, &cmapSize); } if (!cmap) { ttf = false; @@ -218,16 +217,16 @@ int QWindowsFontEngine::getGlyphIndexes(const QChar *str, int numChars, QGlyphLa QStringIterator it(str, str + numChars); while (it.hasNext()) { const uint uc = it.next(); - glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc); + glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc); if(!glyphs->glyphs[glyph_pos] && uc < 0x100) - glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc + 0xf000); + glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc + 0xf000); ++glyph_pos; } } else if (ttf) { QStringIterator it(str, str + numChars); while (it.hasNext()) { const uint uc = it.next(); - glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc); + glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc); ++glyph_pos; } } else { @@ -276,6 +275,7 @@ QWindowsFontEngine::QWindowsFontEngine(const QString &name, hasOutline(0), lw(0), cmap(0), + cmapSize(0), lbearing(SHRT_MIN), rbearing(SHRT_MIN), x_height(-1), @@ -343,11 +343,11 @@ glyph_t QWindowsFontEngine::glyphIndex(uint ucs4) const #if !defined(Q_OS_WINCE) if (symbol) { - glyph = getTrueTypeGlyphIndex(cmap, ucs4); + glyph = getTrueTypeGlyphIndex(cmap, cmapSize, ucs4); if (glyph == 0 && ucs4 < 0x100) - glyph = getTrueTypeGlyphIndex(cmap, ucs4 + 0xf000); + glyph = getTrueTypeGlyphIndex(cmap, cmapSize, ucs4 + 0xf000); } else if (ttf) { - glyph = getTrueTypeGlyphIndex(cmap, ucs4); + glyph = getTrueTypeGlyphIndex(cmap, cmapSize, ucs4); #else if (tm.tmFirstChar > 60000) { glyph = ucs4; diff --git a/src/plugins/platforms/windows/qwindowsfontengine.h b/src/plugins/platforms/windows/qwindowsfontengine.h index 02bc4008d1..c0dda6efca 100644 --- a/src/plugins/platforms/windows/qwindowsfontengine.h +++ b/src/plugins/platforms/windows/qwindowsfontengine.h @@ -147,6 +147,7 @@ private: TEXTMETRIC tm; int lw; const unsigned char *cmap; + int cmapSize; QByteArray cmapTable; mutable qreal lbearing; mutable qreal rbearing; -- cgit v1.2.3 From 40cbf1927bdd2fa9f531a047d1ba66f68c35d170 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 10 Jun 2015 07:42:42 -0700 Subject: Don't add qmutex_xxx.cpp to SOURCES, as qmutex.cpp #include's them Normally qmake catches the #include and drops the source from SOURCES. But the parser has bugs, so help it by never adding the files. The false: SOURCES += is left so that the sources can be found by Qt Creator. Task-number: QTBUG-46582 Change-Id: I049a653beeb5454c9539ffff13e667877350346b Reviewed-by: Jake Petroules --- src/corelib/thread/thread.pri | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/corelib/thread/thread.pri b/src/corelib/thread/thread.pri index 3c1ddd984a..2cb00a6cf4 100644 --- a/src/corelib/thread/thread.pri +++ b/src/corelib/thread/thread.pri @@ -46,21 +46,21 @@ SOURCES += thread/qatomic.cpp \ unix:SOURCES += thread/qthread_unix.cpp \ thread/qwaitcondition_unix.cpp -win32:SOURCES += thread/qmutex_win.cpp \ - thread/qthread_win.cpp \ +win32:SOURCES += thread/qthread_win.cpp \ thread/qwaitcondition_win.cpp -integrity:SOURCES += thread/qmutex_unix.cpp \ - thread/qthread_unix.cpp \ +integrity:SOURCES += thread/qthread_unix.cpp \ thread/qwaitcondition_unix.cpp -unix: { - mac { - SOURCES += thread/qmutex_mac.cpp - } else:linux-*:!linux-lsb-* { - SOURCES += thread/qmutex_linux.cpp - } else { - SOURCES += thread/qmutex_unix.cpp - } +false { + # files #included by others, but listed here so IDEs parsing this file know + # they are part of QtCore. Usually, qmake can find out that certain files + # are #included by others and thus remove from SOURCES, but it gets lost + # with qmutex.cpp. + SOURCES += \ + thread/qmutex_linux.cpp \ + thread/qmutex_mac.cpp \ + thread/qmutex_unix.cpp \ + thread/qmutex_win.cpp } -- cgit v1.2.3 From f18dc91da5924256de54cfe05ca8f75f03a8a829 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 9 Jul 2015 10:48:21 +0200 Subject: Fix crash when mixing widgets with QtQuick 1 and Qt Quick 2 Apply the fix from commit 313a74cc4a9a5d200b2059d3d8767fe1a274c50d also to the QWidget and the QGraphicsObject destructor. Task-number: QTCREATORBUG-10273 Change-Id: I47983b49cc4d9b75a2e1ee838e13403bc4b95a59 Reviewed-by: Friedemann Kleint --- src/widgets/graphicsview/qgraphicsitem.cpp | 11 +++++++---- src/widgets/kernel/qwidget.cpp | 11 +++++++---- 2 files changed, 14 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/widgets/graphicsview/qgraphicsitem.cpp b/src/widgets/graphicsview/qgraphicsitem.cpp index c9a9cf9d79..1332134000 100644 --- a/src/widgets/graphicsview/qgraphicsitem.cpp +++ b/src/widgets/graphicsview/qgraphicsitem.cpp @@ -1425,10 +1425,13 @@ QGraphicsItem::~QGraphicsItem() QObjectPrivate *p = QObjectPrivate::get(o); p->wasDeleted = true; if (p->declarativeData) { - if (QAbstractDeclarativeData::destroyed) - QAbstractDeclarativeData::destroyed(p->declarativeData, o); - if (QAbstractDeclarativeData::destroyed_qml1) - QAbstractDeclarativeData::destroyed_qml1(p->declarativeData, o); + if (static_cast(p->declarativeData)->ownedByQml1) { + if (QAbstractDeclarativeData::destroyed_qml1) + QAbstractDeclarativeData::destroyed_qml1(p->declarativeData, o); + } else { + if (QAbstractDeclarativeData::destroyed) + QAbstractDeclarativeData::destroyed(p->declarativeData, o); + } p->declarativeData = 0; } } diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index dbb229484b..ba0fcf75d0 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -1633,10 +1633,13 @@ QWidget::~QWidget() } if (d->declarativeData) { - if (QAbstractDeclarativeData::destroyed) - QAbstractDeclarativeData::destroyed(d->declarativeData, this); - if (QAbstractDeclarativeData::destroyed_qml1) - QAbstractDeclarativeData::destroyed_qml1(d->declarativeData, this); + if (static_cast(d->declarativeData)->ownedByQml1) { + if (QAbstractDeclarativeData::destroyed_qml1) + QAbstractDeclarativeData::destroyed_qml1(d->declarativeData, this); + } else { + if (QAbstractDeclarativeData::destroyed) + QAbstractDeclarativeData::destroyed(d->declarativeData, this); + } d->declarativeData = 0; // don't activate again in ~QObject } -- cgit v1.2.3 From 79ae2b3963f7356d4931de5fee67f2259ec7f6f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Wed, 13 May 2015 20:31:30 +0200 Subject: QMacStyle: Disable progress bar animations Disable progress bar animations on 10.10 Yosemite and higher - the native style does not animate them any more. Keep the indeterminate progress bar animation. Change-Id: If15fa0321e184101ef19b1050eb5e9d8f27480d8 Reviewed-by: Gabriel de Dietrich --- src/widgets/styles/qmacstyle_mac.mm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/widgets/styles/qmacstyle_mac.mm b/src/widgets/styles/qmacstyle_mac.mm index d9238dc9d5..d13754b36b 100644 --- a/src/widgets/styles/qmacstyle_mac.mm +++ b/src/widgets/styles/qmacstyle_mac.mm @@ -4699,7 +4699,8 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter tdi.value = pb->progress; tdi.attributes = vertical ? 0 : kThemeTrackHorizontal; - if (isIndeterminate || tdi.value < tdi.max) { + const bool usingYosemiteOrLater = QSysInfo::MacintoshVersion > QSysInfo::MV_10_9; + if (isIndeterminate || (tdi.value < tdi.max && !usingYosemiteOrLater)) { if (QProgressStyleAnimation *animation = qobject_cast(d->animation(opt->styleObject))) tdi.trackInfo.progress.phase = animation->animationStep(); else if (opt->styleObject) -- cgit v1.2.3 From 51cf05c1bde7e10aa8b11c1de07542c37263ff5d Mon Sep 17 00:00:00 2001 From: Lorn Potter Date: Tue, 23 Jun 2015 07:14:26 +1000 Subject: Add env variable to control bearer backend polling timers. Scanning and updating networks can cause transmission jitters when scanning every 10 seconds. setting QT_BEARER_POLL_TIMEOUT, in milliseconds will set polling timer for those bearer backends that require polling, such as generic and windows. Task-number: QTBUG-46015 Change-Id: I0338cd34ad78488ebef250a0114d17ce190434e8 Reviewed-by: Alex Blasche --- src/network/bearer/qnetworkconfigmanager_p.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/network/bearer/qnetworkconfigmanager_p.cpp b/src/network/bearer/qnetworkconfigmanager_p.cpp index c1e837de7b..8ff6ee828d 100644 --- a/src/network/bearer/qnetworkconfigmanager_p.cpp +++ b/src/network/bearer/qnetworkconfigmanager_p.cpp @@ -465,15 +465,18 @@ QList QNetworkConfigurationManagerPrivate::engines() const void QNetworkConfigurationManagerPrivate::startPolling() { QMutexLocker locker(&mutex); - - if(!pollTimer) { + if (!pollTimer) { pollTimer = new QTimer(this); - pollTimer->setInterval(10000); + bool ok; + int interval = qgetenv("QT_BEARER_POLL_TIMEOUT").toInt(&ok); + if (!ok) + interval = 10000;//default 10 seconds + pollTimer->setInterval(interval); pollTimer->setSingleShot(true); connect(pollTimer, SIGNAL(timeout()), this, SLOT(pollEngines())); } - if(pollTimer->isActive()) + if (pollTimer->isActive()) return; foreach (QBearerEngine *engine, sessionEngines) { @@ -482,6 +485,7 @@ void QNetworkConfigurationManagerPrivate::startPolling() break; } } + performAsyncConfigurationUpdate(); } void QNetworkConfigurationManagerPrivate::pollEngines() -- cgit v1.2.3 From 24dc5973868358d56afb375cc01c5db7d06c9fbd Mon Sep 17 00:00:00 2001 From: Samuel Gaist Date: Wed, 24 Jun 2015 11:41:16 +0200 Subject: Add reference to QRegularExpression Currently there's no mention of QRegularExpression in QRegExp's documentation. This makes it hard to find QRegularExpression for user used to QRegExp. This patch adds that missing reference. Task-number: QTBUG-46816 Change-Id: If3a981d5759fbed3eecd07e046882e6da378cc4e Reviewed-by: Oswald Buddenhagen Reviewed-by: Sze Howe Koh --- src/corelib/tools/qregexp.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/corelib/tools/qregexp.cpp b/src/corelib/tools/qregexp.cpp index cd8c393d51..f896828e2e 100644 --- a/src/corelib/tools/qregexp.cpp +++ b/src/corelib/tools/qregexp.cpp @@ -115,6 +115,10 @@ int qFindString(const QChar *haystack, int haystackLen, int from, A good text on regexps is \e {Mastering Regular Expressions} (Third Edition) by Jeffrey E. F. Friedl, ISBN 0-596-52812-4. + \note In Qt 5, the new QRegularExpression class provides a Perl + compatible implementation of regular expressions and is recommended + in place of QRegExp. + \tableofcontents \section1 Introduction -- cgit v1.2.3 From 925822eca54d98ea4da73ea75387393e76dbcdda Mon Sep 17 00:00:00 2001 From: Samuel Gaist Date: Sun, 2 Aug 2015 01:50:33 +0200 Subject: QProcessEnvironment documentation typo fix Task-number: QTBUG-45985 Change-Id: I42de961ca6d57847c135abd8395494d0e416ab05 Reviewed-by: Sze Howe Koh --- src/corelib/io/qprocess.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp index 914774b433..af80f4f281 100644 --- a/src/corelib/io/qprocess.cpp +++ b/src/corelib/io/qprocess.cpp @@ -127,7 +127,7 @@ QT_BEGIN_NAMESPACE Unix environment allows both variable names and contents to contain arbitrary binary data (except for the NUL character). QProcessEnvironment will preserve such variables, but does not support manipulating variables whose names or - values are not encodable by the current locale settings (see + values cannot be encoded by the current locale settings (see QTextCodec::codecForLocale). On Windows, the variable names are case-insensitive, but case-preserving. @@ -528,7 +528,7 @@ void QProcessPrivate::Channel::clear() QProcess can merge the two output channels, so that standard output and standard error data from the running process both use the standard output channel. Call setProcessChannelMode() with - MergedChannels before starting the process to activative + MergedChannels before starting the process to activate this feature. You also have the option of forwarding the output of the running process to the calling, main process, by passing ForwardedChannels as the argument. It is also possible to forward @@ -1266,7 +1266,7 @@ QProcess::InputChannelMode QProcess::inputChannelMode() const /*! \since 5.2 - Sets the channel mode of the QProcess standard intput + Sets the channel mode of the QProcess standard input channel to the \a mode specified. This mode will be used the next time start() is called. @@ -2311,7 +2311,7 @@ void QProcess::setArguments(const QStringList &arguments) The process may not exit as a result of calling this function (it is given the chance to prompt the user for any unsaved files, etc). - On Windows, terminate() posts a WM_CLOSE message to all toplevel windows + On Windows, terminate() posts a WM_CLOSE message to all top-level windows of the process and then to the main thread of the process itself. On Unix and OS X the \c SIGTERM signal is sent. @@ -2507,7 +2507,7 @@ QT_END_INCLUDE_NAMESPACE This function does not cache the system environment. Therefore, it's possible to obtain an updated version of the environment if low-level C - library functions like \tt setenv ot \tt putenv have been called. + library functions like \tt setenv or \tt putenv have been called. However, note that repeated calls to this function will recreate the list of environment variables, which is a non-trivial operation. @@ -2537,7 +2537,7 @@ QStringList QProcess::systemEnvironment() It is returned as a QProcessEnvironment. This function does not cache the system environment. Therefore, it's possible to obtain an updated version of the environment if low-level C library - functions like \tt setenv ot \tt putenv have been called. + functions like \tt setenv or \tt putenv have been called. However, note that repeated calls to this function will recreate the QProcessEnvironment object, which is a non-trivial operation. -- cgit v1.2.3 From 6e0a6be105565bd8e5438d0b601e583c5ea74b11 Mon Sep 17 00:00:00 2001 From: Samuel Gaist Date: Thu, 6 Aug 2015 10:46:14 +0200 Subject: Doc: Fix wrong reference QApplication::setStandardPalette MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Task-number: QTBUG-46078 Change-Id: Ifb1c650467a0fc30a0d11ad58708a64e5f9fabd5 Reviewed-by: Leena Miettinen Reviewed-by: Topi Reiniö --- src/widgets/styles/qstyle.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/widgets/styles/qstyle.cpp b/src/widgets/styles/qstyle.cpp index 5e51866d8f..13833d2edd 100644 --- a/src/widgets/styles/qstyle.cpp +++ b/src/widgets/styles/qstyle.cpp @@ -2263,8 +2263,9 @@ int QStyle::sliderValueFromPosition(int min, int max, int pos, int span, bool up standard palette is not used. In particular, the Windows XP, Vista, and Mac styles do not use the standard palette, but make use of native theme engines. With these styles, you should not set - the palette with QApplication::setStandardPalette(). + the palette with QApplication::setPalette(). + \sa QApplication::setPalette() */ QPalette QStyle::standardPalette() const { -- cgit v1.2.3 From 64b53ddf560b790fe4f98bcfc2329293cdc7483e Mon Sep 17 00:00:00 2001 From: Samuel Gaist Date: Mon, 3 Aug 2015 00:37:30 +0200 Subject: Doc: add clarification about signals not being buffered when blocked MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Task-number: QTBUG-15238 Change-Id: Id762007415245f104ffe5cdfd100889f9a73ae95 Reviewed-by: Leena Miettinen Reviewed-by: Topi Reiniö --- src/corelib/kernel/qobject.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 6bc4d7e7ed..bcc4e7f8e6 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -1385,6 +1385,8 @@ bool QObject::eventFilter(QObject * /* watched */, QEvent * /* event */) Note that the destroyed() signal will be emitted even if the signals for this object have been blocked. + Signals emitted while being blocked are not buffered. + \sa signalsBlocked() */ -- cgit v1.2.3 From 141f03a814245e33a1e30d89429dc92783c227bd Mon Sep 17 00:00:00 2001 From: Samuel Gaist Date: Mon, 3 Aug 2015 01:13:07 +0200 Subject: Doc: mark private QChar constructors as internal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Task-number: QTBUG-39862 Change-Id: Ie0d533e3897200589248c803069c41661b15997e Reviewed-by: Sze Howe Koh Reviewed-by: Topi Reiniö --- src/corelib/tools/qchar.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/corelib/tools/qchar.cpp b/src/corelib/tools/qchar.cpp index 5c094772b8..1bf0aa0dec 100644 --- a/src/corelib/tools/qchar.cpp +++ b/src/corelib/tools/qchar.cpp @@ -595,12 +595,14 @@ QT_BEGIN_NAMESPACE /*! \fn QChar::QChar(char ch) + \internal Constructs a QChar corresponding to ASCII/Latin-1 character \a ch. */ /*! \fn QChar::QChar(uchar ch) + \internal Constructs a QChar corresponding to ASCII/Latin-1 character \a ch. */ -- cgit v1.2.3 From 63cd55b1722f43910436e46e7e16d2cf50c9218e Mon Sep 17 00:00:00 2001 From: Samuel Gaist Date: Thu, 6 Aug 2015 09:46:45 +0200 Subject: QTreeView: add size hint handling information to uniformRowHeights Task-number: QTBUG-10802 Change-Id: I6aa60d8fd7678f02003a229e191a5ab4f93c4b9d Reviewed-by: Leena Miettinen --- src/widgets/itemviews/qtreeview.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/widgets/itemviews/qtreeview.cpp b/src/widgets/itemviews/qtreeview.cpp index 9b3e270fdd..57092a7cdc 100644 --- a/src/widgets/itemviews/qtreeview.cpp +++ b/src/widgets/itemviews/qtreeview.cpp @@ -433,6 +433,9 @@ void QTreeView::setRootIsDecorated(bool show) The height is obtained from the first item in the view. It is updated when the data changes on that item. + \note If the editor size hint is bigger than the cell size hint, then the + size hint of the editor will be used. + By default, this property is \c false. */ bool QTreeView::uniformRowHeights() const -- cgit v1.2.3 From 4d572362e882432a9cc8decbea2bcb16d4c7fbcb Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Thu, 23 Jul 2015 23:06:07 +0200 Subject: Fix link to QQ article Change-Id: I04d373778b243fdeb281c98e292359996639c95e Reviewed-by: Richard J. Moore --- src/widgets/kernel/qlayoutitem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/widgets/kernel/qlayoutitem.cpp b/src/widgets/kernel/qlayoutitem.cpp index 3d444136e3..03988aab99 100644 --- a/src/widgets/kernel/qlayoutitem.cpp +++ b/src/widgets/kernel/qlayoutitem.cpp @@ -92,7 +92,7 @@ inline static QSize toLayoutItemSize(QWidgetPrivate *priv, const QSize &size) be expressed using hasHeightForWidth(), heightForWidth(), and minimumHeightForWidth(). For more explanation see the \e{Qt Quarterly} article - \l{http://doc.qt.digia.com/qq/qq04-height-for-width.html}{Trading + \l{http://doc.qt.io/archives/qq/qq04-height-for-width.html}{Trading Height for Width}. \sa QLayout -- cgit v1.2.3 From e92c2e119beb06e3ef47ae6fd871b34ec0ef0939 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Fri, 7 Aug 2015 15:37:07 +0200 Subject: Improve readability of QTextLine's handling of (negative) right bearing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Helper functions in LineBreakHelper have been renamed from adjustFoo to calculateFoo, to signal that they do work, and are not adjusting something relative to something else. - The use of QFixed(1) and >= 0 has been replaced with an explicit constant for the case of the bearing not being calculated yet. - A helper function negativeRightBearing() has been added that returns the absolute value of any negative right bearing, making the width computations simpler. - Comments have been added and rewritten to make the logic clearer. Change-Id: I1d3a0214cfa8b4fed4551f3444b43a37d55bd69b Reviewed-by: Eskil Abrahamsen Blomfeldt Reviewed-by: Tor Arne Vestbø --- src/gui/text/qtextlayout.cpp | 81 ++++++++++++++++++++++++++++++-------------- 1 file changed, 55 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index 7da3e84041..013cd8ae0f 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -1605,8 +1605,8 @@ namespace { bool checkFullOtherwiseExtend(QScriptLine &line); QFixed calculateNewWidth(const QScriptLine &line) const { - return line.textWidth + tmpData.textWidth + spaceData.textWidth + softHyphenWidth - - qMin(rightBearing, QFixed()); + return line.textWidth + tmpData.textWidth + spaceData.textWidth + + softHyphenWidth + negativeRightBearing(); } inline glyph_t currentGlyph() const @@ -1626,33 +1626,51 @@ namespace { } } - inline void adjustRightBearing(glyph_t glyph) + inline void calculateRightBearing(glyph_t glyph) { qreal rb; fontEngine->getGlyphBearings(glyph, 0, &rb); - rightBearing = qMin(QFixed(), QFixed::fromReal(rb)); + + // We only care about negative right bearings, so we limit the range + // of the bearing here so that we can assume it's negative in the rest + // of the code, as well ase use QFixed(1) as a sentinel to represent + // the state where we have yet to compute the right bearing. + rightBearing = qMin(QFixed::fromReal(rb), QFixed(0)); } - inline void adjustRightBearing() + inline void calculateRightBearing() { if (currentPosition <= 0) return; - adjustRightBearing(currentGlyph()); + calculateRightBearing(currentGlyph()); } - inline void adjustPreviousRightBearing() + inline void calculateRightBearingForPreviousGlyph() { if (previousGlyph > 0) - adjustRightBearing(previousGlyph); + calculateRightBearing(previousGlyph); } + static const QFixed RightBearingNotCalculated; + inline void resetRightBearing() { - rightBearing = QFixed(1); // Any positive number is defined as invalid since only - // negative right bearings are interesting to us. + rightBearing = RightBearingNotCalculated; + } + + // We express the negative right bearing as an absolute number + // so that it can be applied to the width using addition. + inline QFixed negativeRightBearing() const + { + if (rightBearing == RightBearingNotCalculated) + return QFixed(0); + + return qAbs(rightBearing); } }; +const QFixed LineBreakHelper::RightBearingNotCalculated = QFixed(1); + inline bool LineBreakHelper::checkFullOtherwiseExtend(QScriptLine &line) { LB_DEBUG("possible break width %f, spacew=%f", tmpData.textWidth.toReal(), spaceData.textWidth.toReal()); @@ -1805,7 +1823,7 @@ void QTextLine::layout_helper(int maxGlyphs) current, lbh.logClusters, lbh.glyphs); } else { lbh.tmpData.length++; - lbh.adjustPreviousRightBearing(); + lbh.calculateRightBearingForPreviousGlyph(); } line += lbh.tmpData; goto found; @@ -1887,22 +1905,29 @@ void QTextLine::layout_helper(int maxGlyphs) lbh.tmpData.textWidth += lbh.glyphs.advances[lbh.logClusters[lbh.currentPosition - 1]]; } - // The actual width of the text needs to take the right bearing into account. The - // right bearing is left-ward, which means that if the rightmost pixel is to the right - // of the advance of the glyph, the bearing will be negative. We flip the sign - // for the code to be more readable. Logic borrowed from qfontmetrics.cpp. - // We ignore the right bearing if the minimum negative bearing is too little to - // expand the text beyond the edge. if (sb_or_ws|breakany) { - QFixed rightBearing = lbh.rightBearing; // store previous right bearing + // To compute the final width of the text we need to take negative right bearing + // into account (negative right bearing means the glyph has pixel data past the + // advance length). Note that the negative right bearing is an absolute number, + // so that we can apply it to the width using straight forward addition. + + // Store previous right bearing (for the already accepted glyph) in case we + // end up breaking due to the current glyph being too wide. + QFixed previousRightBearing = lbh.rightBearing; + + // We ignore the right bearing if the minimum negative bearing is too little to + // expand the text beyond the edge. if (lbh.calculateNewWidth(line) - lbh.minimumRightBearing > line.width) - lbh.adjustRightBearing(); + lbh.calculateRightBearing(); + if (lbh.checkFullOtherwiseExtend(line)) { - // we are too wide, fix right bearing - if (rightBearing <= 0) - lbh.rightBearing = rightBearing; // take from cache + // We are too wide to accept the next glyph with its bearing, so we restore the + // right bearing to that of the previous glyph (the one that was already accepted), + // so that the bearing can be be applied to the final width of the text below. + if (previousRightBearing != LineBreakHelper::RightBearingNotCalculated) + lbh.rightBearing = previousRightBearing; else - lbh.adjustPreviousRightBearing(); + lbh.calculateRightBearingForPreviousGlyph(); if (!breakany) { line.textWidth += lbh.softHyphenWidth; @@ -1919,10 +1944,14 @@ void QTextLine::layout_helper(int maxGlyphs) LB_DEBUG("reached end of line"); lbh.checkFullOtherwiseExtend(line); found: - if (lbh.rightBearing > 0 && !lbh.whiteSpaceOrObject) // If right bearing has not yet been adjusted - lbh.adjustRightBearing(); line.textAdvance = line.textWidth; - line.textWidth -= qMin(QFixed(), lbh.rightBearing); + + // If right bearing has not been calculated yet, do that now + if (lbh.rightBearing == LineBreakHelper::RightBearingNotCalculated && !lbh.whiteSpaceOrObject) + lbh.calculateRightBearing(); + + // Then apply any negative right bearing + line.textWidth += lbh.negativeRightBearing(); if (line.length == 0) { LB_DEBUG("no break available in line, adding temp: length %d, width %f, space: length %d, width %f", -- cgit v1.2.3 From 01c15a94387f8791e2bd600519de98bd0e03f266 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Tue, 14 Jul 2015 15:32:40 +0200 Subject: Always return grayscale indexed8 from QImage::alphaChannel() We shouldn't short-cut alpha8 formats in alphaChannel, the method is used under the assumption that the returned alpha map has encoded the alphas as an indexed grayscale image. The method is also documented as not returning alpha8. Task-number: QTBUG-47138 Change-Id: I1cf16957d12e65d44f2b586d9f127fcb33c549b6 Reviewed-by: Friedemann Kleint Reviewed-by: Gunnar Sletta --- src/gui/image/qimage.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index 08eb759ec2..176cdfe09f 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -4134,9 +4134,6 @@ QImage QImage::alphaChannel() const if (!d) return QImage(); - if (d->format == QImage::Format_Alpha8) - return *this; - int w = d->width; int h = d->height; @@ -4166,6 +4163,10 @@ QImage QImage::alphaChannel() const src_data += d->bytes_per_line; dest_data += image.d->bytes_per_line; } + } else if (d->format == Format_Alpha8) { + const uchar *src_data = d->data; + uchar *dest_data = image.d->data; + memcpy(dest_data, src_data, d->bytes_per_line * h); } else { QImage alpha32 = *this; bool canSkipConversion = (d->format == Format_ARGB32 || d->format == Format_ARGB32_Premultiplied); -- cgit v1.2.3 From bec8c726bf76cda94f73efc76fef6bcea5bc133a Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Sat, 25 Jul 2015 14:43:14 +0200 Subject: Fix out-of-buffer read on image upscale Avoid reading from the next pixel when the sample is fully based on the current pixel. This is particular important for the last pixel in an image when the next pixel might be outside the image buffer. Change-Id: I3607f9c6c332d11ff944ca35d216d417368f9fd5 Task-number: QTBUG-47228 Reviewed-by: Konstantin Ritt Reviewed-by: Gunnar Sletta --- src/gui/painting/qimagescale.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/gui/painting/qimagescale.cpp b/src/gui/painting/qimagescale.cpp index 867c64c5e0..2f85e90c49 100644 --- a/src/gui/painting/qimagescale.cpp +++ b/src/gui/painting/qimagescale.cpp @@ -312,7 +312,10 @@ static void qt_qimageScaleAARGBA_up_xy(QImageScaleInfo *isi, unsigned int *dest, for (int x = dxx; x < end; x++) { const unsigned int *pix = sptr + xpoints[x]; const int xap = xapoints[x]; - *dptr = INTERPOLATE_PIXEL_256(pix[0], 256 - xap, pix[1], xap); + if (xap > 0) + *dptr = INTERPOLATE_PIXEL_256(pix[0], 256 - xap, pix[1], xap); + else + *dptr = pix[0]; dptr++; } } -- cgit v1.2.3 From d2f0f46c459bca229d30132f233e724d55490a78 Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Tue, 4 Aug 2015 17:49:39 +0200 Subject: When the focus changes make sure that the IME finishes correctly When clicking onto another widget while in the middle of composing should cause it to be seen as an acceptance of the composed text so far instead of just cancelling it outright. This was validated against the Japanese, Korean and Chinese IMEs on Windows 7. Task-number: QTBUG-42344 Change-Id: I03be0cd099840f51a9550929f33e2afbbf31e85a Reviewed-by: Friedemann Kleint --- src/plugins/platforms/windows/qwindowsinputcontext.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.cpp b/src/plugins/platforms/windows/qwindowsinputcontext.cpp index 0cce171340..c943438570 100644 --- a/src/plugins/platforms/windows/qwindowsinputcontext.cpp +++ b/src/plugins/platforms/windows/qwindowsinputcontext.cpp @@ -206,7 +206,7 @@ void QWindowsInputContext::setFocusObject(QObject *object) // remains active when this happens resulting in a lock-up. Consecutive // key events still have VK_PROCESSKEY set and are thus ignored. if (m_compositionContext.isComposing) - imeNotifyCancelComposition(m_compositionContext.hwnd); + reset(); const QWindow *window = QGuiApplication::focusWindow(); if (object && window && window->handle()) { -- cgit v1.2.3 From 22e752bada2b1f83f94b95c3473b6c3fe13cd7c5 Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Mon, 3 Aug 2015 15:47:40 +0200 Subject: QLineEdit: update IM status after selection change MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As it stood, we only told the platform about a selection change if the cursor also changed position. But if you have a selection, and press key left, the selection will be cleared without moving the cursor. And for those cases, we didn't report the selection change back to the platform. The result was that the IM status in the platform plugin got out of sync with the widget. This patch will add the missing connection that updates the platform whenever the selection changes. Change-Id: Iab0848f27207b63ed4fb47f0d4f24a6d02e87db1 Reviewed-by: Tor Arne Vestbø --- src/widgets/widgets/qlineedit_p.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/widgets/widgets/qlineedit_p.cpp b/src/widgets/widgets/qlineedit_p.cpp index ad3a92d35a..3f768bfbd3 100644 --- a/src/widgets/widgets/qlineedit_p.cpp +++ b/src/widgets/widgets/qlineedit_p.cpp @@ -188,6 +188,9 @@ void QLineEditPrivate::init(const QString& txt) QObject::connect(control, SIGNAL(selectionChanged()), q, SLOT(update())); + QObject::connect(control, SIGNAL(selectionChanged()), + q, SLOT(updateMicroFocus())); + QObject::connect(control, SIGNAL(displayTextChanged(QString)), q, SLOT(update())); -- cgit v1.2.3 From 7f0f6380b132be76e6d5293b7b357918b7cb3d56 Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Tue, 4 Aug 2015 13:37:00 +0200 Subject: QComboBox: make editable comboboxes usable with input methods MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QComboBox uses a QLineEdit for text editing. But while editing, the combobox is the widget having focus, not the line edit. Instead the combobox forwards all the IM events to the line edit internally. This causes a problem since the line edit will not be able to update the platforms IM state in QWidget::updateMicroFocus() since it doesn't have focus. The result will be that the platforms IM state will get out of sync with the QLineEdit. This patch will add the missing connections that lets QComboBox update the platforms IM state when the inner QLineEdit signals that its needed. Change-Id: Ic3e0fdbf155d4dbeab31e2cd859f6e425ae87375 Reviewed-by: Tor Arne Vestbø --- src/widgets/widgets/qcombobox.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/widgets/widgets/qcombobox.cpp b/src/widgets/widgets/qcombobox.cpp index 17762eb39d..4840b75c1b 100644 --- a/src/widgets/widgets/qcombobox.cpp +++ b/src/widgets/widgets/qcombobox.cpp @@ -1771,6 +1771,8 @@ void QComboBox::setLineEdit(QLineEdit *edit) connect(d->lineEdit, SIGNAL(editingFinished()), this, SLOT(_q_editingFinished())); connect(d->lineEdit, SIGNAL(textChanged(QString)), this, SIGNAL(editTextChanged(QString))); connect(d->lineEdit, SIGNAL(textChanged(QString)), this, SIGNAL(currentTextChanged(QString))); + connect(d->lineEdit, SIGNAL(cursorPositionChanged(int,int)), this, SLOT(updateMicroFocus())); + connect(d->lineEdit, SIGNAL(selectionChanged()), this, SLOT(updateMicroFocus())); d->lineEdit->setFrame(false); d->lineEdit->setContextMenuPolicy(Qt::NoContextMenu); d->updateFocusPolicy(); -- cgit v1.2.3 From 0cf00efcedb8f8ef438f8d204b7adf938849bf9c Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Thu, 2 Jul 2015 11:11:14 +0200 Subject: iOS: support cut/copy/paste shortcuts when using Bluetooth keyboard MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Iaa602771227f64c3a477a27656362a361f78e8dd Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/ios/qiostextresponder.mm | 50 +++++++++++++++++++++----- 1 file changed, 42 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/ios/qiostextresponder.mm b/src/plugins/platforms/ios/qiostextresponder.mm index 09839790fa..e933c43a9e 100644 --- a/src/plugins/platforms/ios/qiostextresponder.mm +++ b/src/plugins/platforms/ios/qiostextresponder.mm @@ -322,6 +322,46 @@ // ------------------------------------------------------------------------- +- (void)sendKeyPressRelease:(Qt::Key)key modifiers:(Qt::KeyboardModifiers)modifiers +{ + QKeyEvent press(QEvent::KeyPress, key, modifiers); + QKeyEvent release(QEvent::KeyRelease, key, modifiers); + [self sendEventToFocusObject:press]; + [self sendEventToFocusObject:release]; +} + +- (void)cut:(id)sender +{ + Q_UNUSED(sender); + [self sendKeyPressRelease:Qt::Key_X modifiers:Qt::ControlModifier]; +} + +- (void)copy:(id)sender +{ + Q_UNUSED(sender); + [self sendKeyPressRelease:Qt::Key_C modifiers:Qt::ControlModifier]; +} + +- (void)paste:(id)sender +{ + Q_UNUSED(sender); + [self sendKeyPressRelease:Qt::Key_V modifiers:Qt::ControlModifier]; +} + +- (void)selectAll:(id)sender +{ + Q_UNUSED(sender); + [self sendKeyPressRelease:Qt::Key_A modifiers:Qt::ControlModifier]; +} + +- (void)delete:(id)sender +{ + Q_UNUSED(sender); + [self sendKeyPressRelease:Qt::Key_Delete modifiers:Qt::ControlModifier]; +} + +// ------------------------------------------------------------------------- + - (void)notifyInputDelegate:(Qt::InputMethodQueries)updatedProperties { // As documented, we should not report textWillChange/textDidChange unless the text @@ -656,10 +696,7 @@ return; if ([text isEqualToString:@"\n"]) { - QKeyEvent press(QEvent::KeyPress, Qt::Key_Return, Qt::NoModifier); - QKeyEvent release(QEvent::KeyRelease, Qt::Key_Return, Qt::NoModifier); - [self sendEventToFocusObject:press]; - [self sendEventToFocusObject:release]; + [self sendKeyPressRelease:Qt::Key_Return modifiers:Qt::NoModifier]; if (self.returnKeyType == UIReturnKeyDone) [self resignFirstResponder]; @@ -677,10 +714,7 @@ // Since we're posting im events directly to the focus object, we should do the // same for key events. Otherwise they might end up in a different place or out // of sync with im events. - QKeyEvent press(QEvent::KeyPress, (int)Qt::Key_Backspace, Qt::NoModifier); - QKeyEvent release(QEvent::KeyRelease, (int)Qt::Key_Backspace, Qt::NoModifier); - [self sendEventToFocusObject:press]; - [self sendEventToFocusObject:release]; + [self sendKeyPressRelease:Qt::Key_Backspace modifiers:Qt::NoModifier]; } @end -- cgit v1.2.3 From afaeecd4e8adc5de3a94bbdbf7e6d805d66c4241 Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Fri, 3 Jul 2015 13:46:21 +0200 Subject: iOS: ensure that we restore text selection with correct cursor and anchor pos MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Qt keeps track of the selection direction since a selection anchor can be placed both to the left or to the right of the cursor. On iOS, the selection should instead always be specified from left to right (using a position together with a positive length). So when restoring the selection after performing the calculation of the text rect, we need to ensure that we follow this format. Change-Id: Id8bea6c35e2781e1431ee963f601b6e9ef05dbf5 Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/ios/qiostextresponder.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/plugins/platforms/ios/qiostextresponder.mm b/src/plugins/platforms/ios/qiostextresponder.mm index e933c43a9e..be9c3b9e27 100644 --- a/src/plugins/platforms/ios/qiostextresponder.mm +++ b/src/plugins/platforms/ios/qiostextresponder.mm @@ -578,7 +578,7 @@ if (cursorPos != int(r.location + r.length) || cursorPos != anchorPos) { attrs = QList(); - attrs << QInputMethodEvent::Attribute(QInputMethodEvent::Selection, cursorPos, (cursorPos - anchorPos), 0); + attrs << QInputMethodEvent::Attribute(QInputMethodEvent::Selection, qMin(cursorPos, anchorPos), qAbs(cursorPos - anchorPos), 0); e = QInputMethodEvent(m_markedText, attrs); [self sendEventToFocusObject:e]; } -- cgit v1.2.3 From 34130b9caf001682f1decb6ba69b80657b814ed0 Mon Sep 17 00:00:00 2001 From: David Faure Date: Mon, 27 Jul 2015 00:22:11 +0200 Subject: QMimeDatabase: use QElapsedTimer instead of QDateTime::currentDateTime() This reduces the number of syscalls greatly, by avoiding the timezone conversion every time. Change-Id: I39a54def4b45f25c6e037ced6943b05ddc749c9d Reviewed-by: Milian Wolff --- src/corelib/mimetypes/qmimeprovider.cpp | 5 ++--- src/corelib/mimetypes/qmimeprovider_p.h | 3 ++- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/corelib/mimetypes/qmimeprovider.cpp b/src/corelib/mimetypes/qmimeprovider.cpp index 7342a5cd77..1ab1a44392 100644 --- a/src/corelib/mimetypes/qmimeprovider.cpp +++ b/src/corelib/mimetypes/qmimeprovider.cpp @@ -79,10 +79,9 @@ Q_CORE_EXPORT int qmime_secondsBetweenChecks = 5; // exported for the unit test bool QMimeProviderBase::shouldCheck() { - const QDateTime now = QDateTime::currentDateTime(); - if (m_lastCheck.isValid() && m_lastCheck.secsTo(now) < qmime_secondsBetweenChecks) + if (m_lastCheck.isValid() && m_lastCheck.elapsed() < qmime_secondsBetweenChecks * 1000) return false; - m_lastCheck = now; + m_lastCheck.start(); return true; } diff --git a/src/corelib/mimetypes/qmimeprovider_p.h b/src/corelib/mimetypes/qmimeprovider_p.h index 5a89ac23c3..eaf95942f7 100644 --- a/src/corelib/mimetypes/qmimeprovider_p.h +++ b/src/corelib/mimetypes/qmimeprovider_p.h @@ -51,6 +51,7 @@ #include #include +#include QT_BEGIN_NAMESPACE @@ -77,7 +78,7 @@ public: QMimeDatabasePrivate *m_db; protected: bool shouldCheck(); - QDateTime m_lastCheck; + QElapsedTimer m_lastCheck; }; /* -- cgit v1.2.3 From af3152adee2de79c03c0926400e920122b669c4d Mon Sep 17 00:00:00 2001 From: Milian Wolff Date: Mon, 13 Jul 2015 15:42:35 +0200 Subject: QMimeProvider: Do not crash when globPatterns is empty. Change-Id: I351a533a1f03ac2e7bdec876b657a80fac60b2ed Reviewed-by: Milian Wolff --- src/corelib/mimetypes/qmimeprovider.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/corelib/mimetypes/qmimeprovider.cpp b/src/corelib/mimetypes/qmimeprovider.cpp index 1ab1a44392..dab5bb81c9 100644 --- a/src/corelib/mimetypes/qmimeprovider.cpp +++ b/src/corelib/mimetypes/qmimeprovider.cpp @@ -624,7 +624,7 @@ void QMimeBinaryProvider::loadMimeTypePrivate(QMimeTypePrivate &data) // Let's assume that shared-mime-info is at least version 0.70 // Otherwise we would need 1) a version check, and 2) code for parsing patterns from the globs file. #if 1 - if (!mainPattern.isEmpty() && data.globPatterns.first() != mainPattern) { + if (!mainPattern.isEmpty() && (data.globPatterns.isEmpty() || data.globPatterns.first() != mainPattern)) { // ensure it's first in the list of patterns data.globPatterns.removeAll(mainPattern); data.globPatterns.prepend(mainPattern); -- cgit v1.2.3 From e3d7cf7c96964f9d55116f235dc3e0cbf5fef971 Mon Sep 17 00:00:00 2001 From: Michael Klein Date: Sat, 8 Aug 2015 21:07:58 +0100 Subject: Cocoa: fix integer multiplication overflow in qt_gettime() Task-number: QTBUG-24031 Change-Id: Iae00b10b6a7423508669ef173a80a03b3dd388c6 Reviewed-by: Thiago Macieira --- src/corelib/tools/qelapsedtimer_mac.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src') diff --git a/src/corelib/tools/qelapsedtimer_mac.cpp b/src/corelib/tools/qelapsedtimer_mac.cpp index a355bf03e8..e946ac096f 100644 --- a/src/corelib/tools/qelapsedtimer_mac.cpp +++ b/src/corelib/tools/qelapsedtimer_mac.cpp @@ -59,8 +59,13 @@ static qint64 absoluteToNSecs(qint64 cpuTime) { if (info.denom == 0) mach_timebase_info(&info); +#ifdef __LP64__ + __uint128_t nsecs = static_cast<__uint128_t>(cpuTime) * info.numer / info.denom; + return static_cast(nsecs); +#else qint64 nsecs = cpuTime * info.numer / info.denom; return nsecs; +#endif } static qint64 absoluteToMSecs(qint64 cpuTime) -- cgit v1.2.3 From 314c83c0c2f91532654f869b7dc6af1b7e8538da Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Fri, 31 Jul 2015 22:55:55 +0200 Subject: Do not use Q_GLOBAL_STATIC in the implementation of QMutex Since Q_GLOBAL_STATIC might use QMutex and cause a stack overflow. Task-number: QTBUG-47554 Change-Id: I4853c5e9b9168d4a417200e2a45a1bf9cb103a30 Reviewed-by: David Faure Reviewed-by: Pierre Rossi Reviewed-by: Thiago Macieira --- src/corelib/thread/qmutex.cpp | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/corelib/thread/qmutex.cpp b/src/corelib/thread/qmutex.cpp index 002a9cc7bc..3269ee3ae8 100644 --- a/src/corelib/thread/qmutex.cpp +++ b/src/corelib/thread/qmutex.cpp @@ -563,7 +563,28 @@ const int FreeListConstants::Sizes[FreeListConstants::BlockCount] = { }; typedef QFreeList FreeList; -Q_GLOBAL_STATIC(FreeList, freelist); +// We cannot use Q_GLOBAL_STATIC because it uses QMutex +#if defined(Q_COMPILER_THREADSAFE_STATICS) +FreeList *freelist() +{ + static FreeList list; + return &list; +} +#else +FreeList *freelist() +{ + static QAtomicPointer list; + FreeList *local = list.loadAcquire(); + if (!local) { + local = new FreeList; + if (!list.testAndSetRelease(0, local)) { + delete local; + local = list.loadAcquire(); + } + } + return local; +} +#endif } QMutexPrivate *QMutexPrivate::allocate() -- cgit v1.2.3 From 109cdeda3008fe57aabf2385f95cf8e55b8c7da2 Mon Sep 17 00:00:00 2001 From: David Faure Date: Fri, 31 Jul 2015 14:15:56 +0200 Subject: qprintdialog_unix.cpp: fix out-of-bounds when cwd is empty. This happens when the cwd got deleted meanwhile; this warning is printed out: QFileSystemEngine::currentPath: getcwd() failed and currentPath() is empty. Not a problem in itself, but qprintdialog should not assume it's not empty, then. Change-Id: I5c89992b36ca58b6325ced399cff33aca9efb7ec Reviewed-by: Thiago Macieira --- src/printsupport/dialogs/qprintdialog_unix.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/printsupport/dialogs/qprintdialog_unix.cpp b/src/printsupport/dialogs/qprintdialog_unix.cpp index f3be45262b..502ff7d98a 100644 --- a/src/printsupport/dialogs/qprintdialog_unix.cpp +++ b/src/printsupport/dialogs/qprintdialog_unix.cpp @@ -803,7 +803,7 @@ void QUnixPrintWidgetPrivate::applyPrinterProperties() QString cur = QDir::currentPath(); if (home.at(home.length()-1) != QLatin1Char('/')) home += QLatin1Char('/'); - if (cur.at(cur.length()-1) != QLatin1Char('/')) + if (!cur.isEmpty() && cur.at(cur.length()-1) != QLatin1Char('/')) cur += QLatin1Char('/'); if (cur.left(home.length()) != home) cur = home; -- cgit v1.2.3 From 68c915f3df4316dc12d98cabc8d645532c26af3b Mon Sep 17 00:00:00 2001 From: Andrew Knight Date: Sun, 2 Aug 2015 13:52:11 +0300 Subject: ANGLE: call flex/bison by their standard names qt5.git now contains the winflexbison tools as flex/bison. Task-number: QTBUG-46852 Change-Id: I8b86cd4211ae8fb120f955be1f423f94b10b318e Reviewed-by: Thiago Macieira Reviewed-by: Maurice Kalinowski --- src/angle/src/compiler/preprocessor/preprocessor.pro | 6 +++--- src/angle/src/compiler/translator.pro | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/angle/src/compiler/preprocessor/preprocessor.pro b/src/angle/src/compiler/preprocessor/preprocessor.pro index 8c5b1555dc..759a3399b4 100644 --- a/src/angle/src/compiler/preprocessor/preprocessor.pro +++ b/src/angle/src/compiler/preprocessor/preprocessor.pro @@ -40,15 +40,15 @@ SOURCES += \ $$ANGLE_DIR/src/compiler/preprocessor/Preprocessor.cpp \ $$ANGLE_DIR/src/compiler/preprocessor/Token.cpp -# NOTE: 'win_flex' and 'bison' can be found in qt5/gnuwin32/bin -flex.commands = $$addGnuPath(win_flex) --noline --nounistd --outfile=${QMAKE_FILE_BASE}.cpp ${QMAKE_FILE_NAME} +# NOTE: 'flex' and 'bison' can be found in qt5/gnuwin32/bin +flex.commands = $$addGnuPath(flex) --noline --nounistd --outfile=${QMAKE_FILE_BASE}.cpp ${QMAKE_FILE_NAME} flex.output = ${QMAKE_FILE_BASE}.cpp flex.input = FLEX_SOURCES flex.dependency_type = TYPE_C flex.variable_out = GENERATED_SOURCES QMAKE_EXTRA_COMPILERS += flex -bison.commands = $$addGnuPath(win_bison) --no-lines --skeleton=yacc.c --output=${QMAKE_FILE_BASE}.cpp ${QMAKE_FILE_NAME} +bison.commands = $$addGnuPath(bison) --no-lines --skeleton=yacc.c --output=${QMAKE_FILE_BASE}.cpp ${QMAKE_FILE_NAME} bison.output = ${QMAKE_FILE_BASE}.cpp bison.input = BISON_SOURCES bison.dependency_type = TYPE_C diff --git a/src/angle/src/compiler/translator.pro b/src/angle/src/compiler/translator.pro index e9d16ca5af..9572a51ad4 100644 --- a/src/angle/src/compiler/translator.pro +++ b/src/angle/src/compiler/translator.pro @@ -162,15 +162,15 @@ SOURCES += \ $$ANGLE_DIR/src/third_party/compiler/ArrayBoundsClamper.cpp -# NOTE: 'win_flex' and 'bison' can be found in qt5/gnuwin32/bin -flex.commands = $$addGnuPath(win_flex) --noline --nounistd --outfile=${QMAKE_FILE_BASE}_lex.cpp ${QMAKE_FILE_NAME} +# NOTE: 'flex' and 'bison' can be found in qt5/gnuwin32/bin +flex.commands = $$addGnuPath(flex) --noline --nounistd --outfile=${QMAKE_FILE_BASE}_lex.cpp ${QMAKE_FILE_NAME} flex.output = ${QMAKE_FILE_BASE}_lex.cpp flex.input = FLEX_SOURCES flex.dependency_type = TYPE_C flex.variable_out = GENERATED_SOURCES QMAKE_EXTRA_COMPILERS += flex -bison.commands = $$addGnuPath(win_bison) --no-lines --skeleton=yacc.c --defines=${QMAKE_FILE_BASE}_tab.h \ +bison.commands = $$addGnuPath(bison) --no-lines --skeleton=yacc.c --defines=${QMAKE_FILE_BASE}_tab.h \ --output=${QMAKE_FILE_BASE}_tab.cpp ${QMAKE_FILE_NAME} bison.output = ${QMAKE_FILE_BASE}_tab.h bison.input = BISON_SOURCES -- cgit v1.2.3 From 40a4105faef14268410b3ab4ae432f386c74d0e2 Mon Sep 17 00:00:00 2001 From: Samuel Gaist Date: Wed, 12 Aug 2015 17:00:49 +0200 Subject: Fix QChar char constructors documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reverts the wrongly added \internal and adds a warning for users that the constructors will not be available if QT_NO_CAST_FROM_ASCII is defined Task-number: QTBUG-39862 Change-Id: I038eea3f4eef0b914b470309a2f515741eec35a9 Reviewed-by: Topi Reiniö Reviewed-by: Sze Howe Koh --- src/corelib/tools/qchar.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/corelib/tools/qchar.cpp b/src/corelib/tools/qchar.cpp index 1bf0aa0dec..014d91162a 100644 --- a/src/corelib/tools/qchar.cpp +++ b/src/corelib/tools/qchar.cpp @@ -595,16 +595,24 @@ QT_BEGIN_NAMESPACE /*! \fn QChar::QChar(char ch) - \internal Constructs a QChar corresponding to ASCII/Latin-1 character \a ch. + + \note This constructor is not available when \c QT_NO_CAST_FROM_ASCII + is defined. + + \sa QT_NO_CAST_FROM_ASCII */ /*! \fn QChar::QChar(uchar ch) - \internal Constructs a QChar corresponding to ASCII/Latin-1 character \a ch. + + \note This constructor is not available when \c QT_NO_CAST_FROM_ASCII + is defined. + + \sa QT_NO_CAST_FROM_ASCII */ /*! -- cgit v1.2.3 From 1ff66a79626d40a8379a639a0fae3696fc7a06c0 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 18 Feb 2015 12:36:47 -0800 Subject: QProcess: Ensure that the stdin buffer is cleared on start() The buffer may have been left dirty if we were unable to write all the data to the child process in the previous run. So ensure we clear it before starting a new one. We already did that for stdout and stderr, for some reason. Task-number: QTBUG-44517 Change-Id: I1a800c709d3543699131ffff13c419da3bbffacf Reviewed-by: Kai Koehne Reviewed-by: Joerg Bornemann Reviewed-by: Thiago Macieira Reviewed-by: Oswald Buddenhagen --- src/corelib/io/qprocess.cpp | 3 ++- src/corelib/io/qwindowspipewriter.cpp | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp index 176386d6df..c29b97b535 100644 --- a/src/corelib/io/qprocess.cpp +++ b/src/corelib/io/qprocess.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. -** Copyright (C) 2014 Intel Corporation +** Copyright (C) 2015 Intel Corporation ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -2135,6 +2135,7 @@ void QProcessPrivate::start(QIODevice::OpenMode mode) qDebug() << "QProcess::start(" << program << ',' << arguments << ',' << mode << ')'; #endif + stdinChannel.buffer.clear(); stdoutChannel.buffer.clear(); stderrChannel.buffer.clear(); diff --git a/src/corelib/io/qwindowspipewriter.cpp b/src/corelib/io/qwindowspipewriter.cpp index add2ac94da..57053f129a 100644 --- a/src/corelib/io/qwindowspipewriter.cpp +++ b/src/corelib/io/qwindowspipewriter.cpp @@ -85,7 +85,7 @@ qint64 QWindowsPipeWriter::write(const char *ptr, qint64 maxlen) return -1; QMutexLocker locker(&lock); - data.append(QByteArray(ptr, maxlen)); + data.append(ptr, maxlen); waitCondition.wakeOne(); return maxlen; } -- cgit v1.2.3 From 4ccf5c6f4a411d367749565323f7c7fd469b025e Mon Sep 17 00:00:00 2001 From: David Faure Date: Thu, 13 Aug 2015 23:51:34 +0200 Subject: QMimeDatabase: adapt to changes in shared-mime-info 1.3 The generated xml file is now lowercase. This was changed in shared-mime-info 3805d0bcf2. It led to runtime warnings "No file found for ...", which helped notice the bug. Change-Id: I31f0fc7f0fe8a098c3f79c0bcbeeb1909d2cc05a Reviewed-by: Thiago Macieira --- src/corelib/mimetypes/qmimeprovider.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/corelib/mimetypes/qmimeprovider.cpp b/src/corelib/mimetypes/qmimeprovider.cpp index dab5bb81c9..887db51e5c 100644 --- a/src/corelib/mimetypes/qmimeprovider.cpp +++ b/src/corelib/mimetypes/qmimeprovider.cpp @@ -560,10 +560,13 @@ void QMimeBinaryProvider::loadMimeTypePrivate(QMimeTypePrivate &data) // load comment and globPatterns const QString file = data.name + QLatin1String(".xml"); - const QStringList mimeFiles = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QString::fromLatin1("mime/") + file); + // shared-mime-info since 1.3 lowercases the xml files + QStringList mimeFiles = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QString::fromLatin1("mime/") + file.toLower()); if (mimeFiles.isEmpty()) { - // TODO: ask Thiago about this - qWarning() << "No file found for" << file << ", even though the file appeared in a directory listing."; + mimeFiles = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QString::fromLatin1("mime/") + file); // pre-1.3 + } + if (mimeFiles.isEmpty()) { + qWarning() << "No file found for" << file << ", even though update-mime-info said it would exist."; qWarning() << "Either it was just removed, or the directory doesn't have executable permission..."; qWarning() << QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QLatin1String("mime"), QStandardPaths::LocateDirectory); return; -- cgit v1.2.3 From 507625d984f9467b056e603560d62a2e4a56074d Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Tue, 28 Jul 2015 13:43:54 +0200 Subject: fix assertion in QProcess/Win Do not call bytesAvailableInChannel if the source pipe end is invalid. This is the case when redirecting channels on Windows. The assertions in bytesAvailableInChannel were triggered whenever an output process or output file was set and waitForBytesWritten was called. Task-number: QTBUG-45548 Change-Id: I225dfea2c5e27e122f75008a3a06d425554e00fe Reviewed-by: Alex Trotsenko Reviewed-by: Oswald Buddenhagen --- src/corelib/io/qprocess_win.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp index cef961ecbd..eb88ded2c9 100644 --- a/src/corelib/io/qprocess_win.cpp +++ b/src/corelib/io/qprocess_win.cpp @@ -704,13 +704,15 @@ bool QProcessPrivate::waitForBytesWritten(int msecs) return true; // If we wouldn't write anything, check if we can read stdout. - if (bytesAvailableInChannel(&stdoutChannel) != 0) { + if (stdoutChannel.pipe[0] != INVALID_Q_PIPE + && bytesAvailableInChannel(&stdoutChannel) != 0) { tryReadFromChannel(&stdoutChannel); timer.resetIncrements(); } // Check if we can read stderr. - if (bytesAvailableInChannel(&stderrChannel) != 0) { + if (stderrChannel.pipe[0] != INVALID_Q_PIPE + && bytesAvailableInChannel(&stderrChannel) != 0) { tryReadFromChannel(&stderrChannel); timer.resetIncrements(); } -- cgit v1.2.3 From 0636ec4ff5d25845b4020358d0570afb92ce580c Mon Sep 17 00:00:00 2001 From: Alexander Volkov Date: Wed, 10 Jun 2015 13:33:09 +0300 Subject: Open menu on the third click on QMenuBar on X11 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We don't replay mouse events after closing popups on X11. This leads to the bug when the menu doesn't show after clicking three times on the menu bar. It can be fixed by reverting 78d7192338e2cbba0c9b53c429d35b9437b7e1cd, but then we need an alternative fix for QTBUG-32807 on Windows. So don't replay mouse events for the menu bar on all platforms. Change-Id: I3db8e24a6de6f35b0a17dffac6a131f1cad42e6d Reviewed-by: Shawn Rutledge Reviewed-by: Friedemann Kleint Reviewed-by: Jørgen Lind --- src/widgets/widgets/qmenubar.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/widgets/widgets/qmenubar.cpp b/src/widgets/widgets/qmenubar.cpp index 1ad99bed9c..883fd3a945 100644 --- a/src/widgets/widgets/qmenubar.cpp +++ b/src/widgets/widgets/qmenubar.cpp @@ -1042,8 +1042,8 @@ void QMenuBar::mousePressEvent(QMouseEvent *e) if(d->currentAction == action && d->popupState) { if(QMenu *menu = d->activeMenu) { d->activeMenu = 0; + menu->setAttribute(Qt::WA_NoMouseReplay); menu->hide(); - d->closePopupMode = 1; } } else { d->setCurrentAction(action, true); -- cgit v1.2.3 From 08150122aaf0e1da706346497cf9767534a455b0 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Tue, 11 Aug 2015 15:09:47 +0200 Subject: Do not add GLSL line statements for old drivers Older VMware virtual machines do not like the #line statements. These were introduced in 5.5.0, meaning that when upgrading from 5.4 in such a VM, shader compilation via QOpenGLShaderProgram stops working. This should be avoided. Task-number: QTBUG-47598 Change-Id: I8cccd76119350e7ce40da96d24a7a6e9eb399052 Reviewed-by: Sean Harmer --- src/gui/opengl/qopenglshaderprogram.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/gui/opengl/qopenglshaderprogram.cpp b/src/gui/opengl/qopenglshaderprogram.cpp index 5de79c9e1e..04b796ddb0 100644 --- a/src/gui/opengl/qopenglshaderprogram.cpp +++ b/src/gui/opengl/qopenglshaderprogram.cpp @@ -525,7 +525,8 @@ bool QOpenGLShader::compileSourceCode(const char *source) // The precision qualifiers are useful on OpenGL/ES systems, // but usually not present on desktop systems. - const QSurfaceFormat currentSurfaceFormat = QOpenGLContext::currentContext()->format(); + QOpenGLContext *ctx = QOpenGLContext::currentContext(); + const QSurfaceFormat currentSurfaceFormat = ctx->format(); QOpenGLContextPrivate *ctx_d = QOpenGLContextPrivate::get(QOpenGLContext::currentContext()); if (currentSurfaceFormat.renderableType() == QSurfaceFormat::OpenGL || ctx_d->workaround_missingPrecisionQualifiers @@ -545,10 +546,16 @@ bool QOpenGLShader::compileSourceCode(const char *source) } #endif - // Append #line directive in order to compensate for text insertion - QByteArray lineDirective = QStringLiteral("#line %1\n").arg(versionDirectivePosition.line).toUtf8(); - sourceChunks.append(lineDirective.constData()); - sourceChunkLengths.append(GLint(lineDirective.length())); + QByteArray lineDirective; + // #line is rejected by some drivers: + // "2.1 Mesa 8.1-devel (git-48a3d4e)" or "MESA 2.1 Mesa 8.1-devel" + const char *version = reinterpret_cast(ctx->functions()->glGetString(GL_VERSION)); + if (!version || !strstr(version, "2.1 Mesa 8")) { + // Append #line directive in order to compensate for text insertion + lineDirective = QStringLiteral("#line %1\n").arg(versionDirectivePosition.line).toUtf8(); + sourceChunks.append(lineDirective.constData()); + sourceChunkLengths.append(GLint(lineDirective.length())); + } // Append rest of shader code sourceChunks.append(source + versionDirectivePosition.position); -- cgit v1.2.3 From be18d6fb01749184d40cdcd079e685d220ff8b80 Mon Sep 17 00:00:00 2001 From: Alexander Volkov Date: Thu, 18 Sep 2014 16:16:26 +0400 Subject: Fix shortcuts with keypad keys The way of searching a shortcut match for a key without the keypad modifier introduced in 547a1bea492954d828aa0798be93384669812489 is not correct. QKeyEvent::setModifiers() doesn't change native scan code so we get the incorrect QKeyEvent object which is eventually passed to the implementation of QPlatformIntegration::possibleKeys(). And then QPlatformIntegration::possibleKeys() returns the same result as for the original QKeyEvent object. So to fix it we have to remove Qt::KeypadModifier from keys after calling the implementation of QPlatformIntegration::possibleKeys(), as it was before 547a1bea492954d828aa0798be93384669812489. Task-number: QTBUG-33093 Task-number: QTBUG-44577 Change-Id: I5b33c9b6cf2c06b133166a31eba9aff9181c9483 Reviewed-by: Gunnar Sletta --- src/gui/kernel/qshortcutmap.cpp | 12 +++++------- src/gui/kernel/qshortcutmap_p.h | 4 ++-- 2 files changed, 7 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/gui/kernel/qshortcutmap.cpp b/src/gui/kernel/qshortcutmap.cpp index 0ff5c36119..3e267f2e0b 100644 --- a/src/gui/kernel/qshortcutmap.cpp +++ b/src/gui/kernel/qshortcutmap.cpp @@ -386,9 +386,7 @@ QKeySequence::SequenceMatch QShortcutMap::nextState(QKeyEvent *e) result = find(e); if (result == QKeySequence::NoMatch && (e->modifiers() & Qt::KeypadModifier)) { // Try to find a match without keypad modifier - QKeyEvent event = *e; - event.setModifiers(e->modifiers() & ~Qt::KeypadModifier); - result = find(&event); + result = find(e, Qt::KeypadModifier); } if (result == QKeySequence::NoMatch && e->modifiers() & Qt::ShiftModifier) { // If Shift + Key_Backtab, also try Shift + Qt::Key_Tab @@ -441,13 +439,13 @@ bool QShortcutMap::hasShortcutForKeySequence(const QKeySequence &seq) const which can be access through matches(). \sa matches */ -QKeySequence::SequenceMatch QShortcutMap::find(QKeyEvent *e) +QKeySequence::SequenceMatch QShortcutMap::find(QKeyEvent *e, int ignoredModifiers) { Q_D(QShortcutMap); if (!d->sequences.count()) return QKeySequence::NoMatch; - createNewSequences(e, d->newEntries); + createNewSequences(e, d->newEntries, ignoredModifiers); #if defined(DEBUG_QSHORTCUTMAP) qDebug() << "Possible shortcut key sequences:" << d->newEntries; #endif @@ -549,7 +547,7 @@ void QShortcutMap::clearSequence(QVector &ksl) Alters \a seq to the new sequence state, based on the current sequence state, and the new key event \a e. */ -void QShortcutMap::createNewSequences(QKeyEvent *e, QVector &ksl) +void QShortcutMap::createNewSequences(QKeyEvent *e, QVector &ksl, int ignoredModifiers) { Q_D(QShortcutMap); QList possibleKeys = QKeyMapper::possibleKeys(e); @@ -579,7 +577,7 @@ void QShortcutMap::createNewSequences(QKeyEvent *e, QVector &ksl) curKsl.setKey(0, 2); curKsl.setKey(0, 3); } - curKsl.setKey(possibleKeys.at(pkNum), index); + curKsl.setKey(possibleKeys.at(pkNum) & ~ignoredModifiers, index); } } } diff --git a/src/gui/kernel/qshortcutmap_p.h b/src/gui/kernel/qshortcutmap_p.h index 242c021ca4..2376d27c78 100644 --- a/src/gui/kernel/qshortcutmap_p.h +++ b/src/gui/kernel/qshortcutmap_p.h @@ -88,10 +88,10 @@ private: QKeySequence::SequenceMatch state(); void dispatchEvent(QKeyEvent *e); - QKeySequence::SequenceMatch find(QKeyEvent *e); + QKeySequence::SequenceMatch find(QKeyEvent *e, int ignoredModifiers = 0); QKeySequence::SequenceMatch matches(const QKeySequence &seq1, const QKeySequence &seq2) const; QVector matches() const; - void createNewSequences(QKeyEvent *e, QVector &ksl); + void createNewSequences(QKeyEvent *e, QVector &ksl, int ignoredModifiers); void clearSequence(QVector &ksl); int translateModifiers(Qt::KeyboardModifiers modifiers); -- cgit v1.2.3 From fae725d45183f44fce93826df66e2f1ab2b6fa74 Mon Sep 17 00:00:00 2001 From: Joni Poikelin Date: Thu, 2 Jul 2015 13:28:29 +0300 Subject: Fix potential SIGFPEs in QRasterizer::rasterizeLine() Task-number: QTBUG-46985 Change-Id: If9897a6d4014dbcbc1f6cac1c6dd5dc648694b96 Reviewed-by: Gunnar Sletta --- src/gui/painting/qrasterizer.cpp | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/gui/painting/qrasterizer.cpp b/src/gui/painting/qrasterizer.cpp index 75bf31cde1..34d72bf493 100644 --- a/src/gui/painting/qrasterizer.cpp +++ b/src/gui/painting/qrasterizer.cpp @@ -863,8 +863,8 @@ void QRasterizer::rasterizeLine(const QPointF &a, const QPointF &b, qreal width, const Q16Dot16 iLeft = int(left); const Q16Dot16 iRight = int(right); const Q16Dot16 leftWidth = IntToQ16Dot16(iLeft + 1) - - FloatToQ16Dot16(left); - const Q16Dot16 rightWidth = FloatToQ16Dot16(right) + - qSafeFloatToQ16Dot16(left); + const Q16Dot16 rightWidth = qSafeFloatToQ16Dot16(right) - IntToQ16Dot16(iRight); Q16Dot16 coverage[3]; @@ -898,8 +898,8 @@ void QRasterizer::rasterizeLine(const QPointF &a, const QPointF &b, qreal width, const Q16Dot16 iTopFP = IntToQ16Dot16(int(pa.y())); const Q16Dot16 iBottomFP = IntToQ16Dot16(int(pb.y())); - const Q16Dot16 yPa = FloatToQ16Dot16(pa.y()); - const Q16Dot16 yPb = FloatToQ16Dot16(pb.y()); + const Q16Dot16 yPa = qSafeFloatToQ16Dot16(pa.y()); + const Q16Dot16 yPb = qSafeFloatToQ16Dot16(pb.y()); for (Q16Dot16 yFP = iTopFP; yFP <= iBottomFP; yFP += Q16Dot16Factor) { const Q16Dot16 rowHeight = qMin(yFP + Q16Dot16Factor, yPb) - qMax(yFP, yPa); @@ -983,16 +983,16 @@ void QRasterizer::rasterizeLine(const QPointF &a, const QPointF &b, qreal width, const Q16Dot16 iRightFP = IntToQ16Dot16(int(right.y())); const Q16Dot16 iBottomFP = IntToQ16Dot16(int(bottomBound)); - Q16Dot16 leftIntersectAf = FloatToQ16Dot16(top.x() + (int(topBound) - top.y()) * topLeftSlope); - Q16Dot16 rightIntersectAf = FloatToQ16Dot16(top.x() + (int(topBound) - top.y()) * topRightSlope); + Q16Dot16 leftIntersectAf = qSafeFloatToQ16Dot16(top.x() + (int(topBound) - top.y()) * topLeftSlope); + Q16Dot16 rightIntersectAf = qSafeFloatToQ16Dot16(top.x() + (int(topBound) - top.y()) * topRightSlope); Q16Dot16 leftIntersectBf = 0; Q16Dot16 rightIntersectBf = 0; if (iLeftFP < iTopFP) - leftIntersectBf = FloatToQ16Dot16(left.x() + (int(topBound) - left.y()) * bottomLeftSlope); + leftIntersectBf = qSafeFloatToQ16Dot16(left.x() + (int(topBound) - left.y()) * bottomLeftSlope); if (iRightFP < iTopFP) - rightIntersectBf = FloatToQ16Dot16(right.x() + (int(topBound) - right.y()) * bottomRightSlope); + rightIntersectBf = qSafeFloatToQ16Dot16(right.x() + (int(topBound) - right.y()) * bottomRightSlope); Q16Dot16 rowTop, rowBottomLeft, rowBottomRight, rowTopLeft, rowTopRight, rowBottom; Q16Dot16 topLeftIntersectAf, topLeftIntersectBf, topRightIntersectAf, topRightIntersectBf; @@ -1000,10 +1000,10 @@ void QRasterizer::rasterizeLine(const QPointF &a, const QPointF &b, qreal width, int leftMin, leftMax, rightMin, rightMax; - const Q16Dot16 yTopFP = FloatToQ16Dot16(top.y()); - const Q16Dot16 yLeftFP = FloatToQ16Dot16(left.y()); - const Q16Dot16 yRightFP = FloatToQ16Dot16(right.y()); - const Q16Dot16 yBottomFP = FloatToQ16Dot16(bottom.y()); + const Q16Dot16 yTopFP = qSafeFloatToQ16Dot16(top.y()); + const Q16Dot16 yLeftFP = qSafeFloatToQ16Dot16(left.y()); + const Q16Dot16 yRightFP = qSafeFloatToQ16Dot16(right.y()); + const Q16Dot16 yBottomFP = qSafeFloatToQ16Dot16(bottom.y()); rowTop = qMax(iTopFP, yTopFP); topLeftIntersectAf = leftIntersectAf + @@ -1021,7 +1021,7 @@ void QRasterizer::rasterizeLine(const QPointF &a, const QPointF &b, qreal width, if (yFP == iLeftFP) { const int y = Q16Dot16ToInt(yFP); - leftIntersectBf = FloatToQ16Dot16(left.x() + (y - left.y()) * bottomLeftSlope); + leftIntersectBf = qSafeFloatToQ16Dot16(left.x() + (y - left.y()) * bottomLeftSlope); topLeftIntersectBf = leftIntersectBf + Q16Dot16Multiply(bottomLeftSlopeFP, rowTopLeft - yFP); bottomLeftIntersectAf = leftIntersectAf + Q16Dot16Multiply(topLeftSlopeFP, rowBottomLeft - yFP); } else { @@ -1031,7 +1031,7 @@ void QRasterizer::rasterizeLine(const QPointF &a, const QPointF &b, qreal width, if (yFP == iRightFP) { const int y = Q16Dot16ToInt(yFP); - rightIntersectBf = FloatToQ16Dot16(right.x() + (y - right.y()) * bottomRightSlope); + rightIntersectBf = qSafeFloatToQ16Dot16(right.x() + (y - right.y()) * bottomRightSlope); topRightIntersectBf = rightIntersectBf + Q16Dot16Multiply(bottomRightSlopeFP, rowTopRight - yFP); bottomRightIntersectAf = rightIntersectAf + Q16Dot16Multiply(topRightSlopeFP, rowBottomRight - yFP); } else { -- cgit v1.2.3 From ba84e346b8a3eba6686fa18e1ef546def98073fa Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Mon, 17 Aug 2015 12:52:53 +0200 Subject: egl: Do not do any further ops when context creation fails Change-Id: I54bf4a720e8d414d310ecdb88f08a9705023aef9 Reviewed-by: Andy Nichols --- src/platformsupport/eglconvenience/qeglplatformcontext.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/platformsupport/eglconvenience/qeglplatformcontext.cpp b/src/platformsupport/eglconvenience/qeglplatformcontext.cpp index 6d9f9e4ae0..5bee29afef 100644 --- a/src/platformsupport/eglconvenience/qeglplatformcontext.cpp +++ b/src/platformsupport/eglconvenience/qeglplatformcontext.cpp @@ -240,7 +240,8 @@ void QEGLPlatformContext::adopt(const QVariant &nativeHandle, QPlatformOpenGLCon void QEGLPlatformContext::initialize() { - updateFormatFromGL(); + if (m_eglContext != EGL_NO_CONTEXT) + updateFormatFromGL(); } EGLSurface QEGLPlatformContext::createTemporaryOffscreenSurface() -- cgit v1.2.3 From 4dccb2ca674e9eafca65da0775254932102c7f4b Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 22 May 2015 09:39:52 +0200 Subject: Handle action events in QLineEditIconButton. Ensure QAction::setVisible() is handled and reposition if visibility changes. Task-number: QTBUG-39660 Change-Id: I14f0659aedc8dc89ddef3159d3a500b40b1563ff Reviewed-by: David Faure --- src/widgets/widgets/qlineedit_p.cpp | 24 ++++++++++++++++++++++-- src/widgets/widgets/qlineedit_p.h | 16 ++++++++++++++-- 2 files changed, 36 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/widgets/widgets/qlineedit_p.cpp b/src/widgets/widgets/qlineedit_p.cpp index 3f768bfbd3..6645a375a7 100644 --- a/src/widgets/widgets/qlineedit_p.cpp +++ b/src/widgets/widgets/qlineedit_p.cpp @@ -324,6 +324,24 @@ void QLineEditIconButton::paintEvent(QPaintEvent *) painter.drawPixmap(pixmapRect, iconPixmap); } +void QLineEditIconButton::actionEvent(QActionEvent *e) +{ + switch (e->type()) { + case QEvent::ActionChanged: { + const QAction *action = e->action(); + if (isVisible() != action->isVisible()) { + setVisible(action->isVisible()); + if (QLineEdit *le = qobject_cast(parentWidget())) + static_cast(qt_widget_private(le))->positionSideWidgets(); + } + } + break; + default: + break; + } + QToolButton::actionEvent(e); +} + void QLineEditIconButton::setOpacity(qreal value) { if (!qFuzzyCompare(m_opacity, value)) { @@ -415,12 +433,14 @@ void QLineEditPrivate::positionSideWidgets() QRect widgetGeometry(QPoint(QLineEditIconButton::IconMargin, (contentRect.height() - iconSize.height()) / 2), iconSize); foreach (const SideWidgetEntry &e, leftSideWidgetList()) { e.widget->setGeometry(widgetGeometry); - widgetGeometry.moveLeft(widgetGeometry.left() + delta); + if (e.widget->isVisible()) + widgetGeometry.moveLeft(widgetGeometry.left() + delta); } widgetGeometry.moveLeft(contentRect.width() - iconSize.width() - QLineEditIconButton::IconMargin); foreach (const SideWidgetEntry &e, rightSideWidgetList()) { e.widget->setGeometry(widgetGeometry); - widgetGeometry.moveLeft(widgetGeometry.left() - delta); + if (e.widget->isVisible()) + widgetGeometry.moveLeft(widgetGeometry.left() - delta); } } } diff --git a/src/widgets/widgets/qlineedit_p.h b/src/widgets/widgets/qlineedit_p.h index 4654262ea7..5a22285149 100644 --- a/src/widgets/widgets/qlineedit_p.h +++ b/src/widgets/widgets/qlineedit_p.h @@ -61,6 +61,8 @@ #include "private/qwidgetlinecontrol_p.h" +#include + QT_BEGIN_NAMESPACE // QLineEditIconButton: This is a simple helper class that represents clickable icons that fade in with text @@ -81,6 +83,7 @@ public: #endif protected: + void actionEvent(QActionEvent *e) Q_DECL_OVERRIDE; void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE; private slots: @@ -226,14 +229,23 @@ private: mutable QSize m_iconSize; }; +static bool isSideWidgetVisible(const QLineEditPrivate::SideWidgetEntry &e) +{ + return e.widget->isVisible(); +} + inline int QLineEditPrivate::effectiveLeftTextMargin() const { - return leftTextMargin + leftSideWidgetList().size() * (QLineEditIconButton::IconMargin + iconSize().width()); + return leftTextMargin + (QLineEditIconButton::IconMargin + iconSize().width()) + * int(std::count_if(leftSideWidgetList().constBegin(), leftSideWidgetList().constEnd(), + isSideWidgetVisible)); } inline int QLineEditPrivate::effectiveRightTextMargin() const { - return rightTextMargin + rightSideWidgetList().size() * (QLineEditIconButton::IconMargin + iconSize().width()); + return rightTextMargin + (QLineEditIconButton::IconMargin + iconSize().width()) + * int(std::count_if(rightSideWidgetList().constBegin(), rightSideWidgetList().constEnd(), + isSideWidgetVisible)); } #endif // QT_NO_LINEEDIT -- cgit v1.2.3 From ee15bef3ea24a78e5fd4708c0a1cebee2e4fac5d Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Mon, 17 Aug 2015 11:28:16 +0200 Subject: QRegularExpression: fix matching over QStringRefs Playing with the offset argument of pcre_exec is not equivalent to adjusting the pointer to the subject string. In particular, PCRE can go behind the offset to check for lookbehinds or "transition" metacharacters (\b, \B, etc.). This made the code that deals with QStringRefs not matching in behavior with the corresponding code dealing with QStrings. For instance, QString subject("Miss"); QRegularExpression re("(?<=M)iss"); re.match(subject.mid(1)); // doesn't match re.match(subject.midRef(1)); // matches!!! Instead, actually adjust the pointer to the subject string so that the behavior is identical. A broken test that relied on the equivalence is also removed. Change-Id: If96333241ef59621d7f5a6a170ebd0a186844874 Reviewed-by: Volker Krause Reviewed-by: Thiago Macieira --- src/corelib/tools/qregularexpression.cpp | 45 +++++++++++++++----------------- 1 file changed, 21 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/corelib/tools/qregularexpression.cpp b/src/corelib/tools/qregularexpression.cpp index 2e3c2ca79f..070e68154f 100644 --- a/src/corelib/tools/qregularexpression.cpp +++ b/src/corelib/tools/qregularexpression.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** -** Copyright (C) 2012 Giuseppe D'Angelo . -** Copyright (C) 2012 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo +** Copyright (C) 2015 Giuseppe D'Angelo . +** Copyright (C) 2015 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** @@ -1325,48 +1325,45 @@ QRegularExpressionMatchPrivate *QRegularExpressionPrivate::doMatch(const QString int * const captureOffsets = priv->capturedOffsets.data(); const int captureOffsetsCount = priv->capturedOffsets.size(); - int realOffset = offset + subjectStart; - const int realSubjectLength = subjectLength + subjectStart; - - const unsigned short * const subjectUtf16 = subject.utf16(); + const unsigned short * const subjectUtf16 = subject.utf16() + subjectStart; int result; if (!previousMatchWasEmpty) { result = pcre16SafeExec(compiledPattern, currentStudyData, - subjectUtf16, realSubjectLength, - realOffset, pcreOptions, + subjectUtf16, subjectLength, + offset, pcreOptions, captureOffsets, captureOffsetsCount); } else { result = pcre16SafeExec(compiledPattern, currentStudyData, - subjectUtf16, realSubjectLength, - realOffset, pcreOptions | PCRE_NOTEMPTY_ATSTART | PCRE_ANCHORED, + subjectUtf16, subjectLength, + offset, pcreOptions | PCRE_NOTEMPTY_ATSTART | PCRE_ANCHORED, captureOffsets, captureOffsetsCount); if (result == PCRE_ERROR_NOMATCH) { - ++realOffset; + ++offset; if (usingCrLfNewlines - && realOffset < realSubjectLength - && subjectUtf16[realOffset - 1] == QLatin1Char('\r') - && subjectUtf16[realOffset] == QLatin1Char('\n')) { - ++realOffset; - } else if (realOffset < realSubjectLength - && QChar::isLowSurrogate(subjectUtf16[realOffset])) { - ++realOffset; + && offset < subjectLength + && subjectUtf16[offset - 1] == QLatin1Char('\r') + && subjectUtf16[offset] == QLatin1Char('\n')) { + ++offset; + } else if (offset < subjectLength + && QChar::isLowSurrogate(subjectUtf16[offset])) { + ++offset; } result = pcre16SafeExec(compiledPattern, currentStudyData, - subjectUtf16, realSubjectLength, - realOffset, pcreOptions, + subjectUtf16, subjectLength, + offset, pcreOptions, captureOffsets, captureOffsetsCount); } } #ifdef QREGULAREXPRESSION_DEBUG qDebug() << "Matching" << pattern << "against" << subject - << "starting at" << subjectStart << "len" << subjectLength << "real len" << realSubjectLength - << "offset" << offset << "real offset" << realOffset + << "starting at" << subjectStart << "len" << subjectLength + << "offset" << offset << matchType << matchOptions << previousMatchWasEmpty << "result" << result; #endif @@ -2041,7 +2038,7 @@ QString QRegularExpressionMatch::captured(int nth) const if (start == -1) // didn't capture return QString(); - return d->subject.mid(start, capturedLength(nth)); + return d->subject.mid(start + d->subjectStart, capturedLength(nth)); } /*! @@ -2062,7 +2059,7 @@ QStringRef QRegularExpressionMatch::capturedRef(int nth) const if (start == -1) // didn't capture return QStringRef(); - return d->subject.midRef(start, capturedLength(nth)); + return d->subject.midRef(start + d->subjectStart, capturedLength(nth)); } /*! -- cgit v1.2.3 From 6a57a260fc1ce8250fef4ed6e0242ac933c7ee56 Mon Sep 17 00:00:00 2001 From: Julien Brianceau Date: Tue, 18 Aug 2015 10:48:26 +0200 Subject: Doc: remove type() reference from QApplication and QGuiApplication QApplication::type() is gone since Qt 5.0. Task-number: QTBUG-28093 Change-Id: I8700c69a42271e8b99f3e86a5014c8abf7711f53 Reviewed-by: Friedemann Kleint --- src/gui/kernel/qguiapplication.cpp | 3 +-- src/widgets/kernel/qapplication.cpp | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index 654567e7df..7dc8444163 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -449,8 +449,7 @@ static QWindowGeometrySpecification windowGeometrySpecification; \row \li Miscellaneous \li startingUp(), - closingDown(), - type(). + closingDown(). \endtable \sa QCoreApplication, QAbstractEventDispatcher, QEventLoop diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index b9fd6312e7..647484ece1 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -339,8 +339,7 @@ void QApplicationPrivate::createEventDispatcher() \li Miscellaneous \li closeAllWindows(), startingUp(), - closingDown(), - type(). + closingDown(). \endtable \sa QCoreApplication, QAbstractEventDispatcher, QEventLoop, QSettings -- cgit v1.2.3 From cc6a06632b26c4f60cb29f540af6eafc31ae3f02 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Wed, 19 Aug 2015 15:22:53 +0200 Subject: xcb: send QTabletEvent before QMouseEvent It was a regression: drawing applications which can handle both mouse and tablet events should not need to wait to see whether a mouse event will be followed by a corresponding tablet event. The tablet event is preferred because it has all the tablet parameters (pressure etc.) Also, show the timestamp of each mouse event in the log message, which helps to verify the correspondence. Task-number: QTBUG-47702 Change-Id: I9e832c19de935ec1243138eb4c1484284f61cbfc Reviewed-by: Laszlo Agocs --- src/plugins/platforms/xcb/qxcbconnection_xi2.cpp | 19 ++++++++++--------- src/plugins/platforms/xcb/qxcbwindow.cpp | 6 +++--- 2 files changed, 13 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp index 335236578b..d7688be0ff 100644 --- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp @@ -971,15 +971,6 @@ bool QXcbConnection::xi2HandleTabletEvent(void *event, TabletData *tabletData, Q xXIGenericDeviceEvent *xiEvent = static_cast(event); xXIDeviceEvent *xiDeviceEvent = reinterpret_cast(xiEvent); -#ifdef XCB_USE_XINPUT22 - // Synthesize mouse events since otherwise there are no mouse events from - // the pen on the XI 2.2+ path. - if (xi2MouseEvents() && eventListener) - eventListener->handleXIMouseEvent(reinterpret_cast(event)); -#else - Q_UNUSED(eventListener); -#endif - switch (xiEvent->evtype) { case XI_ButtonPress: { Qt::MouseButton b = xiToQtMouseButton(xiDeviceEvent->detail); @@ -1064,6 +1055,16 @@ bool QXcbConnection::xi2HandleTabletEvent(void *event, TabletData *tabletData, Q handled = false; break; } + +#ifdef XCB_USE_XINPUT22 + // Synthesize mouse events since otherwise there are no mouse events from + // the pen on the XI 2.2+ path. + if (xi2MouseEvents() && eventListener) + eventListener->handleXIMouseEvent(reinterpret_cast(event)); +#else + Q_UNUSED(eventListener); +#endif + return handled; } diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index af4a88b7bc..4fdebe1ebb 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -2249,17 +2249,17 @@ void QXcbWindow::handleXIMouseEvent(xcb_ge_event_t *event) switch (ev->evtype) { case XI_ButtonPress: - qCDebug(lcQpaXInput, "XI2 mouse press, button %d", button); + qCDebug(lcQpaXInput, "XI2 mouse press, button %d, time %d", button, ev->time); conn->setButton(button, true); handleButtonPressEvent(event_x, event_y, root_x, root_y, ev->detail, modifiers, ev->time); break; case XI_ButtonRelease: - qCDebug(lcQpaXInput, "XI2 mouse release, button %d", button); + qCDebug(lcQpaXInput, "XI2 mouse release, button %d, time %d", button, ev->time); conn->setButton(button, false); handleButtonReleaseEvent(event_x, event_y, root_x, root_y, ev->detail, modifiers, ev->time); break; case XI_Motion: - qCDebug(lcQpaXInput, "XI2 mouse motion %d,%d", event_x, event_y); + qCDebug(lcQpaXInput, "XI2 mouse motion %d,%d, time %d", event_x, event_y, ev->time); handleMotionNotifyEvent(event_x, event_y, root_x, root_y, modifiers, ev->time); break; default: -- cgit v1.2.3 From cc5e84c8788a6d6f05dfdf76fc249177ee74dce1 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 11 Aug 2015 09:59:10 -0700 Subject: Avoid overflow in QTime::addSecs with too big a number of seconds QDateTime::addSecs needs to do something similar, but not identical because it needs the number of days too. And then there are daylight savings transitions... Task-number: QTBUG-47717 Change-Id: I7de033f80b0e4431b7f1ffff13f976f4f5e5a059 Reviewed-by: Allan Sandfeld Jensen --- src/corelib/tools/qdatetime.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp index e445055e1d..eb4eff32b4 100644 --- a/src/corelib/tools/qdatetime.cpp +++ b/src/corelib/tools/qdatetime.cpp @@ -1681,6 +1681,7 @@ bool QTime::setHMS(int h, int m, int s, int ms) QTime QTime::addSecs(int s) const { + s %= SECS_PER_DAY; return addMSecs(s * 1000); } -- cgit v1.2.3 From 025d6a778ceb377e688f1b394aa5252d74d77199 Mon Sep 17 00:00:00 2001 From: Jorgen Lind Date: Mon, 15 Jun 2015 17:57:20 +0200 Subject: Fix unnecessary enter leave events Task-number: QTBUG-45565 Change-Id: I92c1dc0a14440259349eeae40372221dbc3c548f Reviewed-by: Andy Shaw --- src/widgets/kernel/qwidgetwindow.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp index d4e73bcac4..24ef7de1cf 100644 --- a/src/widgets/kernel/qwidgetwindow.cpp +++ b/src/widgets/kernel/qwidgetwindow.cpp @@ -445,11 +445,11 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event) receiver = popupChild; if (receiver != popup) widgetPos = receiver->mapFromGlobal(event->globalPos()); - QWidget *alien = m_widget->childAt(m_widget->mapFromGlobal(event->globalPos())); + QWidget *alien = receiver->childAt(receiver->mapFromGlobal(event->globalPos())); QMouseEvent e(event->type(), widgetPos, event->windowPos(), event->screenPos(), event->button(), event->buttons(), event->modifiers()); QGuiApplicationPrivate::setMouseEventSource(&e, QGuiApplicationPrivate::mouseEventSource(event)); e.setTimestamp(event->timestamp()); - QApplicationPrivate::sendMouseEvent(receiver, &e, alien, m_widget, &qt_button_down, qt_last_mouse_receiver); + QApplicationPrivate::sendMouseEvent(receiver, &e, alien, receiver->window(), &qt_button_down, qt_last_mouse_receiver); qt_last_mouse_receiver = receiver; } else { // close disabled popups when a mouse button is pressed or released -- cgit v1.2.3 From d99c9bcf2c4e14d3db02ad375aa624a0695e838d Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Tue, 7 Apr 2015 15:06:20 +0200 Subject: Fix regression in reading certain compressed bmp images For BITFIELDS compressed images, the image data may be preceded by bitmask fields. The file positioning code that should make sure those were read correctly was erroneously included in the block of code that was moved in 6f1b82fccdaf202856dcc6510c16b0531680fe23. Task-number: QTBUG-45559 Task-number: QTBUG-40890 Done-with: Eirik Aavitsland Change-Id: Id2b3ce078f67ac6ebf75ab0cc463dc719af83393 Reviewed-by: aavit --- src/gui/image/qbmphandler.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/gui/image/qbmphandler.cpp b/src/gui/image/qbmphandler.cpp index f124cede36..ef12b23caa 100644 --- a/src/gui/image/qbmphandler.cpp +++ b/src/gui/image/qbmphandler.cpp @@ -212,6 +212,9 @@ static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, int offset, int int blue_scale = 0; int alpha_scale = 0; + if (!d->isSequential()) + d->seek(startpos + BMP_FILEHDR_SIZE + (bi.biSize >= BMP_WIN4 ? BMP_WIN : bi.biSize)); // goto start of colormap or masks + if (bi.biSize >= BMP_WIN4 || (comp == BMP_BITFIELDS && (nbits == 16 || nbits == 32))) { if (d->read((char *)&red_mask, sizeof(red_mask)) != sizeof(red_mask)) return false; @@ -299,9 +302,6 @@ static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, int offset, int image.setDotsPerMeterX(bi.biXPelsPerMeter); image.setDotsPerMeterY(bi.biYPelsPerMeter); - if (!d->isSequential()) - d->seek(startpos + BMP_FILEHDR_SIZE + (bi.biSize >= BMP_WIN4? BMP_WIN : bi.biSize)); // goto start of colormap - if (ncols > 0) { // read color table uchar rgb[4]; int rgb_len = t == BMP_OLD ? 3 : 4; -- cgit v1.2.3 From bc32c0ebc0bc00db84ca2f28eb16ab2e5b53a1b6 Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Fri, 24 Jul 2015 09:53:20 +0200 Subject: QNAM: Fix reply deadlocks on server closing connection The _q_readyRead can also be called from readMoreLater() because we implemented it so that bandwidth limited reading can be implemented. This can lead to a race condition if the socket is closing at the specific moment and then deadlock the channel: It will stay unusable with a zombie request. The fix in QHttpProtocolaHandler checks if there is actually bytes available to read from the socket and only then continue. The fix in the HTTP channel needs to be done to properly finish the reply in cases of a server replying with HTTP/1.0 or "Connection: close". The delayed incovation of _q_receiveReply will properly finish up the reply. Change-Id: I19ce2ae595f91d56386cc7406ccacc9935672b6b Reviewed-by: Richard J. Moore --- src/network/access/qhttpnetworkconnectionchannel.cpp | 4 ++++ src/network/access/qhttpprotocolhandler.cpp | 7 ++++++- 2 files changed, 10 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp index 7428f9bf5b..257aa13718 100644 --- a/src/network/access/qhttpnetworkconnectionchannel.cpp +++ b/src/network/access/qhttpnetworkconnectionchannel.cpp @@ -829,11 +829,15 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket if (!reply->d_func()->expectContent()) { // No content expected, this is a valid way to have the connection closed by the server + // We need to invoke this asynchronously to make sure the state() of the socket is on QAbstractSocket::UnconnectedState + QMetaObject::invokeMethod(this, "_q_receiveReply", Qt::QueuedConnection); return; } if (reply->contentLength() == -1 && !reply->d_func()->isChunked()) { // There was no content-length header and it's not chunked encoding, // so this is a valid way to have the connection closed by the server + // We need to invoke this asynchronously to make sure the state() of the socket is on QAbstractSocket::UnconnectedState + QMetaObject::invokeMethod(this, "_q_receiveReply", Qt::QueuedConnection); return; } // ok, we got a disconnect even though we did not expect it diff --git a/src/network/access/qhttpprotocolhandler.cpp b/src/network/access/qhttpprotocolhandler.cpp index ab2e3dac57..a2083158f1 100644 --- a/src/network/access/qhttpprotocolhandler.cpp +++ b/src/network/access/qhttpprotocolhandler.cpp @@ -237,7 +237,12 @@ void QHttpProtocolHandler::_q_readyRead() } if (m_channel->isSocketWaiting() || m_channel->isSocketReading()) { - m_channel->state = QHttpNetworkConnectionChannel::ReadingState; + if (m_socket->bytesAvailable()) { + // We might get a spurious call from readMoreLater() + // call of the QHttpNetworkConnection even while the socket is disconnecting. + // Therefore check if there is actually bytes available before changing the channel state. + m_channel->state = QHttpNetworkConnectionChannel::ReadingState; + } if (m_reply) _q_receiveReply(); } -- cgit v1.2.3 From bc867b179451a4c06c669f03f4598ea8799ad9f6 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 24 Aug 2015 11:57:31 +0200 Subject: QWindowsMimeImage: Revert image format handling back to Qt 4. Effectively revert 9150563940f61be9fb17510be49c0734244866a5 for QTBUG-11463 (offering only CF_DIB5 for images of format ARGB32) and 4018cd3529ded32f3434095a2da2568d52dfe16a for QTBUG-46848 adding support for "PNG". The changes broke pasting images into MS Office since it can only handle plain CF_DIB and gets confused if "PNG" is returned as available format. Task-number: QTBUG-47656 Task-number: QTBUG-11463 Task-number: QTBUG-46848 Change-Id: I9b641b4b912b7b16a2f58bc84fa09c28a64e91c8 Reviewed-by: aavit --- src/plugins/platforms/windows/qwindowsmime.cpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/windows/qwindowsmime.cpp b/src/plugins/platforms/windows/qwindowsmime.cpp index f86ab9fee3..622352e987 100644 --- a/src/plugins/platforms/windows/qwindowsmime.cpp +++ b/src/plugins/platforms/windows/qwindowsmime.cpp @@ -990,12 +990,11 @@ QVector QWindowsMimeImage::formatsForMime(const QString &mimeType, co { QVector formatetcs; if (mimeData->hasImage() && mimeType == QLatin1String("application/x-qt-image")) { - //add DIBV5 if image has alpha channel + //add DIBV5 if image has alpha channel. Do not add CF_PNG here as it will confuse MS Office (QTBUG47656). QImage image = qvariant_cast(mimeData->imageData()); if (!image.isNull() && image.hasAlphaChannel()) formatetcs += setCf(CF_DIBV5); formatetcs += setCf(CF_DIB); - formatetcs += setCf(CF_PNG); // QTBUG-86848, Paste into GIMP queries for PNG. } return formatetcs; } @@ -1024,11 +1023,7 @@ bool QWindowsMimeImage::canConvertFromMime(const FORMATETC &formatetc, const QMi const QImage image = qvariant_cast(mimeData->imageData()); if (image.isNull()) return false; - // QTBUG-11463, deny CF_DIB support for images with alpha to prevent loss of - // transparency in conversion. - return cf == CF_DIBV5 - || (cf == CF_DIB && !image.hasAlphaChannel()) - || cf == int(CF_PNG); + return cf == CF_DIBV5 || (cf == CF_DIB) || cf == int(CF_PNG); } bool QWindowsMimeImage::convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const -- cgit v1.2.3 From ffbc2d3dc06017959167feecd60b66891c3b2c7b Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Wed, 19 Aug 2015 14:56:08 +0200 Subject: Doc: Mention Windows limitations in QFileInfo permission methods MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The limitation is already mentioned in the class documentation, but IMO is severe enough to be highlighted in the documentation of the respective methods, too. Change-Id: I16c68eb41ab9d3a7698d7ef06f747cfd98a8aaff Reviewed-by: Oswald Buddenhagen Reviewed-by: Topi Reiniö --- src/corelib/io/qfileinfo.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/corelib/io/qfileinfo.cpp b/src/corelib/io/qfileinfo.cpp index 8a86ec5858..51b39b1114 100644 --- a/src/corelib/io/qfileinfo.cpp +++ b/src/corelib/io/qfileinfo.cpp @@ -263,6 +263,7 @@ QDateTime &QFileInfoPrivate::getFileTime(QAbstractFileEngine::FileTime request) groupId(). You can examine a file's permissions and ownership in a single statement using the permission() function. + \target NTFS permissions \note On NTFS file systems, ownership and permissions checking is disabled by default for performance reasons. To enable it, include the following line: @@ -893,6 +894,9 @@ QDir QFileInfo::absoluteDir() const /*! Returns \c true if the user can read the file; otherwise returns \c false. + \note If the \l{NTFS permissions} check has not been enabled, the result + on Windows will merely reflect whether the file exists. + \sa isWritable(), isExecutable(), permission() */ bool QFileInfo::isReadable() const @@ -911,6 +915,9 @@ bool QFileInfo::isReadable() const /*! Returns \c true if the user can write to the file; otherwise returns \c false. + \note If the \l{NTFS permissions} check has not been enabled, the result on + Windows will merely reflect whether the file is marked as Read Only. + \sa isReadable(), isExecutable(), permission() */ bool QFileInfo::isWritable() const @@ -1137,7 +1144,8 @@ QString QFileInfo::readLink() const returned. This function can be time consuming under Unix (in the order of - milliseconds). + milliseconds). On Windows, it will return an empty string unless + the \l{NTFS permissions} check has been enabled. \sa ownerId(), group(), groupId() */ @@ -1217,6 +1225,9 @@ uint QFileInfo::groupId() const On systems where files do not have permissions this function always returns \c true. + \note The result might be inaccurate on Windows if the + \l{NTFS permissions} check has not been enabled. + Example: \snippet code/src_corelib_io_qfileinfo.cpp 10 @@ -1240,6 +1251,9 @@ bool QFileInfo::permission(QFile::Permissions permissions) const /*! Returns the complete OR-ed together combination of QFile::Permissions for the file. + + \note The result might be inaccurate on Windows if the + \l{NTFS permissions} check has not been enabled. */ QFile::Permissions QFileInfo::permissions() const { -- cgit v1.2.3 From df276787d5bb191da62db632efaeb4256fa5da27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Martins?= Date: Fri, 26 Jun 2015 20:40:50 +0100 Subject: QRasterPaintEngine: Don't detach QImage Caught being detached a few thousand times per second. Change-Id: I6dd5fd69d7d4f32048cdb7e4ac707f24df6c15f8 (cherry picked from commit 2a81516835c680c29f3de9241a8c28027624ce4f) Reviewed-by: Konstantin Ritt Reviewed-by: Allan Sandfeld Jensen --- src/gui/painting/qpaintengine_raster.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index aabf4a9427..a5957ca86e 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -2756,12 +2756,12 @@ bool QRasterPaintEngine::drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs, QFixed spp = fontEngine->subPixelPositionForX(positions[i].x); QPoint offset; - QImage *alphaMap = fontEngine->lockedAlphaMapForGlyph(glyphs[i], spp, neededFormat, s->matrix, - &offset); + const QImage *alphaMap = fontEngine->lockedAlphaMapForGlyph(glyphs[i], spp, neededFormat, s->matrix, + &offset); if (alphaMap == 0 || alphaMap->isNull()) continue; - alphaPenBlt(alphaMap->bits(), alphaMap->bytesPerLine(), alphaMap->depth(), + alphaPenBlt(alphaMap->constBits(), alphaMap->bytesPerLine(), alphaMap->depth(), qFloor(positions[i].x) + offset.x(), qRound(positions[i].y) + offset.y(), alphaMap->width(), alphaMap->height()); -- cgit v1.2.3 From 2518c4c9079efdaa10f33c3c049f62f0c0c44373 Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Fri, 7 Aug 2015 11:01:09 +0200 Subject: iOS: calculate bounds in desktop view using transformed window bounds for both width and height MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Depending on the orientation, UIKit might shrink either the width or the height of the view to fit the status bar. Since we anyway want the view to fill the whole window, we simply ignore this, and use the bounds of the whole window directly. Task-number: QTBUG-47506 Change-Id: I73294e5792f8d98fb0c0b0a42198207baca08e3c Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/ios/qiosviewcontroller.mm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/plugins/platforms/ios/qiosviewcontroller.mm b/src/plugins/platforms/ios/qiosviewcontroller.mm index 6667ec3dd8..a7068b9246 100644 --- a/src/plugins/platforms/ios/qiosviewcontroller.mm +++ b/src/plugins/platforms/ios/qiosviewcontroller.mm @@ -190,8 +190,9 @@ - (void)setBounds:(CGRect)newBounds { + Q_UNUSED(newBounds); CGRect transformedWindowBounds = [self convertRect:self.window.bounds fromView:self.window]; - [super setBounds:CGRectMake(0, 0, CGRectGetWidth(newBounds), CGRectGetHeight(transformedWindowBounds))]; + [super setBounds:CGRectMake(0, 0, CGRectGetWidth(transformedWindowBounds), CGRectGetHeight(transformedWindowBounds))]; } - (void)setCenter:(CGPoint)newCenter -- cgit v1.2.3 From b14550fa45395d6b57d958bb4a4e42212ba0da0f Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 20 Aug 2015 14:51:53 +0200 Subject: Windows/Input context: Update enabling of IME in in update(), too. Amend change b55f88caba339a49bf0ebabfa324dde523c2b866 by splitting out the enabling into a separate function and call that when QWindowsInputContext::update() is triggered to reflect updates of the microfocus in QGraphicsView or item view widgets. Task-number: QTBUG-47679 Task-number: QTBUG-47705 Task-number: QTBUG-40691 Change-Id: I84a6647944f1aaedcd72d7060cc90e29a177f577 Reviewed-by: Liang Qi Reviewed-by: Andy Shaw --- src/plugins/platforms/windows/qwindowsinputcontext.cpp | 17 ++++++++++++++--- src/plugins/platforms/windows/qwindowsinputcontext.h | 1 + 2 files changed, 15 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.cpp b/src/plugins/platforms/windows/qwindowsinputcontext.cpp index c943438570..68e38dc4a6 100644 --- a/src/plugins/platforms/windows/qwindowsinputcontext.cpp +++ b/src/plugins/platforms/windows/qwindowsinputcontext.cpp @@ -200,18 +200,27 @@ void QWindowsInputContext::reset() doneContext(); } -void QWindowsInputContext::setFocusObject(QObject *object) +void QWindowsInputContext::setFocusObject(QObject *) { // ### fixme: On Windows 8.1, it has been observed that the Input context // remains active when this happens resulting in a lock-up. Consecutive // key events still have VK_PROCESSKEY set and are thus ignored. if (m_compositionContext.isComposing) reset(); + updateEnabled(); +} +void QWindowsInputContext::updateEnabled() +{ + if (!QGuiApplication::focusObject()) + return; const QWindow *window = QGuiApplication::focusWindow(); - if (object && window && window->handle()) { + if (window && window->handle()) { QWindowsWindow *platformWindow = QWindowsWindow::baseWindowOf(window); - if (inputMethodAccepted()) { + const bool accepted = inputMethodAccepted(); + if (QWindowsContext::verbose > 1) + qCDebug(lcQpaInputMethods) << __FUNCTION__ << window << "accepted=" << accepted; + if (accepted) { // Re-enable IME by associating default context saved on first disabling. if (platformWindow->testFlag(QWindowsWindow::InputMethodDisabled)) { ImmAssociateContext(platformWindow->handle(), QWindowsInputContext::m_defaultContext); @@ -235,6 +244,8 @@ void QWindowsInputContext::setFocusObject(QObject *object) void QWindowsInputContext::update(Qt::InputMethodQueries queries) { + if (queries & Qt::ImEnabled) + updateEnabled(); QPlatformInputContext::update(queries); } diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.h b/src/plugins/platforms/windows/qwindowsinputcontext.h index 83a39989f6..110986c20c 100644 --- a/src/plugins/platforms/windows/qwindowsinputcontext.h +++ b/src/plugins/platforms/windows/qwindowsinputcontext.h @@ -87,6 +87,7 @@ private: void doneContext(); void startContextComposition(); void endContextComposition(); + void updateEnabled(); const DWORD m_WM_MSIME_MOUSE; static HIMC m_defaultContext; -- cgit v1.2.3 From 4c3fa449acfc7ec43f3b2c53318c2838ceba5a86 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 17 Aug 2015 13:18:28 +0200 Subject: Fix potential crash in QWindowsWindow::setDropSiteEnabled(). Release drop target after CoLockObjectExternal() to prevent a potential access violation. Change-Id: I2c3bde9f8008b1d567544596f56ebfd61fe6ad86 Task-number: QTBUG-47737 Reviewed-by: Joerg Bornemann --- src/plugins/platforms/windows/qwindowswindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index 853cf036a7..288f73cb8f 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -1034,8 +1034,8 @@ void QWindowsWindow::setDropSiteEnabled(bool dropEnabled) RegisterDragDrop(m_data.hwnd, m_dropTarget); CoLockObjectExternal(m_dropTarget, true, true); } else { - m_dropTarget->Release(); CoLockObjectExternal(m_dropTarget, false, true); + m_dropTarget->Release(); RevokeDragDrop(m_data.hwnd); m_dropTarget = 0; } -- cgit v1.2.3 From dbb1e1936ca9ddc66d2032448da63edec651a77a Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Mon, 24 Aug 2015 10:53:00 +0200 Subject: Bump PCRE to r1594 Get a couple of fixes for important bugs (1667, 1672). The WinCE build patch has also been merged upstream, so remove it from our tree. Change-Id: I933c2d824612a70d7bc52648df5f5c481ae066d7 Reviewed-by: Lars Knoll Reviewed-by: Richard J. Moore --- .../patches/0001-Re-fix-X86-Wince-builds.patch | 35 --- src/3rdparty/pcre/pcre.h | 6 +- src/3rdparty/pcre/pcre_compile.c | 271 ++++++++++++------ src/3rdparty/pcre/pcre_exec.c | 3 +- src/3rdparty/pcre/pcre_internal.h | 17 +- src/3rdparty/pcre/pcre_jit_compile.c | 58 +++- src/3rdparty/pcre/pcre_study.c | 19 +- src/3rdparty/pcre/sljit/sljitConfig.h | 9 + src/3rdparty/pcre/sljit/sljitConfigInternal.h | 13 +- src/3rdparty/pcre/sljit/sljitLir.c | 10 +- src/3rdparty/pcre/sljit/sljitLir.h | 40 ++- src/3rdparty/pcre/sljit/sljitNativeARM_32.c | 27 +- src/3rdparty/pcre/sljit/sljitNativeARM_64.c | 48 +++- src/3rdparty/pcre/sljit/sljitNativeARM_T2_32.c | 58 +++- src/3rdparty/pcre/sljit/sljitNativeMIPS_common.c | 15 +- src/3rdparty/pcre/sljit/sljitNativePPC_common.c | 23 +- src/3rdparty/pcre/sljit/sljitNativeSPARC_common.c | 19 +- src/3rdparty/pcre/sljit/sljitNativeTILEGX_64.c | 311 ++++++++++----------- src/3rdparty/pcre/sljit/sljitNativeX86_common.c | 59 ++-- 19 files changed, 643 insertions(+), 398 deletions(-) delete mode 100644 src/3rdparty/pcre/patches/0001-Re-fix-X86-Wince-builds.patch (limited to 'src') diff --git a/src/3rdparty/pcre/patches/0001-Re-fix-X86-Wince-builds.patch b/src/3rdparty/pcre/patches/0001-Re-fix-X86-Wince-builds.patch deleted file mode 100644 index 8cb3c8c608..0000000000 --- a/src/3rdparty/pcre/patches/0001-Re-fix-X86-Wince-builds.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 121e4d1ad09bdbfeb8a871d4f2c3ffe1acb8e2d6 Mon Sep 17 00:00:00 2001 -From: Giuseppe D'Angelo -Date: Tue, 30 Jun 2015 09:41:39 +0200 -Subject: [PATCH] Re-fix X86 Wince builds. - -eebb8de21ce4845866f15e444a4c78fc2cbb7f3f fixed the PCRE -build, but was accidentally overwritten by a subsequent -import of the PCRE tarball. - -Now put the same patch also into patches/ so that we don't -forget it needs to be manually applied. - -Change-Id: I93c2ee9c2e2dd1c48d391ce7e16d33208fb2cbbb ---- - src/3rdparty/pcre/sljit/sljitNativeX86_common.c | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/src/3rdparty/pcre/sljit/sljitNativeX86_common.c b/src/3rdparty/pcre/sljit/sljitNativeX86_common.c -index 22a163f..21b276f 100644 ---- a/src/3rdparty/pcre/sljit/sljitNativeX86_common.c -+++ b/src/3rdparty/pcre/sljit/sljitNativeX86_common.c -@@ -273,7 +273,9 @@ static sljit_si cpu_has_sse2 = -1; - #endif - static sljit_si cpu_has_cmov = -1; - --#if defined(_MSC_VER) && _MSC_VER >= 1400 -+#ifdef _WIN32_WCE -+#include -+#elif defined(_MSC_VER) && _MSC_VER >= 1400 - #include - #endif - --- -1.9.1 - diff --git a/src/3rdparty/pcre/pcre.h b/src/3rdparty/pcre/pcre.h index 58ed46a2a3..c2557cf4b1 100644 --- a/src/3rdparty/pcre/pcre.h +++ b/src/3rdparty/pcre/pcre.h @@ -42,9 +42,9 @@ POSSIBILITY OF SUCH DAMAGE. /* The current PCRE version information. */ #define PCRE_MAJOR 8 -#define PCRE_MINOR 37 -#define PCRE_PRERELEASE -#define PCRE_DATE 2015-04-28 +#define PCRE_MINOR 38 +#define PCRE_PRERELEASE -RC1 +#define PCRE_DATE 2015-05-03 /* When an application links to a PCRE DLL in Windows, the symbols that are imported have to be identified as such. When building PCRE, the appropriate diff --git a/src/3rdparty/pcre/pcre_compile.c b/src/3rdparty/pcre/pcre_compile.c index 0efad2645d..866aa8c693 100644 --- a/src/3rdparty/pcre/pcre_compile.c +++ b/src/3rdparty/pcre/pcre_compile.c @@ -174,7 +174,7 @@ static const short int escapes[] = { -ESC_Z, CHAR_LEFT_SQUARE_BRACKET, CHAR_BACKSLASH, CHAR_RIGHT_SQUARE_BRACKET, CHAR_CIRCUMFLEX_ACCENT, CHAR_UNDERSCORE, - CHAR_GRAVE_ACCENT, 7, + CHAR_GRAVE_ACCENT, ESC_a, -ESC_b, 0, -ESC_d, ESC_e, ESC_f, 0, @@ -202,9 +202,9 @@ static const short int escapes[] = { /* 68 */ 0, 0, '|', ',', '%', '_', '>', '?', /* 70 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 78 */ 0, '`', ':', '#', '@', '\'', '=', '"', -/* 80 */ 0, 7, -ESC_b, 0, -ESC_d, ESC_e, ESC_f, 0, +/* 80 */ 0, ESC_a, -ESC_b, 0, -ESC_d, ESC_e, ESC_f, 0, /* 88 */-ESC_h, 0, 0, '{', 0, 0, 0, 0, -/* 90 */ 0, 0, -ESC_k, 'l', 0, ESC_n, 0, -ESC_p, +/* 90 */ 0, 0, -ESC_k, 0, 0, ESC_n, 0, -ESC_p, /* 98 */ 0, ESC_r, 0, '}', 0, 0, 0, 0, /* A0 */ 0, '~', -ESC_s, ESC_tee, 0,-ESC_v, -ESC_w, 0, /* A8 */ 0,-ESC_z, 0, 0, 0, '[', 0, 0, @@ -219,6 +219,12 @@ static const short int escapes[] = { /* F0 */ 0, 0, 0, 0, 0, 0, 0, 0, /* F8 */ 0, 0, 0, 0, 0, 0, 0, 0 }; + +/* We also need a table of characters that may follow \c in an EBCDIC +environment for characters 0-31. */ + +static unsigned char ebcdic_escape_c[] = "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"; + #endif @@ -458,7 +464,7 @@ static const char error_texts[] = "range out of order in character class\0" "nothing to repeat\0" /* 10 */ - "operand of unlimited repeat could match the empty string\0" /** DEAD **/ + "internal error: invalid forward reference offset\0" "internal error: unexpected repeat\0" "unrecognized character after (? or (?-\0" "POSIX named classes are supported only within a class\0" @@ -527,7 +533,11 @@ static const char error_texts[] = "different names for subpatterns of the same number are not allowed\0" "(*MARK) must have an argument\0" "this version of PCRE is not compiled with Unicode property support\0" +#ifndef EBCDIC "\\c must be followed by an ASCII character\0" +#else + "\\c must be followed by a letter or one of [\\]^_?\0" +#endif "\\k is not followed by a braced, angle-bracketed, or quoted name\0" /* 70 */ "internal error: unknown opcode in find_fixedlength()\0" @@ -1425,7 +1435,16 @@ else c ^= 0x40; #else /* EBCDIC coding */ if (c >= CHAR_a && c <= CHAR_z) c += 64; - c ^= 0xC0; + if (c == CHAR_QUESTION_MARK) + c = ('\\' == 188 && '`' == 74)? 0x5f : 0xff; + else + { + for (i = 0; i < 32; i++) + { + if (c == ebcdic_escape_c[i]) break; + } + if (i < 32) c = i; else *errorcodeptr = ERR68; + } #endif break; @@ -1799,7 +1818,7 @@ for (;;) case OP_ASSERTBACK: case OP_ASSERTBACK_NOT: do cc += GET(cc, 1); while (*cc == OP_ALT); - cc += PRIV(OP_lengths)[*cc]; + cc += 1 + LINK_SIZE; break; /* Skip over things that don't match chars */ @@ -2487,7 +2506,7 @@ for (code = first_significant_code(code + PRIV(OP_lengths)[*code], TRUE); if (c == OP_BRA || c == OP_BRAPOS || c == OP_CBRA || c == OP_CBRAPOS || c == OP_ONCE || c == OP_ONCE_NC || - c == OP_COND) + c == OP_COND || c == OP_SCOND) { BOOL empty_branch; if (GET(code, 1) == 0) return TRUE; /* Hit unclosed bracket */ @@ -3886,11 +3905,11 @@ didn't consider this to be a POSIX class. Likewise for [:1234:]. The problem in trying to be exactly like Perl is in the handling of escapes. We have to be sure that [abc[:x\]pqr] is *not* treated as containing a POSIX class, but [abc[:x\]pqr:]] is (so that an error can be generated). The code -below handles the special case of \], but does not try to do any other escape -processing. This makes it different from Perl for cases such as [:l\ower:] -where Perl recognizes it as the POSIX class "lower" but PCRE does not recognize -"l\ower". This is a lesser evil than not diagnosing bad classes when Perl does, -I think. +below handles the special cases \\ and \], but does not try to do any other +escape processing. This makes it different from Perl for cases such as +[:l\ower:] where Perl recognizes it as the POSIX class "lower" but PCRE does +not recognize "l\ower". This is a lesser evil than not diagnosing bad classes +when Perl does, I think. A user pointed out that PCRE was rejecting [:a[:digit:]] whereas Perl was not. It seems that the appearance of a nested POSIX class supersedes an apparent @@ -3917,21 +3936,16 @@ pcre_uchar terminator; /* Don't combine these lines; the Solaris cc */ terminator = *(++ptr); /* compiler warns about "non-constant" initializer. */ for (++ptr; *ptr != CHAR_NULL; ptr++) { - if (*ptr == CHAR_BACKSLASH && ptr[1] == CHAR_RIGHT_SQUARE_BRACKET) + if (*ptr == CHAR_BACKSLASH && + (ptr[1] == CHAR_RIGHT_SQUARE_BRACKET || + ptr[1] == CHAR_BACKSLASH)) ptr++; - else if (*ptr == CHAR_RIGHT_SQUARE_BRACKET) return FALSE; - else + else if ((*ptr == CHAR_LEFT_SQUARE_BRACKET && ptr[1] == terminator) || + *ptr == CHAR_RIGHT_SQUARE_BRACKET) return FALSE; + else if (*ptr == terminator && ptr[1] == CHAR_RIGHT_SQUARE_BRACKET) { - if (*ptr == terminator && ptr[1] == CHAR_RIGHT_SQUARE_BRACKET) - { - *endptr = ptr; - return TRUE; - } - if (*ptr == CHAR_LEFT_SQUARE_BRACKET && - (ptr[1] == CHAR_COLON || ptr[1] == CHAR_DOT || - ptr[1] == CHAR_EQUALS_SIGN) && - check_posix_syntax(ptr, endptr)) - return FALSE; + *endptr = ptr; + return TRUE; } } return FALSE; @@ -3985,11 +3999,12 @@ have their offsets adjusted. That one of the jobs of this function. Before it is called, the partially compiled regex must be temporarily terminated with OP_END. -This function has been extended with the possibility of forward references for -recursions and subroutine calls. It must also check the list of such references -for the group we are dealing with. If it finds that one of the recursions in -the current group is on this list, it adjusts the offset in the list, not the -value in the reference (which is a group number). +This function has been extended to cope with forward references for recursions +and subroutine calls. It must check the list of such references for the +group we are dealing with. If it finds that one of the recursions in the +current group is on this list, it does not adjust the value in the reference +(which is a group number). After the group has been scanned, all the offsets in +the forward reference list for the group are adjusted. Arguments: group points to the start of the group @@ -4005,29 +4020,21 @@ static void adjust_recurse(pcre_uchar *group, int adjust, BOOL utf, compile_data *cd, size_t save_hwm_offset) { +int offset; +pcre_uchar *hc; pcre_uchar *ptr = group; while ((ptr = (pcre_uchar *)find_recurse(ptr, utf)) != NULL) { - int offset; - pcre_uchar *hc; - - /* See if this recursion is on the forward reference list. If so, adjust the - reference. */ - for (hc = (pcre_uchar *)cd->start_workspace + save_hwm_offset; hc < cd->hwm; hc += LINK_SIZE) { offset = (int)GET(hc, 0); - if (cd->start_code + offset == ptr + 1) - { - PUT(hc, 0, offset + adjust); - break; - } + if (cd->start_code + offset == ptr + 1) break; } - /* Otherwise, adjust the recursion offset if it's after the start of this - group. */ + /* If we have not found this recursion on the forward reference list, adjust + the recursion's offset if it's after the start of this group. */ if (hc >= cd->hwm) { @@ -4037,6 +4044,15 @@ while ((ptr = (pcre_uchar *)find_recurse(ptr, utf)) != NULL) ptr += 1 + LINK_SIZE; } + +/* Now adjust all forward reference offsets for the group. */ + +for (hc = (pcre_uchar *)cd->start_workspace + save_hwm_offset; hc < cd->hwm; + hc += LINK_SIZE) + { + offset = (int)GET(hc, 0); + PUT(hc, 0, offset + adjust); + } } @@ -4465,7 +4481,7 @@ const pcre_uchar *tempptr; const pcre_uchar *nestptr = NULL; pcre_uchar *previous = NULL; pcre_uchar *previous_callout = NULL; -size_t save_hwm_offset = 0; +size_t item_hwm_offset = 0; pcre_uint8 classbits[32]; /* We can fish out the UTF-8 setting once and for all into a BOOL, but we @@ -4767,6 +4783,7 @@ for (;; ptr++) zeroreqchar = reqchar; zeroreqcharflags = reqcharflags; previous = code; + item_hwm_offset = cd->hwm - cd->start_workspace; *code++ = ((options & PCRE_DOTALL) != 0)? OP_ALLANY: OP_ANY; break; @@ -4818,6 +4835,7 @@ for (;; ptr++) /* Handle a real character class. */ previous = code; + item_hwm_offset = cd->hwm - cd->start_workspace; /* PCRE supports POSIX class stuff inside a class. Perl gives an error if they are encountered at the top level, so we'll do that too. */ @@ -5195,9 +5213,9 @@ for (;; ptr++) cd, PRIV(vspace_list)); continue; -#ifdef SUPPORT_UCP case ESC_p: case ESC_P: +#ifdef SUPPORT_UCP { BOOL negated; unsigned int ptype = 0, pdata = 0; @@ -5211,6 +5229,9 @@ for (;; ptr++) class_has_8bitchar--; /* Undo! */ continue; } +#else + *errorcodeptr = ERR45; + goto FAILED; #endif /* Unrecognized escapes are faulted if PCRE is running in its strict mode. By default, for compatibility with Perl, they are @@ -5930,7 +5951,7 @@ for (;; ptr++) { register int i; int len = (int)(code - previous); - size_t base_hwm_offset = save_hwm_offset; + size_t base_hwm_offset = item_hwm_offset; pcre_uchar *bralink = NULL; pcre_uchar *brazeroptr = NULL; @@ -5985,7 +6006,7 @@ for (;; ptr++) if (repeat_max <= 1) /* Covers 0, 1, and unlimited */ { *code = OP_END; - adjust_recurse(previous, 1, utf, cd, save_hwm_offset); + adjust_recurse(previous, 1, utf, cd, item_hwm_offset); memmove(previous + 1, previous, IN_UCHARS(len)); code++; if (repeat_max == 0) @@ -6009,7 +6030,7 @@ for (;; ptr++) { int offset; *code = OP_END; - adjust_recurse(previous, 2 + LINK_SIZE, utf, cd, save_hwm_offset); + adjust_recurse(previous, 2 + LINK_SIZE, utf, cd, item_hwm_offset); memmove(previous + 2 + LINK_SIZE, previous, IN_UCHARS(len)); code += 2 + LINK_SIZE; *previous++ = OP_BRAZERO + repeat_type; @@ -6254,6 +6275,12 @@ for (;; ptr++) while (*scode == OP_ALT); } + /* A conditional group with only one branch has an implicit empty + alternative branch. */ + + if (*bracode == OP_COND && bracode[GET(bracode,1)] != OP_ALT) + *bracode = OP_SCOND; + /* Handle possessive quantifiers. */ if (possessive_quantifier) @@ -6267,11 +6294,11 @@ for (;; ptr++) { int nlen = (int)(code - bracode); *code = OP_END; - adjust_recurse(bracode, 1 + LINK_SIZE, utf, cd, save_hwm_offset); + adjust_recurse(bracode, 1 + LINK_SIZE, utf, cd, item_hwm_offset); memmove(bracode + 1 + LINK_SIZE, bracode, IN_UCHARS(nlen)); code += 1 + LINK_SIZE; nlen += 1 + LINK_SIZE; - *bracode = OP_BRAPOS; + *bracode = (*bracode == OP_COND)? OP_BRAPOS : OP_SBRAPOS; *code++ = OP_KETRPOS; PUTINC(code, 0, nlen); PUT(bracode, 1, nlen); @@ -6401,7 +6428,7 @@ for (;; ptr++) else { *code = OP_END; - adjust_recurse(tempcode, 1 + LINK_SIZE, utf, cd, save_hwm_offset); + adjust_recurse(tempcode, 1 + LINK_SIZE, utf, cd, item_hwm_offset); memmove(tempcode + 1 + LINK_SIZE, tempcode, IN_UCHARS(len)); code += 1 + LINK_SIZE; len += 1 + LINK_SIZE; @@ -6450,7 +6477,7 @@ for (;; ptr++) default: *code = OP_END; - adjust_recurse(tempcode, 1 + LINK_SIZE, utf, cd, save_hwm_offset); + adjust_recurse(tempcode, 1 + LINK_SIZE, utf, cd, item_hwm_offset); memmove(tempcode + 1 + LINK_SIZE, tempcode, IN_UCHARS(len)); code += 1 + LINK_SIZE; len += 1 + LINK_SIZE; @@ -6623,7 +6650,7 @@ for (;; ptr++) newoptions = options; skipbytes = 0; bravalue = OP_CBRA; - save_hwm_offset = cd->hwm - cd->start_workspace; + item_hwm_offset = cd->hwm - cd->start_workspace; reset_bracount = FALSE; /* Deal with the extended parentheses; all are introduced by '?', and the @@ -6641,6 +6668,7 @@ for (;; ptr++) /* ------------------------------------------------------------ */ case CHAR_VERTICAL_LINE: /* Reset capture count for each branch */ reset_bracount = TRUE; + cd->dupgroups = TRUE; /* Record (?| encountered */ /* Fall through */ /* ------------------------------------------------------------ */ @@ -6741,6 +6769,12 @@ for (;; ptr++) { while (IS_DIGIT(*ptr)) { + if (recno > INT_MAX / 10 - 1) /* Integer overflow */ + { + while (IS_DIGIT(*ptr)) ptr++; + *errorcodeptr = ERR61; + goto FAILED; + } recno = recno * 10 + (int)(*ptr - CHAR_0); ptr++; } @@ -6769,7 +6803,7 @@ for (;; ptr++) ptr++; } namelen = (int)(ptr - name); - if (lengthptr != NULL) *lengthptr += IMM2_SIZE; + if (lengthptr != NULL) skipbytes += IMM2_SIZE; } /* Check the terminator */ @@ -6875,6 +6909,11 @@ for (;; ptr++) *errorcodeptr = ERR15; goto FAILED; } + if (recno > INT_MAX / 10 - 1) /* Integer overflow */ + { + *errorcodeptr = ERR61; + goto FAILED; + } recno = recno * 10 + name[i] - CHAR_0; } if (recno == 0) recno = RREF_ANY; @@ -7151,7 +7190,8 @@ for (;; ptr++) if (lengthptr != NULL) { named_group *ng; - + recno = 0; + if (namelen == 0) { *errorcodeptr = ERR62; @@ -7168,20 +7208,6 @@ for (;; ptr++) goto FAILED; } - /* The name table does not exist in the first pass; instead we must - scan the list of names encountered so far in order to get the - number. If the name is not found, set the value to 0 for a forward - reference. */ - - ng = cd->named_groups; - for (i = 0; i < cd->names_found; i++, ng++) - { - if (namelen == ng->length && - STRNCMP_UC_UC(name, ng->name, namelen) == 0) - break; - } - recno = (i < cd->names_found)? ng->number : 0; - /* Count named back references. */ if (!is_recurse) cd->namedrefcount++; @@ -7191,6 +7217,56 @@ for (;; ptr++) 16-bit data item. */ *lengthptr += IMM2_SIZE; + + /* If this is a forward reference and we are within a (?|...) group, + the reference may end up as the number of a group which we are + currently inside, that is, it could be a recursive reference. In the + real compile this will be picked up and the reference wrapped with + OP_ONCE to make it atomic, so we must space in case this occurs. */ + + /* In fact, this can happen for a non-forward reference because + another group with the same number might be created later. This + issue is fixed "properly" in PCRE2. As PCRE1 is now in maintenance + only mode, we finesse the bug by allowing more memory always. */ + + *lengthptr += 2 + 2*LINK_SIZE; + + /* It is even worse than that. The current reference may be to an + existing named group with a different number (so apparently not + recursive) but which later on is also attached to a group with the + current number. This can only happen if $(| has been previous + encountered. In that case, we allow yet more memory, just in case. + (Again, this is fixed "properly" in PCRE2. */ + + if (cd->dupgroups) *lengthptr += 4 + 4*LINK_SIZE; + + /* Otherwise, check for recursion here. The name table does not exist + in the first pass; instead we must scan the list of names encountered + so far in order to get the number. If the name is not found, leave + the value of recno as 0 for a forward reference. */ + + else + { + ng = cd->named_groups; + for (i = 0; i < cd->names_found; i++, ng++) + { + if (namelen == ng->length && + STRNCMP_UC_UC(name, ng->name, namelen) == 0) + { + open_capitem *oc; + recno = ng->number; + if (is_recurse) break; + for (oc = cd->open_caps; oc != NULL; oc = oc->next) + { + if (oc->number == recno) + { + oc->flag = TRUE; + break; + } + } + } + } + } } /* In the real compile, search the name table. We check the name @@ -7237,8 +7313,6 @@ for (;; ptr++) for (i++; i < cd->names_found; i++) { if (STRCMP_UC_UC(slot + IMM2_SIZE, cslot + IMM2_SIZE) != 0) break; - - count++; cslot += cd->name_entry_size; } @@ -7247,6 +7321,7 @@ for (;; ptr++) { if (firstcharflags == REQ_UNSET) firstcharflags = REQ_NONE; previous = code; + item_hwm_offset = cd->hwm - cd->start_workspace; *code++ = ((options & PCRE_CASELESS) != 0)? OP_DNREFI : OP_DNREF; PUT2INC(code, 0, index); PUT2INC(code, 0, count); @@ -7284,9 +7359,14 @@ for (;; ptr++) /* ------------------------------------------------------------ */ - case CHAR_R: /* Recursion */ - ptr++; /* Same as (?0) */ - /* Fall through */ + case CHAR_R: /* Recursion, same as (?0) */ + recno = 0; + if (*(++ptr) != CHAR_RIGHT_PARENTHESIS) + { + *errorcodeptr = ERR29; + goto FAILED; + } + goto HANDLE_RECURSION; /* ------------------------------------------------------------ */ @@ -7323,7 +7403,15 @@ for (;; ptr++) recno = 0; while(IS_DIGIT(*ptr)) + { + if (recno > INT_MAX / 10 - 1) /* Integer overflow */ + { + while (IS_DIGIT(*ptr)) ptr++; + *errorcodeptr = ERR61; + goto FAILED; + } recno = recno * 10 + *ptr++ - CHAR_0; + } if (*ptr != (pcre_uchar)terminator) { @@ -7360,6 +7448,7 @@ for (;; ptr++) HANDLE_RECURSION: previous = code; + item_hwm_offset = cd->hwm - cd->start_workspace; called = cd->start_code; /* When we are actually compiling, find the bracket that is being @@ -7561,7 +7650,11 @@ for (;; ptr++) previous = NULL; cd->iscondassert = FALSE; } - else previous = code; + else + { + previous = code; + item_hwm_offset = cd->hwm - cd->start_workspace; + } *code = bravalue; tempcode = code; @@ -7809,7 +7902,7 @@ for (;; ptr++) const pcre_uchar *p; pcre_uint32 cf; - save_hwm_offset = cd->hwm - cd->start_workspace; /* Normally this is set when '(' is read */ + item_hwm_offset = cd->hwm - cd->start_workspace; /* Normally this is set when '(' is read */ terminator = (*(++ptr) == CHAR_LESS_THAN_SIGN)? CHAR_GREATER_THAN_SIGN : CHAR_APOSTROPHE; @@ -7838,7 +7931,7 @@ for (;; ptr++) if (*p != (pcre_uchar)terminator) { *errorcodeptr = ERR57; - break; + goto FAILED; } ptr++; goto HANDLE_NUMERICAL_RECURSION; @@ -7853,7 +7946,7 @@ for (;; ptr++) ptr[1] != CHAR_APOSTROPHE && ptr[1] != CHAR_LEFT_CURLY_BRACKET)) { *errorcodeptr = ERR69; - break; + goto FAILED; } is_recurse = FALSE; terminator = (*(++ptr) == CHAR_LESS_THAN_SIGN)? @@ -7877,6 +7970,7 @@ for (;; ptr++) HANDLE_REFERENCE: if (firstcharflags == REQ_UNSET) firstcharflags = REQ_NONE; previous = code; + item_hwm_offset = cd->hwm - cd->start_workspace; *code++ = ((options & PCRE_CASELESS) != 0)? OP_REFI : OP_REF; PUT2INC(code, 0, recno); cd->backref_map |= (recno < 32)? (1 << recno) : 1; @@ -7906,6 +8000,7 @@ for (;; ptr++) if (!get_ucp(&ptr, &negated, &ptype, &pdata, errorcodeptr)) goto FAILED; previous = code; + item_hwm_offset = cd->hwm - cd->start_workspace; *code++ = ((escape == ESC_p) != negated)? OP_PROP : OP_NOTPROP; *code++ = ptype; *code++ = pdata; @@ -7946,6 +8041,7 @@ for (;; ptr++) { previous = (escape > ESC_b && escape < ESC_Z)? code : NULL; + item_hwm_offset = cd->hwm - cd->start_workspace; *code++ = (!utf && escape == ESC_C)? OP_ALLANY : escape; } } @@ -7989,6 +8085,7 @@ for (;; ptr++) ONE_CHAR: previous = code; + item_hwm_offset = cd->hwm - cd->start_workspace; /* For caseless UTF-8 mode when UCP support is available, check whether this character has more than one other case. If so, generate a special @@ -9164,6 +9261,7 @@ cd->names_found = 0; cd->name_entry_size = 0; cd->name_table = NULL; cd->dupnames = FALSE; +cd->dupgroups = FALSE; cd->namedrefcount = 0; cd->start_code = cworkspace; cd->hwm = cworkspace; @@ -9198,7 +9296,7 @@ if (errorcode != 0) goto PCRE_EARLY_ERROR_RETURN; DPRINTF(("end pre-compile: length=%d workspace=%d\n", length, (int)(cd->hwm - cworkspace))); - + if (length > MAX_PATTERN_SIZE) { errorcode = ERR20; @@ -9336,6 +9434,16 @@ if (cd->hwm > cd->start_workspace) int offset, recno; cd->hwm -= LINK_SIZE; offset = GET(cd->hwm, 0); + + /* Check that the hwm handling hasn't gone wrong. This whole area is + rewritten in PCRE2 because there are some obscure cases. */ + + if (offset == 0 || codestart[offset-1] != OP_RECURSE) + { + errorcode = ERR10; + break; + } + recno = GET(codestart, offset); if (recno != prev_recno) { @@ -9366,7 +9474,7 @@ used in this code because at least one compiler gives a warning about loss of "const" attribute if the cast (pcre_uchar *)codestart is used directly in the function call. */ -if ((options & PCRE_NO_AUTO_POSSESS) == 0) +if (errorcode == 0 && (options & PCRE_NO_AUTO_POSSESS) == 0) { pcre_uchar *temp = (pcre_uchar *)codestart; auto_possessify(temp, utf, cd); @@ -9380,7 +9488,7 @@ OP_RECURSE that are not fixed length get a diagnosic with a useful offset. The exceptional ones forgo this. We scan the pattern to check that they are fixed length, and set their lengths. */ -if (cd->check_lookbehind) +if (errorcode == 0 && cd->check_lookbehind) { pcre_uchar *cc = (pcre_uchar *)codestart; @@ -9593,4 +9701,3 @@ return (pcre32 *)re; } /* End of pcre_compile.c */ - diff --git a/src/3rdparty/pcre/pcre_exec.c b/src/3rdparty/pcre/pcre_exec.c index c021fe1a4c..24b23ca286 100644 --- a/src/3rdparty/pcre/pcre_exec.c +++ b/src/3rdparty/pcre/pcre_exec.c @@ -6685,7 +6685,8 @@ if (md->offset_vector != NULL) register int *iend = iptr - re->top_bracket; if (iend < md->offset_vector + 2) iend = md->offset_vector + 2; while (--iptr >= iend) *iptr = -1; - md->offset_vector[0] = md->offset_vector[1] = -1; + if (offsetcount > 0) md->offset_vector[0] = -1; + if (offsetcount > 1) md->offset_vector[1] = -1; } /* Set up the first character to match, if available. The first_char value is diff --git a/src/3rdparty/pcre/pcre_internal.h b/src/3rdparty/pcre/pcre_internal.h index dd0ac7fc91..544d9c0709 100644 --- a/src/3rdparty/pcre/pcre_internal.h +++ b/src/3rdparty/pcre/pcre_internal.h @@ -984,7 +984,7 @@ other. NOTE: The values also appear in pcre_jit_compile.c. */ #ifndef EBCDIC #define HSPACE_LIST \ - CHAR_HT, CHAR_SPACE, 0xa0, \ + CHAR_HT, CHAR_SPACE, CHAR_NBSP, \ 0x1680, 0x180e, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, \ 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x202f, 0x205f, 0x3000, \ NOTACHAR @@ -1010,7 +1010,7 @@ other. NOTE: The values also appear in pcre_jit_compile.c. */ #define HSPACE_BYTE_CASES \ case CHAR_HT: \ case CHAR_SPACE: \ - case 0xa0 /* NBSP */ + case CHAR_NBSP #define HSPACE_CASES \ HSPACE_BYTE_CASES: \ @@ -1037,11 +1037,12 @@ other. NOTE: The values also appear in pcre_jit_compile.c. */ /* ------ EBCDIC environments ------ */ #else -#define HSPACE_LIST CHAR_HT, CHAR_SPACE +#define HSPACE_LIST CHAR_HT, CHAR_SPACE, CHAR_NBSP, NOTACHAR #define HSPACE_BYTE_CASES \ case CHAR_HT: \ - case CHAR_SPACE + case CHAR_SPACE: \ + case CHAR_NBSP #define HSPACE_CASES HSPACE_BYTE_CASES @@ -1215,6 +1216,7 @@ same code point. */ #define CHAR_ESC '\047' #define CHAR_DEL '\007' +#define CHAR_NBSP '\x41' #define STR_ESC "\047" #define STR_DEL "\007" @@ -1229,6 +1231,7 @@ a positive value. */ #define CHAR_NEL ((unsigned char)'\x85') #define CHAR_ESC '\033' #define CHAR_DEL '\177' +#define CHAR_NBSP ((unsigned char)'\xa0') #define STR_LF "\n" #define STR_NL STR_LF @@ -1606,6 +1609,7 @@ only. */ #define CHAR_VERTICAL_LINE '\174' #define CHAR_RIGHT_CURLY_BRACKET '\175' #define CHAR_TILDE '\176' +#define CHAR_NBSP ((unsigned char)'\xa0') #define STR_HT "\011" #define STR_VT "\013" @@ -1762,6 +1766,10 @@ only. */ /* Escape items that are just an encoding of a particular data value. */ +#ifndef ESC_a +#define ESC_a CHAR_BEL +#endif + #ifndef ESC_e #define ESC_e CHAR_ESC #endif @@ -2446,6 +2454,7 @@ typedef struct compile_data { BOOL had_pruneorskip; /* (*PRUNE) or (*SKIP) encountered */ BOOL check_lookbehind; /* Lookbehinds need later checking */ BOOL dupnames; /* Duplicate names exist */ + BOOL dupgroups; /* Duplicate groups exist: (?| found */ BOOL iscondassert; /* Next assert is a condition */ int nltype; /* Newline type */ int nllen; /* Newline string length */ diff --git a/src/3rdparty/pcre/pcre_jit_compile.c b/src/3rdparty/pcre/pcre_jit_compile.c index debdf6ef45..868d1d91bf 100644 --- a/src/3rdparty/pcre/pcre_jit_compile.c +++ b/src/3rdparty/pcre/pcre_jit_compile.c @@ -1064,6 +1064,7 @@ pcre_uchar *alternative; pcre_uchar *end = NULL; int private_data_ptr = *private_data_start; int space, size, bracketlen; +BOOL repeat_check = TRUE; while (cc < ccend) { @@ -1071,9 +1072,10 @@ while (cc < ccend) size = 0; bracketlen = 0; if (private_data_ptr > SLJIT_MAX_LOCAL_SIZE) - return; + break; - if (*cc == OP_ONCE || *cc == OP_ONCE_NC || *cc == OP_BRA || *cc == OP_CBRA || *cc == OP_COND) + if (repeat_check && (*cc == OP_ONCE || *cc == OP_ONCE_NC || *cc == OP_BRA || *cc == OP_CBRA || *cc == OP_COND)) + { if (detect_repeat(common, cc)) { /* These brackets are converted to repeats, so no global @@ -1081,6 +1083,8 @@ while (cc < ccend) if (cc >= end) end = bracketend(cc); } + } + repeat_check = TRUE; switch(*cc) { @@ -1136,6 +1140,13 @@ while (cc < ccend) bracketlen = 1 + LINK_SIZE + IMM2_SIZE; break; + case OP_BRAZERO: + case OP_BRAMINZERO: + case OP_BRAPOSZERO: + repeat_check = FALSE; + size = 1; + break; + CASE_ITERATOR_PRIVATE_DATA_1 space = 1; size = -2; @@ -1162,12 +1173,17 @@ while (cc < ccend) size = 1; break; - CASE_ITERATOR_TYPE_PRIVATE_DATA_2B + case OP_TYPEUPTO: if (cc[1 + IMM2_SIZE] != OP_ANYNL && cc[1 + IMM2_SIZE] != OP_EXTUNI) space = 2; size = 1 + IMM2_SIZE; break; + case OP_TYPEMINUPTO: + space = 2; + size = 1 + IMM2_SIZE; + break; + case OP_CLASS: case OP_NCLASS: size += 1 + 32 / sizeof(pcre_uchar); @@ -1316,6 +1332,13 @@ while (cc < ccend) cc += 1 + LINK_SIZE + IMM2_SIZE; break; + case OP_THEN: + stack_restore = TRUE; + if (common->control_head_ptr != 0) + *needs_control_head = TRUE; + cc ++; + break; + default: stack_restore = TRUE; /* Fall through. */ @@ -2220,6 +2243,7 @@ while (current != NULL) SLJIT_ASSERT_STOP(); break; } + SLJIT_ASSERT(current > (sljit_sw*)current[-1]); current = (sljit_sw*)current[-1]; } return -1; @@ -3209,7 +3233,7 @@ bytes[len] = byte; bytes[0] = len; } -static int scan_prefix(compiler_common *common, pcre_uchar *cc, pcre_uint32 *chars, pcre_uint8 *bytes, int max_chars) +static int scan_prefix(compiler_common *common, pcre_uchar *cc, pcre_uint32 *chars, pcre_uint8 *bytes, int max_chars, pcre_uint32 *rec_count) { /* Recursive function, which scans prefix literals. */ BOOL last, any, caseless; @@ -3227,9 +3251,14 @@ pcre_uchar othercase[1]; repeat = 1; while (TRUE) { + if (*rec_count == 0) + return 0; + (*rec_count)--; + last = TRUE; any = FALSE; caseless = FALSE; + switch (*cc) { case OP_CHARI: @@ -3291,7 +3320,7 @@ while (TRUE) #ifdef SUPPORT_UTF if (common->utf && HAS_EXTRALEN(*cc)) len += GET_EXTRALEN(*cc); #endif - max_chars = scan_prefix(common, cc + len, chars, bytes, max_chars); + max_chars = scan_prefix(common, cc + len, chars, bytes, max_chars, rec_count); if (max_chars == 0) return consumed; last = FALSE; @@ -3314,7 +3343,7 @@ while (TRUE) alternative = cc + GET(cc, 1); while (*alternative == OP_ALT) { - max_chars = scan_prefix(common, alternative + 1 + LINK_SIZE, chars, bytes, max_chars); + max_chars = scan_prefix(common, alternative + 1 + LINK_SIZE, chars, bytes, max_chars, rec_count); if (max_chars == 0) return consumed; alternative += GET(alternative, 1); @@ -3556,6 +3585,7 @@ int i, max, from; int range_right = -1, range_len = 3 - 1; sljit_ub *update_table = NULL; BOOL in_range; +pcre_uint32 rec_count; for (i = 0; i < MAX_N_CHARS; i++) { @@ -3564,7 +3594,8 @@ for (i = 0; i < MAX_N_CHARS; i++) bytes[i * MAX_N_BYTES] = 0; } -max = scan_prefix(common, common->start, chars, bytes, MAX_N_CHARS); +rec_count = 10000; +max = scan_prefix(common, common->start, chars, bytes, MAX_N_CHARS, &rec_count); if (max <= 1) return FALSE; @@ -7665,6 +7696,10 @@ while (*cc != OP_KETRPOS) OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); } + /* Even if the match is empty, we need to reset the control head. */ + if (needs_control_head) + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), STACK(stack)); + if (opcode == OP_SBRAPOS || opcode == OP_SCBRAPOS) add_jump(compiler, &emptymatch, CMP(SLJIT_EQUAL, TMP1, 0, STR_PTR, 0)); @@ -7692,6 +7727,10 @@ while (*cc != OP_KETRPOS) OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), (framesize + 1) * sizeof(sljit_sw), STR_PTR, 0); } + /* Even if the match is empty, we need to reset the control head. */ + if (needs_control_head) + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), STACK(stack)); + if (opcode == OP_SBRAPOS || opcode == OP_SCBRAPOS) add_jump(compiler, &emptymatch, CMP(SLJIT_EQUAL, TMP1, 0, STR_PTR, 0)); @@ -7704,9 +7743,6 @@ while (*cc != OP_KETRPOS) } } - if (needs_control_head) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), STACK(stack)); - JUMPTO(SLJIT_JUMP, loop); flush_stubs(common); @@ -9648,6 +9684,7 @@ set_jumps(common->currententry->calls, common->currententry->entry); sljit_emit_fast_enter(compiler, TMP2, 0); allocate_stack(common, private_data_size + framesize + alternativesize); +count_match(common); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(private_data_size + framesize + alternativesize - 1), TMP2, 0); copy_private_data(common, ccbegin, ccend, TRUE, private_data_size + framesize + alternativesize, framesize + alternativesize, needs_control_head); if (needs_control_head) @@ -9992,6 +10029,7 @@ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, stack)); OP1(SLJIT_MOV_UI, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, limit_match)); OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(struct sljit_stack, base)); OP1(SLJIT_MOV, STACK_LIMIT, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(struct sljit_stack, limit)); +OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LIMIT_MATCH, TMP1, 0); if (mode == JIT_PARTIAL_SOFT_COMPILE) diff --git a/src/3rdparty/pcre/pcre_study.c b/src/3rdparty/pcre/pcre_study.c index 998fe2325e..932e9a7c4c 100644 --- a/src/3rdparty/pcre/pcre_study.c +++ b/src/3rdparty/pcre/pcre_study.c @@ -71,6 +71,7 @@ Arguments: startcode pointer to start of the whole pattern's code options the compiling options recurses chain of recurse_check to catch mutual recursion + countptr pointer to call count (to catch over complexity) Returns: the minimum length -1 if \C in UTF-8 mode or (*ACCEPT) was encountered @@ -80,7 +81,8 @@ Returns: the minimum length static int find_minlength(const REAL_PCRE *re, const pcre_uchar *code, - const pcre_uchar *startcode, int options, recurse_check *recurses) + const pcre_uchar *startcode, int options, recurse_check *recurses, + int *countptr) { int length = -1; /* PCRE_UTF16 has the same value as PCRE_UTF8. */ @@ -90,6 +92,8 @@ recurse_check this_recurse; register int branchlength = 0; register pcre_uchar *cc = (pcre_uchar *)code + 1 + LINK_SIZE; +if ((*countptr)++ > 1000) return -1; /* too complex */ + if (*code == OP_CBRA || *code == OP_SCBRA || *code == OP_CBRAPOS || *code == OP_SCBRAPOS) cc += IMM2_SIZE; @@ -131,7 +135,7 @@ for (;;) case OP_SBRAPOS: case OP_ONCE: case OP_ONCE_NC: - d = find_minlength(re, cc, startcode, options, recurses); + d = find_minlength(re, cc, startcode, options, recurses, countptr); if (d < 0) return d; branchlength += d; do cc += GET(cc, 1); while (*cc == OP_ALT); @@ -415,7 +419,8 @@ for (;;) int dd; this_recurse.prev = recurses; this_recurse.group = cs; - dd = find_minlength(re, cs, startcode, options, &this_recurse); + dd = find_minlength(re, cs, startcode, options, &this_recurse, + countptr); if (dd < d) d = dd; } } @@ -451,7 +456,8 @@ for (;;) { this_recurse.prev = recurses; this_recurse.group = cs; - d = find_minlength(re, cs, startcode, options, &this_recurse); + d = find_minlength(re, cs, startcode, options, &this_recurse, + countptr); } } } @@ -514,7 +520,7 @@ for (;;) this_recurse.prev = recurses; this_recurse.group = cs; branchlength += find_minlength(re, cs, startcode, options, - &this_recurse); + &this_recurse, countptr); } } cc += 1 + LINK_SIZE; @@ -1453,6 +1459,7 @@ pcre32_study(const pcre32 *external_re, int options, const char **errorptr) #endif { int min; +int count = 0; BOOL bits_set = FALSE; pcre_uint8 start_bits[32]; PUBL(extra) *extra = NULL; @@ -1539,7 +1546,7 @@ if ((re->options & PCRE_ANCHORED) == 0 && /* Find the minimum length of subject string. */ -switch(min = find_minlength(re, code, code, re->options, NULL)) +switch(min = find_minlength(re, code, code, re->options, NULL, &count)) { case -2: *errorptr = "internal error: missing capturing bracket"; return NULL; case -3: *errorptr = "internal error: opcode not recognized"; return NULL; diff --git a/src/3rdparty/pcre/sljit/sljitConfig.h b/src/3rdparty/pcre/sljit/sljitConfig.h index 10364c3b60..1c8a521aa8 100644 --- a/src/3rdparty/pcre/sljit/sljitConfig.h +++ b/src/3rdparty/pcre/sljit/sljitConfig.h @@ -96,6 +96,15 @@ #define SLJIT_EXECUTABLE_ALLOCATOR 1 #endif +/* Force cdecl calling convention even if a better calling + convention (e.g. fastcall) is supported by the C compiler. + If this option is enabled, C functions without + SLJIT_CALL can also be called from JIT code. */ +#ifndef SLJIT_USE_CDECL_CALLING_CONVENTION +/* Disabled by default */ +#define SLJIT_USE_CDECL_CALLING_CONVENTION 0 +#endif + /* Return with error when an invalid argument is passed. */ #ifndef SLJIT_ARGUMENT_CHECKS /* Disabled by default */ diff --git a/src/3rdparty/pcre/sljit/sljitConfigInternal.h b/src/3rdparty/pcre/sljit/sljitConfigInternal.h index 3284012f19..16e3547c93 100644 --- a/src/3rdparty/pcre/sljit/sljitConfigInternal.h +++ b/src/3rdparty/pcre/sljit/sljitConfigInternal.h @@ -468,7 +468,12 @@ typedef double sljit_d; #ifndef SLJIT_CALL -#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) +#if (defined SLJIT_USE_CDECL_CALLING_CONVENTION && SLJIT_USE_CDECL_CALLING_CONVENTION) + +/* Force cdecl. */ +#define SLJIT_CALL + +#elif (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) #if defined(__GNUC__) && !defined(__APPLE__) @@ -608,6 +613,12 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void); #define SLJIT_LOCALS_OFFSET_BASE ((23 + 1) * sizeof(sljit_sw)) #endif +#elif (defined SLJIT_CONFIG_TILEGX && SLJIT_CONFIG_TILEGX) + +#define SLJIT_NUMBER_OF_REGISTERS 10 +#define SLJIT_NUMBER_OF_SAVED_REGISTERS 5 +#define SLJIT_LOCALS_OFFSET_BASE 0 + #elif (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) #define SLJIT_NUMBER_OF_REGISTERS 0 diff --git a/src/3rdparty/pcre/sljit/sljitLir.c b/src/3rdparty/pcre/sljit/sljitLir.c index 5039a7e04e..0f1b1c9cce 100644 --- a/src/3rdparty/pcre/sljit/sljitLir.c +++ b/src/3rdparty/pcre/sljit/sljitLir.c @@ -845,8 +845,8 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_compiler_verbose(struct sljit_compiler *comp } static SLJIT_CONST char* op0_names[] = { - (char*)"breakpoint", (char*)"nop", - (char*)"lumul", (char*)"lsmul", (char*)"ludiv", (char*)"lsdiv", + (char*)"breakpoint", (char*)"nop", (char*)"lumul", (char*)"lsmul", + (char*)"udivmod", (char*)"sdivmod", (char*)"udivi", (char*)"sdivi" }; static SLJIT_CONST char* op1_names[] = { @@ -1036,7 +1036,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op0(struct sljit_compiler { #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) CHECK_ARGUMENT((op >= SLJIT_BREAKPOINT && op <= SLJIT_LSMUL) - || ((op & ~SLJIT_INT_OP) >= SLJIT_LUDIV && (op & ~SLJIT_INT_OP) <= SLJIT_LSDIV)); + || ((op & ~SLJIT_INT_OP) >= SLJIT_UDIVMOD && (op & ~SLJIT_INT_OP) <= SLJIT_SDIVI)); CHECK_ARGUMENT(op < SLJIT_LUMUL || compiler->scratches >= 2); #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) @@ -1447,6 +1447,8 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_flags(struct sljit_com static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_get_local_base(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw offset) { + SLJIT_UNUSED_ARG(offset); + #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) FUNCTION_CHECK_DST(dst, dstw); #endif @@ -1462,6 +1464,8 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_get_local_base(struct sljit_co static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_const(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw init_value) { + SLJIT_UNUSED_ARG(init_value); + #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) FUNCTION_CHECK_DST(dst, dstw); #endif diff --git a/src/3rdparty/pcre/sljit/sljitLir.h b/src/3rdparty/pcre/sljit/sljitLir.h index 24c0f60399..f0969dac2e 100644 --- a/src/3rdparty/pcre/sljit/sljitLir.h +++ b/src/3rdparty/pcre/sljit/sljitLir.h @@ -687,7 +687,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler * #define SLJIT_OP0_BASE 0 /* Flags: - (never set any flags) - Note: breakpoint instruction is not supported by all architectures (namely ppc) + Note: breakpoint instruction is not supported by all architectures (e.g. ppc) It falls back to SLJIT_NOP in those cases. */ #define SLJIT_BREAKPOINT (SLJIT_OP0_BASE + 0) /* Flags: - (never set any flags) @@ -696,24 +696,42 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler * #define SLJIT_NOP (SLJIT_OP0_BASE + 1) /* Flags: - (may destroy flags) Unsigned multiplication of SLJIT_R0 and SLJIT_R1. - Result goes to SLJIT_R1:SLJIT_R0 (high:low) word */ + Result is placed into SLJIT_R1:SLJIT_R0 (high:low) word */ #define SLJIT_LUMUL (SLJIT_OP0_BASE + 2) /* Flags: - (may destroy flags) Signed multiplication of SLJIT_R0 and SLJIT_R1. - Result goes to SLJIT_R1:SLJIT_R0 (high:low) word */ + Result is placed into SLJIT_R1:SLJIT_R0 (high:low) word */ #define SLJIT_LSMUL (SLJIT_OP0_BASE + 3) /* Flags: I - (may destroy flags) Unsigned divide of the value in SLJIT_R0 by the value in SLJIT_R1. - The result is placed in SLJIT_R0 and the remainder goes to SLJIT_R1. - Note: if SLJIT_R1 contains 0, the behaviour is undefined. */ -#define SLJIT_LUDIV (SLJIT_OP0_BASE + 4) -#define SLJIT_ILUDIV (SLJIT_LUDIV | SLJIT_INT_OP) + The result is placed into SLJIT_R0 and the remainder into SLJIT_R1. + Note: if SLJIT_R1 is 0, the behaviour is undefined. */ +#define SLJIT_UDIVMOD (SLJIT_OP0_BASE + 4) +#define SLJIT_IUDIVMOD (SLJIT_UDIVMOD | SLJIT_INT_OP) /* Flags: I - (may destroy flags) Signed divide of the value in SLJIT_R0 by the value in SLJIT_R1. - The result is placed in SLJIT_R0 and the remainder goes to SLJIT_R1. - Note: if SLJIT_R1 contains 0, the behaviour is undefined. */ -#define SLJIT_LSDIV (SLJIT_OP0_BASE + 5) -#define SLJIT_ILSDIV (SLJIT_LSDIV | SLJIT_INT_OP) + The result is placed into SLJIT_R0 and the remainder into SLJIT_R1. + Note: if SLJIT_R1 is 0, the behaviour is undefined. + Note: if SLJIT_R1 is -1 and SLJIT_R0 is integer min (0x800..00), + the behaviour is undefined. */ +#define SLJIT_SDIVMOD (SLJIT_OP0_BASE + 5) +#define SLJIT_ISDIVMOD (SLJIT_SDIVMOD | SLJIT_INT_OP) +/* Flags: I - (may destroy flags) + Unsigned divide of the value in SLJIT_R0 by the value in SLJIT_R1. + The result is placed into SLJIT_R0. SLJIT_R1 preserves its value. + Note: if SLJIT_R1 is 0, the behaviour is undefined. + Note: SLJIT_SDIV is single precision divide. */ +#define SLJIT_UDIVI (SLJIT_OP0_BASE + 6) +#define SLJIT_IUDIVI (SLJIT_UDIVI | SLJIT_INT_OP) +/* Flags: I - (may destroy flags) + Signed divide of the value in SLJIT_R0 by the value in SLJIT_R1. + The result is placed into SLJIT_R0. SLJIT_R1 preserves its value. + Note: if SLJIT_R1 is 0, the behaviour is undefined. + Note: if SLJIT_R1 is -1 and SLJIT_R0 is integer min (0x800..00), + the behaviour is undefined. + Note: SLJIT_SDIV is single precision divide. */ +#define SLJIT_SDIVI (SLJIT_OP0_BASE + 7) +#define SLJIT_ISDIVI (SLJIT_SDIVI | SLJIT_INT_OP) SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler, sljit_si op); diff --git a/src/3rdparty/pcre/sljit/sljitNativeARM_32.c b/src/3rdparty/pcre/sljit/sljitNativeARM_32.c index aca1d31fdf..5cd4c71a29 100644 --- a/src/3rdparty/pcre/sljit/sljitNativeARM_32.c +++ b/src/3rdparty/pcre/sljit/sljitNativeARM_32.c @@ -1833,18 +1833,33 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler | (reg_map[SLJIT_R0] << 8) | reg_map[TMP_REG1]); #endif - case SLJIT_LUDIV: - case SLJIT_LSDIV: - if (compiler->scratches >= 3) + case SLJIT_UDIVMOD: + case SLJIT_SDIVMOD: + case SLJIT_UDIVI: + case SLJIT_SDIVI: + SLJIT_COMPILE_ASSERT((SLJIT_UDIVMOD & 0x2) == 0 && SLJIT_UDIVI - 0x2 == SLJIT_UDIVMOD, bad_div_opcode_assignments); + SLJIT_COMPILE_ASSERT(reg_map[2] == 1 && reg_map[3] == 2, bad_register_mapping); + + if ((op >= SLJIT_UDIVI) && (compiler->scratches >= 3)) { FAIL_IF(push_inst(compiler, 0xe52d2008 /* str r2, [sp, #-8]! */)); + FAIL_IF(push_inst(compiler, 0xe58d1004 /* str r1, [sp, #4] */)); + } + else if ((op >= SLJIT_UDIVI) || (compiler->scratches >= 3)) + FAIL_IF(push_inst(compiler, 0xe52d0008 | (op >= SLJIT_UDIVI ? 0x1000 : 0x2000) /* str r1/r2, [sp, #-8]! */)); + #if defined(__GNUC__) FAIL_IF(sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_IMM, - (op == SLJIT_LUDIV ? SLJIT_FUNC_OFFSET(__aeabi_uidivmod) : SLJIT_FUNC_OFFSET(__aeabi_idivmod)))); + ((op | 0x2) == SLJIT_UDIVI ? SLJIT_FUNC_OFFSET(__aeabi_uidivmod) : SLJIT_FUNC_OFFSET(__aeabi_idivmod)))); #else #error "Software divmod functions are needed" #endif - if (compiler->scratches >= 3) - return push_inst(compiler, 0xe49d2008 /* ldr r2, [sp], #8 */); + + if ((op >= SLJIT_UDIVI) && (compiler->scratches >= 3)) { + FAIL_IF(push_inst(compiler, 0xe59d1004 /* ldr r1, [sp, #4] */)); + FAIL_IF(push_inst(compiler, 0xe49d2008 /* ldr r2, [sp], #8 */)); + } + else if ((op >= SLJIT_UDIVI) || (compiler->scratches >= 3)) + return push_inst(compiler, 0xe49d0008 | (op >= SLJIT_UDIVI ? 0x1000 : 0x2000) /* ldr r1/r2, [sp], #8 */); return SLJIT_SUCCESS; } diff --git a/src/3rdparty/pcre/sljit/sljitNativeARM_64.c b/src/3rdparty/pcre/sljit/sljitNativeARM_64.c index b66455f756..044a675eee 100644 --- a/src/3rdparty/pcre/sljit/sljitNativeARM_64.c +++ b/src/3rdparty/pcre/sljit/sljitNativeARM_64.c @@ -1087,14 +1087,20 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil saved_regs_size += sizeof(sljit_sw); } local_size -= saved_regs_size + SLJIT_LOCALS_OFFSET; - FAIL_IF(push_inst(compiler, SUBI | RD(TMP_SP) | RN(TMP_SP) | (saved_regs_size << 10))); + if (saved_regs_size > 0) + FAIL_IF(push_inst(compiler, SUBI | RD(TMP_SP) | RN(TMP_SP) | (saved_regs_size << 10))); } tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG; prev = -1; for (i = SLJIT_S0; i >= tmp; i--) { if (prev == -1) { - prev = i; + if (!(offs & (1 << 15))) { + prev = i; + continue; + } + FAIL_IF(push_inst(compiler, STRI | RT(i) | RN(TMP_SP) | (offs >> 5))); + offs += 1 << 15; continue; } FAIL_IF(push_inst(compiler, STP | RT(prev) | RT2(i) | RN(TMP_SP) | offs)); @@ -1104,7 +1110,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) { if (prev == -1) { - prev = i; + if (!(offs & (1 << 15))) { + prev = i; + continue; + } + FAIL_IF(push_inst(compiler, STRI | RT(i) | RN(TMP_SP) | (offs >> 5))); + offs += 1 << 15; continue; } FAIL_IF(push_inst(compiler, STP | RT(prev) | RT2(i) | RN(TMP_SP) | offs)); @@ -1112,8 +1123,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil prev = -1; } - if (prev != -1) - FAIL_IF(push_inst(compiler, STRI | RT(prev) | RN(TMP_SP) | (offs >> 5))); + SLJIT_ASSERT(prev == -1); if (compiler->local_size > (63 * sizeof(sljit_sw))) { /* The local_size is already adjusted by the saved registers. */ @@ -1188,7 +1198,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compi prev = -1; for (i = SLJIT_S0; i >= tmp; i--) { if (prev == -1) { - prev = i; + if (!(offs & (1 << 15))) { + prev = i; + continue; + } + FAIL_IF(push_inst(compiler, LDRI | RT(i) | RN(TMP_SP) | (offs >> 5))); + offs += 1 << 15; continue; } FAIL_IF(push_inst(compiler, LDP | RT(prev) | RT2(i) | RN(TMP_SP) | offs)); @@ -1198,7 +1213,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compi for (i = compiler->scratches; i >= SLJIT_FIRST_SAVED_REG; i--) { if (prev == -1) { - prev = i; + if (!(offs & (1 << 15))) { + prev = i; + continue; + } + FAIL_IF(push_inst(compiler, LDRI | RT(i) | RN(TMP_SP) | (offs >> 5))); + offs += 1 << 15; continue; } FAIL_IF(push_inst(compiler, LDP | RT(prev) | RT2(i) | RN(TMP_SP) | offs)); @@ -1206,13 +1226,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compi prev = -1; } - if (prev != -1) - FAIL_IF(push_inst(compiler, LDRI | RT(prev) | RN(TMP_SP) | (offs >> 5))); + SLJIT_ASSERT(prev == -1); if (compiler->local_size <= (63 * sizeof(sljit_sw))) { FAIL_IF(push_inst(compiler, LDP_PST | 29 | RT2(TMP_LR) | RN(TMP_SP) | (((local_size >> 3) & 0x7f) << 15))); - } else { + } else if (saved_regs_size > 0) { FAIL_IF(push_inst(compiler, ADDI | RD(TMP_SP) | RN(TMP_SP) | (saved_regs_size << 10))); } @@ -1242,12 +1261,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler FAIL_IF(push_inst(compiler, ORR | RD(TMP_REG1) | RN(TMP_ZERO) | RM(SLJIT_R0))); FAIL_IF(push_inst(compiler, MADD | RD(SLJIT_R0) | RN(SLJIT_R0) | RM(SLJIT_R1) | RT2(TMP_ZERO))); return push_inst(compiler, (op == SLJIT_LUMUL ? UMULH : SMULH) | RD(SLJIT_R1) | RN(TMP_REG1) | RM(SLJIT_R1)); - case SLJIT_LUDIV: - case SLJIT_LSDIV: + case SLJIT_UDIVMOD: + case SLJIT_SDIVMOD: FAIL_IF(push_inst(compiler, (ORR ^ inv_bits) | RD(TMP_REG1) | RN(TMP_ZERO) | RM(SLJIT_R0))); - FAIL_IF(push_inst(compiler, ((op == SLJIT_LUDIV ? UDIV : SDIV) ^ inv_bits) | RD(SLJIT_R0) | RN(SLJIT_R0) | RM(SLJIT_R1))); + FAIL_IF(push_inst(compiler, ((op == SLJIT_UDIVMOD ? UDIV : SDIV) ^ inv_bits) | RD(SLJIT_R0) | RN(SLJIT_R0) | RM(SLJIT_R1))); FAIL_IF(push_inst(compiler, (MADD ^ inv_bits) | RD(SLJIT_R1) | RN(SLJIT_R0) | RM(SLJIT_R1) | RT2(TMP_ZERO))); return push_inst(compiler, (SUB ^ inv_bits) | RD(SLJIT_R1) | RN(TMP_REG1) | RM(SLJIT_R1)); + case SLJIT_UDIVI: + case SLJIT_SDIVI: + return push_inst(compiler, ((op == SLJIT_UDIVI ? UDIV : SDIV) ^ inv_bits) | RD(SLJIT_R0) | RN(SLJIT_R0) | RM(SLJIT_R1)); } return SLJIT_SUCCESS; diff --git a/src/3rdparty/pcre/sljit/sljitNativeARM_T2_32.c b/src/3rdparty/pcre/sljit/sljitNativeARM_T2_32.c index 6e38cec899..f9803f5d44 100644 --- a/src/3rdparty/pcre/sljit/sljitNativeARM_T2_32.c +++ b/src/3rdparty/pcre/sljit/sljitNativeARM_T2_32.c @@ -1239,6 +1239,9 @@ extern int __aeabi_idivmod(int numerator, int denominator); SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler, sljit_si op) { + sljit_sw saved_reg_list[3]; + sljit_sw saved_reg_count; + CHECK_ERROR(); CHECK(check_sljit_emit_op0(compiler, op)); @@ -1255,24 +1258,53 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler | (reg_map[SLJIT_R0] << 12) | (reg_map[SLJIT_R0] << 16) | reg_map[SLJIT_R1]); - case SLJIT_LUDIV: - case SLJIT_LSDIV: - if (compiler->scratches >= 4) { - FAIL_IF(push_inst32(compiler, 0xf84d2d04 /* str r2, [sp, #-4]! */)); - FAIL_IF(push_inst32(compiler, 0xf84dcd04 /* str ip, [sp, #-4]! */)); - } else if (compiler->scratches >= 3) - FAIL_IF(push_inst32(compiler, 0xf84d2d08 /* str r2, [sp, #-8]! */)); + case SLJIT_UDIVMOD: + case SLJIT_SDIVMOD: + case SLJIT_UDIVI: + case SLJIT_SDIVI: + SLJIT_COMPILE_ASSERT((SLJIT_UDIVMOD & 0x2) == 0 && SLJIT_UDIVI - 0x2 == SLJIT_UDIVMOD, bad_div_opcode_assignments); + SLJIT_COMPILE_ASSERT(reg_map[2] == 1 && reg_map[3] == 2 && reg_map[4] == 12, bad_register_mapping); + + saved_reg_count = 0; + if (compiler->scratches >= 4) + saved_reg_list[saved_reg_count++] = 12; + if (compiler->scratches >= 3) + saved_reg_list[saved_reg_count++] = 2; + if (op >= SLJIT_UDIVI) + saved_reg_list[saved_reg_count++] = 1; + + if (saved_reg_count > 0) { + FAIL_IF(push_inst32(compiler, 0xf84d0d00 | (saved_reg_count >= 3 ? 16 : 8) + | (saved_reg_list[0] << 12) /* str rX, [sp, #-8/-16]! */)); + if (saved_reg_count >= 2) { + SLJIT_ASSERT(saved_reg_list[1] < 8); + FAIL_IF(push_inst16(compiler, 0x9001 | (saved_reg_list[1] << 8) /* str rX, [sp, #4] */)); + } + if (saved_reg_count >= 3) { + SLJIT_ASSERT(saved_reg_list[2] < 8); + FAIL_IF(push_inst16(compiler, 0x9002 | (saved_reg_list[2] << 8) /* str rX, [sp, #8] */)); + } + } + #if defined(__GNUC__) FAIL_IF(sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_IMM, - (op == SLJIT_LUDIV ? SLJIT_FUNC_OFFSET(__aeabi_uidivmod) : SLJIT_FUNC_OFFSET(__aeabi_idivmod)))); + ((op | 0x2) == SLJIT_UDIVI ? SLJIT_FUNC_OFFSET(__aeabi_uidivmod) : SLJIT_FUNC_OFFSET(__aeabi_idivmod)))); #else #error "Software divmod functions are needed" #endif - if (compiler->scratches >= 4) { - FAIL_IF(push_inst32(compiler, 0xf85dcb04 /* ldr ip, [sp], #4 */)); - return push_inst32(compiler, 0xf85d2b04 /* ldr r2, [sp], #4 */); - } else if (compiler->scratches >= 3) - return push_inst32(compiler, 0xf85d2b08 /* ldr r2, [sp], #8 */); + + if (saved_reg_count > 0) { + if (saved_reg_count >= 3) { + SLJIT_ASSERT(saved_reg_list[2] < 8); + FAIL_IF(push_inst16(compiler, 0x9802 | (saved_reg_list[2] << 8) /* ldr rX, [sp, #8] */)); + } + if (saved_reg_count >= 2) { + SLJIT_ASSERT(saved_reg_list[1] < 8); + FAIL_IF(push_inst16(compiler, 0x9801 | (saved_reg_list[1] << 8) /* ldr rX, [sp, #4] */)); + } + return push_inst32(compiler, 0xf85d0b00 | (saved_reg_count >= 3 ? 16 : 8) + | (saved_reg_list[0] << 12) /* ldr rX, [sp], #8/16 */); + } return SLJIT_SUCCESS; } diff --git a/src/3rdparty/pcre/sljit/sljitNativeMIPS_common.c b/src/3rdparty/pcre/sljit/sljitNativeMIPS_common.c index 3e2c9f0232..cf3535f81a 100644 --- a/src/3rdparty/pcre/sljit/sljitNativeMIPS_common.c +++ b/src/3rdparty/pcre/sljit/sljitNativeMIPS_common.c @@ -1053,8 +1053,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler #endif FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_R0), DR(SLJIT_R0))); return push_inst(compiler, MFHI | D(SLJIT_R1), DR(SLJIT_R1)); - case SLJIT_LUDIV: - case SLJIT_LSDIV: + case SLJIT_UDIVMOD: + case SLJIT_SDIVMOD: + case SLJIT_UDIVI: + case SLJIT_SDIVI: + SLJIT_COMPILE_ASSERT((SLJIT_UDIVMOD & 0x2) == 0 && SLJIT_UDIVI - 0x2 == SLJIT_UDIVMOD, bad_div_opcode_assignments); #if !(defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); @@ -1062,15 +1065,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) if (int_op) - FAIL_IF(push_inst(compiler, (op == SLJIT_LUDIV ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS)); + FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_UDIVI ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS)); else - FAIL_IF(push_inst(compiler, (op == SLJIT_LUDIV ? DDIVU : DDIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS)); + FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_UDIVI ? DDIVU : DDIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS)); #else - FAIL_IF(push_inst(compiler, (op == SLJIT_LUDIV ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS)); + FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_UDIVI ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS)); #endif FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_R0), DR(SLJIT_R0))); - return push_inst(compiler, MFHI | D(SLJIT_R1), DR(SLJIT_R1)); + return (op >= SLJIT_UDIVI) ? SLJIT_SUCCESS : push_inst(compiler, MFHI | D(SLJIT_R1), DR(SLJIT_R1)); } return SLJIT_SUCCESS; diff --git a/src/3rdparty/pcre/sljit/sljitNativePPC_common.c b/src/3rdparty/pcre/sljit/sljitNativePPC_common.c index 08d5356f5a..b6a043f4e4 100644 --- a/src/3rdparty/pcre/sljit/sljitNativePPC_common.c +++ b/src/3rdparty/pcre/sljit/sljitNativePPC_common.c @@ -1267,22 +1267,23 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R1))); return push_inst(compiler, (op == SLJIT_LUMUL ? MULHWU : MULHW) | D(SLJIT_R1) | A(TMP_REG1) | B(SLJIT_R1)); #endif - case SLJIT_LUDIV: - case SLJIT_LSDIV: + case SLJIT_UDIVMOD: + case SLJIT_SDIVMOD: FAIL_IF(push_inst(compiler, OR | S(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R0))); #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) - if (int_op) { - FAIL_IF(push_inst(compiler, (op == SLJIT_LUDIV ? DIVWU : DIVW) | D(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R1))); - FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_R1) | A(SLJIT_R0) | B(SLJIT_R1))); - } else { - FAIL_IF(push_inst(compiler, (op == SLJIT_LUDIV ? DIVDU : DIVD) | D(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R1))); - FAIL_IF(push_inst(compiler, MULLD | D(SLJIT_R1) | A(SLJIT_R0) | B(SLJIT_R1))); - } - return push_inst(compiler, SUBF | D(SLJIT_R1) | A(SLJIT_R1) | B(TMP_REG1)); + FAIL_IF(push_inst(compiler, (int_op ? (op == SLJIT_UDIVMOD ? DIVWU : DIVW) : (op == SLJIT_UDIVMOD ? DIVDU : DIVD)) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1))); + FAIL_IF(push_inst(compiler, (int_op ? MULLW : MULLD) | D(SLJIT_R1) | A(SLJIT_R0) | B(SLJIT_R1))); #else - FAIL_IF(push_inst(compiler, (op == SLJIT_LUDIV ? DIVWU : DIVW) | D(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R1))); + FAIL_IF(push_inst(compiler, (op == SLJIT_UDIVMOD ? DIVWU : DIVW) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1))); FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_R1) | A(SLJIT_R0) | B(SLJIT_R1))); +#endif return push_inst(compiler, SUBF | D(SLJIT_R1) | A(SLJIT_R1) | B(TMP_REG1)); + case SLJIT_UDIVI: + case SLJIT_SDIVI: +#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) + return push_inst(compiler, (int_op ? (op == SLJIT_UDIVI ? DIVWU : DIVW) : (op == SLJIT_UDIVI ? DIVDU : DIVD)) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1)); +#else + return push_inst(compiler, (op == SLJIT_UDIVI ? DIVWU : DIVW) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1)); #endif } diff --git a/src/3rdparty/pcre/sljit/sljitNativeSPARC_common.c b/src/3rdparty/pcre/sljit/sljitNativeSPARC_common.c index 0b1927a824..327c4267be 100644 --- a/src/3rdparty/pcre/sljit/sljitNativeSPARC_common.c +++ b/src/3rdparty/pcre/sljit/sljitNativeSPARC_common.c @@ -777,20 +777,25 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler #else #error "Implementation required" #endif - case SLJIT_LUDIV: - case SLJIT_LSDIV: + case SLJIT_UDIVMOD: + case SLJIT_SDIVMOD: + case SLJIT_UDIVI: + case SLJIT_SDIVI: + SLJIT_COMPILE_ASSERT((SLJIT_UDIVMOD & 0x2) == 0 && SLJIT_UDIVI - 0x2 == SLJIT_UDIVMOD, bad_div_opcode_assignments); #if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) - if (op == SLJIT_LUDIV) + if ((op | 0x2) == SLJIT_UDIVI) FAIL_IF(push_inst(compiler, WRY | S1(0), MOVABLE_INS)); else { FAIL_IF(push_inst(compiler, SRA | D(TMP_REG1) | S1(SLJIT_R0) | IMM(31), DR(TMP_REG1))); FAIL_IF(push_inst(compiler, WRY | S1(TMP_REG1), MOVABLE_INS)); } - FAIL_IF(push_inst(compiler, OR | D(TMP_REG2) | S1(0) | S2(SLJIT_R0), DR(TMP_REG2))); - FAIL_IF(push_inst(compiler, (op == SLJIT_LUDIV ? UDIV : SDIV) | D(SLJIT_R0) | S1(SLJIT_R0) | S2(SLJIT_R1), DR(SLJIT_R0))); + if (op <= SLJIT_SDIVMOD) + FAIL_IF(push_inst(compiler, OR | D(TMP_REG2) | S1(0) | S2(SLJIT_R0), DR(TMP_REG2))); + FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_UDIVI ? UDIV : SDIV) | D(SLJIT_R0) | S1(SLJIT_R0) | S2(SLJIT_R1), DR(SLJIT_R0))); + if (op >= SLJIT_UDIVI) + return SLJIT_SUCCESS; FAIL_IF(push_inst(compiler, SMUL | D(SLJIT_R1) | S1(SLJIT_R0) | S2(SLJIT_R1), DR(SLJIT_R1))); - FAIL_IF(push_inst(compiler, SUB | D(SLJIT_R1) | S1(TMP_REG2) | S2(SLJIT_R1), DR(SLJIT_R1))); - return SLJIT_SUCCESS; + return push_inst(compiler, SUB | D(SLJIT_R1) | S1(TMP_REG2) | S2(SLJIT_R1), DR(SLJIT_R1)); #else #error "Implementation required" #endif diff --git a/src/3rdparty/pcre/sljit/sljitNativeTILEGX_64.c b/src/3rdparty/pcre/sljit/sljitNativeTILEGX_64.c index 1d6aa5a110..4d40392fa8 100644 --- a/src/3rdparty/pcre/sljit/sljitNativeTILEGX_64.c +++ b/src/3rdparty/pcre/sljit/sljitNativeTILEGX_64.c @@ -35,21 +35,21 @@ #define SIMM_16BIT_MIN (-0x8000) #define SIMM_17BIT_MAX (0xffff) #define SIMM_17BIT_MIN (-0x10000) -#define SIMM_32BIT_MIN (-0x80000000) #define SIMM_32BIT_MAX (0x7fffffff) -#define SIMM_48BIT_MIN (0x800000000000L) +#define SIMM_32BIT_MIN (-0x7fffffff - 1) #define SIMM_48BIT_MAX (0x7fffffff0000L) +#define SIMM_48BIT_MIN (-0x800000000000L) #define IMM16(imm) ((imm) & 0xffff) #define UIMM_16BIT_MAX (0xffff) -#define TMP_REG1 (SLJIT_NO_REGISTERS + 1) -#define TMP_REG2 (SLJIT_NO_REGISTERS + 2) -#define TMP_REG3 (SLJIT_NO_REGISTERS + 3) -#define ADDR_TMP (SLJIT_NO_REGISTERS + 4) +#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2) +#define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3) +#define TMP_REG3 (SLJIT_NUMBER_OF_REGISTERS + 4) +#define ADDR_TMP (SLJIT_NUMBER_OF_REGISTERS + 5) #define PIC_ADDR_REG TMP_REG2 -static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 5] = { +static SLJIT_CONST sljit_ub reg_map[SLJIT_NUMBER_OF_REGISTERS + 6] = { 63, 0, 1, 2, 3, 4, 30, 31, 32, 33, 34, 54, 5, 16, 6, 7 }; @@ -58,11 +58,6 @@ static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 5] = { #define TMP_REG2_mapped 16 #define TMP_REG3_mapped 6 #define ADDR_TMP_mapped 7 -#define SLJIT_SAVED_REG1_mapped 30 -#define SLJIT_SAVED_REG2_mapped 31 -#define SLJIT_SAVED_REG3_mapped 32 -#define SLJIT_SAVED_EREG1_mapped 33 -#define SLJIT_SAVED_EREG2_mapped 34 /* Flags are keept in volatile registers. */ #define EQUAL_FLAG 8 @@ -399,6 +394,9 @@ static sljit_si push_inst(struct sljit_compiler *compiler, sljit_ins ins) #define SUB(dst, srca, srcb) \ push_3_buffer(compiler, TILEGX_OPC_SUB, dst, srca, srcb, __LINE__) +#define MUL(dst, srca, srcb) \ + push_3_buffer(compiler, TILEGX_OPC_MULX, dst, srca, srcb, __LINE__) + #define NOR(dst, srca, srcb) \ push_3_buffer(compiler, TILEGX_OPC_NOR, dst, srca, srcb, __LINE__) @@ -547,8 +545,8 @@ const struct Format* compute_format() const struct Format* match = NULL; const struct Format *b = NULL; - unsigned int i = 0; - for (i; i < sizeof formats / sizeof formats[0]; i++) { + unsigned int i; + for (i = 0; i < sizeof formats / sizeof formats[0]; i++) { b = &formats[i]; if ((b->pipe_mask & compatible_pipes) == b->pipe_mask) { match = b; @@ -625,7 +623,6 @@ tilegx_bundle_bits get_bundle_bit(struct jit_instr *inst) static sljit_si update_buffer(struct sljit_compiler *compiler) { - int count; int i; int orig_index = inst_buf_index; struct jit_instr inst0 = inst_buf[0]; @@ -738,8 +735,10 @@ static sljit_si update_buffer(struct sljit_compiler *compiler) static sljit_si flush_buffer(struct sljit_compiler *compiler) { - while (inst_buf_index != 0) - update_buffer(compiler); + while (inst_buf_index != 0) { + FAIL_IF(update_buffer(compiler)); + } + return SLJIT_SUCCESS; } static sljit_si push_4_buffer(struct sljit_compiler *compiler, tilegx_mnemonic opc, int op0, int op1, int op2, int op3, int line) @@ -787,6 +786,7 @@ static sljit_si push_3_buffer(struct sljit_compiler *compiler, tilegx_mnemonic o case TILEGX_OPC_ADD: case TILEGX_OPC_AND: case TILEGX_OPC_SUB: + case TILEGX_OPC_MULX: case TILEGX_OPC_OR: case TILEGX_OPC_XOR: case TILEGX_OPC_NOR: @@ -905,7 +905,6 @@ static SLJIT_INLINE sljit_ins * detect_jump_type(struct sljit_jump *jump, sljit_ sljit_sw diff; sljit_uw target_addr; sljit_ins *inst; - sljit_ins saved_inst; if (jump->flags & SLJIT_REWRITABLE_JUMP) return code_ptr; @@ -1009,7 +1008,7 @@ SLJIT_API_FUNC_ATTRIBUTE void * sljit_generate_code(struct sljit_compiler *compi struct sljit_const *const_; CHECK_ERROR_PTR(); - check_sljit_generate_code(compiler); + CHECK_PTR(check_sljit_generate_code(compiler)); reverse_buf(compiler); code = (sljit_ins *)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_ins)); @@ -1178,13 +1177,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil sljit_si fscratches, sljit_si fsaveds, sljit_si local_size) { sljit_ins base; - sljit_ins bundle = 0; - + sljit_si i, tmp; + CHECK_ERROR(); - check_sljit_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size); + CHECK(check_sljit_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size)); set_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size); - local_size += (saveds + 1) * sizeof(sljit_sw); + local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1); local_size = (local_size + 7) & ~7; compiler->local_size = local_size; @@ -1200,56 +1199,52 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil local_size = 0; } + /* Save the return address. */ FAIL_IF(ADDLI(ADDR_TMP_mapped, base, local_size - 8)); FAIL_IF(ST_ADD(ADDR_TMP_mapped, RA, -8)); - if (saveds >= 1) - FAIL_IF(ST_ADD(ADDR_TMP_mapped, SLJIT_SAVED_REG1_mapped, -8)); - - if (saveds >= 2) - FAIL_IF(ST_ADD(ADDR_TMP_mapped, SLJIT_SAVED_REG2_mapped, -8)); - - if (saveds >= 3) - FAIL_IF(ST_ADD(ADDR_TMP_mapped, SLJIT_SAVED_REG3_mapped, -8)); - - if (saveds >= 4) - FAIL_IF(ST_ADD(ADDR_TMP_mapped, SLJIT_SAVED_EREG1_mapped, -8)); - - if (saveds >= 5) - FAIL_IF(ST_ADD(ADDR_TMP_mapped, SLJIT_SAVED_EREG2_mapped, -8)); - - if (args >= 1) - FAIL_IF(ADD(SLJIT_SAVED_REG1_mapped, 0, ZERO)); + /* Save the S registers. */ + tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG; + for (i = SLJIT_S0; i >= tmp; i--) { + FAIL_IF(ST_ADD(ADDR_TMP_mapped, reg_map[i], -8)); + } - if (args >= 2) - FAIL_IF(ADD(SLJIT_SAVED_REG2_mapped, 1, ZERO)); + /* Save the R registers that need to be reserved. */ + for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) { + FAIL_IF(ST_ADD(ADDR_TMP_mapped, reg_map[i], -8)); + } - if (args >= 3) - FAIL_IF(ADD(SLJIT_SAVED_REG3_mapped, 2, ZERO)); + /* Move the arguments to S registers. */ + for (i = 0; i < args; i++) { + FAIL_IF(ADD(reg_map[SLJIT_S0 - i], i, ZERO)); + } return SLJIT_SUCCESS; } -SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, +SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_set_context(struct sljit_compiler *compiler, sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si fscratches, sljit_si fsaveds, sljit_si local_size) { - CHECK_ERROR_VOID(); - check_sljit_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size); + CHECK_ERROR(); + CHECK(check_sljit_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size)); set_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size); - local_size += (saveds + 1) * sizeof(sljit_sw); + local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1); compiler->local_size = (local_size + 7) & ~7; + + return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compiler, sljit_si op, sljit_si src, sljit_sw srcw) { sljit_si local_size; sljit_ins base; - int addr_initialized = 0; + sljit_si i, tmp; + sljit_si saveds; CHECK_ERROR(); - check_sljit_emit_return(compiler, op, src, srcw); + CHECK(check_sljit_emit_return(compiler, op, src, srcw)); FAIL_IF(emit_mov_before_return(compiler, op, src, srcw)); @@ -1263,50 +1258,20 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compi local_size = 0; } + /* Restore the return address. */ FAIL_IF(ADDLI(ADDR_TMP_mapped, base, local_size - 8)); - FAIL_IF(LD(RA, ADDR_TMP_mapped)); - - if (compiler->saveds >= 5) { - FAIL_IF(ADDLI(ADDR_TMP_mapped, base, local_size - 48)); - addr_initialized = 1; + FAIL_IF(LD_ADD(RA, ADDR_TMP_mapped, -8)); - FAIL_IF(LD_ADD(SLJIT_SAVED_EREG2_mapped, ADDR_TMP_mapped, 8)); + /* Restore the S registers. */ + saveds = compiler->saveds; + tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG; + for (i = SLJIT_S0; i >= tmp; i--) { + FAIL_IF(LD_ADD(reg_map[i], ADDR_TMP_mapped, -8)); } - if (compiler->saveds >= 4) { - if (addr_initialized == 0) { - FAIL_IF(ADDLI(ADDR_TMP_mapped, base, local_size - 40)); - addr_initialized = 1; - } - - FAIL_IF(LD_ADD(SLJIT_SAVED_EREG1_mapped, ADDR_TMP_mapped, 8)); - } - - if (compiler->saveds >= 3) { - if (addr_initialized == 0) { - FAIL_IF(ADDLI(ADDR_TMP_mapped, base, local_size - 32)); - addr_initialized = 1; - } - - FAIL_IF(LD_ADD(SLJIT_SAVED_REG3_mapped, ADDR_TMP_mapped, 8)); - } - - if (compiler->saveds >= 2) { - if (addr_initialized == 0) { - FAIL_IF(ADDLI(ADDR_TMP_mapped, base, local_size - 24)); - addr_initialized = 1; - } - - FAIL_IF(LD_ADD(SLJIT_SAVED_REG2_mapped, ADDR_TMP_mapped, 8)); - } - - if (compiler->saveds >= 1) { - if (addr_initialized == 0) { - FAIL_IF(ADDLI(ADDR_TMP_mapped, base, local_size - 16)); - /* addr_initialized = 1; no need to initialize as it's the last one. */ - } - - FAIL_IF(LD_ADD(SLJIT_SAVED_REG1_mapped, ADDR_TMP_mapped, 8)); + /* Restore the R registers that need to be reserved. */ + for (i = compiler->scratches; i >= SLJIT_FIRST_SAVED_REG; i--) { + FAIL_IF(LD_ADD(reg_map[i], ADDR_TMP_mapped, -8)); } if (compiler->local_size <= SIMM_16BIT_MAX) @@ -1585,7 +1550,7 @@ static SLJIT_INLINE sljit_si emit_op_mem2(struct sljit_compiler *compiler, sljit SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw) { CHECK_ERROR(); - check_sljit_emit_fast_enter(compiler, dst, dstw); + CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw)); ADJUST_LOCAL_OFFSET(dst, dstw); /* For UNUSED dst. Uncommon, but possible. */ @@ -1602,7 +1567,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *c SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_si src, sljit_sw srcw) { CHECK_ERROR(); - check_sljit_emit_fast_return(compiler, src, srcw); + CHECK(check_sljit_emit_fast_return(compiler, src, srcw)); ADJUST_LOCAL_OFFSET(src, srcw); if (FAST_IS_REG(src)) @@ -1636,9 +1601,11 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj if (op == SLJIT_MOV_SI) return BFEXTS(reg_map[dst], reg_map[src2], 0, 31); - return BFEXTU(reg_map[dst], reg_map[src2], 0, 31); - } else if (dst != src2) - SLJIT_ASSERT_STOP(); + return BFEXTU(reg_map[dst], reg_map[src2], 0, 31); + } else if (dst != src2) { + SLJIT_ASSERT(src2 == 0); + return ADD(reg_map[dst], reg_map[src2], ZERO); + } return SLJIT_SUCCESS; @@ -1650,8 +1617,10 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj return BFEXTS(reg_map[dst], reg_map[src2], 0, 7); return BFEXTU(reg_map[dst], reg_map[src2], 0, 7); - } else if (dst != src2) - SLJIT_ASSERT_STOP(); + } else if (dst != src2) { + SLJIT_ASSERT(src2 == 0); + return ADD(reg_map[dst], reg_map[src2], ZERO); + } return SLJIT_SUCCESS; @@ -1663,8 +1632,10 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj return BFEXTS(reg_map[dst], reg_map[src2], 0, 15); return BFEXTU(reg_map[dst], reg_map[src2], 0, 15); - } else if (dst != src2) - SLJIT_ASSERT_STOP(); + } else if (dst != src2) { + SLJIT_ASSERT(src2 == 0); + return ADD(reg_map[dst], reg_map[src2], ZERO); + } return SLJIT_SUCCESS; @@ -1811,7 +1782,6 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj else { /* Rare ocasion. */ FAIL_IF(ADD(TMP_EREG2, reg_map[src1], ZERO)); - overflow_ra = TMP_EREG2; } } @@ -1903,6 +1873,17 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj return SLJIT_SUCCESS; + case SLJIT_MUL: + if (flags & SRC2_IMM) { + FAIL_IF(load_immediate(compiler, TMP_REG2_mapped, src2)); + src2 = TMP_REG2; + flags &= ~SRC2_IMM; + } + + FAIL_IF(MUL(reg_map[dst], reg_map[src1], reg_map[src2])); + + return SLJIT_SUCCESS; + #define EMIT_LOGICAL(op_imm, op_norm) \ if (flags & SRC2_IMM) { \ FAIL_IF(load_immediate(compiler, ADDR_TMP_mapped, src2)); \ @@ -1950,8 +1931,8 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj } else { \ if (op & SLJIT_SET_E) \ FAIL_IF(push_3_buffer( \ - compiler, op_imm, reg_map[dst], reg_map[src1], \ - src2 & 0x3F, __LINE__)); \ + compiler, op_norm, EQUAL_FLAG, reg_map[src1], \ + reg_map[src2], __LINE__)); \ if (CHECK_FLAGS(SLJIT_SET_E)) \ FAIL_IF(push_3_buffer( \ compiler, op_norm, reg_map[dst], reg_map[src1], \ @@ -2105,66 +2086,61 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com { sljit_si sugg_dst_ar, dst_ar; sljit_si flags = GET_ALL_FLAGS(op); + sljit_si mem_type = (op & SLJIT_INT_OP) ? (INT_DATA | SIGNED_DATA) : WORD_DATA; CHECK_ERROR(); - check_sljit_emit_op_flags(compiler, op, dst, dstw, src, srcw, type); + CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, src, srcw, type)); ADJUST_LOCAL_OFFSET(dst, dstw); if (dst == SLJIT_UNUSED) return SLJIT_SUCCESS; op = GET_OPCODE(op); + if (op == SLJIT_MOV_SI || op == SLJIT_MOV_UI) + mem_type = INT_DATA | SIGNED_DATA; sugg_dst_ar = reg_map[(op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2]; compiler->cache_arg = 0; compiler->cache_argw = 0; if (op >= SLJIT_ADD && (src & SLJIT_MEM)) { ADJUST_LOCAL_OFFSET(src, srcw); - FAIL_IF(emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, TMP_REG1_mapped, src, srcw, dst, dstw)); + FAIL_IF(emit_op_mem2(compiler, mem_type | LOAD_DATA, TMP_REG1_mapped, src, srcw, dst, dstw)); src = TMP_REG1; srcw = 0; } - switch (type) { - case SLJIT_C_EQUAL: - case SLJIT_C_NOT_EQUAL: + switch (type & 0xff) { + case SLJIT_EQUAL: + case SLJIT_NOT_EQUAL: FAIL_IF(CMPLTUI(sugg_dst_ar, EQUAL_FLAG, 1)); dst_ar = sugg_dst_ar; break; - case SLJIT_C_LESS: - case SLJIT_C_GREATER_EQUAL: - case SLJIT_C_FLOAT_LESS: - case SLJIT_C_FLOAT_GREATER_EQUAL: + case SLJIT_LESS: + case SLJIT_GREATER_EQUAL: dst_ar = ULESS_FLAG; break; - case SLJIT_C_GREATER: - case SLJIT_C_LESS_EQUAL: - case SLJIT_C_FLOAT_GREATER: - case SLJIT_C_FLOAT_LESS_EQUAL: + case SLJIT_GREATER: + case SLJIT_LESS_EQUAL: dst_ar = UGREATER_FLAG; break; - case SLJIT_C_SIG_LESS: - case SLJIT_C_SIG_GREATER_EQUAL: + case SLJIT_SIG_LESS: + case SLJIT_SIG_GREATER_EQUAL: dst_ar = LESS_FLAG; break; - case SLJIT_C_SIG_GREATER: - case SLJIT_C_SIG_LESS_EQUAL: + case SLJIT_SIG_GREATER: + case SLJIT_SIG_LESS_EQUAL: dst_ar = GREATER_FLAG; break; - case SLJIT_C_OVERFLOW: - case SLJIT_C_NOT_OVERFLOW: + case SLJIT_OVERFLOW: + case SLJIT_NOT_OVERFLOW: dst_ar = OVERFLOW_FLAG; break; - case SLJIT_C_MUL_OVERFLOW: - case SLJIT_C_MUL_NOT_OVERFLOW: + case SLJIT_MUL_OVERFLOW: + case SLJIT_MUL_NOT_OVERFLOW: FAIL_IF(CMPLTUI(sugg_dst_ar, OVERFLOW_FLAG, 1)); dst_ar = sugg_dst_ar; type ^= 0x1; /* Flip type bit for the XORI below. */ break; - case SLJIT_C_FLOAT_EQUAL: - case SLJIT_C_FLOAT_NOT_EQUAL: - dst_ar = EQUAL_FLAG; - break; default: SLJIT_ASSERT_STOP(); @@ -2180,11 +2156,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com if (op >= SLJIT_ADD) { if (TMP_REG2_mapped != dst_ar) FAIL_IF(ADD(TMP_REG2_mapped, dst_ar, ZERO)); - return emit_op(compiler, op | flags, CUMULATIVE_OP | LOGICAL_OP | IMM_OP | ALT_KEEP_CACHE, dst, dstw, src, srcw, TMP_REG2, 0); + return emit_op(compiler, op | flags, mem_type | CUMULATIVE_OP | LOGICAL_OP | IMM_OP | ALT_KEEP_CACHE, dst, dstw, src, srcw, TMP_REG2, 0); } if (dst & SLJIT_MEM) - return emit_op_mem(compiler, WORD_DATA, dst_ar, dst, dstw); + return emit_op_mem(compiler, mem_type, dst_ar, dst, dstw); if (sugg_dst_ar != dst_ar) return ADD(sugg_dst_ar, dst_ar, ZERO); @@ -2194,7 +2170,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler, sljit_si op) { CHECK_ERROR(); - check_sljit_emit_op0(compiler, op); + CHECK(check_sljit_emit_op0(compiler, op)); op = GET_OPCODE(op); switch (op) { @@ -2204,10 +2180,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler case SLJIT_BREAKPOINT: return PI(BPT); - case SLJIT_UMUL: - case SLJIT_SMUL: - case SLJIT_UDIV: - case SLJIT_SDIV: + case SLJIT_LUMUL: + case SLJIT_LSMUL: + case SLJIT_UDIVI: + case SLJIT_SDIVI: SLJIT_ASSERT_STOP(); } @@ -2217,7 +2193,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler, sljit_si op, sljit_si dst, sljit_sw dstw, sljit_si src, sljit_sw srcw) { CHECK_ERROR(); - check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw); + CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw)); ADJUST_LOCAL_OFFSET(dst, dstw); ADJUST_LOCAL_OFFSET(src, srcw); @@ -2273,7 +2249,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler return emit_op(compiler, SLJIT_SUB | GET_ALL_FLAGS(op), IMM_OP, dst, dstw, SLJIT_IMM, 0, src, srcw); case SLJIT_CLZ: - return emit_op(compiler, op, 0, dst, dstw, TMP_REG1, 0, src, srcw); + return emit_op(compiler, op, (op & SLJIT_INT_OP) ? INT_DATA : WORD_DATA, dst, dstw, TMP_REG1, 0, src, srcw); } return SLJIT_SUCCESS; @@ -2282,7 +2258,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler, sljit_si op, sljit_si dst, sljit_sw dstw, sljit_si src1, sljit_sw src1w, sljit_si src2, sljit_sw src2w) { CHECK_ERROR(); - check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w); + CHECK(check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w)); ADJUST_LOCAL_OFFSET(dst, dstw); ADJUST_LOCAL_OFFSET(src1, src1w); ADJUST_LOCAL_OFFSET(src2, src2w); @@ -2325,7 +2301,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label * sljit_emit_label(struct sljit_comp flush_buffer(compiler); CHECK_ERROR_PTR(); - check_sljit_emit_label(compiler); + CHECK_PTR(check_sljit_emit_label(compiler)); if (compiler->last_label && compiler->last_label->size == compiler->size) return compiler->last_label; @@ -2344,7 +2320,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compil flush_buffer(compiler); CHECK_ERROR(); - check_sljit_emit_ijump(compiler, type, src, srcw); + CHECK(check_sljit_emit_ijump(compiler, type, src, srcw)); ADJUST_LOCAL_OFFSET(src, srcw); if (FAST_IS_REG(src)) { @@ -2404,8 +2380,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compil return SLJIT_SUCCESS; - } else if (src & SLJIT_MEM) + } else if (src & SLJIT_MEM) { FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_REG2, 0, TMP_REG1, 0, src, srcw)); + flush_buffer(compiler); + } FAIL_IF(JR_SOLO(reg_map[src_r])); @@ -2432,7 +2410,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump * sljit_emit_jump(struct sljit_compil flush_buffer(compiler); CHECK_ERROR_PTR(); - check_sljit_emit_jump(compiler, type); + CHECK_PTR(check_sljit_emit_jump(compiler, type)); jump = (struct sljit_jump *)ensure_abuf(compiler, sizeof(struct sljit_jump)); PTR_FAIL_IF(!jump); @@ -2440,48 +2418,42 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump * sljit_emit_jump(struct sljit_compil type &= 0xff; switch (type) { - case SLJIT_C_EQUAL: - case SLJIT_C_FLOAT_NOT_EQUAL: + case SLJIT_EQUAL: BR_NZ(EQUAL_FLAG); break; - case SLJIT_C_NOT_EQUAL: - case SLJIT_C_FLOAT_EQUAL: + case SLJIT_NOT_EQUAL: BR_Z(EQUAL_FLAG); break; - case SLJIT_C_LESS: - case SLJIT_C_FLOAT_LESS: + case SLJIT_LESS: BR_Z(ULESS_FLAG); break; - case SLJIT_C_GREATER_EQUAL: - case SLJIT_C_FLOAT_GREATER_EQUAL: + case SLJIT_GREATER_EQUAL: BR_NZ(ULESS_FLAG); break; - case SLJIT_C_GREATER: - case SLJIT_C_FLOAT_GREATER: + case SLJIT_GREATER: BR_Z(UGREATER_FLAG); break; - case SLJIT_C_LESS_EQUAL: - case SLJIT_C_FLOAT_LESS_EQUAL: + case SLJIT_LESS_EQUAL: BR_NZ(UGREATER_FLAG); break; - case SLJIT_C_SIG_LESS: + case SLJIT_SIG_LESS: BR_Z(LESS_FLAG); break; - case SLJIT_C_SIG_GREATER_EQUAL: + case SLJIT_SIG_GREATER_EQUAL: BR_NZ(LESS_FLAG); break; - case SLJIT_C_SIG_GREATER: + case SLJIT_SIG_GREATER: BR_Z(GREATER_FLAG); break; - case SLJIT_C_SIG_LESS_EQUAL: + case SLJIT_SIG_LESS_EQUAL: BR_NZ(GREATER_FLAG); break; - case SLJIT_C_OVERFLOW: - case SLJIT_C_MUL_OVERFLOW: + case SLJIT_OVERFLOW: + case SLJIT_MUL_OVERFLOW: BR_Z(OVERFLOW_FLAG); break; - case SLJIT_C_NOT_OVERFLOW: - case SLJIT_C_MUL_NOT_OVERFLOW: + case SLJIT_NOT_OVERFLOW: + case SLJIT_MUL_NOT_OVERFLOW: BR_NZ(OVERFLOW_FLAG); break; default: @@ -2536,7 +2508,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const * sljit_emit_const(struct sljit_comp flush_buffer(compiler); CHECK_ERROR_PTR(); - check_sljit_emit_const(compiler, dst, dstw, init_value); + CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value)); ADJUST_LOCAL_OFFSET(dst, dstw); const_ = (struct sljit_const *)ensure_abuf(compiler, sizeof(struct sljit_const)); @@ -2572,3 +2544,18 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_consta inst[3] = (inst[3] & ~(0xFFFFL << 43)) | ((new_constant & 0xFFFFL) << 43); SLJIT_CACHE_FLUSH(inst, inst + 4); } + +SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_register_index(sljit_si reg) +{ + CHECK_REG_INDEX(check_sljit_get_register_index(reg)); + return reg_map[reg]; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_custom(struct sljit_compiler *compiler, + void *instruction, sljit_si size) +{ + CHECK_ERROR(); + CHECK(check_sljit_emit_op_custom(compiler, instruction, size)); + return SLJIT_ERR_UNSUPPORTED; +} + diff --git a/src/3rdparty/pcre/sljit/sljitNativeX86_common.c b/src/3rdparty/pcre/sljit/sljitNativeX86_common.c index 21b276fb8d..e148c34cd1 100644 --- a/src/3rdparty/pcre/sljit/sljitNativeX86_common.c +++ b/src/3rdparty/pcre/sljit/sljitNativeX86_common.c @@ -744,8 +744,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler break; case SLJIT_LUMUL: case SLJIT_LSMUL: - case SLJIT_LUDIV: - case SLJIT_LSDIV: + case SLJIT_UDIVMOD: + case SLJIT_SDIVMOD: + case SLJIT_UDIVI: + case SLJIT_SDIVI: compiler->flags_saved = 0; #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) #ifdef _WIN64 @@ -763,9 +765,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler #endif compiler->mode32 = op & SLJIT_INT_OP; #endif + SLJIT_COMPILE_ASSERT((SLJIT_UDIVMOD & 0x2) == 0 && SLJIT_UDIVI - 0x2 == SLJIT_UDIVMOD, bad_div_opcode_assignments); op = GET_OPCODE(op); - if (op == SLJIT_LUDIV) { + if ((op | 0x2) == SLJIT_UDIVI) { #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || defined(_WIN64) EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_R1, 0); inst = emit_x86_instruction(compiler, 1, SLJIT_R1, 0, SLJIT_R1, 0); @@ -776,7 +779,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler *inst = XOR_r_rm; } - if (op == SLJIT_LSDIV) { + if ((op | 0x2) == SLJIT_SDIVI) { #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || defined(_WIN64) EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_R1, 0); #endif @@ -807,10 +810,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler FAIL_IF(!inst); INC_SIZE(2); *inst++ = GROUP_F7; - *inst = MOD_REG | ((op >= SLJIT_LUDIV) ? reg_map[TMP_REG1] : reg_map[SLJIT_R1]); + *inst = MOD_REG | ((op >= SLJIT_UDIVMOD) ? reg_map[TMP_REG1] : reg_map[SLJIT_R1]); #else #ifdef _WIN64 - size = (!compiler->mode32 || op >= SLJIT_LUDIV) ? 3 : 2; + size = (!compiler->mode32 || op >= SLJIT_UDIVMOD) ? 3 : 2; #else size = (!compiler->mode32) ? 3 : 2; #endif @@ -819,11 +822,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler INC_SIZE(size); #ifdef _WIN64 if (!compiler->mode32) - *inst++ = REX_W | ((op >= SLJIT_LUDIV) ? REX_B : 0); - else if (op >= SLJIT_LUDIV) + *inst++ = REX_W | ((op >= SLJIT_UDIVMOD) ? REX_B : 0); + else if (op >= SLJIT_UDIVMOD) *inst++ = REX_B; *inst++ = GROUP_F7; - *inst = MOD_REG | ((op >= SLJIT_LUDIV) ? reg_lmap[TMP_REG1] : reg_lmap[SLJIT_R1]); + *inst = MOD_REG | ((op >= SLJIT_UDIVMOD) ? reg_lmap[TMP_REG1] : reg_lmap[SLJIT_R1]); #else if (!compiler->mode32) *inst++ = REX_W; @@ -838,15 +841,21 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler case SLJIT_LSMUL: *inst |= IMUL; break; - case SLJIT_LUDIV: + case SLJIT_UDIVMOD: + case SLJIT_UDIVI: *inst |= DIV; break; - case SLJIT_LSDIV: + case SLJIT_SDIVMOD: + case SLJIT_SDIVI: *inst |= IDIV; break; } #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) && !defined(_WIN64) - EMIT_MOV(compiler, SLJIT_R1, 0, TMP_REG1, 0); + if (op <= SLJIT_SDIVMOD) + EMIT_MOV(compiler, SLJIT_R1, 0, TMP_REG1, 0); +#else + if (op >= SLJIT_UDIVI) + EMIT_MOV(compiler, SLJIT_R1, 0, TMP_REG1, 0); #endif break; } @@ -1907,60 +1916,62 @@ static sljit_si emit_test_binary(struct sljit_compiler *compiler, return SLJIT_SUCCESS; } - if (FAST_IS_REG(src1)) { + if (!(src1 & SLJIT_IMM)) { if (src2 & SLJIT_IMM) { #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) if (IS_HALFWORD(src2w) || compiler->mode32) { - inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, src1, 0); + inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, src1, src1w); FAIL_IF(!inst); *inst = GROUP_F7; } else { FAIL_IF(emit_load_imm64(compiler, TMP_REG2, src2w)); - inst = emit_x86_instruction(compiler, 1, TMP_REG2, 0, src1, 0); + inst = emit_x86_instruction(compiler, 1, TMP_REG2, 0, src1, src1w); FAIL_IF(!inst); *inst = TEST_rm_r; } #else - inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, src1, 0); + inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, src1, src1w); FAIL_IF(!inst); *inst = GROUP_F7; #endif + return SLJIT_SUCCESS; } - else { + else if (FAST_IS_REG(src1)) { inst = emit_x86_instruction(compiler, 1, src1, 0, src2, src2w); FAIL_IF(!inst); *inst = TEST_rm_r; + return SLJIT_SUCCESS; } - return SLJIT_SUCCESS; } - if (FAST_IS_REG(src2)) { + if (!(src2 & SLJIT_IMM)) { if (src1 & SLJIT_IMM) { #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) if (IS_HALFWORD(src1w) || compiler->mode32) { - inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src1w, src2, 0); + inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src1w, src2, src2w); FAIL_IF(!inst); *inst = GROUP_F7; } else { FAIL_IF(emit_load_imm64(compiler, TMP_REG2, src1w)); - inst = emit_x86_instruction(compiler, 1, TMP_REG2, 0, src2, 0); + inst = emit_x86_instruction(compiler, 1, TMP_REG2, 0, src2, src2w); FAIL_IF(!inst); *inst = TEST_rm_r; } #else - inst = emit_x86_instruction(compiler, 1, src1, src1w, src2, 0); + inst = emit_x86_instruction(compiler, 1, src1, src1w, src2, src2w); FAIL_IF(!inst); *inst = GROUP_F7; #endif + return SLJIT_SUCCESS; } - else { + else if (FAST_IS_REG(src2)) { inst = emit_x86_instruction(compiler, 1, src2, 0, src1, src1w); FAIL_IF(!inst); *inst = TEST_rm_r; + return SLJIT_SUCCESS; } - return SLJIT_SUCCESS; } EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w); -- cgit v1.2.3 From 53ecaade10319ecc1d8115521ae6d8eba1ee55c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Thu, 13 Aug 2015 21:42:10 +0200 Subject: Cocoa: Fix backing store performance regression. Commit 916dfcb8 introduced a regression where QNSView would hold a copy if the backing store QImage, which would cause a detach and deep copy if/when the image was painted on while the copy was held. Revert back to the previous share-by-pointer scheme. Make sure the following bugs stays fixed: QTBUG-38377 QTBUG-42206 QTBUG-44313 Change-Id: Ib8049051d51947113f23b66ee61dc34c22388914 Task-number: QTBUG-46959 Reviewed-by: Gabriel de Dietrich --- src/plugins/platforms/cocoa/qcocoabackingstore.mm | 2 ++ src/plugins/platforms/cocoa/qnsview.h | 4 +-- src/plugins/platforms/cocoa/qnsview.mm | 31 +++++++++++++---------- 3 files changed, 22 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.mm b/src/plugins/platforms/cocoa/qcocoabackingstore.mm index 6a4f7ed8ee..ca92103826 100644 --- a/src/plugins/platforms/cocoa/qcocoabackingstore.mm +++ b/src/plugins/platforms/cocoa/qcocoabackingstore.mm @@ -44,6 +44,8 @@ QCocoaBackingStore::QCocoaBackingStore(QWindow *window) QCocoaBackingStore::~QCocoaBackingStore() { + if (QCocoaWindow *cocoaWindow = static_cast(window()->handle())) + [cocoaWindow->m_qtView clearBackingStore:this]; } QPaintDevice *QCocoaBackingStore::paintDevice() diff --git a/src/plugins/platforms/cocoa/qnsview.h b/src/plugins/platforms/cocoa/qnsview.h index 05ab8ae2c7..14a61554a3 100644 --- a/src/plugins/platforms/cocoa/qnsview.h +++ b/src/plugins/platforms/cocoa/qnsview.h @@ -51,8 +51,7 @@ QT_END_NAMESPACE Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper)); @interface QT_MANGLE_NAMESPACE(QNSView) : NSView { - QImage m_backingStore; - qreal m_pixelRatio; + QCocoaBackingStore* m_backingStore; QPoint m_backingStoreOffset; CGImageRef m_maskImage; uchar *m_maskData; @@ -86,6 +85,7 @@ Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper)); - (void)setQCocoaGLContext:(QCocoaGLContext *)context; #endif - (void)flushBackingStore:(QCocoaBackingStore *)backingStore region:(const QRegion &)region offset:(QPoint)offset; +- (void)clearBackingStore:(QCocoaBackingStore *)backingStore; - (void)setMaskRegion:(const QRegion *)region; - (void)invalidateWindowShadowIfNeeded; - (void)drawRect:(NSRect)dirtyRect; diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index d802a36676..f27335d752 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -135,7 +135,7 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil; { self = [super initWithFrame : NSMakeRect(0,0, 300,300)]; if (self) { - m_pixelRatio = 1.; + m_backingStore = 0; m_maskImage = 0; m_shouldInvalidateWindowShadow = false; m_window = 0; @@ -371,7 +371,7 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil; if (!m_platformWindow->m_inSetGeometry) QWindowSystemInterface::flushWindowSystemEvents(); else - m_backingStore = QImage(); + m_backingStore = 0; } } @@ -476,12 +476,16 @@ QT_WARNING_POP - (void) flushBackingStore:(QCocoaBackingStore *)backingStore region:(const QRegion &)region offset:(QPoint)offset { - m_backingStore = backingStore->toImage(); - m_pixelRatio = backingStore->getBackingStoreDevicePixelRatio(); - m_backingStoreOffset = offset * m_pixelRatio; - foreach (QRect rect, region.rects()) { + m_backingStore = backingStore; + m_backingStoreOffset = offset * m_backingStore->getBackingStoreDevicePixelRatio(); + foreach (QRect rect, region.rects()) [self setNeedsDisplayInRect:NSMakeRect(rect.x(), rect.y(), rect.width(), rect.height())]; - } +} + +- (void)clearBackingStore:(QCocoaBackingStore *)backingStore +{ + if (backingStore == m_backingStore) + m_backingStore = 0; } - (BOOL) hasMask @@ -544,7 +548,7 @@ QT_WARNING_POP if (m_platformWindow->m_drawContentBorderGradient) NSDrawWindowBackground(dirtyRect); - if (m_backingStore.isNull()) + if (!m_backingStore) return; // Calculate source and target rects. The target rect is the dirtyRect: @@ -552,10 +556,11 @@ QT_WARNING_POP // The backing store source rect will be larger on retina displays. // Scale dirtyRect by the device pixel ratio: - CGRect dirtyBackingRect = CGRectMake(dirtyRect.origin.x * m_pixelRatio, - dirtyRect.origin.y * m_pixelRatio, - dirtyRect.size.width * m_pixelRatio, - dirtyRect.size.height * m_pixelRatio); + const qreal devicePixelRatio = m_backingStore->getBackingStoreDevicePixelRatio(); + CGRect dirtyBackingRect = CGRectMake(dirtyRect.origin.x * devicePixelRatio, + dirtyRect.origin.y * devicePixelRatio, + dirtyRect.size.width * devicePixelRatio, + dirtyRect.size.height * devicePixelRatio); NSGraphicsContext *nsGraphicsContext = [NSGraphicsContext currentContext]; CGContextRef cgContext = (CGContextRef) [nsGraphicsContext graphicsPort]; @@ -581,7 +586,7 @@ QT_WARNING_POP dirtyBackingRect.size.width, dirtyBackingRect.size.height ); - CGImageRef bsCGImage = qt_mac_toCGImage(m_backingStore); + CGImageRef bsCGImage = qt_mac_toCGImage(m_backingStore->toImage()); CGImageRef cleanImg = CGImageCreateWithImageInRect(bsCGImage, backingStoreRect); // Optimization: Copy frame buffer content instead of blending for -- cgit v1.2.3