From 2398e225abdea36321670d34a8238b6e64dba281 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 8 Sep 2015 20:35:33 -0300 Subject: Auto-detect whether 64-bit std::atomic really works The C++ standard says it must, but some badly-configured toolchains seem to be lacking support. In particular, for some 32-bit platforms without native support for them, GCC implements 64-bit atomics via out-of-line functions in libatomic. If that library is missing... well, then std::atomic 64-bit doesn't work and we mustn't try to use it. This was found when trying to compile Qt 5.6 for MIPS 32-bit: Linking library libQt5Core.so.5.6.0 .obj/qsimd.o: In function `std::__atomic_base::load(std::memory_order) const': /opt/poky/1.7/sysroots/mips32r2-poky-linux/usr/include/c++/4.9.1/bits/atomic_base.h:500: undefined reference to `__atomic_load_8' .obj/qsimd.o: In function `std::__atomic_base::store(unsigned long long, std::memory_order)': /opt/poky/1.7/sysroots/mips32r2-poky-linux/usr/include/c++/4.9.1/bits/atomic_base.h:478: undefined reference to `__atomic_store_8' Yocto bug report: https://bugzilla.yoctoproject.org/show_bug.cgi?id=8274 Change-Id: I42e7ef1a481840699a8dffff140224d6614e5c36 Reviewed-by: Oswald Buddenhagen Reviewed-by: Lars Knoll Reviewed-by: Thiago Macieira (cherry picked from commit 3d7586b760550b7d89594c8d7462fc30b868ecc6) Reviewed-by: Dmitry Shachnev --- src/corelib/arch/arch.pri | 2 ++ src/corelib/arch/qatomic_cxx11.h | 12 +++++++----- 2 files changed, 9 insertions(+), 5 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/arch/arch.pri b/src/corelib/arch/arch.pri index 16fe8b8e5c..083d912331 100644 --- a/src/corelib/arch/arch.pri +++ b/src/corelib/arch/arch.pri @@ -10,6 +10,8 @@ HEADERS += \ arch/qatomic_gcc.h \ arch/qatomic_cxx11.h +atomic64-libatomic: LIBS += -latomic + unix { # fallback implementation when no other appropriate qatomic_*.h exists HEADERS += arch/qatomic_unix.h diff --git a/src/corelib/arch/qatomic_cxx11.h b/src/corelib/arch/qatomic_cxx11.h index 0e06ca951a..4136e09ce2 100644 --- a/src/corelib/arch/qatomic_cxx11.h +++ b/src/corelib/arch/qatomic_cxx11.h @@ -78,11 +78,13 @@ template<> struct QAtomicOpsSupport<8> { enum { IsSupported = 1 }; }; #define Q_ATOMIC_INT16_FETCH_AND_STORE_IS_ALWAYS_NATIVE #define Q_ATOMIC_INT16_FETCH_AND_ADD_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT64_IS_SUPPORTED -#define Q_ATOMIC_INT64_REFERENCE_COUNTING_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT64_TEST_AND_SET_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT64_FETCH_AND_STORE_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT64_FETCH_AND_ADD_IS_ALWAYS_NATIVE +#ifndef QT_NO_STD_ATOMIC64 +# define Q_ATOMIC_INT64_IS_SUPPORTED +# define Q_ATOMIC_INT64_REFERENCE_COUNTING_IS_ALWAYS_NATIVE +# define Q_ATOMIC_INT64_TEST_AND_SET_IS_ALWAYS_NATIVE +# define Q_ATOMIC_INT64_FETCH_AND_STORE_IS_ALWAYS_NATIVE +# define Q_ATOMIC_INT64_FETCH_AND_ADD_IS_ALWAYS_NATIVE +#endif template struct QAtomicOps { -- cgit v1.2.3 From 1440c13c8c1ed8eaa99c5d5edbd6fa61fd5eee8b Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Thu, 10 Dec 2015 11:37:59 +0100 Subject: Check if the file is writable even while QT_BOOTSTRAPPED QConfFile::isWritable() has the extra effect that it will try and create the path where the file should be if it does not already exist. So this cannot be omitted as 'qmake -set' may be used in a situation where the path does not yet exist. Change-Id: I0113644259f78d090a0687c44cf60d400be9c859 Reviewed-by: Oswald Buddenhagen --- src/corelib/io/qsettings.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp index 413f5693f0..52bcb153ae 100644 --- a/src/corelib/io/qsettings.cpp +++ b/src/corelib/io/qsettings.cpp @@ -1383,13 +1383,17 @@ void QConfFileSettingsPrivate::syncConfFile(int confFileNo) Concurrent read and write are not a problem because the writing operation is atomic. */ QLockFile lockFile(confFile->name + QLatin1String(".lock")); +#endif if (!readOnly) { - if (!confFile->isWritable() || !lockFile.lock() ) { + if (!confFile->isWritable() +#ifndef QT_BOOTSTRAPPED + || !lockFile.lock() +#endif + ) { setStatus(QSettings::AccessError); return; } } -#endif /* We hold the lock. Let's reread the file if it has changed -- cgit v1.2.3 From 6e14d63db023fdad223d9dc35b0e1ba31aac997d Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Mon, 7 Dec 2015 14:52:33 +0100 Subject: Add explicit note about removeMappings() not disconnecting the signal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There can be a bit of confusion here regarding what removeMappings() will do in this case so add an explicit note to be clearer. Task-number: QTBUG-49499 Change-Id: Iabcf5cb2653f0b747727b2c92a244e95ec1836f8 Reviewed-by: Topi Reiniö --- src/corelib/kernel/qsignalmapper.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/corelib') diff --git a/src/corelib/kernel/qsignalmapper.cpp b/src/corelib/kernel/qsignalmapper.cpp index 00aa31383f..5e8ce0c251 100644 --- a/src/corelib/kernel/qsignalmapper.cpp +++ b/src/corelib/kernel/qsignalmapper.cpp @@ -220,6 +220,9 @@ QObject *QSignalMapper::mapping(QObject *object) const Removes all mappings for \a sender. This is done automatically when mapped objects are destroyed. + + \note This does not disconnect any signals. If \a sender is not destroyed + then this will need to be done explicitly if required. */ void QSignalMapper::removeMappings(QObject *sender) { -- cgit v1.2.3 From b2c7c489ab40efb1f2f64aba5b90f5f4fb8d8536 Mon Sep 17 00:00:00 2001 From: David Fries Date: Tue, 24 Nov 2015 17:29:59 -0600 Subject: QLockFile: decide on locking strategy per path It is filesystem dependent if flock and fcntl locks are independent or the same underlying lock (which causes getting the second lock to fail). A temporary file in /tmp might be on a local file system and pass while the lock file is placed on NFS and fail with: setNativeLocks failed: Resource temporarily unavailable Instead check for lock conflicts per path and cache the result. Change-Id: I39c59bb240cd99ef0a0ec271243770ffd5df8a7d Reviewed-by: David Faure --- src/corelib/io/qlockfile_p.h | 2 +- src/corelib/io/qlockfile_unix.cpp | 42 +++++++++++++++++++++++++++------------ 2 files changed, 30 insertions(+), 14 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/io/qlockfile_p.h b/src/corelib/io/qlockfile_p.h index 168062f467..48b642abd0 100644 --- a/src/corelib/io/qlockfile_p.h +++ b/src/corelib/io/qlockfile_p.h @@ -78,7 +78,7 @@ public: static QString processNameByPid(qint64 pid); #ifdef Q_OS_UNIX - static int checkFcntlWorksAfterFlock(); + static int checkFcntlWorksAfterFlock(const QString &fn); #endif QString fileName; diff --git a/src/corelib/io/qlockfile_unix.cpp b/src/corelib/io/qlockfile_unix.cpp index bd9f8a5988..667b108ba0 100644 --- a/src/corelib/io/qlockfile_unix.cpp +++ b/src/corelib/io/qlockfile_unix.cpp @@ -39,6 +39,10 @@ #include "QtCore/qfileinfo.h" #include "QtCore/qdebug.h" #include "QtCore/qdatetime.h" +#include "QtCore/qfileinfo.h" +#include "QtCore/qcache.h" +#include "QtCore/qglobalstatic.h" +#include "QtCore/qmutex.h" #include "private/qcore_unix_p.h" // qt_safe_open #include "private/qabstractfileengine_p.h" @@ -89,10 +93,10 @@ static qint64 qt_write_loop(int fd, const char *data, qint64 len) return pos; } -int QLockFilePrivate::checkFcntlWorksAfterFlock() +int QLockFilePrivate::checkFcntlWorksAfterFlock(const QString &fn) { #ifndef QT_NO_TEMPORARYFILE - QTemporaryFile file; + QTemporaryFile file(fn); if (!file.open()) return 0; const int fd = file.d_func()->engine()->handle(); @@ -114,24 +118,34 @@ int QLockFilePrivate::checkFcntlWorksAfterFlock() #endif } -static QBasicAtomicInt fcntlOK = Q_BASIC_ATOMIC_INITIALIZER(-1); +// Cache the result of checkFcntlWorksAfterFlock for each directory a lock +// file is created in because in some filesystems, like NFS, both locks +// are the same. This does not take into account a filesystem changing. +// QCache is set to hold a maximum of 10 entries, this is to avoid unbounded +// growth, this is caching directories of files and it is assumed a low number +// will be sufficient. +typedef QCache CacheType; +Q_GLOBAL_STATIC_WITH_ARGS(CacheType, fcntlOK, (10)); +static QBasicMutex fcntlLock; /*! \internal Checks that the OS isn't using POSIX locks to emulate flock(). OS X is one of those. */ -static bool fcntlWorksAfterFlock() +static bool fcntlWorksAfterFlock(const QString &fn) { - int value = fcntlOK.load(); - if (Q_UNLIKELY(value == -1)) { - value = QLockFilePrivate::checkFcntlWorksAfterFlock(); - fcntlOK.store(value); + QMutexLocker lock(&fcntlLock); + bool *worksPtr = fcntlOK->object(fn); + if (!worksPtr) { + worksPtr = new bool(QLockFilePrivate::checkFcntlWorksAfterFlock(fn)); + fcntlOK->insert(fn, worksPtr); } - return value == 1; + + return *worksPtr; } -static bool setNativeLocks(int fd) +static bool setNativeLocks(const QString &fileName, int fd) { #if defined(LOCK_EX) && defined(LOCK_NB) if (flock(fd, LOCK_EX | LOCK_NB) == -1) // other threads, and other processes on a local fs @@ -143,8 +157,10 @@ static bool setNativeLocks(int fd) flockData.l_start = 0; flockData.l_len = 0; // 0 = entire file flockData.l_pid = getpid(); - if (fcntlWorksAfterFlock() && fcntl(fd, F_SETLK, &flockData) == -1) // for networked filesystems + if (fcntlWorksAfterFlock(QDir::cleanPath(QFileInfo(fileName).absolutePath()) + QString('/')) + && fcntl(fd, F_SETLK, &flockData) == -1) { // for networked filesystems return false; + } return true; } @@ -171,7 +187,7 @@ QLockFile::LockError QLockFilePrivate::tryLock_sys() } } // Ensure nobody else can delete the file while we have it - if (!setNativeLocks(fd)) { + if (!setNativeLocks(fileName, fd)) { const int errnoSaved = errno; qWarning() << "setNativeLocks failed:" << qt_error_string(errnoSaved); } @@ -195,7 +211,7 @@ bool QLockFilePrivate::removeStaleLock() const int fd = qt_safe_open(lockFileName.constData(), O_WRONLY, 0644); if (fd < 0) // gone already? return false; - bool success = setNativeLocks(fd) && (::unlink(lockFileName) == 0); + bool success = setNativeLocks(fileName, fd) && (::unlink(lockFileName) == 0); close(fd); return success; } -- cgit v1.2.3 From 1823c8f2ddd0a5c1b4301e7af7109796090a3c9a Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Wed, 16 Dec 2015 14:04:27 +0100 Subject: Fix utf8->utf16 BOM/ZWNBSP decoding. When the byte sequence for a BOM occurs in the middle of a utf8 stream, it is a ZWNBSP. When a ZWNBSP occurs in the middle of a utf8 character sequence, and the SIMD conversion does some work (meaning: the length is at least 16 characters long), it would not recognize the fact some charactes were already decoded. So the conversion would then strip the ZWNBSP out, thinking it's a BOM. The non-SIMD conversion did not have this problem: the very first character conversion would already set the headerdone flag. Change-Id: I39aacf607e2e068107106254021a8042d164f628 Reviewed-by: Thiago Macieira --- src/corelib/codecs/qutfcodec.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/codecs/qutfcodec.cpp b/src/corelib/codecs/qutfcodec.cpp index 98d4b2e4e3..a33c1bc9ce 100644 --- a/src/corelib/codecs/qutfcodec.cpp +++ b/src/corelib/codecs/qutfcodec.cpp @@ -364,6 +364,7 @@ QString QUtf8::convertToUnicode(const char *chars, int len, QTextCodec::Converte // main body, stateless decoding res = 0; const uchar *nextAscii = src; + const uchar *start = src; while (res >= 0 && src < end) { if (src >= nextAscii && simdDecodeAscii(dst, nextAscii, src, end)) break; @@ -372,9 +373,11 @@ QString QUtf8::convertToUnicode(const char *chars, int len, QTextCodec::Converte res = QUtf8Functions::fromUtf8(ch, dst, src, end); if (!headerdone && res >= 0) { headerdone = true; - // eat the UTF-8 BOM - if (dst[-1] == 0xfeff) - --dst; + if (src == start + 3) { // 3 == sizeof(utf8-bom) + // eat the UTF-8 BOM (it can only appear at the beginning of the string). + if (dst[-1] == 0xfeff) + --dst; + } } if (res == QUtf8BaseTraits::Error) { res = 0; -- cgit v1.2.3 From e96fa5a780665e24fe4710868e399b3216a5d3b3 Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Mon, 21 Dec 2015 11:37:49 +0100 Subject: Fix timeout calculations using qt_subtract_from_timeout Commit ed0c0070 introduced qt_subtract_from_timeout but used it incorrectly in several places. Change-Id: I80ea16088707929a45d5a61ec6f3370f8e63d1cd Reviewed-by: Oswald Buddenhagen --- src/corelib/io/qwinoverlappedionotifier.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/corelib') diff --git a/src/corelib/io/qwinoverlappedionotifier.cpp b/src/corelib/io/qwinoverlappedionotifier.cpp index c6ce15c2c9..8b7d70cf71 100644 --- a/src/corelib/io/qwinoverlappedionotifier.cpp +++ b/src/corelib/io/qwinoverlappedionotifier.cpp @@ -364,7 +364,7 @@ bool QWinOverlappedIoNotifier::waitForNotified(int msecs, OVERLAPPED *overlapped return false; if (triggeredOverlapped == overlapped) return true; - msecs = qt_subtract_from_timeout(msecs, stopWatch.elapsed()); + t = qt_subtract_from_timeout(msecs, stopWatch.elapsed()); if (t == 0) return false; } -- cgit v1.2.3 From 655246969eaa916fbc098a7315dc24830f5b8b5d Mon Sep 17 00:00:00 2001 From: Raphael Kubo da Costa Date: Mon, 28 Dec 2015 11:43:36 +0100 Subject: forkfd: Also define BSD visibility macros in forkfd_qt.cpp. This is a follow-up to c8c4ad0 ("forkfd: Define __BSD_VISIBLE and _NETBSD_SOURCE"). Defining those macros in forkfd.c is not enough: forkfd_qt.cpp also sets _POSIX_C_SOURCE, and sys/cdefs.h can be included implicitly via Qt's headers ( ends up pulling unistd.h that leads to sys/cdefs.h and sys/types.h with both libstdc++ and older libc++ versions). In this case, __BSD_VISIBLE/_NETBSD_SOURCE are not defined, _POSIX_C_SOURCE is, several type definitions are omitted and by the time we include sys/time.h in forkfd.c the build fails. On FreeBSD < 11, the error looks like this: In file included from io/../../3rdparty/forkfd/forkfd.c:36, from io/forkfd_qt.cpp:80: /usr/include/sys/time.h:94: error: 'u_int' has not been declared Change-Id: I01fa2f5861027d99936d3026faeee9f0db3ecabd Reviewed-by: Thiago Macieira --- src/corelib/io/forkfd_qt.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src/corelib') diff --git a/src/corelib/io/forkfd_qt.cpp b/src/corelib/io/forkfd_qt.cpp index 6704ec6f2a..d282c08fbd 100644 --- a/src/corelib/io/forkfd_qt.cpp +++ b/src/corelib/io/forkfd_qt.cpp @@ -39,6 +39,15 @@ # define _XOPEN_SOURCE 700 #endif +// Define BSD visibility macros. These are also defined in forkfd.c, but the +// headers using them may be included before forkfd.c itself. +#ifndef _NETBSD_SOURCE +# define _NETBSD_SOURCE 1 +#endif +#ifndef __BSD_VISIBLE +# define __BSD_VISIBLE 1 +#endif + #include #include "qprocess_p.h" -- cgit v1.2.3 From e0a5f661e52fd09611f406ae82128b6ef81fe90e Mon Sep 17 00:00:00 2001 From: Masaru Ueki Date: Sat, 26 Dec 2015 16:01:25 +0900 Subject: QStateMachine: fix ignore high-priority events. When a high-priority event is posted in overrided 'QStateMachine::beginSelectTransitions', the event may be remained in event queue, and be not dispatched until another event posted. Change-Id: Ifda288d9c00ac7985e426b9cc02bda382ebaac35 Reviewed-by: Erik Verbruggen --- src/corelib/statemachine/qstatemachine.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index e5d019dc8b..ee522218ee 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -1946,12 +1946,14 @@ void QStateMachinePrivate::_q_process() } } if (enabledTransitions.isEmpty()) { - processing = false; - stopProcessingReason = EventQueueEmpty; - noMicrostep(); + if (isInternalEventQueueEmpty()) { + processing = false; + stopProcessingReason = EventQueueEmpty; + noMicrostep(); #ifdef QSTATEMACHINE_DEBUG - qDebug() << q << ": no transitions enabled"; + qDebug() << q << ": no transitions enabled"; #endif + } } else { didChange = true; q->beginMicrostep(e); -- cgit v1.2.3 From 02f70004c266f4c35f098f49cfb3ca0284e28cac Mon Sep 17 00:00:00 2001 From: Alex Trotsenko Date: Sat, 5 Dec 2015 23:55:17 +0200 Subject: Allow socket events processing with a foreign event loop on Windows While a native dialog is open, the application message queue is handled by the native event loop which is external to Qt. In this case, QEventDispatcherWin32::processEvents() does not run and socket notifiers will not be activated. So, this patch moves the notifier activation code into the window procedure, which enables socket event processing with native dialogs. Task-number: QTBUG-49782 Task-number: QTBUG-48901 Change-Id: Icbdd96b2e80c50b73505f4fe74957575b83d6cf1 Reviewed-by: Oswald Buddenhagen Reviewed-by: Kai Koehne Reviewed-by: Joerg Bornemann --- src/corelib/kernel/qeventdispatcher_win.cpp | 44 ++++++++++++++++++++--------- src/corelib/kernel/qeventdispatcher_win_p.h | 2 ++ 2 files changed, 33 insertions(+), 13 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp index 695eb3d5d0..812494372d 100644 --- a/src/corelib/kernel/qeventdispatcher_win.cpp +++ b/src/corelib/kernel/qeventdispatcher_win.cpp @@ -79,6 +79,7 @@ extern uint qGlobalPostedEventsCount(); enum { WM_QT_SOCKETNOTIFIER = WM_USER, WM_QT_SENDPOSTEDEVENTS = WM_USER + 1, + WM_QT_ACTIVATENOTIFIERS = WM_USER + 2, SendPostedEventsWindowsTimerId = ~1u }; @@ -309,7 +310,7 @@ static void resolveTimerAPI() QEventDispatcherWin32Private::QEventDispatcherWin32Private() : threadId(GetCurrentThreadId()), interrupt(false), closingDown(false), internalHwnd(0), getMessageHook(0), serialNumber(0), lastSerialNumber(0), sendPostedEventsWindowsTimerId(0), - wakeUps(0) + wakeUps(0), activateNotifiersPosted(false) { resolveTimerAPI(); } @@ -393,6 +394,7 @@ LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPA if (sn) { d->doWsaAsyncSelect(sn->fd, 0); d->active_fd[sn->fd].selected = false; + d->postActivateSocketNotifiers(); if (type < 3) { QEvent event(QEvent::SockAct); QCoreApplication::sendEvent(sn->obj, &event); @@ -403,6 +405,20 @@ LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPA } } return 0; + } else if (message == WM_QT_ACTIVATENOTIFIERS) { + Q_ASSERT(d != 0); + + // register all socket notifiers + for (QSFDict::iterator it = d->active_fd.begin(), end = d->active_fd.end(); + it != end; ++it) { + QSockFd &sd = it.value(); + if (!sd.selected) { + d->doWsaAsyncSelect(it.key(), sd.event); + sd.selected = true; + } + } + d->activateNotifiersPosted = false; + return 0; } else if (message == WM_QT_SENDPOSTEDEVENTS // we also use a Windows timer to send posted events when the message queue is full || (message == WM_TIMER @@ -643,6 +659,12 @@ void QEventDispatcherWin32Private::doWsaAsyncSelect(int socket, long event) WSAAsyncSelect(socket, internalHwnd, event ? int(WM_QT_SOCKETNOTIFIER) : 0, event); } +void QEventDispatcherWin32Private::postActivateSocketNotifiers() +{ + if (!activateNotifiersPosted) + activateNotifiersPosted = PostMessage(internalHwnd, WM_QT_ACTIVATENOTIFIERS, 0, 0); +} + void QEventDispatcherWin32::createInternalHwnd() { Q_D(QEventDispatcherWin32); @@ -761,16 +783,6 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags) d->queuedSocketEvents.append(msg); continue; } - } else if (!(flags & QEventLoop::ExcludeSocketNotifiers)) { - // register all socket notifiers - for (QSFDict::iterator it = d->active_fd.begin(), end = d->active_fd.end(); - it != end; ++it) { - QSockFd &sd = it.value(); - if (!sd.selected) { - d->doWsaAsyncSelect(it.key(), sd.event); - sd.selected = true; - } - } } } if (!haveMessage) { @@ -891,6 +903,8 @@ void QEventDispatcherWin32::registerSocketNotifier(QSocketNotifier *notifier) "same socket %d and type %s", sockfd, t[type]); } + createInternalHwnd(); + QSockNot *sn = new QSockNot; sn->obj = notifier; sn->fd = sockfd; @@ -915,6 +929,8 @@ void QEventDispatcherWin32::registerSocketNotifier(QSocketNotifier *notifier) } else { d->active_fd.insert(sockfd, QSockFd(event)); } + + d->postActivateSocketNotifiers(); } void QEventDispatcherWin32::unregisterSocketNotifier(QSocketNotifier *notifier) @@ -940,10 +956,12 @@ void QEventDispatcherWin32::unregisterSocketNotifier(QSocketNotifier *notifier) d->doWsaAsyncSelect(sockfd, 0); const long event[3] = { FD_READ | FD_CLOSE | FD_ACCEPT, FD_WRITE | FD_CONNECT, FD_OOB }; sd.event ^= event[type]; - if (sd.event == 0) + if (sd.event == 0) { d->active_fd.erase(it); - else + } else if (sd.selected) { sd.selected = false; + d->postActivateSocketNotifiers(); + } } QSNDict *sn_vec[3] = { &d->sn_read, &d->sn_write, &d->sn_except }; diff --git a/src/corelib/kernel/qeventdispatcher_win_p.h b/src/corelib/kernel/qeventdispatcher_win_p.h index 8578110ee4..9a53e06730 100644 --- a/src/corelib/kernel/qeventdispatcher_win_p.h +++ b/src/corelib/kernel/qeventdispatcher_win_p.h @@ -178,7 +178,9 @@ public: QSNDict sn_write; QSNDict sn_except; QSFDict active_fd; + bool activateNotifiersPosted; void doWsaAsyncSelect(int socket, long event); + void postActivateSocketNotifiers(); QList winEventNotifierList; void activateEventNotifier(QWinEventNotifier * wen); -- cgit v1.2.3 From 71ea41f999c1dbe83cba2491f5ac99d6c5a3d98c Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Wed, 6 Jan 2016 13:50:56 +0100 Subject: Fix UB in QVariant::canConvert() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 'currentType' was not sanitized before being used as a shift. Fix by checking for a valid shift amount before shifting. Also change the shifted value from 1 (int) to 1U (uint). It's just the right thing to do. Found by UBSan: qtbase/src/corelib/kernel/qvariant.cpp:3131:59: runtime error: shift exponent 1114 is too large for 32-bit type 'unsigned int' Change-Id: Id3910d6d7f166fd7c80adf5ce1699f0eeb453562 Reviewed-by: Jędrzej Nowacki Reviewed-by: Thiago Macieira --- src/corelib/kernel/qvariant.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index f7a4abbf68..811483d74f 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -2891,6 +2891,7 @@ static const quint32 qCanConvertMatrix[QVariant::LastCoreType + 1] = /*QUuid*/ 1 << QVariant::String }; +static const size_t qCanConvertMatrixMaximumTargetType = 8 * sizeof(*qCanConvertMatrix); #ifndef QT_BOOTSTRAPPED /*! @@ -3140,8 +3141,9 @@ bool QVariant::canConvert(int targetTypeId) const case QMetaType::ULong: case QMetaType::Short: case QMetaType::UShort: - return qCanConvertMatrix[QVariant::Int] & (1 << currentType) - || currentType == QVariant::Int + return currentType == QVariant::Int + || (currentType < qCanConvertMatrixMaximumTargetType + && qCanConvertMatrix[QVariant::Int] & (1U << currentType)) || QMetaType::typeFlags(currentType) & QMetaType::IsEnumeration; case QMetaType::QObjectStar: return canConvertMetaObject(currentType, targetTypeId, d.data.o); @@ -3152,7 +3154,8 @@ bool QVariant::canConvert(int targetTypeId) const if (targetTypeId == String && currentType == StringList) return v_cast(&d)->count() == 1; - return qCanConvertMatrix[targetTypeId] & (1 << currentType); + return currentType < qCanConvertMatrixMaximumTargetType + && qCanConvertMatrix[targetTypeId] & (1U << currentType); } /*! -- cgit v1.2.3 From b4ab4868bc8422e09590d13d35c2bba7a195ccf5 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Wed, 6 Jan 2016 12:58:56 +0100 Subject: Fix UB in QFSFileEnginePrivate::writeFdFh() Apparently, it is considered valid to call the function with 'data' set to nullptr, and 'len' to zero. But doing so invokes undefined behavior because nullptr is passed to fwrite(). Fix by protecting the loops with 'if (len)'. Found by UBSan: qtbase/src/corelib/io/qfsfileengine.cpp:732:84: runtime error: null pointer passed as argument 1, which is declared to never be null Change-Id: Idfe23875c868ebb21d2164550de3304d2f01e9df Reviewed-by: Oswald Buddenhagen Reviewed-by: Thiago Macieira --- src/corelib/io/qfsfileengine.cpp | 46 ++++++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 21 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/io/qfsfileengine.cpp b/src/corelib/io/qfsfileengine.cpp index 429c40da1a..10e116a23a 100644 --- a/src/corelib/io/qfsfileengine.cpp +++ b/src/corelib/io/qfsfileengine.cpp @@ -724,29 +724,33 @@ qint64 QFSFileEnginePrivate::writeFdFh(const char *data, qint64 len) qint64 writtenBytes = 0; - if (fh) { - // Buffered stdlib mode. - - size_t result; - do { - result = fwrite(data + writtenBytes, 1, size_t(len - writtenBytes), fh); - writtenBytes += result; - } while (result == 0 ? errno == EINTR : writtenBytes < len); + if (len) { // avoid passing nullptr to fwrite() or QT_WRITE() (UB) - } else if (fd != -1) { - // Unbuffered stdio mode. + if (fh) { + // Buffered stdlib mode. + + size_t result; + do { + result = fwrite(data + writtenBytes, 1, size_t(len - writtenBytes), fh); + writtenBytes += result; + } while (result == 0 ? errno == EINTR : writtenBytes < len); + + } else if (fd != -1) { + // Unbuffered stdio mode. + + SignedIOType result; + do { + // calculate the chunk size + // on Windows or 32-bit no-largefile Unix, we'll need to read in chunks + // we limit to the size of the signed type, otherwise we could get a negative number as a result + quint64 wantedBytes = quint64(len) - quint64(writtenBytes); + UnsignedIOType chunkSize = std::numeric_limits::max(); + if (chunkSize > wantedBytes) + chunkSize = wantedBytes; + result = QT_WRITE(fd, data + writtenBytes, chunkSize); + } while (result > 0 && (writtenBytes += result) < len); + } - SignedIOType result; - do { - // calculate the chunk size - // on Windows or 32-bit no-largefile Unix, we'll need to read in chunks - // we limit to the size of the signed type, otherwise we could get a negative number as a result - quint64 wantedBytes = quint64(len) - quint64(writtenBytes); - UnsignedIOType chunkSize = std::numeric_limits::max(); - if (chunkSize > wantedBytes) - chunkSize = wantedBytes; - result = QT_WRITE(fd, data + writtenBytes, chunkSize); - } while (result > 0 && (writtenBytes += result) < len); } if (len && writtenBytes == 0) { -- cgit v1.2.3 From 13189360e50a429ee43ce927c29ebcd3948619b7 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Wed, 6 Jan 2016 13:31:11 +0100 Subject: Fix UB in QFileDevice::writeData() Passing nullptr as the 2nd argument of memcpy constitutes undefined behavior. Fix by protecting the block with 'if (len)', which, presumably, is the only valid case where 'data' may be nullptr. Change-Id: I7647d7e0808b1f26444ea3cf8bbf5cda9ddc9e6c Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/io/qfiledevice.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/corelib') diff --git a/src/corelib/io/qfiledevice.cpp b/src/corelib/io/qfiledevice.cpp index 3ee0e33573..2d6be5fb80 100644 --- a/src/corelib/io/qfiledevice.cpp +++ b/src/corelib/io/qfiledevice.cpp @@ -560,7 +560,7 @@ qint64 QFileDevice::writeData(const char *data, qint64 len) char *writePointer = d->writeBuffer.reserve(len); if (len == 1) *writePointer = *data; - else + else if (len) ::memcpy(writePointer, data, len); return len; } -- cgit v1.2.3 From 61169b72c24b336af23702fda1e86d1d1c2c8095 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Wed, 6 Jan 2016 10:36:41 +0100 Subject: Fix UB in QIODevicePrivate Passing nullptr as the second argument of memcpy/memmove constitutes undefined behavior, even if the length argument is zero at the same time. Fix by protecting mem{cpy,move,chr} from nullptrs. Found by UBSan: qtbase/src/corelib/io/qiodevice_p.h:105:33: runtime error: null pointer passed as argument 2, which is declared to never be null qtbase/src/corelib/io/qiodevice_p.h:175:53: runtime error: null pointer passed as argument 2, which is declared to never be null Change-Id: I979158b0a74169ca4eb459928398ebc40f77dfb5 Reviewed-by: Alex Trotsenko Reviewed-by: Thiago Macieira --- src/corelib/io/qiodevice_p.h | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/io/qiodevice_p.h b/src/corelib/io/qiodevice_p.h index f4cf387eb5..8342176cff 100644 --- a/src/corelib/io/qiodevice_p.h +++ b/src/corelib/io/qiodevice_p.h @@ -102,14 +102,17 @@ public: } qint64 read(char* target, qint64 size) { qint64 r = qMin(size, len); - memcpy(target, first, r); - len -= r; - first += r; + if (r) { + memcpy(target, first, r); + len -= r; + first += r; + } return r; } qint64 peek(char* target, qint64 size) { qint64 r = qMin(size, len); - memcpy(target, first, r); + if (r) + memcpy(target, first, r); return r; } char* reserve(qint64 size) { @@ -141,7 +144,7 @@ public: return r; } bool canReadLine() const { - return memchr(first, '\n', len); + return first && memchr(first, '\n', len); } void ungetChar(char c) { if (first == buf) { @@ -172,7 +175,8 @@ private: if (newCapacity > capacity) { // allocate more space char* newBuf = new char[newCapacity]; - memmove(newBuf + moveOffset, first, len); + if (first) + memmove(newBuf + moveOffset, first, len); delete [] buf; buf = newBuf; capacity = newCapacity; -- cgit v1.2.3 From 434302eae1a0c5d3016fe07c7d343bdbad118a8a Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 12 Jan 2016 13:55:01 -0800 Subject: Fix non-Latin1 strings in QJsonDocument on big-endian platforms QJsonDocument stores the entire JSON tree in its binary format. Since the binary format is the same on-disk as in-memory, it has a fixed endianness. But when converting from QString to the little-endian format, the code accidentally converted twice (from little endian, to little endian), which resulted in a no-op and the string got stored as big-endian. It's like encrypting with double-ROT13. No new testcase because tst_QtJson::removeNonLatinKey was already failing and gets fixed by this commit. Task-number: QTBUG-50419 Change-Id: I408dcb81ba654c929f25ffff1428cc79472bbe13 Reviewed-by: Olivier Goffart (Woboq GmbH) Reviewed-by: Lars Knoll --- src/corelib/json/qjson_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/corelib') diff --git a/src/corelib/json/qjson_p.h b/src/corelib/json/qjson_p.h index 5fc021c841..17f49d41c8 100644 --- a/src/corelib/json/qjson_p.h +++ b/src/corelib/json/qjson_p.h @@ -305,7 +305,7 @@ public: { d->length = str.length(); #if Q_BYTE_ORDER == Q_BIG_ENDIAN - const qle_ushort *uc = (const qle_ushort *)str.unicode(); + const ushort *uc = (const ushort *)str.unicode(); for (int i = 0; i < str.length(); ++i) d->utf16[i] = uc[i]; #else -- cgit v1.2.3 From 5ef14c52d0275e721153b15acfb0410b9889014a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Klitzing?= Date: Wed, 13 Jan 2016 15:20:37 +0100 Subject: Fix QFileSelector::select if called with QUrl and scheme "assets" QFileSelector::select(QUrl) will use ":" for scheme "qrc" to call QFileSelector::select(QString). Scheme "assets" needs to remain "assets:" for select(QString), otherwise it won't recognize the file in "assets". Following failed because it was passed as ":/qml/example.qml" to select(QString): select(QUrl("assets:/qml/example.qml")); This will call select(QString) to: select("assets:/qml/example.qml"); Change-Id: I6bdeed6bb67992498ae3b8e1273c20e70049381a Task-number: QTBUG-50435 Reviewed-by: BogDan Vatra --- src/corelib/io/qfileselector.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/io/qfileselector.cpp b/src/corelib/io/qfileselector.cpp index 85d9b0bfcb..af8d9b2b36 100644 --- a/src/corelib/io/qfileselector.cpp +++ b/src/corelib/io/qfileselector.cpp @@ -248,9 +248,16 @@ QUrl QFileSelector::select(const QUrl &filePath) const return filePath; QUrl ret(filePath); if (isLocalScheme(filePath.scheme())) { - QString equivalentPath = QLatin1Char(':') + filePath.path(); + QLatin1String scheme(":"); +#ifdef Q_OS_ANDROID + // use other scheme because ":" means "qrc" here + if (filePath.scheme() == QLatin1String("assets")) + scheme = QLatin1String("assets:"); +#endif + + QString equivalentPath = scheme + filePath.path(); QString selectedPath = d->select(equivalentPath); - ret.setPath(selectedPath.remove(0, 1)); + ret.setPath(selectedPath.remove(0, scheme.size())); } else { ret = QUrl::fromLocalFile(d->select(ret.toLocalFile())); } -- cgit v1.2.3