From 700ea0af687d90ef98d3e9bee57e164174cce4e4 Mon Sep 17 00:00:00 2001 From: Frederik Schwarzer Date: Fri, 28 Oct 2016 11:39:34 +0200 Subject: QMainWindow: fix wording in apidoc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I5cb44bed7e946574eb3e08ff51948f901b2bb78c Reviewed-by: Topi Reiniö --- src/widgets/widgets/qmainwindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/widgets/widgets/qmainwindow.cpp b/src/widgets/widgets/qmainwindow.cpp index e454e3e991..aefd028305 100644 --- a/src/widgets/widgets/qmainwindow.cpp +++ b/src/widgets/widgets/qmainwindow.cpp @@ -320,7 +320,7 @@ void QMainWindowPrivate::init() direction. Two dock widgets may also be stacked on top of each other. A - QTabBar is then used to select which of the widgets that should be + QTabBar is then used to select which of the widgets should be displayed. We give an example of how to create and add dock widgets to a -- cgit v1.2.3 From 1df45820d4ccbb67b9ad0f3eed167342f2917cf8 Mon Sep 17 00:00:00 2001 From: Martin Smith Date: Fri, 23 Sep 2016 14:20:16 +0200 Subject: doc: Document two undocumented functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This change provides missing documentation for two member functions of QString. QString QString::fromUtf16(const char16_t *str, int size) QString QString::fromUcs4(const char32_t *str, int size) Change-Id: I94a9437a457062e49e4457f5876e4d7c31fff24c Reviewed-by: André Hartmann Reviewed-by: Topi Reiniö --- src/corelib/tools/qstring.cpp | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) (limited to 'src') diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index b7f83e4b9d..645d213d82 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -4818,6 +4818,39 @@ QString QString::fromUtf16(const ushort *unicode, int size) return QUtf16::convertToUnicode((const char *)unicode, size*2, 0); } +/*! + \fn QString QString::fromUtf16(const char16_t *str, int size) + \since 5.3 + + Returns a QString initialized with the first \a size characters + of the Unicode string \a str (ISO-10646-UTF-16 encoded). + + If \a size is -1 (default), \a str must be terminated + with a 0. + + This function checks for a Byte Order Mark (BOM). If it is missing, + host byte order is assumed. + + This function is slow compared to the other Unicode conversions. + Use QString(const QChar *, int) or QString(const QChar *) if possible. + + QString makes a deep copy of the Unicode data. + + \sa utf16(), setUtf16(), fromStdU16String() +*/ + +/*! + \fn QString QString::fromUcs4(const char32_t *str, int size) + \since 5.3 + + Returns a QString initialized with the first \a size characters + of the Unicode string \a str (ISO-10646-UCS-4 encoded). + + If \a size is -1 (default), \a str must be terminated + with a 0. + + \sa toUcs4(), fromUtf16(), utf16(), setUtf16(), fromWCharArray(), fromStdU32String() +*/ /*! \since 4.2 -- cgit v1.2.3 From dcedce51a62ae9519d8e85c004c2f93159be8751 Mon Sep 17 00:00:00 2001 From: Jesus Fernandez Date: Tue, 1 Nov 2016 11:35:02 +0100 Subject: Include intrin.h header when using MSVC Fixes the build with MSVC15 Change-Id: I7f22938583775bb3f0767d50cf59a43cab95eede Reviewed-by: Friedemann Kleint --- src/corelib/tools/qalgorithms.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/corelib/tools/qalgorithms.h b/src/corelib/tools/qalgorithms.h index ffa3082d5e..b22c5e219c 100644 --- a/src/corelib/tools/qalgorithms.h +++ b/src/corelib/tools/qalgorithms.h @@ -36,6 +36,10 @@ #include +#if defined(Q_CC_MSVC) && _MSC_VER > 1500 +#include +#endif + QT_BEGIN_NAMESPACE QT_WARNING_PUSH QT_WARNING_DISABLE_GCC("-Wdeprecated-declarations") -- cgit v1.2.3 From c5010107221ce1ba8dd08f2067c7921389baa96b Mon Sep 17 00:00:00 2001 From: Sergio Martins Date: Fri, 21 Oct 2016 19:41:44 +0100 Subject: Mention QDialog::setSizeGripEnabled() in QSizeGrip's docs The same way it also mentions QStatusBar. Change-Id: Ic084466310c989d1a79ba5ba21d6784acaa38e6e Reviewed-by: Martin Smith --- src/widgets/widgets/qsizegrip.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/widgets/widgets/qsizegrip.cpp b/src/widgets/widgets/qsizegrip.cpp index b2ffef2a5a..5cacff7e0d 100644 --- a/src/widgets/widgets/qsizegrip.cpp +++ b/src/widgets/widgets/qsizegrip.cpp @@ -178,9 +178,12 @@ Qt::Corner QSizeGripPrivate::corner() const Put this widget anywhere in a widget tree and the user can use it to resize the top-level window or any widget with the Qt::SubWindow flag set. Generally, this should be in the lower right-hand corner. + Note that QStatusBar already uses this widget, so if you have a status bar (e.g., you are using QMainWindow), then you don't need - to use this widget explicitly. + to use this widget explicitly. The same goes for QDialog, for which + you can just call \l {QDialog::setSizeGripEnabled()} + {QDialog::setSizeGripEnabled()}. On some platforms the size grip automatically hides itself when the window is shown full screen or maximised. -- cgit v1.2.3 From b5fc085e712815bcd465370f88d1df8179b538e3 Mon Sep 17 00:00:00 2001 From: Jesus Fernandez Date: Wed, 2 Nov 2016 10:40:37 +0100 Subject: Add QPixmapIconEngine::pixmap pointer check Dereference after null check (FORWARD_NULL)5. var_deref_op: Dereferencing null pointer pe. pe pointer it's being checked at the beginning of the function so it implies pe might be null. Coverity-Id: 11106 Change-Id: Ie88b27877a46cdd20a317fb5e21c3fdec1b99dda Reviewed-by: Edward Welbourne --- src/gui/image/qicon.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp index 3531be412e..5098955825 100644 --- a/src/gui/image/qicon.cpp +++ b/src/gui/image/qicon.cpp @@ -294,7 +294,7 @@ QPixmap QPixmapIconEngine::pixmap(const QSize &size, QIcon::Mode mode, QIcon::St QString key = QLatin1String("qt_") % HexString(pm.cacheKey()) - % HexString(pe->mode) + % HexString(pe ? pe->mode : QIcon::Normal) % HexString(QGuiApplication::palette().cacheKey()) % HexString(actualSize.width()) % HexString(actualSize.height()); -- cgit v1.2.3 From 5f6c0418fe911b7afe34153b16b3f00839354afd Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Tue, 1 Nov 2016 14:54:16 +0100 Subject: winrt: Fixed assignment of readOrigin in readDatagram Change-Id: I0455b6526b8bacd30622698e0a497fa2da3932ba Reviewed-by: David Faure --- src/network/socket/qnativesocketengine_winrt.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/network/socket/qnativesocketengine_winrt.cpp b/src/network/socket/qnativesocketengine_winrt.cpp index b6a739d1b8..920b8e2cb1 100644 --- a/src/network/socket/qnativesocketengine_winrt.cpp +++ b/src/network/socket/qnativesocketengine_winrt.cpp @@ -641,7 +641,7 @@ qint64 QNativeSocketEngine::readDatagram(char *data, qint64 maxlen, QIpPacketHea QByteArray readOrigin; // Do not read the whole datagram. Put the rest of it back into the "queue" if (maxlen < datagram.data.length()) { - QByteArray readOrigin = datagram.data.left(maxlen); + readOrigin = datagram.data.left(maxlen); datagram.data = datagram.data.remove(0, maxlen); d->pendingDatagrams.prepend(datagram); } else { -- cgit v1.2.3 From ca4d93d85ee446c5e30ec8e7814651e45cbf1218 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 12 Nov 2015 10:14:51 -0800 Subject: Stop unloading plugins in QPluginLoader and QFactoryLoader QPluginLoader hasn't unloaded in its destructor since Qt 5.0, but we missed the equivalent code in QFactoryLoader (which bypasses QPluginLoader). Besides, QPluginLoader::unload() was still doing unloading, which it won't anymore. Not unloading plugins is Qt's policy, as decided during the 5.0 development process and reaffirmed now in 5.6. This is due to static data in plugins leaking out and remaining in use past the unloading of the plugin, causing crashes. This does not affect QLibrary and QLibrary::unload(). Those are meant for non-Qt loadable modules, so unloading them may be safe. Task-number: QTBUG-49061 Discussed-on: http://lists.qt-project.org/pipermail/development/2015-November/023681.html Change-Id: I461e9fc7199748faa187ffff1416070f138df8db (cherry picked from commit 494376f980e96339b6f1eff7c41336ca4d853065) Discussed-again-on: http://lists.qt-project.org/pipermail/development/2016-October/027476.html Reviewed-by: Lars Knoll --- src/corelib/plugin/qfactoryloader.cpp | 6 ++++-- src/corelib/plugin/qpluginloader.cpp | 5 +++-- 2 files changed, 7 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/corelib/plugin/qfactoryloader.cpp b/src/corelib/plugin/qfactoryloader.cpp index dcf1b1a81d..b6558f5834 100644 --- a/src/corelib/plugin/qfactoryloader.cpp +++ b/src/corelib/plugin/qfactoryloader.cpp @@ -208,10 +208,12 @@ void QFactoryLoader::update() ++keyUsageCount; } } - if (keyUsageCount || keys.isEmpty()) + if (keyUsageCount || keys.isEmpty()) { + library->setLoadHints(QLibrary::PreventUnloadHint); // once loaded, don't unload d->libraryList += library; - else + } else { library->release(); + } } } #else diff --git a/src/corelib/plugin/qpluginloader.cpp b/src/corelib/plugin/qpluginloader.cpp index 37f2368413..0ea8280fef 100644 --- a/src/corelib/plugin/qpluginloader.cpp +++ b/src/corelib/plugin/qpluginloader.cpp @@ -148,6 +148,7 @@ QPluginLoader::QPluginLoader(const QString &fileName, QObject *parent) : QObject(parent), d(0), did_load(false) { setFileName(fileName); + setLoadHints(QLibrary::PreventUnloadHint); } /*! @@ -342,7 +343,7 @@ static QString locatePlugin(const QString& fileName) void QPluginLoader::setFileName(const QString &fileName) { #if defined(QT_SHARED) - QLibrary::LoadHints lh; + QLibrary::LoadHints lh = QLibrary::PreventUnloadHint; if (d) { lh = d->loadHints(); d->release(); @@ -391,7 +392,7 @@ Q_GLOBAL_STATIC(StaticPluginList, staticPluginList) \brief Give the load() function some hints on how it should behave. You can give hints on how the symbols in the plugin are - resolved. By default, none of the hints are set. + resolved. By default since Qt 5.7, QLibrary::PreventUnloadHint is set. See the documentation of QLibrary::loadHints for a complete description of how this property works. -- cgit v1.2.3 From 9e53a91e99accae299ff7b4cc0a9c3675606d688 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Fri, 21 Oct 2016 18:28:55 +0200 Subject: Fix tiling on a width over 2048 The blend_tiled_argb and blend_tiled_rgb565 was not correctly handling widths larger than the buffer size. This patch adds the same pattern used in blend_tiled_generic, which worked correctly. Change-Id: Ie22c2a21d96cb0477cd0990bf01451ab907a4768 Task-number: QTBUG-56364 Reviewed-by: Eirik Aavitsland --- src/gui/painting/qdrawhelper.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index 39ff4142b8..c0a662b002 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -4509,8 +4509,10 @@ static void blend_tiled_argb(int count, const QSpan *spans, void *userData) uint *dest = ((uint *)data->rasterBuffer->scanLine(spans->y)) + x; op.func(dest, src, l, coverage); x += l; + sx += l; length -= l; - sx = 0; + if (sx >= image_width) + sx = 0; } ++spans; } @@ -4568,7 +4570,9 @@ static void blend_tiled_rgb565(int count, const QSpan *spans, void *userData) memcpy(dest, src, l * sizeof(quint16)); length -= l; tx += l; - sx = 0; + sx += l; + if (sx >= image_width) + sx = 0; } // Now use the rasterBuffer as the source of the texture, @@ -4601,8 +4605,10 @@ static void blend_tiled_rgb565(int count, const QSpan *spans, void *userData) const quint16 *src = (const quint16 *)data->texture.scanLine(sy) + sx; blend_sourceOver_rgb16_rgb16(dest, src, l, alpha, ialpha); x += l; + sx += l; length -= l; - sx = 0; + if (sx >= image_width) + sx = 0; } } } -- cgit v1.2.3 From 1a1a0e31590a5a7f360a86de5c34a2aec8e17157 Mon Sep 17 00:00:00 2001 From: Dmitry Shachnev Date: Thu, 3 Nov 2016 12:06:43 +0300 Subject: GTK+ dialogs: Get rid of deprecated GtkStock usage GtkStock has been deprecated since GTK+ 3.10, and is removed in GTK+ 4. Use the standard button names provided by Qt instead. Change-Id: I55e8452178544b4a9ebf5c75b70f4c5c56c047f4 Reviewed-by: J-P Nurmi --- src/plugins/platformthemes/gtk3/qgtk3dialoghelpers.cpp | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/plugins/platformthemes/gtk3/qgtk3dialoghelpers.cpp b/src/plugins/platformthemes/gtk3/qgtk3dialoghelpers.cpp index c2a116b03c..ba88af917d 100644 --- a/src/plugins/platformthemes/gtk3/qgtk3dialoghelpers.cpp +++ b/src/plugins/platformthemes/gtk3/qgtk3dialoghelpers.cpp @@ -38,6 +38,7 @@ ****************************************************************************/ #include "qgtk3dialoghelpers.h" +#include "qgtk3theme.h" #include #include @@ -56,6 +57,11 @@ QT_BEGIN_NAMESPACE +static const char *standardButtonText(int button) +{ + return QGtk3Theme::defaultStandardButtonText(button).toUtf8(); +} + class QGtk3Dialog : public QWindow { Q_OBJECT @@ -237,8 +243,10 @@ QGtk3FileDialogHelper::QGtk3FileDialogHelper() { d.reset(new QGtk3Dialog(gtk_file_chooser_dialog_new("", 0, GTK_FILE_CHOOSER_ACTION_OPEN, - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_OK, GTK_RESPONSE_OK, NULL))); + standardButtonText(QPlatformDialogHelper::Cancel), GTK_RESPONSE_CANCEL, + standardButtonText(QPlatformDialogHelper::Ok), GTK_RESPONSE_OK, + NULL))); + connect(d.data(), SIGNAL(accept()), this, SLOT(onAccepted())); connect(d.data(), SIGNAL(reject()), this, SIGNAL(reject())); @@ -435,9 +443,9 @@ void QGtk3FileDialogHelper::applyOptions() if (opts->isLabelExplicitlySet(QFileDialogOptions::Accept)) gtk_button_set_label(GTK_BUTTON(acceptButton), opts->labelText(QFileDialogOptions::Accept).toUtf8()); else if (opts->acceptMode() == QFileDialogOptions::AcceptOpen) - gtk_button_set_label(GTK_BUTTON(acceptButton), GTK_STOCK_OPEN); + gtk_button_set_label(GTK_BUTTON(acceptButton), standardButtonText(QPlatformDialogHelper::Open)); else - gtk_button_set_label(GTK_BUTTON(acceptButton), GTK_STOCK_SAVE); + gtk_button_set_label(GTK_BUTTON(acceptButton), standardButtonText(QPlatformDialogHelper::Save)); } GtkWidget *rejectButton = gtk_dialog_get_widget_for_response(gtkDialog, GTK_RESPONSE_CANCEL); @@ -445,7 +453,7 @@ void QGtk3FileDialogHelper::applyOptions() if (opts->isLabelExplicitlySet(QFileDialogOptions::Reject)) gtk_button_set_label(GTK_BUTTON(rejectButton), opts->labelText(QFileDialogOptions::Reject).toUtf8()); else - gtk_button_set_label(GTK_BUTTON(rejectButton), GTK_STOCK_CANCEL); + gtk_button_set_label(GTK_BUTTON(rejectButton), standardButtonText(QPlatformDialogHelper::Cancel)); } } -- cgit v1.2.3 From cf4e7575cad8975442191160723d766b48a9623f Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 31 Oct 2016 23:57:36 -0700 Subject: Fix GCC warning about ODR violation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are two enums called "Operator" qdrawhelper_p.h:201:8: warning: type ‘struct Operator’ violates the C++ One Definition Rule [-Wodr] qopengl.cpp:138:6: note: a different type is defined in another translation unit Change-Id: I09100678ff4443e6be06fffd1482da1f636614b7 Reviewed-by: Marc Mutz --- src/gui/opengl/qopengl.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/gui/opengl/qopengl.cpp b/src/gui/opengl/qopengl.cpp index 3dedd7d7be..9f48d82c9d 100644 --- a/src/gui/opengl/qopengl.cpp +++ b/src/gui/opengl/qopengl.cpp @@ -129,9 +129,6 @@ QDebug operator<<(QDebug d, const QOpenGLConfig::Gpu &g) return d; } -enum Operator { NotEqual, LessThan, LessEqualThan, Equals, GreaterThan, GreaterEqualThan }; -static const char operators[][3] = {"!=", "<", "<=", "=", ">", ">="}; - static inline QString valueKey() { return QStringLiteral("value"); } static inline QString opKey() { return QStringLiteral("op"); } static inline QString versionKey() { return QStringLiteral("version"); } @@ -169,6 +166,9 @@ static inline bool contains(const QJsonArray &haystack, const QString &needle) } namespace { +enum Operator { NotEqual, LessThan, LessEqualThan, Equals, GreaterThan, GreaterEqualThan }; +static const char operators[][3] = {"!=", "<", "<=", "=", ">", ">="}; + // VersionTerm describing a version term consisting of number and operator // found in os.version and driver_version. struct VersionTerm { -- cgit v1.2.3 From 4b6784b49c6dcf0add9ec0cbb4ad97cd191c2aa3 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 15 Sep 2016 14:07:59 -0700 Subject: Stop using readdir_r: glibc deprecated it and it's not a good idea MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit POSIX does not require that readdir() be reentrant even for operations on different dirent objects, but all implementations (according to the glibc documentation) already do that. Moreover, it's not a good idea to use readdir_r since the buffer space is limited by the caller, so certain file names may be too long (ENAMETOOLONG) -- we had a workaround for QNX, but for no other OS. According to the glibc documentation, it is expected that POSIX will mark readdir_r obsolete and instead require some form of reentrancy for readdir. This commit makes everyone use readdir instead. The macros in qplatformdefs.h are left behind in case someone else is using them. With glibc 2.24, we started getting: qplatformdefs.h:150:35: warning: ‘int readdir_r(DIR*, dirent*, dirent**)’ is deprecated [-Wdeprecated-declarations] qfilesystemiterator_unix.cpp:112:17: note: in expansion of macro ‘QT_READDIR_R’ Task-number: QTBUG-56088 Change-Id: I33dc971f005a4848bb8ffffd14749b4082f62e69 Reviewed-by: Edward Welbourne Reviewed-by: James McDonnell --- src/corelib/io/qfilesystemengine.cpp | 4 +-- src/corelib/io/qfilesystemiterator_p.h | 8 ------ src/corelib/io/qfilesystemiterator_unix.cpp | 38 ----------------------------- 3 files changed, 2 insertions(+), 48 deletions(-) (limited to 'src') diff --git a/src/corelib/io/qfilesystemengine.cpp b/src/corelib/io/qfilesystemengine.cpp index 02aa2ff4b7..055ff3600b 100644 --- a/src/corelib/io/qfilesystemengine.cpp +++ b/src/corelib/io/qfilesystemengine.cpp @@ -216,7 +216,7 @@ bool QFileSystemEngine::fillMetaData(int fd, QFileSystemMetaData &data) return false; } -#if defined(QT_EXT_QNX_READDIR_R) +#if defined(_DEXTRA_FIRST) static void fillStat64fromStat32(struct stat64 *statBuf64, const struct stat &statBuf32) { statBuf64->st_mode = statBuf32.st_mode; @@ -281,7 +281,7 @@ void QFileSystemMetaData::fillFromStatBuf(const QT_STATBUF &statBuffer) void QFileSystemMetaData::fillFromDirEnt(const QT_DIRENT &entry) { -#if defined(QT_EXT_QNX_READDIR_R) +#if defined(_DEXTRA_FIRST) knownFlagsMask = 0; entryFlags = 0; for (dirent_extra *extra = _DEXTRA_FIRST(&entry); _DEXTRA_VALID(extra, &entry); diff --git a/src/corelib/io/qfilesystemiterator_p.h b/src/corelib/io/qfilesystemiterator_p.h index 119068a648..51dfe65f57 100644 --- a/src/corelib/io/qfilesystemiterator_p.h +++ b/src/corelib/io/qfilesystemiterator_p.h @@ -87,14 +87,6 @@ private: #else QT_DIR *dir; QT_DIRENT *dirEntry; -#if defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_CYGWIN) || defined(QT_EXT_QNX_READDIR_R) - // for readdir_r - QScopedPointer mt_file; -#if defined(QT_EXT_QNX_READDIR_R) - // for _readdir_r - size_t direntSize; -#endif -#endif int lastError; #endif diff --git a/src/corelib/io/qfilesystemiterator_unix.cpp b/src/corelib/io/qfilesystemiterator_unix.cpp index 6f094bd3b2..7d0e910188 100644 --- a/src/corelib/io/qfilesystemiterator_unix.cpp +++ b/src/corelib/io/qfilesystemiterator_unix.cpp @@ -46,9 +46,6 @@ QFileSystemIterator::QFileSystemIterator(const QFileSystemEntry &entry, QDir::Fi : nativePath(entry.nativeFilePath()) , dir(0) , dirEntry(0) -#if defined(Q_OS_QNX) && defined(__EXT_QNX__READDIR_R) - , direntSize(0) -#endif , lastError(0) { Q_UNUSED(filters) @@ -58,32 +55,8 @@ QFileSystemIterator::QFileSystemIterator(const QFileSystemEntry &entry, QDir::Fi if ((dir = QT_OPENDIR(nativePath.constData())) == 0) { lastError = errno; } else { - if (!nativePath.endsWith('/')) nativePath.append('/'); - -#if defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_CYGWIN) || defined(QT_EXT_QNX_READDIR_R) - // ### Race condition; we should use fpathconf and dirfd(). - size_t maxPathName = ::pathconf(nativePath.constData(), _PC_NAME_MAX); - if (maxPathName == size_t(-1)) - maxPathName = FILENAME_MAX; - maxPathName += sizeof(QT_DIRENT) + 1; - - QT_DIRENT *p = reinterpret_cast(::malloc(maxPathName)); - Q_CHECK_PTR(p); - - mt_file.reset(p); -#if defined(QT_EXT_QNX_READDIR_R) - direntSize = maxPathName; - - // Include extra stat information in the readdir() call (d_stat member of - // dirent_extra_stat). This is used in QFileSystemMetaData::fillFromDirEnt() to - // avoid extra stat() calls when iterating over directories - int flags = dircntl(dir, D_GETFLAG) | D_FLAG_STAT | D_FLAG_FILTER; - if (dircntl(dir, D_SETFLAG, flags) == -1) - lastError = errno; -#endif -#endif } } @@ -98,18 +71,7 @@ bool QFileSystemIterator::advance(QFileSystemEntry &fileEntry, QFileSystemMetaDa if (!dir) return false; -#if defined(QT_EXT_QNX_READDIR_R) - lastError = QT_EXT_QNX_READDIR_R(dir, mt_file.data(), &dirEntry, direntSize); - if (lastError) - return false; -#elif defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_CYGWIN) - lastError = QT_READDIR_R(dir, mt_file.data(), &dirEntry); - if (lastError) - return false; -#else - // ### add local lock to prevent breaking reentrancy dirEntry = QT_READDIR(dir); -#endif // _POSIX_THREAD_SAFE_FUNCTIONS if (dirEntry) { fileEntry = QFileSystemEntry(nativePath + QByteArray(dirEntry->d_name), QFileSystemEntry::FromNativePath()); -- cgit v1.2.3 From 15df60239d2dd3b0f0844e3ec8c91300fb7a4b67 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Wed, 2 Nov 2016 09:37:42 +0100 Subject: Fix OOM crashes for huge json documents Check all places where we reallocate our internal data structure and return a DocumentTooLarge parse error if we can't get enough memory. Change-Id: I006d0170d941837220c7dad0508571b68e2cbfd7 Reviewed-by: Edward Welbourne Reviewed-by: Kati Kankaanpaa Reviewed-by: Simon Hausmann --- src/corelib/json/qjsonparser.cpp | 79 ++++++++++++++++++++++++++++++++++++---- src/corelib/json/qjsonparser_p.h | 4 ++ 2 files changed, 76 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/corelib/json/qjsonparser.cpp b/src/corelib/json/qjsonparser.cpp index b8a628fdcc..c7b16d5ec9 100644 --- a/src/corelib/json/qjsonparser.cpp +++ b/src/corelib/json/qjsonparser.cpp @@ -385,6 +385,8 @@ bool Parser::parseObject() } int objectOffset = reserveSpace(sizeof(QJsonPrivate::Object)); + if (objectOffset < 0) + return false; BEGIN << "parseObject pos=" << objectOffset << current << json; ParsedObject parsedObject(this, objectOffset); @@ -417,6 +419,9 @@ bool Parser::parseObject() if (parsedObject.offsets.size()) { int tableSize = parsedObject.offsets.size()*sizeof(uint); table = reserveSpace(tableSize); + if (table < 0) + return false; + #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN memcpy(data + table, parsedObject.offsets.constData(), tableSize); #else @@ -446,6 +451,8 @@ bool Parser::parseObject() bool Parser::parseMember(int baseOffset) { int entryOffset = reserveSpace(sizeof(QJsonPrivate::Entry)); + if (entryOffset < 0) + return false; BEGIN << "parseMember pos=" << entryOffset; bool latin1; @@ -469,6 +476,42 @@ bool Parser::parseMember(int baseOffset) return true; } +namespace { + struct ValueArray { + static const int prealloc = 128; + ValueArray() : data(stackValues), alloc(prealloc), size(0) {} + ~ValueArray() { if (data != stackValues) free(data); } + + inline bool grow() { + alloc *= 2; + if (data == stackValues) { + QJsonPrivate::Value *newValues = static_cast(malloc(alloc*sizeof(QJsonPrivate::Value))); + if (!newValues) + return false; + memcpy(newValues, data, size*sizeof(QJsonPrivate::Value)); + data = newValues; + } else { + data = static_cast(realloc(data, alloc*sizeof(QJsonPrivate::Value))); + if (!data) + return false; + } + return true; + } + bool append(const QJsonPrivate::Value &v) { + if (alloc == size && !grow()) + return false; + data[size] = v; + ++size; + return true; + } + + QJsonPrivate::Value stackValues[prealloc]; + QJsonPrivate::Value *data; + int alloc; + int size; + }; +} + /* array = begin-array [ value *( value-separator value ) ] end-array */ @@ -482,8 +525,10 @@ bool Parser::parseArray() } int arrayOffset = reserveSpace(sizeof(QJsonPrivate::Array)); + if (arrayOffset < 0) + return false; - QVarLengthArray values; + ValueArray values; if (!eatSpace()) { lastError = QJsonParseError::UnterminatedArray; @@ -496,7 +541,10 @@ bool Parser::parseArray() QJsonPrivate::Value val; if (!parseValue(&val, arrayOffset)) return false; - values.append(val); + if (!values.append(val)) { + lastError = QJsonParseError::DocumentTooLarge; + return false; + } char token = nextToken(); if (token == EndArray) break; @@ -510,20 +558,22 @@ bool Parser::parseArray() } } - DEBUG << "size =" << values.size(); + DEBUG << "size =" << values.size; int table = arrayOffset; // finalize the object - if (values.size()) { - int tableSize = values.size()*sizeof(QJsonPrivate::Value); + if (values.size) { + int tableSize = values.size*sizeof(QJsonPrivate::Value); table = reserveSpace(tableSize); - memcpy(data + table, values.constData(), tableSize); + if (table < 0) + return false; + memcpy(data + table, values.data, tableSize); } QJsonPrivate::Array *a = (QJsonPrivate::Array *)(data + arrayOffset); a->tableOffset = table - arrayOffset; a->size = current - arrayOffset; a->is_object = false; - a->length = values.size(); + a->length = values.size; DEBUG << "current=" << current; END; @@ -732,6 +782,8 @@ bool Parser::parseNumber(QJsonPrivate::Value *val, int baseOffset) } int pos = reserveSpace(sizeof(double)); + if (pos < 0) + return false; qToLittleEndian(ui, reinterpret_cast(data + pos)); if (current - baseOffset >= Value::MaxSize) { lastError = QJsonParseError::DocumentTooLarge; @@ -850,6 +902,9 @@ bool Parser::parseString(bool *latin1) // try to write out a latin1 string int stringPos = reserveSpace(2); + if (stringPos < 0) + return false; + BEGIN << "parse string stringPos=" << stringPos << json; while (json < end) { uint ch = 0; @@ -872,6 +927,8 @@ bool Parser::parseString(bool *latin1) break; } int pos = reserveSpace(1); + if (pos < 0) + return false; DEBUG << " " << ch << (char)ch; data[pos] = (uchar)ch; } @@ -887,6 +944,8 @@ bool Parser::parseString(bool *latin1) // write string length *(QJsonPrivate::qle_ushort *)(data + stringPos) = ushort(current - outStart - sizeof(ushort)); int pos = reserveSpace((4 - current) & 3); + if (pos < 0) + return false; while (pos & 3) data[pos++] = 0; END; @@ -916,10 +975,14 @@ bool Parser::parseString(bool *latin1) } if (QChar::requiresSurrogates(ch)) { int pos = reserveSpace(4); + if (pos < 0) + return false; *(QJsonPrivate::qle_ushort *)(data + pos) = QChar::highSurrogate(ch); *(QJsonPrivate::qle_ushort *)(data + pos + 2) = QChar::lowSurrogate(ch); } else { int pos = reserveSpace(2); + if (pos < 0) + return false; *(QJsonPrivate::qle_ushort *)(data + pos) = (ushort)ch; } } @@ -933,6 +996,8 @@ bool Parser::parseString(bool *latin1) // write string length *(QJsonPrivate::qle_int *)(data + stringPos) = (current - outStart - sizeof(int))/2; int pos = reserveSpace((4 - current) & 3); + if (pos < 0) + return false; while (pos & 3) data[pos++] = 0; END; diff --git a/src/corelib/json/qjsonparser_p.h b/src/corelib/json/qjsonparser_p.h index a395c0c92e..82a7899a51 100644 --- a/src/corelib/json/qjsonparser_p.h +++ b/src/corelib/json/qjsonparser_p.h @@ -102,6 +102,10 @@ private: if (current + space >= dataLength) { dataLength = 2*dataLength + space; data = (char *)realloc(data, dataLength); + if (!data) { + lastError = QJsonParseError::DocumentTooLarge; + return -1; + } } int pos = current; current += space; -- cgit v1.2.3